.net System.Drawing.Drawing2D矩阵的实现或文档是否不正确?

hts6caw3  于 2023-05-23  发布在  .NET
关注(0)|答案(3)|浏览(215)

当您获取Array的元素(系数),然后以线性代数定义的标准方式使用它们将矩阵与向量相乘时,您将得到与为Matrix调用TransformPoints方法不同的答案。我认为这是Microsoft文档或实现中的错误。
也就是说,给定矩阵M和点a,其中M(a)是调用M的结果。
M(a).x**!=M11ax + M12ay + dx

M(a)·y
i =**M21ax + M22ay + dy
然而,查看所有的定义,我可以找到乘一个矩阵和一个向量和矩阵符号(i,j),其中i是行,j是列,上述方程应该是相等的。你得到正确答案的唯一方法是如果你把上面的M12和M21的位置交换一下。然而,如果你这样做,方程就不再符合矩阵和向量(或点)相乘的标准概念和常见用法。
请参阅下面的MSDN文档和我编写的示例程序的更详细的解释。

构造函数取6个Single的文档为Matrix Constructor

矩阵构造器(单,单,单,单,单,单)
语法:
public Matrix(float m11,float m12,float m21,float m22,float dx,float dy)
产品参数:

  • m11类型:系统。单个新矩阵第一行第一列的值。
  • m12类型:系统。单个新矩阵第一行第二列的值。
  • m21类型:系统。单个新矩阵第二行第一列的值。
  • m22 Type:System.Single新矩阵第二行第二列的值。
  • dx Type:System.Single新矩阵第三行第一列的值。
  • dy Type:System.Single新矩阵第三行第二列的值。

Elements属性文档为:Matrix.Elements Property

  • 获取表示此Matrix的元素的浮点值数组。

物业价值

  • 类型:系统。单[]
  • 的元素的浮点值数组

这个矩阵。
备注:矩阵的元素m11,m12,m21,m22,dx和dy由数组中的值按此顺序表示。
我写了一个示例程序来确认我所看到的,它如下所示。注意,使用等式中的元素(矩阵系数)仅在我转置m12和m21时才起作用,这与一般矩阵(i,j)(行,列)符号和乘法不一致。我的程序在下面。我的问题是微软的文档/实现是否是错误的?是我忽略了什么还是做错了什么?
在我的代码中,PointsA[0]的X,Y值仅等于x1,y1的X和Y值,其中m12和m21元素值在等式中转置。代码如下:

class Program
   {
      static void Main(string[] args)
      {
         var pointsA = new Point[1];
         pointsA[0].X = 1;
         pointsA[0].Y = 1;
         var pointsB = new Point[1];
         pointsB[0].X = 1;
         pointsB[0].Y = 1;

         // Transform PointsA using Matrix
         Matrix m = new Matrix(1,1,0,1,0,0);
         m.TransformPoints(pointsA);

         // Transform PointsB using Elements.
         var elements = m.Elements;
         var m11 = elements[0];
         var m12 = elements[1];
         var m21 = elements[2];
         var m22 = elements[3];
         var dx  = elements[4];
         var dy  = elements[5];

         var pointB = pointsB[0];

         var x = m11 * pointB.X + m12 * pointB.Y + dx;
         var y = m21 * pointB.X + m22 * pointB.Y + dy;

         // Correct answer but had to transpose positions of m12 and m21 from what would be the normal matrix x vector multiplication.
         var x1 = m11*pointB.X + m21*pointB.Y + dx;
         var y1 = m12*pointB.X + m22*pointB.Y + dy;
      }
   }
2ul0zpep

2ul0zpep1#

正确答案是:

var x1 = m11*pointB.X + m21*pointB.Y + dx;
var y1 = m12*pointB.X + m22*pointB.Y + dy;

但没有错误。矩阵的描述给了我们这个,3行,2列(3x2):

[m11 m12]
[m21 m22]
[dx  dy ]

当乘以必须为1行3列(1x3)的向量时:

[ax ay 1][m11 m12]
         [m21 m22]
         [dx  dy ]

得到1x2的结果:

[ax * m11 + ay * m21 + dx , ax * m12 + ay * m22 + dy]

This documentation演示了它们使用行为主的矩阵和行向量,而不是更常见的列为主和列向量的数学约定。

因此,实际上,矩阵表示3x3,因此它们可以链接在一起,但这没有区别,因为在仿射变换中,最后一列总是0 0 1,这是该类所能表示的全部。

[ax ay 1][m11 m12 0] = [ax * m11 + ay * m21 + dx , ax * m12 + ay * m22 + dy , 1]
         [m21 m22 0]
         [dx  dy  1]

此订单的加号

如果我有一个点(P),我想平移(T),然后缩放(S),我发现用这个符号更可读:

transformedPoint = P*T*S

而不是:

transformedPoint = S*T*P

所以使用这种顺序的代码也会更易读。

mrwjdhj3

mrwjdhj32#

标准笛卡尔坐标系是右手坐标系,即你必须将一个指向x方向的矢量逆时针旋转90度,以使它指向y方向。System.Drawing中使用的坐标系是左手坐标系,因为y轴指向下方。这可能解释了差异。

|    x
--+----->
  |           Coordinate system used by System.Drawing
 y|
  v
tjvv9vkg

tjvv9vkg3#

System.Drawing.Drawing2D.Matrix向我们展示了先转置的向量乘以变换矩阵与转置的变换矩阵乘以vector.

相同

相关问题