2

GDI +を使用してスケーラブルなベクターグラフィックを描画していますが、mousemoveでhitttestを実行する必要があります。私が見たすべての例では、変換なしでモデル空間=ワールド空間を使用しています。問題の簡単な例を次に示します。

Imports System.Drawing.Drawing2D

Public Class Form1

  Private myrect As New GraphicsPath

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

    ' The rectangle's centre is at 30,10. Move to origin to rotate
    e.Graphics.TranslateTransform(-30, -10, Drawing2D.MatrixOrder.Append)
    e.Graphics.RotateTransform(45, Drawing2D.MatrixOrder.Append)

    ' Move it back, 50x50 away from the origin 
    ' (80,60 because we moved -30,-10 to rotate)
    e.Graphics.TranslateTransform(80, 60, Drawing2D.MatrixOrder.Append)
    e.Graphics.DrawPath(New Pen(Brushes.Black, 2), myrect)

    ' ...loads more painting, many paths, many varying transformations

  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load

    ' Make a rectangle 60x20 with top-left corner at the origin
    myrect.AddLine(0, 0, 60, 0)
    myrect.AddLine(60, 0, 60, 20)
    myrect.AddLine(60, 20, 0, 20)
    myrect.CloseFigure()

    ' ...loads more shapes created here

  End Sub

  Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

    ' Pretend that all the drawing stuff above happened some unspecified time ago, 
    ' in different assembly, written by a martian, in some other vile language.
    ' Obviously, his "e.graphics" has long since been garbage-collected.
    If myrect.IsVisible(e.Location) Then
        ' Works when moving over the path at the origin, ignores transforms.
        Debug.WriteLine("Over the rectangle at " & e.Location.ToString)
    End If

  End Sub

End Class

これは(マウスが赤く動く)を生成します ここに画像の説明を入力してください

IsVisibleは、長方形が変換前にあった原点の近くでキックインします。

OnPaintでグラフィックスを使用していれば、それを使用して変換をヒットテストできることは知っていますが、黄金律には「グラフィックスを保存しない」と書かれています。

どんな提案でも大歓迎です。


事後分析:記録として、Vincentの回答の実装は次のとおりです。これはうまく機能します。

Imports System.Drawing.Drawing2D

Public Class Form1

  Private myrect As New GraphicsPath
  Private mytransform As Matrix

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

    ' The rectangle's centre is at 30,10. Move to origin to rotate
    e.Graphics.TranslateTransform(-30, -10, Drawing2D.MatrixOrder.Append)
    e.Graphics.RotateTransform(45, Drawing2D.MatrixOrder.Append)

    ' Move it back, 50x50 away from the origin 
    ' (80,60 because we moved -30,-10 to rotate)
    e.Graphics.TranslateTransform(80, 60, Drawing2D.MatrixOrder.Append)
    e.Graphics.DrawPath(New Pen(Brushes.Black, 2), myrect)
    mytransform = e.Graphics.Transform

    ' ...loads more painting, many paths, many varying transformations

  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load

    ' Make a rectangle 60x20 with top-left corner at the origin
    myrect.AddLine(0, 0, 60, 0)
    myrect.AddLine(60, 0, 60, 20)
    myrect.AddLine(60, 20, 0, 20)
    myrect.CloseFigure()

    ' ...loads more shapes created here

  End Sub

  Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

    mytransform.Invert()
    Dim mouseat() As Point = {e.Location}
    mytransform.TransformPoints(mouseat)
    If myrect.IsVisible(mouseat(0)) Then
        ' Works when moving over the path at the origin, ignores transforms.
        Debug.WriteLine("Over the rectangle at " & e.Location.ToString)
    End If

  End Sub

End Class
4

2 に答える 2

3

ScaleTransformメソッドとTranslateTransformメソッドは、Graphics.Matrixプロパティを変更します。それを維持したいので、同じ変換をマウスの位置に適用すると非常に便利になります。個々の形状に変換を適用するため、各形状の行列を保存する必要があります。

次に、Matrix.TransformPoints()が問題を解決します。

于 2012-05-24T01:41:52.263 に答える
2

Graphicsオブジェクトのワールド変換行列(Graphics.Transform)を保存し、反転します(つまり、ページからワールド座標に移動します-この場合、ページ座標はデバイス座標と等しいと思いますが、そうでない場合は、さらに作業を行う必要がありますスケーリングを説明するために)、ヒットテストを行う前にそれを使用してポイントを変換します。

編集:OnPaintのロジックを因数分解して、ワールド変換をGraphicsオブジェクトを必要としない別のメソッドに構築し、Matrixを返すこともできます。これは、Graphics.MultiplyTransformで使用するか、反転して変更に使用できます。入力座標。

于 2012-05-24T00:42:26.113 に答える