为什么平移和缩放的行为符合预期,但旋转在天真的变换实现中却没有?
Why do translations and scaling behave as expected but rotation does not in a naive transform implementation?
我在手动将变换矩阵应用于 2D 点时遇到了一个奇怪的问题。当我对变换矩阵应用平移或缩放时,二维点的结果位置就是人们期望的位置。另一方面,旋转似乎以奇怪和意想不到的方式扭曲和旋转形状。
几天来我一直在努力弄清楚为什么会出现这个问题,但无济于事。我检查了数学,它似乎不是问题的原因(当通过 SVG 中的变换属性应用时,复合变换的行为符合预期,但当手动应用于每个像素时则不然),所以我领先相信这是我对如何将转换矩阵实际应用于 2D 点的理解的缺陷。我天真地将 2D 点与变换矩阵相乘以获得新点。
为什么旋转没有按预期运行?
jsfiddle 上提供了说明此问题的示例。忽略倒置的 y 轴,因为即使使用了正确定向的旋转矩阵,问题也会自行显现。这是主要部分:
window.onload = function(e) {
var canvas = document.getElementsByTagName('canvas')[0];
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var ctm = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
ctx.lineWidth = 0.0;
function matrix_mul(a, b) {
return [
a[1]*b[2] + a[0]*b[0],
a[1]*b[3] + a[0]*b[1],
a[3]*b[2] + a[2]*b[0],
a[3]*b[3] + a[2]*b[1],
b[4] + a[5]*b[2] + a[4]*b[0],
b[5] + a[5]*b[3] + a[4]*b[1]
];
}
function rotate(ang) {
ctm = matrix_mul(ctm, [Math.cos(ang), Math.sin(ang), -Math.sin(ang), Math.cos(ang), 0.0, 0.0]);
}
function paint_point(x, y) {
var x = ctm[0]*x + ctm[2]*y + ctm[4];
var y = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x, y, 1, 1);
}
function square() {
for (i = 0; i <= 100; ++i) { paint_point(150+i, 150); }
for (j = 0; j <= 100; ++j) { paint_point(150, 150+j);
paint_point(250, 150+j); }
for (i = 0; i <= 100; ++i) { paint_point(150+i, 250); }
}
square();
for (d=0; d<3; ++d) {
rotate(Math.PI/14);
ctx.fillStyle = 'rgb(0, ' + d+30*40 + ', 0)';
square();
}
ctm = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
ctx.fillStyle = 'rgb(0, 0, 255)';
rotate(Math.PI/14 * 3);
square();
} else {
alert("Something bad happend");
}
};
只是你的转换函数中的一个简单错字
function paint_point(x, y) {
var x = ctm[0]*x + ctm[2]*y + ctm[4];
var y = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x, y, 1, 1);
}
您已声明 x
和 y
,但它们已被定义为参数。因此 x
在第一行被修改,使第二行使用不正确的值 x
.
修复很简单。
function paint_point(x, y) {
var x1 = ctm[0]*x + ctm[2]*y + ctm[4];
var y1 = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x1, y1, 1, 1);
}
或更好
function paint_point(x, y) {
ctx.fillRect(
ctm[0]*x + ctm[2]*y + ctm[4],
ctm[1]*x + ctm[3]*y + ctm[5],
1, 1
);
}
我在手动将变换矩阵应用于 2D 点时遇到了一个奇怪的问题。当我对变换矩阵应用平移或缩放时,二维点的结果位置就是人们期望的位置。另一方面,旋转似乎以奇怪和意想不到的方式扭曲和旋转形状。
几天来我一直在努力弄清楚为什么会出现这个问题,但无济于事。我检查了数学,它似乎不是问题的原因(当通过 SVG 中的变换属性应用时,复合变换的行为符合预期,但当手动应用于每个像素时则不然),所以我领先相信这是我对如何将转换矩阵实际应用于 2D 点的理解的缺陷。我天真地将 2D 点与变换矩阵相乘以获得新点。
为什么旋转没有按预期运行?
jsfiddle 上提供了说明此问题的示例。忽略倒置的 y 轴,因为即使使用了正确定向的旋转矩阵,问题也会自行显现。这是主要部分:
window.onload = function(e) {
var canvas = document.getElementsByTagName('canvas')[0];
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var ctm = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
ctx.lineWidth = 0.0;
function matrix_mul(a, b) {
return [
a[1]*b[2] + a[0]*b[0],
a[1]*b[3] + a[0]*b[1],
a[3]*b[2] + a[2]*b[0],
a[3]*b[3] + a[2]*b[1],
b[4] + a[5]*b[2] + a[4]*b[0],
b[5] + a[5]*b[3] + a[4]*b[1]
];
}
function rotate(ang) {
ctm = matrix_mul(ctm, [Math.cos(ang), Math.sin(ang), -Math.sin(ang), Math.cos(ang), 0.0, 0.0]);
}
function paint_point(x, y) {
var x = ctm[0]*x + ctm[2]*y + ctm[4];
var y = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x, y, 1, 1);
}
function square() {
for (i = 0; i <= 100; ++i) { paint_point(150+i, 150); }
for (j = 0; j <= 100; ++j) { paint_point(150, 150+j);
paint_point(250, 150+j); }
for (i = 0; i <= 100; ++i) { paint_point(150+i, 250); }
}
square();
for (d=0; d<3; ++d) {
rotate(Math.PI/14);
ctx.fillStyle = 'rgb(0, ' + d+30*40 + ', 0)';
square();
}
ctm = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
ctx.fillStyle = 'rgb(0, 0, 255)';
rotate(Math.PI/14 * 3);
square();
} else {
alert("Something bad happend");
}
};
只是你的转换函数中的一个简单错字
function paint_point(x, y) {
var x = ctm[0]*x + ctm[2]*y + ctm[4];
var y = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x, y, 1, 1);
}
您已声明 x
和 y
,但它们已被定义为参数。因此 x
在第一行被修改,使第二行使用不正确的值 x
.
修复很简单。
function paint_point(x, y) {
var x1 = ctm[0]*x + ctm[2]*y + ctm[4];
var y1 = ctm[1]*x + ctm[3]*y + ctm[5];
ctx.fillRect(x1, y1, 1, 1);
}
或更好
function paint_point(x, y) {
ctx.fillRect(
ctm[0]*x + ctm[2]*y + ctm[4],
ctm[1]*x + ctm[3]*y + ctm[5],
1, 1
);
}