等分された円周上の点を線で結んでみる ② 座標の取得とクラス化

昨日は、等分された円周上の点を、とにかく全部線で結ぶ関数を作成してみた。
infoment.hatenablog.com

今日から複数回に分けて、等間隔(素数)で点を結ぶ「糸かけ曼荼羅」を作成することに挑戦する。
f:id:Infoment:20200512203027j:plain

線を引くためには、始点と終点の座標が必要だ。そこで、この座標を手っ取り早く取得するために、昨日作成した関数の一部でクラスモジュールを作成してみた。

なお数学で馴染みの表記となるよう、今回は座標をジャグ配列で持たせている。<<座標(i)=(x座標,y座標)>>

クラスモジュール(Mandara)
Enum 座標軸名
    x座標
    y座標
End Enum

Public 分割数 As Long
Public 旋回中心 As Variant
Public 旋回半径 As Double

Private Sub Class_Initialize()
    分割数 = 30
    旋回中心 = Array(500, 500)
    旋回半径 = 200
End Sub

Public Sub Reset()
    ' 元々書いてある線を削除。
    On Error Resume Next
    ActiveSheet.Shapes.SelectAll
    Selection.Delete
End Sub

Public Property Get 各座標取得() As Variant
    Dim arr() As Variant
    ReDim arr(1 To 分割数 + 1)
    Dim x As Double
    Dim y As Double
    Dim i As Long
    Dim θ As Double
        θ = 2 * WorksheetFunction.Pi / 分割数
        For i = 1 To 分割数
            x = 旋回中心(x座標) + 旋回半径 * Sin(i * θ)
            y = 旋回中心(y座標) - 旋回半径 * (1 - Cos(i * θ))
            arr(i) = Array(x, y)
        Next
        arr(分割数 + 1) = arr(1)
    
        各座標取得 = arr
End Property

続いて、等間隔ごとにポイントをスキップしながら線を引いてみよう。
簡単のため、5等分した点を3つずつ数えて線を引いた場合について考える。

始点が1点目の場合 ⇒ 終点は1+3=4点目
始点が4点目の場合 ⇒ 終点は4+3=1周+2点目

f:id:Infoment:20200512204644p:plain

このことからn+1点目は、nを5で割った余りで求まりそうに思える。
しかし実際は、割り切れるとき余りが0になって上手く行かない。
f:id:Infoment:20200512204949p:plain

こんな時は、nからまず1引いておき、余りに1を足すと良い。
f:id:Infoment:20200512205150p:plain

これを踏まえて、先程のクラスモジュールに ↓ を追加した。

Sub PrimeMandara(prime_number As Long, _
        Optional wait_flag As Boolean = False)
    Dim 始点 As Long: 始点 = 1
    Dim 終点 As Long: 終点 = 1
    Dim 各座標 As Variant
        各座標 = 各座標取得
    
        Do
            始点 = 終点
            終点 = ((始点 + prime_number - 1) Mod 分割数) + 1
    
            ActiveSheet.Shapes.AddConnector msoConnectorStraight, _
                                            各座標(始点)(x座標), 各座標(始点)(y座標), _
                                            各座標(終点)(x座標), 各座標(終点)(y座標)
    
            If wait_flag Then
                Application.Wait [Now() + "00:00:00.1"]
            End If
            
            If 終点 = 1 Then Exit Do
        Loop
End Sub

これで先程の5分割を3つずつ結ぶと、お星さまが出来上がった。
f:id:Infoment:20200512205829p:plain

傾いている(或いは、ひっくり返っている?)のは、ご愛敬。

それでは早速、テストしてみよう。

Sub test()
    With New Mandara
        .Reset
        .分割数 = 64
        .PrimeMandara 31
        .PrimeMandara 29
        .PrimeMandara 23
        .PrimeMandara 19
        .PrimeMandara 17
        .PrimeMandara 13
        .PrimeMandara 11
        .PrimeMandara 7
        .PrimeMandara 3
    End With
End Sub

結果は ↓ こちら。
f:id:Infoment:20200512210421g:plain

一応、描画は上手く行ったようだ。
だが、課題がまだいくつもある(線の色をどうするか、など)。

ということで、次回に続きます。

参考まで。