【问题标题】:Knowing two points of a rectangle, how can I figure out the other two?知道一个矩形的两个点,我怎么能算出另外两个?
【发布时间】:2010-02-08 01:14:26
【问题描述】:

大家好,我正在学习 processing.js,遇到了一个数学问题,我似乎无法用我有限的几何学和三角学知识或在维基百科的帮助下解决这个问题。

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

不保证盒子的方向。

有什么帮助吗?这似乎应该很容易,但它真的难倒我。

【问题讨论】:

  • 我收回我的答案.. 这是可以解决的!
  • 我认为这可以任意角度旋转,你不知道角度?

标签: math geometry trigonometry processing.js


【解决方案1】:

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

如果点是 (x1,y1) 和 (x2,y2),并且如果这两个点不是完全垂直 (x1 = x2) 或水平 (y1 = y2),则矩形是

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

另一边的斜率为:

m2 = - 1 / m1

如果你知道边的长度,以及两个相对边的中点,那么角点很容易通过将 dx,dy 添加到中点来确定:(如果 L 是中点所在边的长度)

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

dy = m2 * dx

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

【讨论】:

  • 太棒了。这正是我所需要的。谢谢。
  • 使用此方法,您需要确保为 x1 == x2y1 == y2 添加特殊情况,否则您最终会被零除。使用向量而不是斜率进行计算可以避免这种情况(尽管您仍然需要检查您的两个点是否不完全相同)。
  • @Dave,正确,先生,我已经编辑了我的答案来解决这个问题。
【解决方案2】:

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

  • (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)

【讨论】:

    【解决方案3】:
      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
    

    【讨论】:

      【解决方案4】:

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

      您知道长边的方向和长度,并且您知道它们的中点,因此很容易从那里找到角。

      实现留给读者作为练习。

      【讨论】:

      • 长边平行于我知道的一条线。我也知道短边的长度和它们的斜率,因为我知道垂直于它们的一条线的斜率。我仍然不知道如何获得这四分。也许这对你来说似乎很简单,但我的数学背景很少。
      • 您知道中点,以及中点所在边的长度。这意味着角距该点为length/2。所以你知道方向,你知道距离......你还需要知道什么?
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        如果您知道顶部的中点和顶部的长度,那么您就知道两个顶角的 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
        

        【讨论】:

        • 这个盒子的角度未知,我怎么能假设 y 会保持不变?
        【解决方案7】:

        “四边形”和“矩形”是有区别的。

        如果你有顶部和底部的中点,以及边长,剩下的就很简单了。

        给定:

        (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。 arctangent(dy / dx) 是直线的角度。

        从中你可以得到你的方向。

        (请注意,有些游戏有象限、标志和其他东西来解决这个问题——但这就是它的要点。)

        确定方向后,您可以将线“旋转”回 Y 轴。查找 2D 图形进行数学运算,很简单。

        这会让你获得正常的方向。然后以这种新的范式计算矩形点,最后将它们旋转回来。

        维奥拉。矩形。

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

        【讨论】:

          【解决方案8】:

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

          从那个角度减去 90 度得到上边缘的方向

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

          使用适当的角度和宽度的 sin 和 cos 围绕矩形继续

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

          【讨论】:

            【解决方案9】:
            /* 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};
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-06-16
              • 2012-09-27
              • 1970-01-01
              • 1970-01-01
              • 2011-05-16
              • 2020-04-24
              • 2021-04-09
              • 2023-03-03
              相关资源
              最近更新 更多