Calculate rotation data between two planes

Let’s say I have plane A and plane B, and they are oriented differently from each other. I want to figure out how much pitch (rotation about the local X axis), roll (rotation about the local Y axis) and yaw (rotation about the local Z axis) rotation is required to orient from plane A to plane B. Is there a tool that will give me those angles?

No one has any ideas? Is there no way to decompose the transformation/orientation data?

You can decompose the resulting transformation matrix, yes

That might help.

What do the contents of the matrix represent? I’m looking for rotation about the X, Y and Z axis specifically.

Here is code that calculates angles of rotation in order to orient plane to be parallel to XY plane.
Maybe this can help you to get idea how to solve your problem:

    public static double[] getPlaneToXY_RotationAngles(Plane plane1)
        // Method will calcualte angles for rotation arround 
        //   1st World X-axis, 
        //   then World Y-axis 
        //   and at the end World Z-axis
        //  in order to orient plane1 to XY-world parallel plane

        double[] angles = new double[3];
        // angles[0] =>  X-axis angle
        // angles[1] =>  Y-axis angle
        // angles[2] =>  Z-axis angle

        var A = plane1.ZAxis;
        // 1. rotate vector A to XZ-plane arrouind X-axis
        angles[0] = Math.Atan2(A.Y , A.Z) ;

        // 2. now rotate vector arround Y-Axis to be parallel to World Z-Axis
        angles[1] = 2*Math.PI - Math.Asin(A.X/A.Length) ;

        // 3. orient plane1.XAxis to be parallel with  World X-Axis
        var B = plane1.XAxis;
        // dXZ - projection of XAxis to YZ-plane
        var dXZ = Math.Sqrt(B.Y * B.Y  +  B.Z * B.Z );
        // gama - andgle btw projection of XAxis to YZ-plane and Y-Axis
        var gama = Math.Atan2(B.Z, B.Y); 
        var y1 = dXZ * Math.Cos(angles[0] + gama);             
        angles[2] = Math.PI - Math.Acos(y1/B.Length);
        return angles;

All transforamtion in 3D is generaly described by transforamtion matrix from which you can convert into quaternions and from tehre into axis angles and tehre is add-on for it - see above.
Understanding transforamtion matrix requires some knoledge of math…

Thanks for showing me your code. I eventually found a way to do something like that by doing plane intersections in grasshopper. However I did find that order of operation does matter. If you align X axis first, the angle to then align the Y axis will be different from the angle if you aligned the Y axis before the X axis.

Yes, although it is a bit anti-intuitive, 3D rotation arround X,Y and Z axis are not comutative operation.
If Rx(A) is rotation arround X axis through angle A, Ry(B) is rotation arround Y axis through angle B, then:
Rx(A) o Ry(B) <> Ry(B) o Rx(A) (not comutative)

This is easly proved if we write rotation matrix for each rotation and multiplzythem, then we will get different result if we swap order or rotation = swap matrix (Rx * Ry <> Ry * Rx).

Hi @lawrenceyy,

I’m wondering of you create a plane-to-plane transform and then try to decompose it using something like this would help?

– Dale

I’ve found a way to do it in grasshopper by aligning one axis at time.The point of extracting the rotation angle is so that the transformation is reproducible in another software. Ideally someone else would be able to use a gumball like tool to rotate the object about the X axis, then the object’s Y axis, and then the Z axis.

What is the other software you are working with? It might be able to use the transformation matrix directly.

The data is for someone else. It is a back up for if they want to verify the orientation of the geometry. They really should not be rotating the geometry after I export it out of Rhino.


Curiously, I was just trying to use my rotation data to rotate my geometry with gumball and I stumbled upon an inconsistency in Rhino. As I mentioned before I use planes and vectors to align the planes one axis at a time, there for my rotation data is based on YZ, XZ and XY (about X,Y and Z axis). Following right-hand-rule, the YZ plane’s normal points in the positive X direction. The XY plane’s normal points in the positive Z direction. And the XZ plane points in negative Y direction. However the Y axis in gumball points positive Y, making my rotation opposite of what I was expecting. I think gumball is correct in pointing in positive Y as that makes the most sense, therefore I think the XZ plane in grasshopper should be changed to ZX for consistency. I understand that XZ looks like front view, but the rotation problem seems like a bigger issue. It took me a while to figure out why Y rotation was off. Or at least there should be some kind of disclaimer that the XZ plane is not typical.

Hi @lawrenceyy,

The XZPlane component is Grasshopper is correct, as the x-axis is based on the world x-axis (1,0,0). the y-axis is based on the world z-axis (0,0,1). and the cross product of these is (0, -1, 0). (12.5 KB)

Before I can make heads or tails of what you are reporting, I’ll need a concise way of reproducing what you are seeing. Is this something you can provide?

– Dale


Essentially what I was pointing out is that the direction of rotation of the XZ plane is different than that of gumball. My suggestion is that the XZ plane be discontinued in favor of ZX plane so there is a plane with a normal pointing in positive Y. Why is there no plane leading with Z anyway?



Any thoughts on this?

That is correct behaviour, if your plane is XZ then normal vector in -Y direction.
But if you look at plane ZX then normal vector is in +Y direction.
So if gumball is pointing in +Y direction then right-hand-rule says that positive rotation (arround +Y) leeds from Z-to-X axis. Because of this, angle obtained from XZ-plane rotation (-Y normal vector = angle leeds from X to Z axis) has oposite sign than angle of rotation arround +Y axis.

I understand that the XZ plane’s normal points in the negative Y direction. My question is why do we even use the XZ plane. We should use the ZX plane because its normal points in the positive Y direction. The XY plane’s normal points in the positive Z direction, and the YZ plane’s normal points in the positive X direction. Why not be consistent and use a ZX plane instead of a XZ plane, so that all default plane normals are pointing in a positive axis direction?

1 Like

I came across this the other day:

Seems like RhinoCommon has it right.

To future internet travelers:
per axis you can use:
Plane - Align Plane
(give the reference you want to align against. Likely a world normal) then you’ll get the angle delta in radians.

The angle vector component doesn’t work for planes, since the cast from plane to vector gets a little strange, but the above method works.