VBA에서 두 도형의 교차 혹은 충돌여부를 판단할 때 

단순한 사각형의 경우 AABB 방식으로 두 도형의 좌표와 넓이와 높이를 비교해서 알아낼 수 있습니다.

 

하지만 도형이 회전한 경우나 사각형이 아닌 복잡한 도형의 경우 AABB방식은 실패합니다.

그래서 두 도형간에 선을 그어서 교차하는 점이 몇개인지 검사하거나 다른 복잡한 알고리즘들을 사용합니다.

두 도형간의 교차 여부를 알려주는 프로그램언어도 있지만

VBA에서는 도형의 충돌체크가 간단하지 않습니다.

 

이 경우

시간은 좀 걸릴 수 있지만

간단히 두 도형을 도형병합(교차)을 이용해서

교차시켜보고 나오는 도형이 있는지 검사해본다면

쉽게 충돌여부를 알아낼 수 있습니다.

(단, 도형병합을 지원하는 2010버전 이상이어야겠습니다.)

위의 그림에서 왼쪽 두 번개는 충돌하지 않고

오른쪽 두 번개는 약간의 교차도형이 발생해서 충돌로 판단이 됩니다.

 

더보기
Option Explicit

Sub Test()
    
    Dim sr As ShapeRange
    
    If ActiveWindow.Selection.Type <> ppSelectionShapes Then GoTo Err
    
    Set sr = ActiveWindow.Selection.ShapeRange
    If sr.Count <> 2 Then GoTo Err
 
    MsgBox IIf(MergeTest(sr(1), sr(2)), "충돌!", "충돌하지 않음!")
    Exit Sub
    
Err:
    MsgBox "도형 충돌여부를 체크하려면 두 도형을 선택하세요."

End Sub

Function MergeTest(A As Shape, B As Shape) As Boolean

    Dim sld As Slide
    Dim AA As Shape, BB As Shape
    Dim oldCnt As Long, newCnt As Long
    
    Set sld = A.Parent
    Set AA = A.Duplicate(1): DoEvents
    AA.Left = A.Left
    AA.Top = A.Top
    
    Set BB = B.Duplicate(1): DoEvents
    BB.Left = B.Left
    BB.Top = B.Top
    
    oldCnt = sld.Shapes.Count
    '도형병합(교차하기)
    sld.Shapes.Range(Array(AA.ZOrderPosition, BB.ZOrderPosition)).MergeShapes msoMergeIntersect
    newCnt = sld.Shapes.Count
    
    If newCnt = oldCnt - 1 Then
        sld.Shapes(newCnt).Delete
        MergeTest = True
    Else
        MergeTest = False
    End If
    
End Function

 

도형병합 전의 도형개수와 도형병합 후의 도형개수를 비교하는 방법으로 검사합니다.

도형병합결과 연결되지 않은 복잡한 도형이 생기더라도 1개의 도형으로 생성되기 때문에 개수비교방식은 문제가 없습니다.

아래와 같이 여러가지 도형의 경우를 테스트를 해볼 수 있습니다.

 

첨부파일을 매크로 허용해서 열고 나서

(365버전의 경우 최초 1회 다운로드 받은 pptm 파일 속성에서 차단해제 체크하고 '확인' 클릭 필수)

원하는 두 개의 도형을 선택하고 Alt-F8 등으로 Test 매크로를 실행합니다.

 

단점은 두 도형을 매번 복제하고 교차도형이 생길 경우 삭제를 하게 되어 속도가 느려질 수 있다는 것입니다.

장점은 그 어떤 자유형 도형이라도 도형의 교차여부를 정확히 테스트할 수 있다는 것입니다.

특히 아래와 같은 경우도 충돌여부를 정확히 알 수 있습니다.

(파워포인트 내부적인 도형병합 알고리즘이 무척 궁금하긴 합니다.)

 

샘플 파일 첨부합니다.

 

MergeTest1.pptm
0.06MB