Thread: Mirror shapes
View Single Post
Old 16-01-2011, 19:50
runflacruiser's Avatar
runflacruiser runflacruiser is offline
Senior Member
Join Date: Jun 2009
Location: Pigeon Forge, TN USA
Posts: 811
Default Mirror shapes

Here's my take on a recent post about mirroring shapes to the other side of a line segment. Line segment can be at any angle. Shape will be duplicated/mirrored to the other side. Similar to an Autocad feature.


Option Explicit

Sub mirrorIt() 'begin
End Sub

Private Sub flipIt()
    Dim sr As ShapeRange, s1 As Shape, leftOrRight As String
    Dim x As Double, y As Double, w As Double, h As Double
    Dim xC As Double, yC As Double, dS2L As Double
    Dim s As Shape, s2 As Shape, angle As Double, sNew As Shape
    Dim srFinal As ShapeRange
    Set sr = getSelectionShapes()
    If sr.count <> 2 Then Exit Sub
    ActiveDocument.BeginCommandGroup "flipIt"
    sr.GetBoundingBox x, y, w, h
    Set s1 = sr(1)
    Set s2 = sr(2)
    If s2.Type <> cdrCurveShape Then s2.ConvertToCurves
    s2.Curve.Segments(1).GetPointPositionAt xC, yC, 0.5
    'get angle of rotation using function that gets perpendicular angle from line segment.
    angle = getAngle(s2) * -1
    Set s = sr.Group
    'get center rotation point which we use now and when rotating back
    'rotation put is in the middle of line segment.
    s.RotationCenterX = xC: s.RotationCenterY = yC
    s.Rotate angle
    If s1.CenterX < s2.CenterX Then 'flip the duplicate shapes left or right based on the items horizontal position.
        leftOrRight = "r"
        leftOrRight = "l"
    End If
    sr.AddRange flipSide(sr, leftOrRight) 'flip in the flip funcction!
    sr.RotationCenterX = xC: sr.RotationCenterY = yC
    sr.Rotate -angle 'rotate both back to original palce
End Sub

Private Function flipSide(ByRef sr As ShapeRange, rl As String) As ShapeRange

Dim s1 As Shape, sDup As Shape
Dim x1 As Double, y1 As Double, w1 As Double, h1 As Double 'entire selection shape
Set flipSide = CreateShapeRange

sr.GetBoundingBox x1, y1, w1, h1
ActiveDocument.ReferencePoint = cdrBottomLeft
Set sDup = sr.Group.Duplicate
sDup.Flip cdrFlipHorizontal
If rl = "r" Then
    sDup.SetPosition x1 + w1, y1
    sDup.SetPosition x1 - w1, y1
End If
Set flipSide = sDup.UngroupEx

End Function

Private Function getSelectionShapes() As ShapeRange
    Dim shift As Long
    Dim bClick As Boolean
    Dim s As Shape
    Dim x As Double, y As Double
    Dim dTol As Double
    dTol = 0.1 ' select shape tolerance
    Set getSelectionShapes = CreateShapeRange
    'MsgBox "Select shape first and then line second" '(optional)
    While Not bClick
        bClick = False
        bClick = ActiveDocument.GetUserClick(x, y, shift, 10, False, cdrCursorEyeDrop)
        If Not bClick Then
          Set s = ActivePage.SelectShapesAtPoint(x, y, True, dTol)
        End If
        If s.Shapes.count < 1 Then
            Dim mRetry As Integer
            mRetry = MsgBox("No shape selected. Try again?", vbOKCancel, "GDG")
            If mRetry = 1 Then
                GoTo retrySelectPath:
                Exit Function
            End If
        End If
        getSelectionShapes.Add s.Shapes(1)
        If getSelectionShapes.Shapes.count = 2 Then GoTo exitLoop:
End Function

Private Function getAngle(s As Shape) As Double

    If s.Type <> cdrCurveShape Then s.ConvertToCurves
    getAngle = s.Curve.Segments(1).GetPerpendicularAt(0.5)
End Function
Reply With Quote