I have a set of 3D points. All these points are on the same plane. I have the normal of the plane.
Now I need to rotate them in such a way that the Z value of all these points become zero. (that is, 3D to XY plane)
I have Googled a lot. I got very few results and most of them are very much mathematical. Few are about projection and few are with solution with OpenGL APIs.
I have seen this solution: Rotating 3d plane to XY plane
Based on this, I have implemented something like this:
public static List<Vector3D> RotateCoplanar3DPointsToXY(IList<Vector3D> points, Vector3D planeNormal)
{
var zAxis = new Vector3D(0, 0, 1);
var rotationAxis = zAxis.Cross(planeNormal);
rotationAxis.Normalize();
var rotationAngle = (float)Math.Acos(zAxis.Dot(planeNormal));
var matrix = Matrix4x4.FromAngleAxis(rotationAngle, rotationAxis);
var newPoints = new List<Vector3D>();
for (var i = 0; i < points.Count; i++)
{
var p = points[i];
var newPoint = p.Transform(matrix);
newPoints.Add(newPoint);
}
return newPoints;
}
But this implementation is not working.
I have another implementation below based on @Bálint's comment. This is also not working.
public static Vector3D Cross(Vector3D a, Vector3D b)
{
return new Vector3D(
a.Y * b.Z - a.Z * b.Y,
a.Z * b.X - a.X * b.Z,
a.X * b.Y - a.Y * b.X);
}
public static Matrix4x4 GetMatrixForRotatingCoplanar3DPointsToXY(Vector3D planeNormal)
{
var Z_NORMAL = new Vector3D(1, 0, 0);
var d = planeNormal;
var u = Z_NORMAL;
var r = Cross(d, u);
var t = Cross(r, d);
var matrix = new Matrix4x4(
r.X, t.X, d.X, 0,
r.Y, t.Y, d.Y, 0,
r.Z, t.Z, d.Z, 0,
0, 0, 0, 1);
return matrix;
}
if(planeNormal==zAxis) { return new List(points);
}
– Chakravarthi Oruganti Jul 16 '19 at 23:10