8

Hey there guys, I'm learning processing.js, and I've come across a mathematical problem, which I can't seem to solve with my limited geometry and trigonometry knowledge or by help of Wikipedia.

I need to draw a rectangle. To draw this rectangle, I need to know the coordinate points of each corner. All I know is x and y for the midpoints of the top and bottom of the box, and the length of all four sides.

There is no guarantee on the orientation of the box.

Any help? This seems like it should be easy, but it is really stumping me.

4

9 回答 9

9

If this quadrilateral is a rectangle (all four angles are 90 degrees), then it can be solved. (if it could be any quadrilateral, then it is not solvable)

if the points are (x1,y1), and (x2, y2), and if the two points are not perfectly vertical (x1 = x2) or horizontal (y1 = y2), then the slope of one edge of the rectangle is

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

and the slope of the other edge is:

m2 = - 1 / m1

If you know the lengths of the sides, and the midpoints of two opposite sides, then the corrner points are easily determined by adding dx, dy to the midpoints: (if L is length of the sides that the midpoints are on)

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

and

dy = m2 * dx

NOTE: if the points are vertically or horizontally aligned, this technique will not work, although the obvious solution for those degenerative cases is much simpler.

于 2010-02-08T01:37:49.733 回答
6

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

  • (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 度旋转原来只是交换坐标并否定其中一个。您只需在纸上尝试即可看到这一点。或者看一下二维旋转的方程并替换为 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)

于 2010-02-08T02:22:32.727 回答
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
于 2016-09-03T18:11:16.747 回答
0

It's definitely a rectangle? Then you know the orientation of the short sides (they're parallel to the line between your points), and hence the orientation of the long sides.

You know the orientation and length of the long sides, and you know their midpoints, so it's straightforward to find the corners from there.

Implementation is left as an exercise to the reader.

于 2010-02-08T01:23:18.600 回答
0

This means that there will be two lines parallel to the line between the two points you have. Get the corners by translating the line you have 1/2 the length of the top side in each direction perpendicular to the line you have.

于 2010-02-08T01:23:33.310 回答
0

If you know the midpoint for the top, and the length of the top, then you know that the y will stay the same for both top corners, and the x will be the midpoint plus/minus the width of the rectangle. This will also be true for the bottom.

Once you have the four corners, there is no need to worry about the side lengths, as their points are the same as those used for the top and bottom.

                         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
于 2010-02-08T01:27:19.443 回答
0

There's a difference between a "quadrilateral" and a "rectangle".

If you have the midpoint of the top and bottom, and the sides lengths, the rest is simple.

Given:

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

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

and top/bottom length along with right/left length.

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

y1 = top_middle_y y2 = bottom_middle_y

Obviously, that's the simplest case and assuming that the line of (tmx, tmy) (bmx, bmy) is solely along the Y axis.

We'll call that line the "mid line".

The next trick is to take the mid line, and calculate it's rotational offset off the Y axis.

Now, my trig is super rusty.

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

So, the tangent of the angle is dy / dx. The arctangent(dy / dx) is the angle of the line.

From that you can get your orientation.

(mind, there's some games with quadrants, and signs, and stuff to get this right -- but this is the gist of it.)

Once you have the orientation, you can "rotate" the line back to the Y axis. Look up 2D graphics for the math, it's straight forward.

That gets you your normal orientation. Then calculate the rectangles points, in this new normal form, and finally, rotate them back.

Viola. Rectangle.

Other things you can do is "rotate" a line that's half the length of the "top" line to where it's 90 deg of the mid line. So, say you have a mid line that's 45 degrees. You would start this line at tmx, tmy, and rotate this line 135 degrees (90 + 45). That point would be your "top left" corner. Rotate it -45 (45 - 90) to get the "top right" point. Then do something similar with the lower points.

于 2010-02-08T01:37:37.887 回答
0

Calculate the angle of the line joining the two midpoints using an arc-tangent function applied to the vector you get between them.

Subtract 90 degrees from that angle to get the direction of the top edge

Starting from the top-center point, move relative (1/2 top width x sin(angle), 1/2 top width x cos(angle)) - that gets the top right corner point.

Continue around the rectangle using the sin and cos of the angles and widths as appropriate

As a test: Check you made it back to the starting point

于 2010-02-08T01:40:10.253 回答
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};
}
于 2013-04-24T08:31:16.000 回答