平移变换

实现图元的平移需要首先在CGElement类中添加一个需要重写的Move 方法,然后在各派生类中重写它。图元类更新以后,创建一个平移交互类CMove,它定义鼠标事件时的响应。

更新图元类

1. 在CGElement类中添加 Move方法

首先在CGElement类中添加一个Move方法,该方法有3个参数:Graphics对象g、移动的基点basePos和移动的第2点desPos。desPos点相对于base点的移动方向和距离就是图元相对于当前位置的移动方向和距离。

code.vb.net
'平移图元
Public MustOverride Sub Move(ByVal g As Graphics,
    ByVal basePos As PointF, ByVal desPos As PointF)

2. 在CLine类中重写基类的Move方法

在CLine类中重写基类的Move方法。首先计算basePos和desPos在横向上和纵向上的偏移量,然后利用该偏移量得到平移后直线段端点的坐标。

code.vb.net
    '平移变换
    Public Overrides Sub Move(ByVal g As Graphics, ByVal basePos As PointF, ByVal desPos As PointF)
        Dim xx As Single
        Dim yy As Single
        '计算偏移量
        xx = desPos.X - basePos.X
        yy = desPos.Y - basePos.Y
        '偏移后的起点和终点坐标
        m_Begin.X += xx
        m_Begin.Y += yy
        m_End.X += xx
        m_End.Y += yy
    End Sub

3. 在CRectangle类中重写基类的Move方法

在CRectangle类中重写基类的Move方法,计算矩形平移以后起点和终点的坐标。

code.vb.net
    '平移变换
    Public Overrides Sub Move(ByVal g As Graphics, ByVal basePos As PointF, ByVal desPos As PointF)
        Dim xx As Single
        Dim yy As Single
        '计算偏移量
        xx = desPos.X - basePos.X
        yy = desPos.Y - basePos.Y
        '偏移后的起点和终点坐标
        m_basePos.X += xx
        m_basePos.Y += yy
        m_desPos.X += xx
        m_desPos.Y += yy
    End Sub

4. 在CCircle类中重写基类的Move方法

在CCircle类中重写基类的Move方法,利用第1点和第2点得到的横向和纵向上的偏移量来计算平移后圆心和圆上一点的新坐标值。

code.vb.net
    '平移变换
    Public Overrides Sub Move(ByVal g As Graphics, _
              ByVal basePos As PointF, ByVal desPos As PointF)
        Dim xx As Single
        Dim yy As Single
        '计算偏移量
        xx = desPos.X - basePos.X
        yy = desPos.Y - basePos.Y
        '平移圆心和圆上一点
        With m_Center
            .X += xx
            .Y += yy
        End With
        With m_PCircle
            .X += xx
            .Y += yy
        End With
    End Sub

5. 在CArc类中重写基类的Move方法

在CArc类中重写基类的Move方法,利用给定的两个点的坐标值计算平移后圆弧圆心、起点和终点的坐标值。

code.vb.net
    '平移变换
    Public Overrides Sub Move(ByVal g As Graphics, ByVal basePos As PointF, ByVal desPos As PointF)
        Dim xx, yy As Single
        '计算在X和Y两个方向上的位移量
        xx = desPos.X - basePos.X
        yy = desPos.Y - basePos.Y
        With m_Center
            .X += xx
            .Y += yy
        End With
        With m_Begin
            .X += xx
            .Y += yy
        End With
        With m_End
            .X += xx
            .Y += yy
        End With
    End Sub

创建CMove类

CMove类是一个平移交互类,它实现了ICommand接口。CMove 类的作用是定义图元平移操作过程中程序对鼠标事件的响应。第1次单击鼠标时,确定第1点(即基点)的位置。

移动鼠标时,显示橡皮线。第2次单击鼠标时,确定第2点的位置。用这两个点的坐标值来计算横向上和纵向上的偏移量,然后利用该偏移量计算平移后图元控制点的位置。在新位置上绘制图元,并在屏幕上删除图元在原来位置上的显示。当然,上面所说的图元都是指选择集中的图元。

code.vb.net
'平移变换类
Public Class CMove
    Implements ICommand
    Private m_Step As Integer
    Private m_basePos, m_desPos As PointF
    '单击鼠标左键时的绘图行为
    Public Sub LButtonDown(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.LButtonDown
        Dim i As Integer
        m_Step += 1
        Select Case m_Step
            Case 1
                m_basePos = aPos
                m_desPos = aPos
            Case 2
                '清除最后一条橡皮线
                Dim tempLine As New CLine(m_basePos, m_desPos)
                tempLine.Draw(g, CGElement.geDrawMode.Drag)
                tempLine = Nothing
                '如果选择集中的图元个数大于0
                If geSels.Count > 0 Then
                    For i = 0 To geSels.Count - 1
                        '清除图元在当前位置上的图形
                        geSels(i).draw(g, CGElement.geDrawMode.Delete)
                        '将所有被选中的图元移动到目标位置并进行绘制
                        geSels(i).Move(g, m_basePos, m_desPos)
                        geSels(i).Draw(g, CGElement.geDrawMode.Selec)
                    Next i
                End If
                m_Step = 0
        End Select
    End Sub
    '移动鼠标时的绘图行为
    Public Sub MouseMove(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.MouseMove
        Select Case m_Step
            Case 1
                Dim prePos As New PointF()
                Dim curPos As New PointF()
                prePos = m_desPos
                curPos = aPos
                '清除上一条橡皮线
                Dim tempLine1 As New CLine(m_basePos, prePos)
                tempLine1.Draw(g, CGElement.geDrawMode.Drag)
                tempLine1 = Nothing
                '绘当前位置的橡皮线
                Dim tempLine2 As New CLine(m_basePos, curPos)
                tempLine2.Draw(g, CGElement.geDrawMode.Drag)
                tempLine2 = Nothing
                m_desPos = aPos
        End Select
    End Sub
    '单击鼠标右键时的绘图行为
    Public Sub RButtonDown(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.RButtonDown
        If m_Step = 1 Then
            '清除上一条橡皮线
            Dim tempLine As New CLine(m_basePos, m_desPos)
            tempLine.Draw(g, CGElement.geDrawMode.Drag)
            tempLine = Nothing
        End If
    End Sub
End Class

实现平移图元

要实现图元变换,需要首先添加菜单资源。在前面程序的基础上添加一个"几何变换"菜单,如图6-1所示。菜单中包括5个选项,即"平移"、"旋转"、"镜像"、"比例放大"和"比例缩小"。名称分别为:mnuTMove,mnuTRotate,mnuTMirror,mnuTZoomin和mnuTZoomOut。

Document Image
\[\]

图6-1添加"几何变换"菜单

实现选定图元的平移需要首先创建一个CMove类实例,然后在Form1类中用一个公共的ICommand对象引用它,其代码如下:

code.vb.net
Public transMove As New Cmove()
Private Sub mnuTMove_Click(ByVal sender As System.Object,
        ByVal e As System.EventArgs) Handles mnuTMove.Click
    aCommand = transMove
End Sub

运行程序,可以选择绘制的图元并平移它们。图元平移的效果如图6-2、图6-3所示。其中,图6-2为平移前的图形,图6-3为平移后的图形。

Document Image
\[\]

图6-2 平移前的图形

Document Image
\[\]

图6-3平移后的图形