在本人的视频课程《【VB.NET】二维图形绘制》里曾经演示了如何利用渐变颜色填充五角星的代码,在这里我再补充讲解下如何利用数学三角函数计算绘制五角星的10个顶点坐标。
1.比如要在一个长宽均为400像素的矩形框范围内绘制一个五角星,可以定义这个矩形框为:
Dim rect As New Rectangle(0, 0, 400, 400)
2.我们要绘制的五角星的五个顶点,则位于这个矩形框定义的圆形的圆周上,再加上每两个顶点(比如A和C)之间的凹入点(比如B点),10个点与圆心的连线将圆周角分成10等份(每份2π/10=π/5)。
3.我们先计算出此矩形rect长和宽的一半值,存入cx和cy两个变量:
Dim cx As Integer = rect.Width \ 2
Dim cy As Integer = rect.Height \ 2
4.如果我们把连接圆心和五角星顶点的大圆半径(比如OA和OC)定义为r1,把连接圆心和五角星凹点的小圆半径(比如OB和OD)定义为r2,我们可以指定它们的长度为:
Dim r1 As Integer = Min(cx, cy) '用Min是因为有可能矩形是一个长方形
Dim r2 As Integer = Min(cx, cy) \ 2 '即为大圆半径的一半
5.如果从A点开始按照顺时针方向(ABCD方向)分别求取这10个点的坐标的话,每相邻的两个半径r1和r2所在的圆周角角度值都相差π/5,可以看到OA角度为-π/2(-90°),OB角度为-(π/2-π/5)=π/5-π/2,π在VB里表达为System.Math.PI,以此类推,可以利用一个For循环求得对应两个相邻r1和r2的角度值为:
For i As Integer = 0 To 9 Step 2
'设置Step 2以便执行五次循环,让每个相邻r1和r2对应的圆周角为一个循环
Dim angle1 As Double = i * PI / 5 - PI / 2 '对应r1
Dim angle2 As Double = (i + 1) * PI / 5 - PI / 2 '对应r2
Next
6.请看下图对应r1的直角三角形△COM,和对应r2的直角三角形△DOL:
可见对应C点的坐标为(cx+OM,cy-CM),对应D点的坐标为(cx+OL,cy+LD),而由于:
OM=|Cos(∠COM)*OC|
CM=|Sin(∠COM)*OC|
OL=|Cos(∠DOL)*OD|
LD=|Sin(∠DOL)*OD|
以上书写表示计算直角边线段长度的伪代码:各直角边线段长度等于相应角度正弦值或余弦值的绝对值。因为0°到180°之间的角的正弦值为正数,反之为负数;-90°到90°之间角的余弦值为正数,反之为负数。所以C点坐标(cx+OM,cy-CM)可以表达为(cx+Cos(∠COM)*OC,cy+Sin(∠COM)*OC),相邻的D点坐标(cx+OL,cy+LD)可以表达为(cx+Cos(∠DOL)*OD,cy+Sin(∠DOL)*OD)。在VB里求余弦用System.Math.Cos函数,求正弦用System.Math.Sin函数。据此可推算出:对于每组相邻的r1和r2,根据斜边r1和锐角angle1,斜边r2和锐角angle2构成的直角三角形,五角星每组相应顶点p1和凹点p2的坐标可表达为:
Dim p1 As New PointF(cx+Cos(angle1)*r1,cy+Sin(angle1)*r1)
Dim p2 As New PointF(cx+Cos(angle2)*r2,cy+Sin(angle2)*r2)
7.根据以上分析,整理绘制五角星的代码如下:
Option Strict On
Option Infer Off
Imports System.Math
Imports System.Drawing.Drawing2D
Public Class Form1
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim rect As New Rectangle(0, 0, 400, 400)
Dim cx As Integer = rect.Width \ 2
Dim cy As Integer = rect.Height \ 2
Dim r1 As Integer = Min(cx, cy)
Dim r2 As Integer = Min(cx, cy) \ 2
Dim pts(9) As PointF '用于存储10个点的坐标
For i As Integer = 0 To 9 Step 2
Dim angle1 As Double = i * PI / 5 - PI / 2
Dim angle2 As Double = (i + 1) * PI / 5 - PI / 2
pts(i).X = cx + CSng(r1 * Cos(angle1))
pts(i).Y = cy + CSng(r1 * Sin(angle1))
pts(i + 1).X = cx + CSng(r2 * Cos(angle2))
pts(i + 1).Y = cy + CSng(r2 * Sin(angle2))
Next i
e.Graphics.DrawPolygon(Pens.Black, pts)
End Sub
End Class
绘制效果如下: