我正在尝试在 javascript 的 2D 空间中实现一组基本的欧几里得变换,但我的旋转似乎遇到了问题。
// simple 2d html5 interface
"use strict";
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
mul(c){
this.x *= c;
this.y *= c;
}
}
class TransMatrix{
/* see https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/geometry/geo-tran.html
* for more info.
* c1 c2 c3
* c4 c5 c6
* c7 c8 c9
*/
constructor(){
this.c1 = 1;
this.c2 = 0;
this.c3 = 0;
this.c4 = 0;
this.c5 = 1;
this.c6 = 0;
this.c7 = 0;
this.c8 = 0;
this.c9 = 1;
}
applyMatrix(point){
point.x = this.c1*point.x + this.c2*point.y + this.c3;
point.y = this.c4*point.x + this.c5*point.y + this.c6;
}
copy(){
var matrix = new TransMatrix();
matrix.c1 = this.c1;
matrix.c2 = this.c2;
matrix.c3 = this.c3;
matrix.c4 = this.c4;
matrix.c5 = this.c5;
matrix.c6 = this.c6;
matrix.c7 = this.c7;
matrix.c8 = this.c8;
matrix.c9 = this.c9;
return matrix;
}
translation(x,y){
var newMatrix = this.copy();
newMatrix.c3 += x;
newMatrix.c6 += y;
return newMatrix;
}
scale(s){
var newMatrix = this.copy();
newMatrix.c1 += s;
newMatrix.c5 += s;
return newMatrix;
}
rotation(r){ //radians
var newMatrix = this.copy();
newMatrix.c1 += Math.cos(r);
newMatrix.c2 += -Math.sin(r);
newMatrix.c4 += Math.sin(r);
newMatrix.c5 += Math.cos(r);
return newMatrix;
}
}
function drawHexagon(canvas, matrix, strokeColor, fillColor) {
if (!canvas) {
return;
}
var points = [new Point(0.5 , 1),
new Point(1 , 0),
new Point(0.5 , -1),
new Point(-0.5, -1),
new Point(-1 , 0),
new Point(-0.5, 1)
];
points.forEach(point => {
matrix.applyMatrix(point);
});
drawHexagonLit(canvas,points[0],points[1],points[2],points[3],points[4],points[5], "red", "green");
}
function drawHexagonLit(canvas, p1, p2, p3 ,p4 ,p5, p6, strokeColor, fillColor){ // add border cases here
if(!canvas){
return;
}
var ctx = canvas.getContext("2d");
if(!ctx){
return;
}
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.lineTo(p3.x, p3.y);
ctx.lineTo(p4.x, p4.y);
ctx.lineTo(p5.x, p5.y);
ctx.lineTo(p6.x, p6.y);
ctx.lineTo(p1.x, p1.y);
ctx.strokeStyle = strokeColor;
ctx.fillColor = fillColor;
ctx.stroke();
ctx.fill();
ctx.closePath();
}
function dynamicBackgroundInit(canvas){
if(!canvas){
return;
}
var worldMatrix = new TransMatrix();
var rotate = 0;
function step(){
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
rotate += 0.01;
var transform = worldMatrix.rotation(rotate); // this is better reflected by a matrix inside an object
transform = transform.translation(50,50);
transform = transform.scale(30,30);
drawHexagon(canvas, transform, "red", "green");
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
}
呼叫和翻译按预期工作,但轮换似乎产生不良结果。最初我以为我只是在外部原点上旋转,但我不再这么认为,因为当初始对象被简单地放大时,问题仍然存在。
转换代码会产生工件,因为您在转换之前和之后都使用点坐标,因此在第二行中使用了转换后的坐标而不是原始坐标:
applyMatrix(point){
point.x = this.c1*point.x + this.c2*point.y + this.c3;
point.y = this.c4*point.x + this.c5*point.y + this.c6; // transformed point.x is used instead of the original point.x
}
而是执行以下操作:
applyMatrix(point){
var x = point.x, y = point.y;
point.x = this.c1*x + this.c2*y + this.c3;
point.y = this.c4*x + this.c5*y + this.c6;
}
在您尝试以简单方式应用的任何其他转换中使用原始坐标的类似缓存。首先将它们存储在临时变量中,然后使用原始和新坐标作为不同的变量应用