Given two 3D points A(x1, y1, z1) and B(x2, y2, z2). Find the four vertices of a square plane which is perpendicular to line AB and centered at A

3d

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:

result

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$.

Related Question