線を引いて動かす ⑧ まとめ

中学数学の図形問題説明のため、Excelで線を引き動かしてみた。
infoment.hatenablog.com

今日は、これらを纏めてみる。
f:id:Infoment:20200917224112p:plain

前回は、この5つの角の総和を求める方法を三通り紹介した。
f:id:Infoment:20200915223827p:plain

しかし勿論、他にも方法があると思う。例えば、こんな感じだ。
f:id:Infoment:20200917224337g:plain

黄と緑は0°となり、青は「対頂角は等しい」により、このようになる。
f:id:Infoment:20200917224500p:plain

この解法でも、5角の総和が180°であることが直感的に理解できるだろう。

さて、それでは7回にわたり作りこんだコードを、今回はまとめて掲載。

Function GetLine(Sx As Double, _
                 Sy As Double, _
                 Ex As Double, _
                 Ey As Double) As Shape
    Set GetLine = ActiveSheet.Shapes.AddConnector(msoConnectorStraight, _
                                                  Sx, Sy, _
                                                  Ex, Ey)
End Function

Function GetPosisionArray(target_shape As Variant) As Variant
        If Not TypeName(target_shape) = "Shape" Then
            GetPosisionArray = Array()
            Exit Function
        End If
    
    Dim Sx As Double
    Dim Sy As Double
    Dim Ex As Double
    Dim Ey As Double
        Select Case target_shape.HorizontalFlip
            Case True
                Sx = target_shape.Left + target_shape.Width
                Ex = target_shape.Left
            Case False
                Sx = target_shape.Left
                Ex = target_shape.Left + target_shape.Width
        End Select
        
        Select Case target_shape.VerticalFlip
            Case True
                Sy = target_shape.Top + target_shape.Height
                Ey = target_shape.Top
            Case False
                Sy = target_shape.Top
                Ey = target_shape.Top + target_shape.Height
        End Select
        
        GetPosisionArray = Array(Sx, Sy, Ex, Ey)
End Function

Function DrawRegularPolygon(Optional vertex_number As Long = 6, _
                            Optional radius As Double = 100, _
                            Optional Ox As Double = 300, _
                            Optional Oy As Double = 300) As Boolean

    Dim θ As Double
        θ = 2 * WorksheetFunction.Pi / vertex_number
        
    Dim Sx() As Double: ReDim Sx(1 To vertex_number)
    Dim Sy() As Double: ReDim Sy(1 To vertex_number)
    Dim Ex() As Double: ReDim Ex(1 To vertex_number)
    Dim Ey() As Double: ReDim Ey(1 To vertex_number)
        
    Dim i As Long
        For i = 1 To vertex_number
            Ex(i) = Ox - Sin((i - 1) * θ) * radius
            Ey(i) = Oy - Cos((i - 1) * θ) * radius
            Select Case i
                Case 1
                Case Else
                    Sx(i) = Ex(i - 1)
                    Sy(i) = Ey(i - 1)
            End Select
        Next
        
        Sx(1) = Ex(vertex_number)
        Sy(1) = Ey(vertex_number)
        
        For i = 1 To vertex_number
            GetLine Sx(i), Sy(i), Ex(i), Ey(i)
        Next
        
End Function

Sub MoveLine(ByVal start_position_array As Variant, _
             ByVal end_position_array As Variant, _
             Optional moving_times As Long = 30, _
             Optional delete_flag As Boolean = False)
    
    ReDim Preserve start_position_array(1 To UBound(start_position_array) - LBound(start_position_array) + 1)
    ReDim Preserve end_position_array(1 To UBound(end_position_array) - LBound(end_position_array) + 1)
    
    Dim LineNumber As Long
        LineNumber = UBound(start_position_array)
    
    ' 始点のx,y座標。
    Dim Sx() As Double: ReDim Sx(1 To LineNumber, moving_times)
    Dim Sy() As Double: ReDim Sy(1 To LineNumber, moving_times)
    ' 終点のx,y座標
    Dim Ex() As Double: ReDim Ex(1 To LineNumber, moving_times)
    Dim Ey() As Double: ReDim Ey(1 To LineNumber, moving_times)
    ' 一回当たりの移動量(始点)
    Dim dSx() As Double: ReDim dSx(1 To LineNumber)
    Dim dSy() As Double: ReDim dSy(1 To LineNumber)
    ' 一回当たりの移動量(終点)
    Dim dEx() As Double: ReDim dEx(1 To LineNumber)
    Dim dEy() As Double: ReDim dEy(1 To LineNumber)
    
    Dim myLine() As Shape: ReDim myLine(1 To LineNumber, moving_times)

    Dim i As Long
    Dim j As Long
        For i = 1 To LineNumber
    
            ' 初期値設定
            Sx(i, 0) = WorksheetFunction.Index(start_position_array(i), 1)
            Sy(i, 0) = WorksheetFunction.Index(start_position_array(i), 2)
            Ex(i, 0) = WorksheetFunction.Index(start_position_array(i), 3)
            Ey(i, 0) = WorksheetFunction.Index(start_position_array(i), 4)
        
            ' 移動後の座標設定。
            Sx(i, moving_times) = WorksheetFunction.Index(end_position_array(i), 1)
            Sy(i, moving_times) = WorksheetFunction.Index(end_position_array(i), 2)
            Ex(i, moving_times) = WorksheetFunction.Index(end_position_array(i), 3)
            Ey(i, moving_times) = WorksheetFunction.Index(end_position_array(i), 4)
        

            dSx(i) = (Sx(i, moving_times) - Sx(i, 0)) / moving_times
            dSy(i) = (Sy(i, moving_times) - Sy(i, 0)) / moving_times
    
            dEx(i) = (Ex(i, moving_times) - Ex(i, 0)) / moving_times
            dEy(i) = (Ey(i, moving_times) - Ey(i, 0)) / moving_times

            For j = 1 To moving_times - 1
                Sx(i, j) = Sx(i, j - 1) + dSx(i)
                Sy(i, j) = Sy(i, j - 1) + dSy(i)
                Ex(i, j) = Ex(i, j - 1) + dEx(i)
                Ey(i, j) = Ey(i, j - 1) + dEy(i)
            Next
        
        Next
    
        ' 設定した移動回数で変形。
        For j = 0 To moving_times
            For i = 1 To LineNumber
                Set myLine(i, j) = GetLine(Sx(i, j), Sy(i, j), Ex(i, j), Ey(i, j))
                If delete_flag Then
                    On Error Resume Next
                    myLine(i, j - 1).Delete
                End If
                Application.Wait [Now() + "00:00:00.01"]
            Next
        Next

End Sub

今回のシリーズも、これが出来たからと言って業務の足しになる訳ではない。
でも、まあ面白かったから、良しとしよう。

ということで、本シリーズはこれでおしまいです。

参考まで。