Как рассчитать угол поворота из прямоугольных точек?

У меня есть 4 точки 1, 2, 3, 4, которые закрывают прямоугольник.

Точки находятся в массиве следующим образом: x1 y1 x2 y2 x3 y3 x4 y4

Проблема заключается в том, что прямоугольник можно поворачивать под углом.

Как рассчитать исходные точки (серый контур) и угол?

enter image description here

Я пытаюсь воспроизвести этот эффект в 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)";

}

Ответы

Ответ 1

Вы можете использовать любую пару координат на одной стороне для вычисления угла поворота. Обратите внимание, что математические углы обычно принимают значение 0 по длине + ve X и увеличиваются вращением против часовой стрелки (так что вдоль оси + ve Y составляет 90 °, ось X - 180 ° и т.д.).

Кроме того, функции тригонометрии javascript возвращают значения в радианах, которые должны быть преобразованы в градусы перед использованием в преобразовании CSS.

Если фигура не поворачивается более чем на 90 °, тогда жизнь довольно проста, и вы можете использовать соотношение татмет треугольника с прямым углом:

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

Для OP лучшие углы для использования - 1 и 4, так что вращение сохраняется в первом квадранте и по часовой стрелке (на черновик CSS3 spec). В условиях javascript:

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

Чтобы преобразовать в градусы:

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

Если вращение более 90 °, вам необходимо отрегулировать угол. например где угол больше 90 °, но меньше 180 °, вы получите результат из вышеизложенного и должны добавить 180 °:

  rotationDegrees += 180;

Кроме того, если вы используете параметры страницы, координаты y увеличиваются по страницам, что противоположно нормальному математическому смыслу, поэтому вам нужно изменить значение y1 - y4 в приведенном выше.

Изменить

Основываясь на ориентации точек в OP, следующая функция является общей функцией для возвращения центра и вращения по часовой стрелке прямоугольника в градусах. Это все, что вам нужно, хотя вы можете поворачивать углы, чтобы "выровнять" себя, если хотите. Вы можете применить тригонометрические функции для вычисления новых углов или просто сделать некоторые средние значения (аналогичные ответам Ian).

/*  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];
}

Ответ 2

Центр прямоугольника находится справа между двумя противоположными углами:

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)

(Я не уверен, какой именно угол он возвращает, или какой угол вы ожидаете в этом отношении, поэтому вы можете немного проверить).

Ответ 3

Ум, математика средней школы?

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