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);
            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);
            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;
  • 2
    \$\begingroup\$ At first glance it looks ok. Are you getting wrong results? If so, what results are you getting? Otherwise, please clarify the problem. \$\endgroup\$ – Theraot Jul 16 '19 at 22:54
  • \$\begingroup\$ I think, it is working fine after checking a condition like if(planeNormal==zAxis) { return new List<Vector3D>(points); } \$\endgroup\$ – Chakravarthi Oruganti Jul 16 '19 at 23:10
  • \$\begingroup\$ Hi @Bálint, Thanks for your solution. I have implemented your suggestion. Somewhere I am wrong. I have updated the question with your answer. Can you please look into this? \$\endgroup\$ – Chakravarthi Oruganti Jul 18 '19 at 23:18
  • \$\begingroup\$ "not working" is never enough information to diagnose a specific problem. Always be sure to include the exact symptoms you're observing, like a test case for which the output differs from the desired output. \$\endgroup\$ – DMGregory Jul 18 '19 at 23:19

Doing this requires high-level mathematics (college/university), so it's no wonder those are the only solutions you found. If you know how matrices work, it's pretty simple.

I already described how you can get a rotation matrix from a normal in this post. Your problem is the exact inverse of this: instead of going from points in the XY plane to a rotated version, you need to go from the rotated version back to the XY plane. To do this, you need the inverse of the rotation matrix.

Thankfully, it's pretty simple to do that with rotation matrices, since to inverse one, you just need to transpose it. There should be a method for it in your library of choice, but if there isn't one, it's simply swapping the values out in the following way:

$$\begin{bmatrix} a & b & c & d\\ e & f & g & h\\ i & j & k & l\\ m & n & o & p \end{bmatrix}\rightarrow \begin{bmatrix} a & e & i & m\\ b & f & j & n\\ c & g & k & o\\ d & h & l &p \end{bmatrix} $$

Now just multiply every point with this matrix and you'll transform them in the XY plane.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.