繁体   English   中英

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

[英]How to calculate rotation angle from rectangle points?

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

这些点以如下方式排列在一个数组中: x1 y1 x2 y2 x3 y3 x4 y4

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

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

在此处输入图片说明

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

我只是通过比较点来知道矩形是否是直的,例如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)";

}

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

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

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

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

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

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

转换为度数:

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

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

  rotationDegrees += 180;

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

编辑

基于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).
 *
 * @see https://stackoverflow.com/a/13003782/938822
 */
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];
}

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

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

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

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

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

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

角是正方形边的反正切:

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

(我不确定它返回的是哪个角度,或者您对此期望的角度是什么,因此您可以稍微测试一下。)

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

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

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

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

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

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

您想使用负边距技巧。

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

暂无
暂无

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

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