简体   繁体   English

2d 转换,旋转不符合预期

[英]2d transformations, rotation not as intended

I'm trying to implement a set of basic euclidean transforms in 2d space in javascript and I seem to be having a problem with my rotation.我正在尝试在 javascript 中的二维空间中实现一组基本的欧几里得变换,但我的旋转似乎有问题。

    // 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);
}

Calling and translation work as intended but rotation seems to generate poor results.调用和翻译按预期工作,但旋转似乎产生不良结果。 Initially I thought I was just rotating on an external origin point but I no longer think so as the problem is still there when the initial object is simply scaled up.最初我以为我只是在外部原点上旋转,但我不再这么认为,因为当初始对象只是按比例放大时,问题仍然存在。

Your transformation code produces artifacts because you use point coordinates both before and after transform, so in second line the transformed coordinate in used instead of the original:您的转换代码会产生伪像,因为您在转换之前和之后都使用了点坐标,因此在第二行中使用的是转换后的坐标而不是原始坐标:

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

} }

Instead do the following:而是执行以下操作:

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;
    }

Use similar caching of original coordinates in any other transformation you try to apply simlultaneously.在您尝试同时应用的任何其他转换中使用原始坐标的类似缓存。 Store them in temp variables first then apply using original and new coords as different variables首先将它们存储在临时变量中,然后使用原始和新坐标作为不同的变量进行应用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM