delphi – 使用世界坐标SVG图像中的屏幕坐标的Hittest

如何使用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(角度)= R( – 角)等。然而,您必须推导出转换的论点,如果您只能访问转换矩阵,这可能并不容易。

我猜,世界坐标是通过翻译和比例矩阵的组合转换为屏幕坐标。相对于整个场景的缩放因子(以及可能的显示器的DPI),最后一个负责从世界坐标到像素的“改变单位”。另一方面,翻译矩阵反映了场景平移,并且可以在比例矩阵之前或之后应用。在第一种情况下,平移存储在世界坐标中,在第二次平移中存储在屏幕坐标中。

我也会猜测,所有的对象变换都在世界坐标中完成(对于我来说听起来比在屏幕坐标中这样做更方便)。所以,您可能会期望每个对象的观点都受到以下转换:

W(S(R(T(P))))= W * S * R * T * P,

其中W是世界到屏幕转换,S是scale,R是rotation,T是translation。

希望我至少帮助了一点…

更新于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上的一个封装函数。

我猜,这可能是一个很好的地方开始:)

http://stackoverflow.com/questions/5642646/hittest-using-screen-coordinates-in-svg-images-in-world-coordinates

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:delphi – 使用世界坐标SVG图像中的屏幕坐标的Hittest