What's New
Q & A
Tip Jar
C# Helper...
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 _
    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
    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)
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 _
    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.
        remainder = a Mod b
        If remainder = 0 Then Exit Do
        a = b
        b = remainder

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