What is the right method to convert quaternion to plane using rhinocommon

What would be the way to convert Quaternion to plane in Rhino?

Lets say I have Quaternion q.
Can I write Plane plane = new Plane(q.A,q.B,q.C,q.D); ?

Two ways
Rhinocommon

Quaternion.GetRotation(out Plane)
https://developer.rhino3d.com/wip/api/RhinoCommon/html/M_Rhino_Geometry_Quaternion_GetRotation.htm

Or I made that (I see that there are other method that I can join if needed)

//! <summary>
        //! Fonction pour reproduire la fonction de RhinoCommon Instance de Quaternion.GetRotation(out Plane)
        //! </summary>
        //! <param name="arg_quat">Quaternion</param>
        //! <returns></returns>
        public static Plane GetPlaneFromQuaternion(Quaternion arg_quat)
        {
            //TODO ne doit pas être très fiable pour les valeurs proches de 0
            double yaw=0;
            double pitch=0;
            double roll=0;

            // arg_quat.Unitize();//NĂ©cessaire // Rhinocommon
            arg_quat = GUtil.Unitize(arg_quat);//NĂ©cessaire //Rhino3dmIO
            ToEulerAngles(arg_quat, out yaw, out pitch, out roll);

            Plane plane = Plane.WorldXY;
            Transform tf_yaw = Transform.Rotation(yaw, Vector3d.ZAxis, Point3d.Origin);
            Transform tf_pitch = Transform.Rotation(pitch, Vector3d.YAxis, Point3d.Origin);
            Transform tf_roll = Transform.Rotation(roll, Vector3d.XAxis, Point3d.Origin);
            Transform tf = tf_yaw * tf_pitch * tf_roll;

            plane.Transform(tf);
            return plane;
        }
1 Like

Thank you, it is also nice to see Euler angles implementation.

It is not an effective way but it was done to test methods

 //! <summary>
        //! Quaternion to Euler Angles Conversion
        //! https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
        //! </summary>
        //! <param name="q"></param>
        //! <param name="yaw"></param>
        //! <param name="pitch"></param>
        //! <param name="roll"></param>
        public static void ToEulerAngles(Quaternion q, out double yaw, out double pitch, out double roll)
        {          
            // roll (x-axis rotation)
            double sinr_cosp = 2 * (q.A * q.B + q.C * q.D);
            double cosr_cosp = 1 - 2 * (q.B * q.B + q.C * q.C);
            roll =Math.Atan2(sinr_cosp, cosr_cosp);

            // pitch (y-axis rotation)
            double sinp = 2 * (q.A * q.C - q.D * q.B);
            if (Math.Abs(sinp) >= 1)
                pitch = Math.Sign(sinp) * Math.PI; // use 90 degrees if out of range
            else
                pitch = Math.Asin(sinp);

            // yaw (z-axis rotation)
            double siny_cosp = 2 * (q.A * q.D + q.B * q.C);
            double cosy_cosp = 1 - 2 * (q.C * q.C + q.D * q.D);
            yaw = Math.Atan2(siny_cosp, cosy_cosp);
        }

The fast way is this

  public static void ToPlane(Quaternion quat, out Plane plane)
    {
      Quaternion vx = new Quaternion(0, 1, 0, 0);
      Quaternion vy = new Quaternion(0, 0, 1, 0);

      vx = quat * vx * quat.Conjugate;
      vy = quat * vy * quat.Conjugate;

      plane = new Plane(Point3d.Origin, vx.Vector, vy.Vector);
    }
2 Likes

Do you also know conversion to construct Quaternion from Euler angles?

Here something I already have

  /// <summary>
        /// Euler Angles to Quaternion Conversion
        /// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
        /// </summary>
        /// <param name="yaw"></param>
        /// <param name="pitch"></param>
        /// <param name="roll"></param>
        /// <returns></returns>
        public static Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
        {
            // Abbreviations for the various angular functions
            double cy = Math.Cos(yaw * 0.5);
            double sy = Math.Sin(yaw * 0.5);
            double cp = Math.Cos(pitch * 0.5);
            double sp = Math.Sin(pitch * 0.5);
            double cr = Math.Cos(roll * 0.5);
            double sr = Math.Sin(roll * 0.5);

            Quaternion q;
            q = Quaternion.Zero;
            q.A = cy * cp * cr + sy * sp * sr;
            q.B = cy * cp * sr - sy * sp * cr;
            q.C = sy * cp * sr + cy * sp * cr;
            q.D = sy * cp * cr - cy * sp * sr;

            return q;
        }
1 Like

Thank you very very much :wink:

Martin Baker’s site also has a good collection of conversions between all the different rotation representations

1 Like

Thanks @DanielPiker

You are welcome as I have done a 6DoF simulation model for flying things, all that stuff is quite useful.

Can we see it ? :slight_smile:

It seems I am again stuck in Unity and Rhino conversions.

I have a quaternion (0,0,1,0), by converting this quaternion to Euler angles in Unity I get (0,0,180), while using your formula I get (180,0,180), I tried both @DanielPiker and @laurent_delrieu and I get (180,0,180).

I am wondering if by any chance you know what is happening at Unity side when Quaternion is converted to Euler angles and how can I get (0,0,180)?

Unfortunately no, it is a work done for my job.

For the problem of angles, it is surely due to the axes. I use “aeronautic” one. X is in front, Z under, and Y to the right side so all angles are on the “good” direction, roll on X, …
https://www.grc.nasa.gov/www/k-12/airplane/rotations.html

Or could it be because unity Quaternion are xyxw instead of wxyz in Rhino?

Yup tried that it does not work due to different axis system I am quite lost, because I want to replicate Quternion.eulerAngles method and it does not produce good result.

And as we know Unity forum is like a desert comparing to McNeel.

I also looked at source code, but this method is C++ and is not open for developer:

Did you look at my last comment about the fact that it seems that quaternion are not coded the same xyzw vs wxyz ?

Hmm, this produces (180,0,0) instead of (0,0,180)

Unity and rhino XYZ differs like this XZY, still not quite good

I will try to have a look tonight… Axis transformation are always a bit tricky

Thanks, it would be a great help for me.

What is also wierd that Unity print degrees between 0 to 360, while rhino from 0 to 180

This one in Unity:

Quaternion testQ = new Quaternion(0.1f, 0.2f, 0.4f, 0.5f);
Vector3 testA = testQ.eulerAngles;

results in vector (352.5, 37.9,74.7)

This is the Unity conversion, is it somehow possible to use your method when Euler angles in Unity are YXZ ?

In whatever order I am swapping quaternion values,
it does not produce good result.