|
|
Title | Draw "stars" inside regular polygons |
Description | This example shows how to draw "stars" inside regular polygons in Visual Basic. |
Keywords | star, polygon |
Categories | Graphics |
|
|
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.
Subroutine DrawStars draws the stars for a polygon with a given number of points. 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 and the program draws the "star."
|
|
' Draw the applicable stars.
Private Sub DrawStars()
Const RADIUS As Single = 40
Const PI As Double = 3.14159265
Dim skip, i, x, y As Integer
Dim pts() As POINTAPI
Dim theta As Double
Dim dtheta As Double
If m_NumPoints < 3 Then Exit Sub
' Position the original points.
ReDim pts(0 To m_NumPoints - 1)
theta = -PI / 2
dtheta = 2 * PI / m_NumPoints
For i = 0 To m_NumPoints - 1
pts(i).x = RADIUS * Cos(theta)
pts(i).y = RADIUS * Sin(theta)
theta = theta + dtheta
Next i
' Draw stars.
y = RADIUS + 5
x = RADIUS + 5
picCanvas.Cls
For skip = 1 To m_NumPoints \ 2
' See if they are relatively prime.
If GCD(skip, m_NumPoints) = 1 Then
' Draw the star.
DrawStar picCanvas.hDC, x, y, pts, skip
' Draw a label.
CenterTextHorizontally picCanvas, _
Format$(skip), x, y + RADIUS + 2
x = x + 2 * RADIUS + 5
If x + RADIUS >= picCanvas.ScaleWidth Then
y = y + 2 * RADIUS + 15
x = RADIUS + 5
End If
End If
Next skip
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
GCD = b
End Function
|
|
|
|
|
|