投稿者 るきお  (社会人) 投稿日時 2019/9/20 22:19:49
Yudaiさんがどこまで理解されているのかわからないのでとりあえず簡単に一通り書きます。

正n角形はすべての頂点が同じ円周上にあります。
3角形の場合、点1と原点Oと点2が作る角度は120度です。
4角形の場合、90度です。
n角形の場合、360÷n 度 です。

つまり、1つ目の点の場所が決まれば同じ円周上の(360÷n)度先に次の点があることになります。
その次の点は(360÷n)×2度回転した先、その次の点は(360÷n)×3度回転した先にあり、この角度を利用すればすべての点の位置を決めることができます。

VBでは通常は点はxとyの座標で示すので、「回転した先」というのを (x, y)の座標で表す必要があります。

最初の1点目(点0)はたとえばy軸上にあると仮定すれば、点(0,半径) というように単純に決められます。
2つ目の点(点1)はこれを 360÷m度回転させた先にあります。

ところで、点0と原点と点1を結ぶと必ず直角三角形になります。斜辺が半径です。
xとyはそれぞれ残りの辺の長さです。
それから、この直角三角形のもう1つの角は(360÷n)度です。
以上から、この直角三角形ではすべての角の角度と斜辺の長さがわかっています。

この直角三角形の残りの2辺の長さを求めることがx,yを求めることにつながります。

さて、直角三角形の辺の長さの比率は紀元前から表にまとめられており、角度と1つの辺の長さがわかればこの比率から他の辺の長さが求められるようになっています。この比率を三角比と呼びます。三角形に辺が3つあるので、三角比には6種類あり、それぞれsin, cos, tan, cot, sec, cosecと名前がついています。

VBではMathクラスを使って角度を元にSin, Cos, Tanメソッドを使ってこの比を取得できます。
これは角度を引数にして比率を返すという観点では関数であり、三角関数と呼びます。

この理屈をプログラムしたのが下記です。
VBではy軸が学校数学と違って、下が正であることと、角度の単位がラジアンであることが大きな違いです。
このせいで学校数学では見慣れない処理が少し入りますが、理屈はここまで説明したとおりです。

※なお、ラジアンとは 360度を 2π とする単位です。180度はπです。VBではπはMath.PIで定義されています。

この例は7角形を描画します。試すにはPictureBoxを大きめに配置してください。


Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint

    DrawPolygon(7, e.Graphics)

End Sub

Private Sub DrawPolygon(index As Integer, g As Graphics)

    Const radius As Integer = 200 '外接円の半径 

    '中心角(360度)をn等分したときの1角あたりの角度(単位はラジアン) 
    Dim degree As Double = (Math.PI * 2) / index

    Dim points As New List(Of Point)

    For i As Integer = 0 To index - 1

        '点0から点iの角度(角 点1-O-点iの角度)に180度加えたもの。単位はラジアン。 
        '180度 = Math.PIラジアン 
        '180度加えなくても良いのですが、学校数学とy軸の方向が逆になっているので、180度加えることで、 
        '学校数学でなじんだような配置になります。 
        Dim thisDegree As Double = degree * i + Math.PI

        '点iのx座標 
        Dim x As Double = Math.Sin(thisDegree) * radius

        '点iのy座標 
        Dim y As Double = Math.Cos(thisDegree) * radius

        'この点を記憶しておく 
        points.Add(New Point(CInt(x), CInt(y)))
    Next

    '第4象限まで見えるように平行移動させる。(既定では第1象限しか表示されていない。) 
    g.TranslateTransform(radius, radius)

    '背景色黒 
    g.Clear(Color.Black)

    '座標を配列化して間を線で結ぶ。 
    g.DrawPolygon(Pens.Blue, points.ToArray)


End Sub