使用世界坐标SVG图像中的屏幕坐标进行命中测试

| 如何使用GDI +将鼠标坐标转换为世界坐标? 还是为使用GDI +绘制的SVG形状获取边界框(甚至更好)的旧的skool区域? 无论如何。我一直在寻找SVG代码并发现: http://development.mwcs.de/svgimage.html 这是第一个实际用于SVG的Delphi组件,但我离题了。 该组件使用GDI +显示圆,曲线等。 GDI +使用矩阵将世界坐标,旋转和变形转换为屏幕坐标。 这部分我了解。您使用矩阵乘法进行转换。 问题是 如果我将鼠标光标指向封闭的形状: 我从哪里得到矩阵,它将鼠标的屏幕点转换为可以测试到屏幕上画出的圆的世界点? 在所有这些GDI对象中,有太多矩阵可供选择。 请不要给我有关绘制位图和在光标下测试魔术颜色的东西,这不是我想要的。 如果有一串矩阵,我如何以正确的(倒置的)顺序遍历它们,以便将屏幕坐标正确地引导到世界坐标? 换一种说法 从SVG图像读取的形状是基元,它们被矩阵扭曲成屏幕坐标。 如何将屏幕坐标反向转换为可用于查看我是否在形状内的坐标。 请注意 我需要知道我处于哪种形状。 由于设置SVG图像的方式,每个形状都有一个ID,我想用它来查看我用鼠标击中的区域。 编辑 或者 我可以在屏幕坐标中为每个形状获得边界矩形,以便可以以此来检查鼠标坐标。 我可以得到一个旧的Skool GDI区域吗,可以在其中使用屏幕坐标来做一个PtInRegion。 希望您能帮助我找到所有这些变形路径的​​方法:-)。     
已邀请:
我没有深入研究代码,但是我可以在矩阵方面有所帮助(第3点)。 我猜想,使用了三个基本的转换矩阵:旋转,缩放和平移矩阵。让我们分别称它们为R,S和T。 关于将矩阵应用于该点有一个棘手的部分。假设您要平移点,然后绕原点中心旋转。换句话说,您想将旋转应用于点的平移效果。因此,矩阵将通过以下方式应用: R(T(P))= R * T * P = S 其中*是矩阵乘法。请注意,相乘矩阵的顺序与您的意图相反。 但是,如果要进行逆变换,除了要逆转矩阵的顺序外,还必须评估它们的逆。我们平移了点,然后旋转了-现在我们将其旋转回去,然后平移回去: T ^ -1(R ^ -1(S))= T ^ -1 * R ^ -1 * S = P 请注意,您不必计算每个矩阵的逆,显然T ^ -1(x)= T(-x),R ^ -1(angle)= R(-angle)等上。但是,您必须推断出转换的参数,如果仅访问转换矩阵,则可能不容易。 我猜想,世界坐标是通过转换矩阵和比例矩阵的组合转换为屏幕坐标的。最后一个负责相对于整个场景的缩放因子(可能还有显示器的DPI)从世界坐标“更改单位”到像素。另一方面,转换矩阵反映场景平移,可以在比例矩阵之前或之后应用;在第一种情况下,平移存储在世界坐标中;在第二种情况中,平移存储在屏幕坐标中。 我还会猜想,所有对象转换都是在世界坐标中完成的(对我来说,这比在屏幕坐标中进行操作更方便)。因此,您可能希望每个对象的点都经过以下转换: W(S(R(T(P()))))= W * S * R * T * P, 其中W是世界到屏幕的转换,S是比例,R是旋转,T是平移。 希望我至少可以帮助一点... 更新17-04-2011 好的,我现在已经查看了代码内部。 SVG对象的PaintTo方法如下所示:
procedure TSVG.PaintTo(Graphics: TGPGraphics; Bounds: TGPRectF;
  Rects: PRectArray; RectCount: Integer);
var 
  M: TGPMatrix;
  MA: TMatrixArray;
begin
  M := TGPMatrix.Create;
  try
    Graphics.GetTransform(M);
    try
      M.GetElements(MA);

      FInitialMatrix.Cells[0, 0] := MA[0];
      FInitialMatrix.Cells[0, 1] := MA[1];
      FInitialMatrix.Cells[1, 0] := MA[2];
      FInitialMatrix.Cells[1, 1] := MA[3];
      FInitialMatrix.Cells[2, 0] := MA[4];
      FInitialMatrix.Cells[2, 1] := MA[5];
      FInitialMatrix.Cells[2, 2] := 1;

      SetBounds(Bounds);

      Paint(Graphics, Rects, RectCount);
    finally
      Graphics.SetTransform(M);
    end;
  finally
    M.Free;
  end;
end;
在绘制任何图形之前,该方法将调用Graphics.GetTransform(M)。反过来,这个调用GdipGetWorldTransform,它似乎是WinAPI的GetWorldTransform的包装函数。 我想这可能是一个不错的起点:)     
使用GDI +时,您必须跟踪自己的工作/所做的事情,因为在绘制像素之后,GDI +会忘记像素本身,但会忘记一切。 SVG单元必须始终保持绘制所有形状和设置GDI +视口所需的一切。因此,从SVG库中获取您的后续信息会更加容易。     

要回复问题请先登录注册