知道一个矩形的两个点,我怎么能弄清楚另外两个?

时间:2010-02-08 01:14:26

标签: math geometry trigonometry processing.js

嘿那些人,我正在学习processing.js,而且我遇到了一个数学问题,我似乎无法通过有限的几何和三角知识或维基百科的帮助解决这个问题。

我需要绘制一个矩形。要绘制这个矩形,我需要知道每个角的坐标点。我所知道的是盒子顶部和底部中点的x和y,以及所有四个边的长度。

无法保证盒子的方向。

有任何帮助吗?这看起来应该很容易,但它确实让我感到难过。

9 个答案:

答案 0 :(得分:9)

如果这个四边形是一个矩形(所有四个角都是90度),那么它就可以解决了。 (如果它可能是任何四边形,那么它是不可解决的)

如果点是(x1,y1)和(x2,y2),并且如果两个点不是完全垂直(x1 = x2)或水平(y1 = y2),那么一个边的斜率是矩形是

m1 = (y2-y1) / (x2-x1) 

,另一边的斜率为:

m2 = - 1 / m1

如果您知道边的长度以及两个相对边的中点,则可以通过将dx,dy添加到中点来轻松确定corrner点:(如果L是中点所在的边的长度)

dx = Sqrt( L^2 / (1 + m2^2) ) / 2

dy = m2 * dx

注意:如果这些点是垂直或水平对齐的,这种技术将不起作用,尽管这些退化情况的明显解决方案要简单得多。

答案 1 :(得分:5)

如果你知道你的四边形是一个矩形,那么你可以使用一些简单的矢量数学来找到角的坐标。知识是:

  • (x1,y1) - 顶行中点的坐标
  • (x2,y2) - 底线中点的坐标
  • l1 - 顶行和底行的长度
  • l2 - 其他两行的长度

首先,我们找到两个已知点之间的向量。该向量与侧线平行:

(vx, vy) = (x2 - x1, y2 - y1)

我们需要对此向量进行标准化(即使其长度为1),以便我们稍后可以使用它作为查找坐标的基础。

vlen = sqrt(vx*vx + vy*vy)

(v1x, v1y) = (vx / vlen, vy / vlen)

接下来,我们将这个向量逆时针旋转90度。旋转的矢量将与顶部和底部线平行。 90度旋转结果只是交换坐标并否定其中一个。你可以通过在纸上试一试来看到这一点。或者看看equations for 2D rotations并以90度替换。

(u1x, u1y) = (-v1y, v1x)

现在我们有足够的信息来找到“左上角”。我们只是从我们的(x1, y1)点开始,沿着那边向后移动一半的边长:

(p1x, p1y) = (x1 - u1x * l1 / 2, y1 - u1y * l1 / 2)

从这里我们可以通过添加适当的基数向量来找到剩余的点。实现这一点时,你可以通过一次只计算每个唯一的乘法来加快速度:

(p2x, p2y) = (p1x + u1x * l1, p1y + u1y * l1)

(p3x, p3y) = (p1x + v1x * l2, p1y + v1y * l2)

(p4x, p4y) = (p3x + u1x * l1, p3y + u1y * l1)

答案 2 :(得分:2)

  function getFirstPoint(x1,y1,x2,y2,l1,l2)
    distanceV = {x2 - x1, y2 - y1}
    vlen = math.sqrt(distanceV[1]^2 + distanceV[2]^2)
    normalized = {distanceV[1] / vlen, distanceV[2] / vlen}
    rotated = {-normalized[2], normalized[1]}
    p1 = {x1 - rotated[1] * l1 / 2, y1 - rotated[2] * l1 / 2}
    p2 = {p1[1] + rotated[1] * l1, p1[2] + rotated[2] * l1}
    p3 = {p1[1] + normalized[1] * l2, p1[2] + normalized[2] * l2}
    p4 = {p3[1] + rotated[1] * l1, p3[2] + rotated[2] * l1}
    points = { p1 , p2 , p3 , p4}
    return p1
