글목록

2022년 4월 1일

곡선형 도형 변환 - 3. 2차원 벡터 계산용 함수

Shape.Vertices 속성으로부터 도형의 모든 Nodes의 위치 정보를 가져오게 되면, Vertices는 (1 to n, 1 to 2) 배열값을 가집니다. 첫번째 인덱스 1~n은 Nodes의 순서이며, 두번째 인덱스는 가로 방향 위치 X와 세로방향 위치 Y를 의미합니다. 즉, (n, 1)은 n번째 점의 X좌표, (n, 2)는 n번째 점의 Y좌표를 의미합니다.

만약, Vertices 배열을 가져온 후, i 번째 점의 위치만 추출하고자 한다면, 아래와 같은 함수를 쓸 수 있습니다. 또한 모든 점들에 대한 정보는 2개의 숫자 배열이며, 이는 벡터와 동일한 역할을 합니다. 점들의 좌표, 즉 벡터에 대한 연산을 위해 아래와 같이 간단한 함수들을 미리 만들어두면 향후 코드가 간결해질 수 있습니다.

'----------------------
'Vertices 배열에서 특정 인덱스의 점을 추출
Function Node_Point(iVertices() As Single, iIndex As Long) As Single()
  Dim tNode(1 To 2) As Single
  tNode(1) = 
iVertices(iIndex, 1)
  tNode(2) = 
iVertices(iIndex, 2)
  Node_Point = tNode
End Function

'----------------------
'내적 함수
Function Vec_Inner(iVec1() As Single, iVec2() As Single) As Single
  Vec_Inner = iVec1(1) * iVec2(1) + iVec1(2) * iVec2(2)
End Function

'----------------------
'벡터에 상수를 사칙연산
Function Vec_OprConst(iVec() As Single, iConst As Single, Optional iOperation As String = "+") As Single()
  Dim tVec() As Single
  ReDim tVec(1 To 2)
  Select Case iOperation
    Case "+"
      tVec(1) = iVec(1) + iConst: tVec(2) = iVec(2) + iConst
    Case "-"
      tVec(1) = iVec(1) - iConst: tVec(2) = iVec(2) - iConst
    Case "*"
      tVec(1) = iVec(1) * iConst: tVec(2) = iVec(2) * iConst
    Case "/"
      If iConst = 0 Then
        tVec(1) = iVec(1): tVec(2) = iVec(2)
      Else
        tVec(1) = iVec(1) / iConst: tVec(2) = iVec(2) / iConst
      End If
  End Select
  Vec_OprConst = tVec
End Function
'----------------------
'벡터와 벡터에 대한 사칙연산
Function Vec_Opr(iVec1() As Single, iVec2() As Single, Optional iOperation As String = "+") As Single()
  Dim tVec() As Single
  ReDim tVec(1 To 2)
  Select Case iOperation
    Case "+"
      tVec(1) = iVec1(1) + iVec2(1): tVec(2) = iVec1(2) + iVec2(2)
    Case "-"
      tVec(1) = iVec1(1) - iVec2(1): tVec(2) = iVec1(2) - iVec2(2)
    Case "*"
      tVec(1) = iVec1(1) * iVec2(1): tVec(2) = iVec1(2) * iVec2(2)
    Case "/"
      tVec(1) = iVec1(1) / iVec2(1): tVec(2) = iVec1(2) / iVec2(2)
  End Select
  Vec_Opr = tVec
End Function
'----------------------

위의 함수들은 단순히 배열에 대한 연산이니 쉽게 이해될 수 있습니다. 앞으로 모든 좌표들은 2차원 벡터 연산이 주로 되는데, 그러다보면 어떤 벡터에 수직인 성분과 수평인 성분으로 분해하는 경우가 자주 있습니다. 따라서, 아래와 같이, 임의의 벡터를 다른 벡터에 나란한 성분과 수직인 성분으로 분해하는 함수를 만들어둘 수 있습니다.




'----------------------
'임의의 벡터를 다른 벡터에 대해 평행한 성분과 수직인 성분으로 분해
Function Vec_Decomp(iVec() As Single, iVecTool() As Single, oTan() As Single, oNorm() As Single)
  Dim tL As Single
  ReDim oTan(1 To 2): ReDim oNorm(1 To 2)
  tL = Sqr(Vec_Inner(iVecTool, iVecTool))
  If tL = 0 Then
    oTan(1) = 0: oTan(2) = 0
    oNorm = iVec
  Else
    oTan = Vec_OprConst(iVecTool, Vec_Inner(iVec, iVecTool) / tL ^ 2, "*")
    oNorm = Vec_Opr(iVec, oTan, "-")
  End If
End Function
'----------------------

많이 본 글 :