Find points of Rectangle given two diagonal points and a normal in 3D

2.8k Views Asked by At

I'm developing a geometry framework in a program I'm working on that contains all the good stuff like vectors, points, lines, planes, polygons, etc. I was attempting to create a rectangle object, but have run into a problem which is that there is little information available on deriving points of a rectangle with a minimal amount of information given. When programming, the less provided the object, the more accurate the results. So with this in mind, I was attempting to create a rectangle with only the following given:

  • Two diagonal points
  • Normal of the plane created by the rectangle. There's still some room for error here, but should limit it since if upon a check that the normal is not indeed orthogonal to the line created by the two diagonal points, then I can throw an exception.

I thought I had it figured out, but evidently not. If I define the four points in CCW direction as P0, P1, P2, and P3. P0 and P2 are therefore given. And N is the normal to the plane that will be defined by the rectangle.

Vector V1, runs from P0 to P1. Vector V2, runs from P1 to P2.

V1, V2, and N should all be orthogonal to each other. Therefore,

V2 = N x V1

And since

P2 = P0 + V1 + V2

Then

P2 = P0 + V1 + N x V1

This can be put into Ax=b form and using Cramer's rule find the values for each component of V1.

I'm ending up with some skewed results though that seem to be beyond rounding errors. What am I doing wrong?

1

There are 1 best solutions below

10
On

A single diagonal isn’t enough to identify a unique rectangle:

ambiguous rectangles


Adding the length of a side along with some convention as to which side it means isn’t the most efficient way to represent a rectangle, but let’s explore it a bit.

I always find it easier to work things out in a convenient coordinate system and then apply appropriate transformations to generalize. We’ll use the convention that the specified side is attached to the first point of the diagonal and that the diagonal is counterclockwise from it. So, let’s put our rectangle in the $xy$-plane with the first vertex at the origin and the known side along the $x$-axis:rect with vectors

The sides and diagonal form a Pythagorean triple, so in this coordinate system, $P_1=(s,\sqrt{d^2-s^2})$, where $s$ is the given side length and $d=\|P_1-P_0\|$, the length of the given diagonal. It shouldn’t be too hard to work out the transformation that’s required to move this rectangle into the required position. One thing that might make it easier is to first rotate so that the diagonal is along the $x$-axis: $\cos\theta=s/d$ and after applying a rotation through $-\theta$ we end up with $$\begin{align} P_2 &= \left({s^2\over d},-\frac s d\sqrt{d^2-s^2}\right) \\ P_3 &= \left({d^2-s^2\over d},\frac s d\sqrt{d^2-s^2}\right) \end{align}$$ for the missing corners.


Another possibility—again sticking with the diagonal—is to take advantage of the fact that the chords drawn from a point on a circle to the endpoints of a diameter form a right angle. Placing the known diagonal on the $x$-axis with its midpoint on the origin, you can locate the other corners with an angle $0<\theta<\pi$. The coordinates are simply $(\frac d2\cos\theta, \frac d2\sin\theta)$ and its negative. That might make the computations simpler, but it's hardly an intuitive way to specify a rectangle, I think.


Moving the rectangle into position is straightforward.

Translate so that $P_0$ is at the origin. We have the vector $\mathbf d=P_1-P_0$ for the diagonal, $\mathbf n$ for the normal, and the side length $\|\mathbf s\|$. The vectors $\mathbf d$ and $\mathbf d\times\mathbf n$ form an orthogonal basis for the plane of the rectangle. Using the result for the $xy$-plane from above and keeping in mind that the local coordinate system is left-handed, we get $$ \mathbf s = \|\mathbf s\|{\|\mathbf s\| \over \|\mathbf d\|}{\mathbf d\over\|\mathbf d\|} + \|\mathbf s\|{\sqrt{\|\mathbf d\|^2-\|\mathbf s\|^2}\over\|\mathbf d\|}{\mathbf d\times\mathbf n\over\|\mathbf d\times\mathbf n\|} $$ for the vector representing side $P_0P_2$. Note that this construction doesn't require that $\mathbf n$ actually be normal to the rectangle, only that the above cross product lie in its plane.

Translating back to where the rectangle is supposed to be, we end up with $P_0+\mathbf s$ and $P_1-\mathbf s$ for the two missing corners. The “normal” vector clearly encodes redundant information. It could be replaced by an angle of rotation around the line defined by $\mathbf d$, bringing the number of pieces of information needed to specify a rectangle down to eight, but it would likely be simpler overall to specify it with a corner and vectors that define the two sides instead.