在画布旋转后查找矢量属性

时间:2016-04-29 12:26:20

标签: javascript math canvas geometry

编辑:我做了一个视频来解释我不想做的事情https://youtu.be/-6I503Urhvg

目标:在旋转后在画布上查找初始X,初始Y,最终X和最终Y点。

问题:公式在我的代码中不起作用,我需要找出我做错了什么。

问题:我想知道我使用的公式是否正确以及如何正确使用它来查找目标

我正在使用的公式是:

  

nX = x * Math.cos(-angle) - y * Math.sin(-angle)

     

nY = x * sin(-angle)+ y * Math.cos(-angle)

公式似乎几乎可以工作,因为它紧跟矢量的旋转。我正在使用小方块来看看公式给我的位置是什么。

代码中的公式:

this.nix = this.ix * Math.cos(-(rotation * (Math.PI / 180))) - this.iy * Math.sin(-(rotation * (Math.PI / 180)));
        this.niy = this.ix * Math.sin(-(rotation * (Math.PI / 180))) + this.iy * Math.cos(-(rotation * (Math.PI / 180)));
        this.nfx = this.fx * Math.cos(-(rotation * (Math.PI / 180))) - this.fy * Math.sin(-(rotation * (Math.PI / 180)));
        this.nfy = this.fx * Math.sin(-(rotation * (Math.PI / 180))) + this.fy * Math.cos(-(rotation * (Math.PI / 180)));
        ctx.fillRect(this.nix,this.niy,5,5);
        ctx.fillRect(this.nfx,this.nfy,5,5);



