円の内側で円を転がす

円の内側で円を転がす様子を描画したら、面白いかなと思った。

まず大きな円の半径を  r_1 、小さな円の半径を  r_2 とするとき、
小さな円が大きな円の中心から見て  θ_1 回転したときを考えてみる。
f:id:Infoment:20211002113043p:plain
Excelの数式では、sinやcosに与える角度の単位は「°」ではなく「rad」。
360° で  2π rad(ラジアン)となる。そこで以降、特に明記しない
限り角度の単位はradとする。

 θ_1 回転したときの弧の長さ  ℓ は、以下のとおり。

\displaystyle{ℓ=2πr_{1}×\frac{θ_{1}}{2π}}=r_{1}θ_{1}

弧の長さ=半径×角度ということで、とても単純な式になる。初めてradを
習ったときは「° でいいじゃん」と思っていたが、改めてradって便利だと
思った。

内側の小さな円も同じ長さを転がるわけだから、同様にして

\displaystyle{ℓ=2πr_{2}×\frac{θ_{2}}{2π}}=r_{2}θ_{2}
r_{1}θ_{1}=r_{2}θ_{2}

\displaystyle{∴θ_{2}=θ_{1}\frac{r_{1}}{r_{2}}}

となる。当たり前といえば当たり前、直感的に納得される方も多いと思う。
後は円を二つ書くだけなので、

θ_1の範囲:0 ⇒ 2π
大きな円の中心:(x_{0}, y_{0})=(0,0)
大きな円の座標:(x_{1}, y_{1})=(r_{1}cosθ_{1}, r_{1}sinθ_{1})

でぐるっと一周回せばよい。小さな円も同様だ。
※ただし今回は、二つの角度の関係維持は不要。円を描くだけなので。
θ_2の範囲:0 ⇒ 2π
小さな円の中心:\displaystyle{(x_{0}^{'}, y_{0}^{'})=(\frac{r_{1}-r_{2}}{r_{1}}x_{1}, \frac{r_{1}-r_{2}}{r_{1}}y_{1})}
小さな円の座標:(x_{2}, y_{2})=((x_{0}^{'}+r_{2}cosθ_{2}, y_{0}^{'}+r_{2}sinθ_{2})

それでは早速、散布図にしてみよう。

Sub ぐるぐる()

        Cells(2, 1).Resize(Rows.Count - 1, 3).Clear
    
    Dim π As Double
        π = WorksheetFunction.Pi
    
    Dim r(1 To 2) As Double
        ' 大きな円の半径。
        r(1) = 40
        ' 小さな円の半径。
        r(2) = 8
        
    Dim ox1 As Double
    Dim oy1 As Double
        ' 大きな円の中心座標。
        ox1 = 0: oy1 = 0
      
    Dim dc As Double
        ' 円周の分割数(Division Count)
        dc = 36
        
    DimAs Double= 2 * π / dc
    
    ' 大きい円の座標。
    Dim x1() As Double: ReDim x1(1 To dc + 1)
    Dim y1() As Double: ReDim y1(1 To dc + 1)
    ' 小さい円の座標。
    Dim x2() As Double: ReDim x2(1 To dc + 1)
    Dim y2() As Double: ReDim y2(1 To dc + 1)
    ' 小さい円の中心。
    Dim ox2() As Double: ReDim ox2(1 To dc + 1)
    Dim oy2() As Double: ReDim oy2(1 To dc + 1)
        
    Dim i As Long
    Dim j As Long

        ' 大きな円の描画。
        For i = 1 To dc + 1
            x1(i) = r(1) * Cos(* (i - 1))
            y1(i) = r(1) * Sin(* (i - 1))
            Cells(i + 1, 1) = x1(i)
            Cells(i + 1, 2) = y1(i)
        Next
    
        ' 続けて描画するため、iの最終値を保存。
    Dim LastIndex As Long
        LastIndex = i
        
        For i = 1 To dc + 1
            ' 小さな円の中心。
            ox2(i) = x1(i) * (r(1) - r(2)) / r(1)
            oy2(i) = y1(i) * (r(1) - r(2)) / r(1)

            Application.Wait [Now() + "00:00:00.01"]
            DoEvents
            
            ' 小さい円を描画。
            For j = 1 To dc + 1
                x2(i) = ox2(i) + r(2) * Cos(* (j - 1))
                y2(i) = oy2(i) + r(2) * Sin(* (j - 1))
                Cells(LastIndex + j, 1) = x2(i)
                Cells(LastIndex + j, 3) = y2(i)
            Next
        Next

End Sub

f:id:Infoment:20211002130504g:plain

一周だと、あっという間に終わってしまう。

ぐるぐる回してるだけだと退屈なので、もう少し面白くしてみたいです。

参考まで。