【问题标题】:Find rectangle vertices given its coordinates, width and height在给定坐标、宽度和高度的情况下查找矩形顶点
【发布时间】:2019-10-13 10:24:14
【问题描述】:

我有一个可以旋转的矩形。在每次旋转时,我都需要知道它的新顶部、左侧、右侧和底部顶点。

我尝试循环遍历新的矩形坐标,但我想在没有循环的情况下计算顶点以减少执行时间

首先,我计算新的旋转坐标,然后找到新的顶点。

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
}

【问题讨论】:

  • 没有循环?复杂的计算需要像循环这样的算法,否则为什么要使用程序?使用循环可以减少时间或至少是正确编写的时间。
  • @zer00ne,我相信应该有数学解决方案
  • @BohdanVovchuck 你是对的,这种问题可以用矩阵乘法来解决,但是为了在javascript中实现矩阵乘法,你需要一个循环。 zer00ne 是对的,循环不会自动效率低下。
  • 如果您打算提高执行时间,那么您可以通过将乘积计算(例如 x * xAx)存储在中间变量中来改进 rotatedRectCorners 函数,目前每个都是计算的在返回结果之前两次。您还可以将rectVertices 中的条件句数减少一半,例如if (maxX === null ||corner.x > maxX) { maxX =corner.x; vertices.right =corner } 这将减少处理器需要执行的指令数量,但速度提升将在几毫秒内。

标签: javascript math vertices


【解决方案1】:

让矩形顶点从左上角顺时针方向编号。我们可以看到,V[0] 是角度范围0..Pi/2(90 度,CCW 方向的角度)的最左侧顶点,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 

并不是说在任何情况下您都必须计算顶点坐标(更多时间)

【讨论】:

  • 我明白了。聪明的主意!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多