javascript 如何从矩形点计算旋转角度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13002979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 17:36:22  来源:igfitidea点击:

How to calculate rotation angle from rectangle points?

javascriptmathcssgeometry

提问by Vitim.us

I have 4 points 1,2,3,4that closes a rectangle.

我有 4 个点1, 2, 3,4可以闭合一个矩形。

The points are in a array in this following way: x1y1x2y2x3y3x4y4

这些点以如下方式排列在一个数组中: x1y1x2y2x3y3x4y4

The problem I have is that the rectangle can be rotated in a angle.

我的问题是矩形可以旋转一个角度。

How can I calculate the original points (gray outline), and the angle?

如何计算原始点(灰色轮廓)和角度?

enter image description here

在此处输入图片说明

I'm trying to reproduce this effect in javascript+css3-transform, so I need to first know the straight dimensions and then rotate with the css.

我试图在 javascript+css3-transform 中重现这种效果,所以我需要先知道直线尺寸,然后用 css 旋转。

I just know if the rectangle is straight by comparing points e.g. y1==y2

我只是通过比较点知道矩形是否是直的,例如 y1==y2

if(x1==x4 && x2==x3 && y1==y2 && y4==y3){

    rectangle.style.top = y1;
    rectangle.style.left = x1;
    rectangle.style.width = x2-x1;
    rectangle.style.height = y4-y1;
    rectangle.style.transform = "rotate(?deg)";

}

采纳答案by RobG

You can use any coordinate pair on the same side to calculate the rotation angle. Note that mathematic angles normally assume 0 as long the +ve X axis and increase by rotating anti–clockwise (so along the +ve Y axis is 90°, -ve X axis is 180° and so on).

您可以使用同一侧的任何坐标对来计算旋转角度。请注意,数学角度通常假定为 0,只要 +ve X 轴越长,并通过逆时针旋转而增加(因此沿 +ve Y 轴为 90°,-ve X 轴为 180°,依此类推)。

Also, javascript trigonometry functions return values in radians that must be converted to degrees before being used in a CSS transform.

此外,javascript 三角函数以弧度形式返回值,在用于 CSS 转换之前必须将其转换为度数。

If the shape is not rotated more than 90°, then life is fairly simple and you can use the tanget ratio of a right angle triangle:

如果形状旋转不超过 90°,那么生活就相当简单,您可以使用直角三角形的切线比:

tan(angle) = length of opposite side / length of adjacent side

For the OP, the best corners to use are 1 and 4 so that rotation is kept in the first quadrant and clockwise (per the draft CSS3 spec). In javascript terms:

对于 OP,最好使用 1 和 4 角,以便旋转保持在第一象限和顺时针(根据CSS3 规范草案)。在 JavaScript 术语中:

var rotationRadians = Math.atan((x1 - x4) / (y1 - y4));

To convert to degrees:

转换为度数:

var RAD2DEG = 180 / Math.PI;
var rotationDegrees = rotationRadians * RAD2DEG;

If the rotation is more than 90°, you will need to adjust the angle. e.g. where the angle is greater than 90° but less than 180°, you'll get a -ve result from the above and need to add 180°:

如果旋转超过 90°,则需要调整角度。例如,当角度大于 90° 但小于 180° 时,您会从上面得到 -ve 结果,需要加上 180°:

  rotationDegrees += 180;

Also, if you are using page dimentions, y coordinates increase going down the page, which is the opposite of the normal mathetmatic sense so you need to reverse the sense of y1 - y4in the above.

此外,如果您使用的是页面尺寸,则 y 坐标会随着页面向下而增加,这与正常的数学意义相反,因此您需要反转上述意义y1 - y4

Edit

编辑

Based on the orientation of points in the OP, the following is a general function to return the center and clockwise rotation of the rectangle in degrees. That's all you should need, though you can rotate the corners to be "level" yourself if you wish. You can apply trigonometric functions to calculate new corners or just do some averages (similar to Ian's answer).

