Rotate plane by Quaternion

Hi,

How can I rotate a plane using Quaternion?

Before I got answer @laurent_delrieu that I can convert Quaternion to a plane.
But how can I rotate an existing plane by adding a quaternion rotation.
(The base plane is not XY plane, but arbitrary one)

Hi,
I am not sure but you can use
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Quaternion_GetRotation_1.htm

double angleRadians;
Vector3d axis;
if ( quaternion.GetRotation( out angleRadians, 	out axis))
{
plane.Transform(Transform.Rotation(angleRadians, axis, plane.Origin))
}

Thanks it does help.
But it is not very intuitive how the rotation works, somehow need to set always a rotation to 1, to get good rotation. Quaternions is a mystery for me.

private void RunScript(Plane Pl0, double x, double y, double z, double vx, double vy, double vz, double rotX, double rotY, double rotZ, ref object Pl1)
  {

    Plane plane = new Plane(Pl0);
    plane.Translate(new Vector3d(x, y, z));
    plane.Translate(plane.XAxis * vx);
    plane.Translate(plane.YAxis * vy);
    plane.Translate(plane.ZAxis * vz);
    plane.Rotate(Rhino.RhinoMath.ToRadians(rotX), plane.XAxis);
    plane.Rotate(Rhino.RhinoMath.ToRadians(rotY), plane.YAxis);
    plane.Rotate(Rhino.RhinoMath.ToRadians(rotZ), plane.ZAxis);
    
    
    
    
    Quaternion quaternion = new Quaternion(a,b,c,d);

    double angleRadians;
    Vector3d axis;
    if ( quaternion.GetRotation(out angleRadians, out axis))
      plane.Transform(Transform.Rotation(angleRadians, axis, plane.Origin));

    Pl1 = plane;

  }

  // <Custom additional code> 
  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);
  }
  // </Custom additional code> 
}

I don’t understand what you intend to do with your code, but to rotate a plane with a quaternion you just need to do what Laurent suggested. A quaternion is equivalent to a rotation vector and an angle and it’s not equivalent to rotating first in X, then in Y and then in Z, the quaternion does it all at the same time, or so I think. And the quaternions don’t support position, it’s not like a rotation from an axis that you are using a line (so, it has a position), it’s just rotation (in 4d).

@Petras_Vestartas for sure Quaternion are a bit abstract, but as it is a class you can use them quite without knowing what is behind. Like @Dani_Abalde said it is a “simple” rotation.

They are not very useful if you just use them from time to time in your code. They will be more useful if they are used all along rotation calculations. For example if you want to interpolate angular position (see SLERP). It is their power.
For my need I used them to track the rotation of a Rigid Body with 6 degree of freedom. I have quite the same values as input (position, velocity, acceleration, angle position, angle velocity and angle acceleration). So inside my solver I don’t use at all “classical” Euler angles. Angles are just used as input and output.

Quaternion is very similar to a Plane but without a position. Here what I use ti track the state of a Rigid Body

    public class State
    {
        //Declarations Variables
        /// <summary>
        /// temps relatif (s)
        /// </summary>
        public double Time;
        /// <summary>
        /// Position (m) dans le repère ECEF
        /// </summary>
        public Point3d PositionECEF; 
        /// <summary>
        /// Vitesse (m/s) dans le repère ECEF
        /// </summary>
        public Vector3d VelocityECEF;
        /// <summary>
        /// Accélération (m/s²) dans le repère ECEF
        /// </summary>
        public Vector3d AccelerationECEF; 
        /// <summary>
        /// Position angulaire dans le repère ECEF
        /// </summary>
        public Quaternion AngularPositionECEF; 
        /// <summary>
        /// Dérivé de la position angulaire 
        /// </summary>
        public Quaternion AngularDerivativeECEF;
        /// <summary>
        /// 
        /// </summary>
        public Quaternion AngularAccelerationECEF;
        private Vector3d _angularVelocityBodyFrame;
        /// <summary>
        /// Vitesse angulaire dans le repère du corps
        /// </summary>
        public Vector3d AngularVelocityBodyFrame
        {
            get { return _angularVelocityBodyFrame; }
            set
            {
                _angularVelocityBodyFrame = value;
                Quaternion wBody = new Quaternion(0, _angularVelocityBodyFrame.X, _angularVelocityBodyFrame.Y, _angularVelocityBodyFrame.Z);
                Quaternion wECEF = AngularPositionECEF * wBody * AngularPositionECEF.Conjugate;
                _angularVelocityECEF = wECEF.Vector;
            }
        }
        private Vector3d _angularVelocityECEF;
        /// <summary>
        /// Vitesse angulaire dans le repère ECEF
        /// </summary>
        public Vector3d AngularVelocityECEF
        {
            get { return _angularVelocityECEF; }
            set
            {
                _angularVelocityECEF = value;
                Quaternion quat = new Quaternion(0, _angularVelocityECEF.X, _angularVelocityECEF.Y, _angularVelocityECEF.Z);
                Quaternion wBody = AngularPositionECEF.Conjugate * quat * AngularPositionECEF;
                _angularVelocityBodyFrame = wBody.Vector;
            }
        }
2 Likes

Thank you, I was trying to optimize a scanner calibration. Euler angles was not working because rotations accumulates per each rotation. The example of yours was working well.

1 Like