Найти вершины прямоугольника по его координатам, ширине и высоте - PullRequest
0 голосов
/ 28 мая 2019

У меня есть прямоугольник, который можно вращать. При каждом повороте мне нужно знать его новую верхнюю, левую, правую и нижнюю вершины.

Before After rotate Я пытался перебрать новые прямоугольные координаты, но я хочу вычислить вершины без цикла, чтобы сократить время выполнения

Сначала я вычисляю новые повернутые координаты, а затем нахожу новые вершины.

rotatedRectCorners(element, center, angle) {
    const theta = (Math.PI / 180) * angle
    const ox = center.x
    const oy = center.y
    const xAx = Math.cos(theta)  // x axis x
    const xAy = Math.sin(theta)  // x axis y
    const x = element.left - ox  // move rectangle onto origin
    const y = element.top - oy

    return {
        topLeft: {
            x: x * xAx - y * xAy + ox,   // Get the top left rotated position
            y: x * xAy + y * xAx + oy
        },
        topRight: {
            x: (x + element.width) * xAx - y * xAy + ox,   // Get the top right rotated position
            y: (x + element.width) * xAy + y * xAx + oy
        },
        bottomRight: {
            x: (x + element.width) * xAx - (y + element.height) * xAy + ox,   // Get the bottom right rotated position
            y: (x + element.width) * xAy + (y + element.height) * xAx + oy
        },
        bottomLeft: {
            x: x * xAx - (y + element.height) * xAy + ox,   // Get the bottom left rotated position
            y: x * xAy + (y + element.height) * xAx + oy
        }
    }
}

rectVertices(element, center, angle) {
    const corners = rotatedRectCorners(element, center, angle)
    const vertices = {
        top: {x: 0, y: 0},
        left: {x: 0, y: 0},
        right: {x: 0, y: 0},
        bottom: {x: 0, y: 0}
    }
    let maxX = null
    let minX = null
    let minY = null
    let maxY = null
    each(corners, (corner) => {
        if (maxX === null) {
            maxX = corner.x
            vertices.right = corner
        }
        if (minX === null) {
            minX = corner.x
            vertices.left = corner
        }
        if (minY === null) {
            minY = corner.y
            vertices.top = corner
        }
        if (maxY === null) {
            maxY = corner.y
            vertices.bottom = corner
        }
        if (corner.y > maxY) {
            maxY = corner.y
            vertices.bottom = corner
        }
        if (corner.x > maxX) {
            maxX = corner.x
            vertices.right = corner
        }
        if (corner.x < minX) {
            minX = corner.x
            vertices.left = corner
        }
        if (corner.y < minY) {
            minY = corner.y
            vertices.top = corner
        }
    })

    return vertices
}

1 Ответ

1 голос
/ 28 мая 2019

Позвольте нумерации вершин прямоугольника из верхнего левого угла по часовой стрелке.Мы видим, что V [0] является самой левой вершиной в диапазоне углов 0..Pi/2 (90 градусов, угол в направлении против часовой стрелки), V [1] становится самой левой в диапазоне углов Pi/2..Pi и так далее.

Таким образом, мы можем согласовать два массива, циклически соответствующих углу поворота

V[0]    V[1]    V[2]    V[3]   
           <==>                      //small angle
left    top     right  bottom


V[2]    V[3]     V[0]    V[1]   
           <==>                     //angle in range 180..270 (Pi..3Pi/2)
left    top     right  bottom




left_index = angle / 90   //integer division if possible in JS
top_index = (1 + angle / 90) % 4 
right_index = (2 + angle / 90) % 4 
bottom_index = (3 + angle / 90) % 4 

Не то чтобы в любом случае вам приходилось вычислять координаты вершин (гораздо больше времени)

...