基于OP中点的方向,下面是一个通用函数,以度数为单位返回矩形的中心和顺时针旋转。这就是您所需要的全部内容,但如果您愿意,您可以自己旋转角以使其“水平”。您可以应用三角函数来计算新的角或只是做一些平均值(类似于伊恩的回答)。

/*  General case solution for a rectangle
 *
 *  Given coordinages of [x1, y1, x2, y2, x3, y3, x4, y4]
 *  where the corners are:
 *            top left    : x1, y1
 *            top right   : x2, y2
 *            bottom right: x3, y3
 *            bottom left : x4, y4
 *
 *  The centre is the average top left and bottom right coords:
 *  center: (x1 + x3) / 2 and (y1 + y3) / 2
 *
 *  Clockwise rotation: Math.atan((x1 - x4)/(y1 - y4)) with
 *  adjustment for the quadrant the angle is in.
 *
 *  Note that if using page coordinates, y is +ve down the page which
 *  is the reverse of the mathematic sense so y page coordinages
 *  should be multiplied by -1 before being given to the function.
 *  (e.g. a page y of 400 should be -400).
 */
function getRotation(coords) {
    // Get center as average of top left and bottom right
    var center = [(coords[0] + coords[4]) / 2,
                  (coords[1] + coords[5]) / 2];

    // Get differences top left minus bottom left
    var diffs = [coords[0] - coords[6], coords[1] - coords[7]];

    // Get rotation in degrees
    var rotation = Math.atan(diffs[0]/diffs[1]) * 180 / Math.PI;

    // Adjust for 2nd & 3rd quadrants, i.e. diff y is -ve.
    if (diffs[1] < 0) {
        rotation += 180;

    // Adjust for 4th quadrant
    // i.e. diff x is -ve, diff y is +ve
    } else if (diffs[0] < 0) {
        rotation += 360;
    }
    // return array of [[centerX, centerY], rotation];
    return [center, rotation];
}

回答by Guffa

The center of the rectangle is right between two opposite corners:

矩形的中心位于两个对角之间:

cx = (x1 + x3) / 2
cy = (y1 + y3) / 2

The size of the rectangle is the distance between two points:

矩形的大小是两点之间的距离:

w = sqrt(pow(x2-x1, 2) + pow(y2-y1, 2))
h = sqrt(pow(x3-x2, 2) + pow(y3-y2, 2))

The corners of the gray rectangle can be calculated from the center and the size, for example the top left corner:

灰色矩形的角可以从中心和大小计算,例如左上角:

x = cx - w / 2
y = cy - h / 2

The angle is the arctangent of a side of the square:

角是正方形边的反正切:

a = arctan2(y4 - y1, x4 - x1)

(I'm not sure exactly which angle it returns, or what angle you expect for that matter, so you get to test a bit.)

(我不确定它返回的是哪个角度,或者你期望哪个角度,所以你可以测试一下。)

回答by J. K.

This is how you get the angle between the vertical pink line and the black line starting at the pink line intersection:

这是您如何获得垂直粉红色线和从粉红色线交点开始的黑色线之间的角度:

var deg = 90 - Math.arctan((x2-x1) / (y2-y1));

The dimensions can be calculated with the help of the Pythagoras theorem:

可以借助毕达哥拉斯定理计算维度:

var width = Math.sqrt((x2-x1)^2 / (y2-y1)^2));
var height = Math.sqrt((x1-x4)^2) / (y4-y1)^2));

The positional coordinates (left and top) are the averages of x1 and x3 and y1 and y3 respectively.

位置坐标(左和上)分别是 x1 和 x3 以及 y1 和 y3 的平均值。

var left = Math.floor((x1 + x3) / 2);
var top = Math.floor((y1 + y3) / 2);

You want to use the negative-margin trick.

您想使用负边距技巧。

var marginLeft = -Math.ceil(width / 2);
var marginTop = -Math.ceil(height / 2);