Knowing two points of a rectangle, how can I figur

2019-02-16 23:09发布

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.

9条回答
爷的心禁止访问
2楼-- · 2019-02-16 23:20

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.

查看更多
3楼-- · 2019-02-16 23:21

If you know your quadrilateral is a rectangle, then you can use some simple vector maths to find the coordinates of the corners. The knowns are:

  • (x1,y1) - the coordinate of the midpoint on the top line
  • (x2,y2) - the coordinate of the midpoint on the bottom line
  • l1 - the length of the top and bottom lines
  • l2 - the length of the other two lines

First, we find the vector between the two known points. This vector is parallel to the side lines:

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

We need to normalize this vector (i.e. make it length 1) so we can use it later as a basis to find our coordinates.

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

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

Next, we rotate this vector anticlockwise by 90 degrees. The rotated vector will be parallel to the top and bottom lines. 90 degree rotation turns out to just be swapping the coordinates and negating one of them. You can see this just by trying it out on paper. Or take at look at the equations for 2D rotations and substitute in 90 degrees.

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

Now we have enough information to find the 'top-left' corner. We simply start at our point (x1, y1) and move back along that side by half the side length:

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

From here we can find the remaining points just by adding the appropriate multiples of our basis vectors. When implementing this you can obviously speed it up by only calculating each unique multiplication a single time:

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

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

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

查看更多
劫难
4楼-- · 2019-02-16 23:24

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

查看更多
Ridiculous、
5楼-- · 2019-02-16 23:27
  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
查看更多
孤傲高冷的网名
6楼-- · 2019-02-16 23:31
/* 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};
}
查看更多
The star\"
7楼-- · 2019-02-16 23:34

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.

查看更多
登录 后发表回答