end

答案 3 :(得分:0)

这绝对是一个长方形?然后你知道短边的方向(它们与你的点之间的线平行),因此你知道长边的方向。

你知道长边的方向和长度,你知道它们的中点,所以从那里找到角落很简单。

实施留给读者练习。

答案 4 :(得分:0)

这意味着将有两条线平行于您拥有的两点之间的线。通过在垂直于您所在线的每个方向上平移顶边长度的1/2线来获取角点。

答案 5 :(得分:0)

如果您知道顶部的中点和顶部的长度,那么您就知道两个顶角的y将保持相同,而x将是中点加/减矩形的宽度。底部也是如此。

一旦你有四个角,就不必担心边长,因为它们的点与顶部和底部的点相同。

                         midpoint
     x,10                 10,10                   x,10
      *--------------------------------------------*
                         width = 30

    mx = midpoint x.
    top left corner = (w/2) - mx  or 15 - 10
    top left corner coords = -5,10

    mx = midpoint x.
    top right corner = (w/2) + mx  or 15 + 10
    top left corner coords = 25,10

答案 6 :(得分:0)

“四边形”和“矩形”之间存在差异。

如果你有顶部和底部的中点,以及两边的长度,其余部分很简单。

假设:

(x1, y1) -- (top_middle_x, top_middle_y) -- (x2, y1)

(x1, y2) -- (btm_middle_x, btm_middle_y) -- (x2, y2)

和上/下长度以及右/左长度。

x1 = top_middle_x - top / bottom_length / 2; x2 = x1 + top / bottom_length;

y1 = top_middle_y y2 = bottom_middle_y

显然,这是最简单的情况,并假设(tmx,tmy)(bmx,bmy)的行仅沿Y轴。

我们将该行称为“中线”。

接下来的技巧是取中线,并计算它离Y轴的旋转偏移。

现在,我的触发器非常生锈。

dx = tmx - bmx,dy = tmy - bmy。

因此,角度的正切为dy / dx。反正切(dy / dx)是直线的角度。

由此您可以获得您的指导。

(记住,有一些游戏有象限,标志和东西才能做到这一点 - 但这是它的要点。)

一旦有了方向,就可以将线“旋转”回Y轴。查找数学的2D图形,它是直接的。

这可以让你正常的方向。然后以这个新的法线形式计算矩形点,最后将它们旋转回来。

中提琴。矩形。

你可以做的其他事情是“旋转”一条线,它是“顶部”线长度的一半,到达中线90度的位置。所以,假设你有一个45度的中线。你可以在tmx,tmy开始这一行,并将这条线旋转135度(90 + 45)。这一点将是你的“左上角”。将其旋转-45(45 - 90)以获得“右上角”点。然后用较低的点做类似的事情。

答案 7 :(得分:0)

使用应用于它们之间的矢量的反正切函数计算连接两个中点的直线的角度。

从该角度减去90度以获得顶边的方向

从顶部中心点开始,移动相对(1/2顶部宽度x sin(角度),1/2顶部宽度x cos(角度)) - 得到右上角点。

使用角度和宽度的sin和cos在矩形周围继续

作为测试:检查你是否已回到起点

答案 8 :(得分:0)

/* rcx = center x rectangle, rcy = center y rectangle, rw = width rectangle, rh = height rectangle, rr = rotation in radian from the rectangle (around it's center point) */

function toRectObjectFromCenter(rcx, rcy, rw, rh, rr){
    var a = {
        x: rcx+(Math.sin((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)), 
        y: rcy-(Math.cos((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2))
    };
    var b = {
        x: a.x+Math.cos(rr)*rw,
        y: a.y+Math.sin(rr)*rw
    };
    var c = {
        x: b.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
        y: b.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
    };
    var d = {
        x: a.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
        y: a.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
    };
    return {a:a,b:b,c:c,d:d};
}