Option Strict On Imports System.Drawing.Drawing2D Public Class Form1 ''' <summary>正多角形の頂点座標を取得します。</summary> ''' <param name="number">頂点数</param> ''' <param name="origin">中心座標</param> ''' <param name="point">第一頂点座標</param> ''' <returns><see cref="number"/>個の要素をもつ一次元配列</returns> Public Shared Function GetRegularPolygonF(number As Integer, origin As PointF, point As PointF) As PointF() If number < 3 Then Throw New ArgumentOutOfRangeException("number", number, "3 以上を指定してください。") End If Dim radian As Double = Math.Atan2(point.Y - origin.Y, point.X - origin.X) Dim radius As Double = (point.X - origin.X) / Math.Cos(radian) Dim vertex(number - 1) As PointF Dim theta As Double = Math.PI * 2.0R / number For n = 0 To number - 1 Dim d As Double = n * theta + radian vertex(n).X = origin.X + CSng(radius * Math.Cos(d)) vertex(n).Y = origin.Y + CSng(radius * Math.Sin(d)) Next Return vertex End Function ''' <summary>多角形の頂点の数。NumericUpDown1 で変更する。</summary> Public Property VertexCount As Integer = 7 ''' <summary>中心座標。PictureBox1 を左クリックして指定する。</summary> Public Property Origin As Nullable(Of Point) ''' <summary>頂点座標。PictureBox1 を左ドラッグして指定する。</summary> Public Property Vertex As Point Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load NumericUpDown1.DataBindings.Add("Value", Me, "VertexCount", False, DataSourceUpdateMode.OnPropertyChanged) End Sub Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint If Origin IsNot Nothing Then Render(e.Graphics, draft:=True) End If End Sub Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown If e.Button.HasFlag(MouseButtons.Left) Then Origin = e.Location Vertex = e.Location End If End Sub Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove If e.Button.HasFlag(MouseButtons.Left) Then Vertex = e.Location PictureBox1.Invalidate() End If End Sub Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp If Origin Is Nothing Then Return End If Vertex = e.Location '描画した多角形は累積して重ねていきたいので 'PictureBox に直接描画するのではなく、Image プロパティに残す Dim newImage As Image Dim oldImage = PictureBox1.Image Dim rect = PictureBox1.ClientRectangle If oldImage Is Nothing Then newImage = New Bitmap(rect.Width, rect.Height) Else newImage = New Bitmap(Math.Max(oldImage.Width, rect.Width), Math.Max(oldImage.Height, rect.Height)) End If Using g = Graphics.FromImage(newImage) g.Clear(Color.Transparent) If oldImage IsNot Nothing Then g.DrawImage(oldImage, Point.Empty) End If Render(g, draft:=False) End Using PictureBox1.Image = newImage Origin = Nothing If oldImage IsNot Nothing Then oldImage.Dispose() End If End Sub '多角形の描画 Private Sub Render(g As Graphics, draft As Boolean) Try Dim state = g.Save() g.SmoothingMode = SmoothingMode.HighQuality g.PixelOffsetMode = PixelOffsetMode.HighQuality If Origin.HasValue Then Using redPen As New Pen(If(draft, Brushes.Salmon, Brushes.Red), 3) g.DrawPolygon(redPen, GetRegularPolygonF(VertexCount, Origin.Value, Vertex)) If draft Then g.FillEllipse(Brushes.Salmon, Origin.Value.X - 3, Origin.Value.Y - 3, 5, 5) End If End Using End If g.Restore(state) Catch ex As Exception End Try End Sub End Class