글목록

2022년 3월 25일

도형 변환하기 - 6. 자유형 도형(msoFreedom)의 Node 분할하기

Powerpoint는 직선이나 다각형, 원 등 완성된 도형은 템플릿으로 구할 수 있지만, 원의 일부분인 호나 직각선, 혹은 특정 각도를 갖는 선, 호와 선이 연결된 도형, 나선 등.. 여러가지 도형을 자유롭게 생성하기 어렵습니다.

비록 도형의 병합, 분할 등의 기능을 이용하여 여러가지 모양을 만들어 낼 수는 있습니다만, 면이 아닌 선으로만 구성된 도형을 생성하는 것은 쉽지 않습니다. 물론 수작업으로 점을 그려나가는 방법도 있지만, 모양이 원하는대로 잘 그려지지 않습니다.

아래와 같이 원기둥을 그린다고 하겠습니다. 도형 템플릿에 이미 원기둥 모양이 있으니 그냥 사용하셔도 되고, 원을 그린 후 3차원 설정을 할수도 있습니다. 혹은 원과 사각형을 조합하여 도형 병합과 빼기를 이용할 수도 있습니다.

여기에서는 새로운 방법으로 아래와 같이 원과 직선을 그리고, 원의 node를 분할한 후, 일부 곡선들을 다시 연결해서 원기둥의 옆면을 만들고, 다시 원을 붙여서 아래와 같이 원기둥 모양을 만들 수 있습니다.



도형을 위와 같이 node를 분할하고, 다시 원하는 선들만 모아서 결합할 수 있다면, 새로운 많은 도형을 생성할 수 있습니다. 아래와 같이 원의 node를 분할해서, 분할된 곡선의 크기를 조금씩 바꿔서 다시 연결하면 나선을 만드는 것도 가능합니다.



이러한 작업을 위해 우선 임의의 도형의 node를 분할해서 각각의 선으로 나눠주는 매크로를 작성하도록 하겠습니다. 다음에는 나눠진 선들을 다시 결합하여 1개 도형을 생성하도록 할 예정입니다.


'-------------------------------------
Function Sh_IsDrawing(iSh As Shape) As Boolean
  '현재 선택된 도형이 Drawing 형태인지 체크하는 함수입니다. 취급하려는 개체를 아래의 종류로만 한정했습니다만, 사용자가 자주 사용하는 shape 종류를 추가로 포함하거나, 사용하지 않는 경우에는 제외시켜도 됩니다.
  Sh_IsDrawing = (iSh.Type = msoAutoShape Or iSh.Type = msoFreeform Or iSh.Type = msoGroup Or iSh.Type = msoLine Or iSh.Type = msoTextBox)
End Function
'-------------------------------------
Function Sh_SplitNodes(iSlide As Slide, iSh As Shape) As Shape
  On Error GoTo ErrorHandler
  Dim tSL As ShapeRange, tSh() As Shape, tNode() As Single, tPoints() As Single, n As Long
  If Not Sh_IsDrawing(iSh) Then Set Sh_SplitNodes = iSh: Exit Function
  '단일 도형을 입력했을 때, 각 node에서 분할하는 함수입니다.
  '미리 만들어둔 함수를 이용하여, 도형의 각 node, 즉 end point와 control point의 좌표를 구해줍니다. 이때, 곡선을 유지할 수 있도록 모든 segment를 곡선형으로 만들어줍니다.
  tPoints = GetVertices(iSh, False)
  ReDim tNode(1 To 4, 1 To 2)
  n = 0
  '각 4개의 node, 즉 1~4, 4~7, 7~11.. 구간의 node만 잘라서 곡선을 생성해주고 원본은 삭제합니다.
  For i = 1 To UBound(tPoints, 1) - 1 Step 3
    n = n + 1
    ReDim Preserve tSh(1 To n)
    For j = 1 To 4
      tNode(j, 1) = tPoints(i + j - 1, 1): tNode(j, 2) = tPoints(i + j - 1, 2)
    Next
    Set tSh(n) = iSlide.Shapes.AddCurve(tNode)
  Next
  iSh.Delete
  '만약 1개의 segment였다면 생성된 현을 그대로 반환하고, 2개 이상의 segment로 나눠져있다면 생성된 도형을 그룹화해서 반환해줍니다. 여러 개로 나눠진 경우, 도형을 다시 선택할 때 귀찮기 때문에 그룹화해서 반환합니다.
  If n = 1 Then Set Sh_SplitNodes = tSh(n) Else Set Sh_SplitNodes = GetShapeRange(iSlide, tSh).Group
ErrorHandler:
  Erase tSh, tNode, tPoints
End Function
'-------------------------------------
Function Shs_SplitNodes(iSlide As Slide, iSh As Shape) As Shape
  On Error GoTo ErrorHandler
  Dim tSL As ShapeRange, tSh() As Shape, i As Long
  If Not Sh_IsDrawing(iSh) Then Set Shs_SplitNodes = iSh: Exit Function
  '슬라이드에서 여러 개의 도형을 선택한 상태에서 일괄 분할하기 위한 함수입니다.
  '재귀함수이며, 그룹화된 도형은 계속 그룹해제하고, 단일 도형인 경우에는 node를 분할해줍니다. 아래와 같이 생성하게 되면, 원래 그룹화된 순서를 그대로 유지하면서 segment로 모두 분할됩니다.
  If iSh.Type = msoGroup Then
    Set tSL = iSh.Ungroup
    ReDim tSh(1 To tSL.Count)
    For i = 1 To tSL.Count
      Set tSh(i) = Shs_SplitNodes(iSlide, tSL(i))
    Next
    Set Shs_SplitNodes = GetShapeRange(iSlide, tSh).Group
  Else
    Set Shs_SplitNodes = Sh_SplitNodes(iSlide, iSh)
  End If
ErrorHandler:
  Erase tSh
End Function
'-------------------------------------
Sub 도형생성_선분할()
  On Error GoTo ErrorHandler
  Dim tSR As ShapeRange, tSh() As Shape, i As Long, tSlide As Slide
  '현재 슬라이드에서 도형을 선택한 상태에서 매크로를 실행하게 되면, 선택된 모든 도형을  node에서 분할하여 segment로 나눠주게 됩니다.
  Set tSlide = ActiveSlide
  Set tSR = SelectedShapeRange(False)
  ReDim tSh(1 To tSR.Count)
  For i = LBound(tSh) To UBound(tSh)
    Set tSh(i) = Shs_SplitNodes(tSlide, tSR(i))
  Next
  GetShapeRange(tSlide, tSh).Select msoTrue
ErrorHandler:
  Erase tSh
End Sub


댓글 없음:

댓글 쓰기

의견이나 질문이 있으신 분은 언제든지 댓글을 달아주세요~

많이 본 글 :