Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleDraw "stars" inside regular polygons in VB .NET
DescriptionThis example shows how to draw "stars" inside regular polygons in Visual Basic .NET.
Keywordsstar, polygon, VB.NET
CategoriesGraphics, VB.NET
 
The program draws stars by drawing lines between the vertices on a regular polygon. It always connects the current vertex to the Kth vertex after it. For example, a normal five-pointed star is drawn inside a pentagon by connecting every 2nd vertex. I.e. vertex 0 is connected to vertex 2, then vertex 4, then vertex 1, then vertex 3, then vertex 0 (draw one on paper if you don't understand this).

This drawing scheme will visit every vertex in the polygon before repeating if and only if the number of vertices N and the number K is relatively prime (i.e. have no common factors). I'll leave the proof to you. In the previous example, N = 5 and K = 2 are relatively prime so that drawing method visits every point before repeating.

Note that K = 1 is relatively prime to any number N so drawing with K = 1 visits every vertex before repeating. That just gives the polygon itself.

Also note that K = k and K = N - k draw the same "star." Try K = 2 and K = 3 for a pentagon.

The picCanvas control's Paint event handler draws the stars. It allocates space for the polygon's points and places them evenly spaced around a circle. It then loops over the numbers 1 through N \ 2 and tries using them as K. It doesn't need to examine values N \ 2 through N because of the second note above.

For each skip (K) value, the program determines the greatest common divisor (GCD) of K and N. If the GCD is 1, then N and K are relatively prime so the program calls subroutine DrawStar to draw the "star" and draws a label showing the number K.

 
' Draw the applicable stars.
Private Sub picCanvas_Paint(ByVal sender As Object, ByVal e _
    As System.Windows.Forms.PaintEventArgs) Handles _
    picCanvas.Paint
    If m_NumPoints < 3 Then Exit Sub

    Const RADIUS As Integer = 40
    Dim x, y As Integer

    ' Position the original points.
    Dim pts(m_NumPoints - 1) As PointF
    Dim theta As Double = -PI / 2
    Dim dtheta As Double = 2 * PI / m_NumPoints
    For i As Integer = 0 To m_NumPoints - 1
        pts(i).X = RADIUS * Cos(theta)
        pts(i).Y = RADIUS * Sin(theta)
        theta += dtheta
    Next i

    ' Draw stars.
    y = RADIUS + 5
    x = RADIUS + 5
    Dim sf As New StringFormat
    sf.Alignment = StringAlignment.Center
    sf.LineAlignment = StringAlignment.Near
    e.Graphics.Clear(picCanvas.BackColor)
    For skip As Integer = 1 To m_NumPoints \ 2
        ' See if they are relatively prime.
        If GCD(skip, m_NumPoints) = 1 Then
            ' Draw the star.
            DrawStar(e.Graphics, x, y, pts, skip)

            ' Draw a label.
            e.Graphics.DrawString(skip.ToString, _
                picCanvas.Font, Brushes.Black, x, y + _
                RADIUS + 2, sf)

            x += 2 * RADIUS + 5
            If x + RADIUS >= picCanvas.Width Then
                y += 2 * RADIUS + 15
                x = RADIUS + 5
            End If
        End If
    Next skip
End Sub
 
Subroutine DrawStar draws a "star" centered at a point. It makes a new array containing the polygon's vertices in the proper order to draw the "star," translates the Graphics object to position the "star," and then draws it.
 
' Draw a star centered at (x, y) using this skip value.
Private Sub DrawStar(ByVal gr As Graphics, ByVal x As _
    Integer, ByVal y As Integer, ByVal orig_pts() As _
    PointF, ByVal skip As Integer)
    ' Make a PointF array with the points in the proper
    ' order.
    Dim pts(m_NumPoints - 1) As PointF
    For i As Integer = 0 To m_NumPoints - 1
        pts(i) = orig_pts((i * skip) Mod m_NumPoints)
    Next i

    ' Draw the star.
    gr.TranslateTransform(x, y)
    gr.DrawPolygon(Pens.Blue, pts)
    gr.ResetTransform()
End Sub
 
Subroutine GCD determines the greatest common divisor of two numbers. I'll leave this proof to you, too.
 
' Return the greatest common divisor (GCD) of a and b.
Public Function GCD(ByVal a As Long, ByVal b As Long) As _
    Long
    Dim tmp As Long
    Dim remainder As Long

    ' Make a >= b.
    a = Abs(a)
    b = Abs(b)
    If a < b Then
        tmp = a
        a = b
        b = tmp
    End If

    ' Pull out remainders.
    Do
        remainder = a Mod b
        If remainder = 0 Then Exit Do
        a = b
        b = remainder
    Loop

    Return b
End Function
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated