当您获取Array的元素(系数),然后以线性代数定义的标准方式使用它们将矩阵与向量相乘时,您将得到与为Matrix调用TransformPoints方法不同的答案。我认为这是Microsoft文档或实现中的错误。
也就是说,给定矩阵M和点a,其中M(a)是调用M的结果。
M(a).x**!=M11ax + M12ay + dx
和
M(a)·yi =**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;
}
}
3条答案
按热度按时间2ul0zpep1#
正确答案是:
但没有错误。矩阵的描述给了我们这个,3行,2列(3x2):
当乘以必须为1行3列(1x3)的向量时:
得到1x2的结果:
This documentation演示了它们使用行为主的矩阵和行向量,而不是更常见的列为主和列向量的数学约定。
因此,实际上,矩阵表示3x3,因此它们可以链接在一起,但这没有区别,因为在仿射变换中,最后一列总是
0 0 1
,这是该类所能表示的全部。此订单的加号
如果我有一个点(P),我想平移(T),然后缩放(S),我发现用这个符号更可读:
而不是:
所以使用这种顺序的代码也会更易读。
mrwjdhj32#
标准笛卡尔坐标系是右手坐标系,即你必须将一个指向x方向的矢量逆时针旋转90度,以使它指向y方向。
System.Drawing
中使用的坐标系是左手坐标系,因为y轴指向下方。这可能解释了差异。tjvv9vkg3#
System.Drawing.Drawing2D.Matrix向我们展示了先转置的向量乘以变换矩阵与转置的变换矩阵乘以vector.
相同