/*GLOBAL*/var check,lineSquare,rotation,lineRotate;
rotation = 0;
check = false;
lineRotate = false;
function lineRotateBtn(){
    lineRotate = true;
}
function setRotate(){
    var intervalo2 = setInterval(function(){rotation += 0.01;},1000/60);
}
function load() {
    var canvas = document.getElementById('box');
    var ctx = canvas.getContext('2d');

    function player(x, y, width) {
        this.x = x;
        this.y = y;
        this.width = width;

        this.vx = 3;
        this.vy = 3;

        this.up = false;
        this.down = false;
        this.left = false;
        this.right = false;

        this.drawn = function () {
            ctx.fillStyle = "black";
            ctx.fillRect(this.x, this.y, this.width, this.width);
            if (this.up) {
                this.y -= this.vy;
            }
            if (this.down) {
                this.y += this.vy;
            }
            if (this.left) {
                this.x -= this.vx;
            }
            if (this.right) {
                this.x += this.vx;
            }
        }
    }

    var players = new player(100, 100, 20);

    var keyUp, keyDown, keyLeft, keyRight;
    keyUp = 87;
    keyDown = 83;
    keyLeft = 65;
    keyRight = 68;
    window.addEventListener("keydown", checkKeyDown, false);
    function checkKeyDown(event) {
        if (event.keyCode == keyUp) {
            players.up = true;
        } else if (event.keyCode == keyDown) {
            players.down = true;
        } else if (event.keyCode == keyLeft) {
            players.left = true;
        } else if (event.keyCode == keyRight) {
            players.right = true;
        }
    }

    window.addEventListener("keyup", checkKeyUp, false);
    function checkKeyUp(event) {
        if (event.keyCode == keyUp) {
            players.up = false;
        } else if (event.keyCode == keyDown) {
            players.down = false;
        } else if (event.keyCode == keyLeft) {
            players.left = false;
        } else if (event.keyCode == keyRight) {
            players.right = false;
        }
    }

    document.onmousemove = mouseMove;
    function mouseMove(event) {
        event = event || canvas.event
        mouseX = event.pageX;
        mouseY = event.pageY;
        mouseX = mouseX - 11;
        mouseY = mouseY - 13;
        document.getElementById('test2').innerHTML = mouseX + " " + mouseY;
    }

    function line(ix, iy, fx, fy) {
        this.ix = ix;
        this.iy = iy;
        this.fx = fx;
        this.fy = fy;

        this.update = function () {
            this.nix = this.ix * Math.cos(-(rotation * (Math.PI / 180))) - this.iy * Math.sin(-(rotation * (Math.PI / 180)));
            this.niy = this.ix * Math.sin(-(rotation * (Math.PI / 180))) + this.iy * Math.cos(-(rotation * (Math.PI / 180)));
            this.nfx = this.fx * Math.cos(-(rotation * (Math.PI / 180))) - this.fy * Math.sin(-(rotation * (Math.PI / 180)));
            this.nfy = this.fx * Math.sin(-(rotation * (Math.PI / 180))) + this.fy * Math.cos(-(rotation * (Math.PI / 180)));
            ctx.fillRect(this.nix,this.niy,5,5);
            ctx.fillRect(this.nfx,this.nfy,5,5);

            var v1 = {}; //Player
            v1.vx = players.vx;
            v1.vy = players.vy;
            v1.m = Math.sqrt(v1.vx * v1.vx + v1.vy * v1.vy);
            v1.dx = v1.vx / v1.m;
            v1.dy = v1.vy / v1.m;
            var v2 = {ln: {}}; //Line;
            v2.ix = this.ix;
            v2.iy = this.iy;
            v2.fx = this.fx;
            v2.fy = this.fy;
            v2.vx = v2.fx - v2.ix;
            v2.vy = v2.fy - v2.iy;
            v2.m = Math.sqrt(v2.vx * v2.vx + v2.vy * v2.vy);v2.dx = v2.vx / v2.m;
            v2.dy = v2.vy / v2.m;
            v2.ln.vx = v2.vy;
            v2.ln.vy = -v2.vx;v2.ln.dx = v2.ln.vx / v2.m || 0;
            v2.ln.dy = v2.ln.vy / v2.m || 0;
            var v3 = {};
            v3.vx = v2.ix - players.x;v3.vy = v2.iy - players.y;
            var dp1 = v3.vx * v2.dx + v3.vy * v2.dy;
            var dp2 = v3.vx * v2.ln.dx + v3.vy * v2.ln.dy;

            if (dp1 > -v2.m && dp1 < 0) {
                if (dp2 <= 2 && dp2 >= 0) {
                    console.log('colision');
                    if (players.up && players.right){
                        players.x -= players.vx*2;
                        players.y += players.vy*2;
                    }
                    players.x -= players.vx;
                    players.y += players.vy;
                }
                if (dp2 < -1 && dp2 >= -4) {
                    console.log('colision');
                    if (players.down && players.left){
                        players.x -= players.vx*2;
                        players.y += players.vy*2;
                    }
                    players.x += players.vx;
                    players.y -= players.vy;
                }
            }
            ctx.save();
            ctx.translate(this.ix + v2.vx / 2, this.iy + v2.vy / 2);
            ctx.rotate(rotation * (Math.PI / 180));
            ctx.translate(-(this.ix + v2.vx / 2), -(this.iy + v2.vy / 2));

            ctx.beginPath();
            ctx.moveTo(this.ix, this.iy);
            ctx.lineTo(this.fx, this.fy);
            ctx.stroke();

            ctx.restore();

            document.getElementById('test1').innerHTML = "dotProduct1: " + dp1 + "v2.m: " + (-v2.m) + "<br>" + dp2;
        }
    }
    var linez = new line(300,300,400,400);

    var intervalo = setInterval(animation, 1000 / 60);
    function animation() {
        check = true;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        players.drawn();
        linez.update();
    }
}
&#13;
#box {
	border: 1px solid black;
}
#button {
	border: none;
	background-color: gray;
	width: 70;
	height: 50;
}
canvas {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
html {
	background-color: white;
	color: black;
	font-family: courier new;
}
&#13;
<html>
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" type="text/css" href="css/estilo.css">
		<script src="js/main.js"></script>
	</head>
	<body onload="load()">
		<canvas id="box" width="1330" height="500"></canvas>
		<button onclick="setRotate()">Rotate</button>
		<h2 id="test1"></h2>
		<h2 id="test2"></h2>
	</body>
</html>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

根据视频,你的旋转左上角窗口 - 坐标原点。

要围绕任意点cx,cy 进行旋转,您必须使用以下公式:

 NX = CX + (X0-CX) * Cos(Theta) - (Y0-CY) * Sin(Theta)
 NY = CY + (X0-CX) * Sin(Theta) + (Y0-CY) * Cos(Theta)

答案 1 :(得分:0)

这里的第一个关键概念是你需要识别旋转原点的发生位置。旋转画布时,它会围绕与页面垂直的轴旋转;用二维的说法,它围绕原点旋转。

考虑尾部为原点且其尖端位于某一点(X,Y)的向量,其中X和Y是从原点(以适当的单位)测量的。我们可以使用您在上面提到的公式计算新的旋转点(X&#39;,Y&#39;):

X' = X cos(A) - Y sin(A) and 
Y' = X sin(A) + Y cos(A), where A is the angle of rotation measured in radians.

我们可以从X&#39;中恢复X和Y.和Y&#39;通过轮换-A来实现:

X = X' cos(-A) - Y' sin(-A)
Y = X' sin(-A) + Y' cos(-A)

这是您在帖子中的公式,它是正确的。

如果我的矢量没有从原点开始的尾部怎么办?好吧,事实证明你只需要将变换应​​用到该向量的尾部以获得新的尾部,然后再次到头部以获得新的头部。如果你有一个从(A,B)开始到(C,D)结束的向量,那么变换后的向量将是(A&#39;,B&#39;),头部将是(C&#39;, d&#39)。您可以使用逆转回(A,B); (C,D)来自旋转的帧。

如果您使用此公式但没有得到正确的答案,请确保您正确地从正在旋转的原点进行测量。您可能正在正确计算原始矢量,但是您错过了一些真正属于您正在尝试测量的关键偏移。