I have two 3D points: $A = (x_1, y_1, z_1)$ and $B = (x_2, y_2, z_2$). Consider A as the start point and B as the end point. There should be one and only one plane that is perpendicular to line AB and also contains Point A. I need to find the coordinates of the four vertices of a square on this plane so that its side length is L and is centered at Point A.
This https://stackoverflow.com/questions/53981411/how-to-find-a-point-in-3-d-at-an-arbitrary-perpendicular-line-given-distance-to?rq=1 helps to get the coordinate of the first vertex. But, how to get the rest three vertices? I tried to find them by rotating the first vertex point on the plane around axis/line AB by 90, 180 and 270 degrees, respectively. But, it didn't work properly. Instead of a square, I got the following:
Here is my implementation in Java:
public static Vector3d[] getCoordinates(Vector3d start, Vector3d end, double length) {
Vector3d[] corners = new Vector3d[4];
Vector3d line = new Vector3d(end.x - start.x, end.y - start.y, end.z - start.z);
double normalValue = Math.sqrt(Math.pow(line.x, 2.0) + Math.pow(line.y, 2.0) + Math.pow(line.z, 2.0));
Vector3d normalizedLine;
if (normalValue != 0) {
normalizedLine = new Vector3d(line.x / normalValue, line.y / normalValue, line.z / normalValue);
} else {
normalizedLine = new Vector3d(0, 0, 0);
}
double distance = (length*Math.sqrt(2))/2;
Vector3d vec = new Vector3d(1, 0, 0);
Vector3d cross = line.cross(vec);
double factor = distance / Math.sqrt(Math.pow(cross.x, 2) + Math.pow(cross.y, 2) + Math.pow(cross.z, 2));
Vector3d newVec = new Vector3d(factor * cross.x, factor * cross.y, factor * cross.z);
corners[0] = new Vector3d(start.x + newVec.x, start.y + newVec.y, start.z + newVec.z);
corners[1] = corners[0].rotateAxis(90, normalizedLine.x, normalizedLine.y, normalizedLine.z, new Vector3d(0,0,0));
corners[2] = corners[0].rotateAxis(180, normalizedLine.x, normalizedLine.y, normalizedLine.z, new Vector3d(0,0,0));
corners[3] = corners[0].rotateAxis(270, normalizedLine.x, normalizedLine.y, normalizedLine.z, new Vector3d(0,0,0));
return corners;
}
Any help will be greatly appreciated.
Best Answer
The vector perpendicular to the plane is $\vec{p} = (x_2 - x_1, y_2 - y_1, z_2 - z_1)$. First, you need to find two length-1 vectors $\vec{v}_1, \vec{v}_2$ that are perpendicular both to each other and to $\vec{p}$. One possibility, as mentioned in the answer that you linked: choose any vector $\vec{q}$ that is not a multiple of $\vec{p}$, and define $\vec{u}_1 = \vec{p} \times \vec{q}$ and $\vec{u}_2 = \vec{p} \times \vec{u}_1$, then scale the vectors to unit length: $\vec{v}_i = \vec{u}_i/||\vec{u}_i||$. Alternatively, you could choose two vectors that form a linearly independent set with $\vec{p}$, and then use Gram-Schmidt orthogonalization.
Once you have these vectors, you can choose the four vertices for your square according to the formula $A \pm \frac{L}{2} \vec{v}_1 \pm \frac{L}{2} \vec{v}_2$.