Javascript 找到给定坐标、宽度和高度的矩形顶点

Javascript 找到给定坐标、宽度和高度的矩形顶点,javascript,math,vertices,Javascript,Math,Vertices,我有一个矩形,可以旋转。在每次旋转时,我需要知道它的新顶部、左侧、右侧和底部顶点 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(thet

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

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
}

我已经尝试在新的矩形坐标中循环,但是我想在不循环的情况下计算顶点,以减少执行时间

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

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
}

rotatedRectCorners(元素、中心、角度){
常数θ=(Math.PI/180)*角度
常数x=中心.x
常数oy=中心y
const xAx=Math.cos(θ)//x轴
常数xAy=Math.sin(θ)//x轴y
const x=element.left-ox//将矩形移动到原点
常数y=元素.top-oy
返回{
左上角:{
x:x*xAx-y*xAy+ox,//获取左上角的旋转位置
y:x*xAy+y*xAx+oy
},
右上角:{
x:(x+element.width)*xAx-y*xAy+ox,//获取右上角的旋转位置
y:(x+元素宽度)*xAy+y*xAx+oy
},
右下角:{
x:(x+元素.宽度)*xAx-(y+元素.高度)*xAy+ox,//获得右下角的旋转位置
y:(x+元素.宽度)*xAy+(y+元素.高度)*xAx+oy
},
左下角:{
x:x*xAx-(y+元素.高度)*xAy+ox,//获取左下角的旋转位置
y:x*xAy+(y+元素高度)*xAx+oy
}
}
}
矩形顶点(元素、中心、角度){
常量角点=旋转的角点(元素、中心、角度)
常数顶点={
顶部:{x:0,y:0},
左:{x:0,y:0},
右:{x:0,y:0},
底部:{x:0,y:0}
}
设maxX=null
设minX=null
设minY=null
设maxY=null
每个(角,(角)=>{
如果(maxX==null){
maxX=角点.x
顶点。右=角点
}
如果(minX==null){
minX=corner.x
顶点。左=角
}
if(minY==null){
minY=拐角处
顶点。顶部=角点
}
如果(maxY==null){
maxY=角点.y
顶点。底部=角点
}
如果(角点y>最大值){
maxY=角点.y
顶点。底部=角点
}
if(corner.x>maxX){
maxX=角点.x
顶点。右=角点
}
if(角点x
从左上角顺时针方向为矩形顶点编号。我们可以看到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 
V[0]V[1]V[2]V[3]
//小角度
左上右下
V[2]V[3]V[0]V[1]
//180..270范围内的角度(π..3Pi/2)
左上右下
左索引=角度/90//JS中的整数除法(如果可能)
顶部指数=(1+角度/90)%4
右指数=(2+角度/90)%4
底部指数=(3+角度/90)%4

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

而不使用循环?复杂的计算需要像循环一样的算法,否则为什么要使用程序?使用循环可以减少时间,或者至少可以正确地编写循环。@zer00ne,我认为应该有一个数学模型solution@BohdanVovchuck你是对的,这种问题可以通过矩阵乘法来解决,但是为了在javascript中实现矩阵乘法,你需要一个循环。zer00ne是对的,循环不会自动失效。如果您打算提高执行时间,则可以通过将乘积计算(例如x*xAx)存储在中间变量中来改进
rotatedRectCorners
函数,目前每个计算在返回结果之前会计算两次。您还可以将
rectVertexts
中的条件数减少一半,例如,如果(maxX==null | | | corner.x>maxX){maxX=corner.x;texts.right=corner}这将减少处理器需要执行的指令数,但速度的提高将以毫秒为单位。我明白了。好主意!