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

I converted some C++ code from this website http://bediyap.com/programming/convert-quaternion-to-euler-rotations/ to C# seems to work. Apparently swaping axis is not enough. Hope it helps for someone suffering from Unity Axis system and Rhino integration.

  private void RunScript(object y, ref object A)
  {




    Quaternion q = new Quaternion(0.1f, 0.2f, 0.4f, 0.5f);
    //Quaternion q = new Quaternion(0, 0,1, 0);
    // Quaternion q = new Quaternion(0, 0,0.7, -0.7);
    q.normalize();
    double[] res = new double[3]{0,0,0};
    quaternion2Euler(q, ref res, RotSeq.yxz);//yxz
    res[0] = rad2deg(res[0]) ;
    res[1] = rad2deg(res[1]) ;
    res[2] = rad2deg(res[2]) ;
    A = new double[]{res[1],res[2],res[0]};

  }

  // <Custom additional code> 


  ///////////////////////////////
  // Quaternion struct
  // Simple incomplete quaternion struct for demo purpose
  ///////////////////////////////
  public struct Quaternion{
    //
    //    public  Quaternion(){
    //      this.x = 0;
    //      this.y = 0;
    //      this.z = 0;
    //      this.w = 0;
    //
    //    }

    public  Quaternion(double x, double y, double z, double w){
      this.x = x;
      this.y = y;
      this.z = z;
      this.w = w;

    }

    public  void normalize(){
      double norm = Math.Sqrt(x * x + y * y + z * z + w * w);
      x /= norm;
      y /= norm;
      z /= norm;
      w /= norm;
    }

    public double norm(){
      return Math.Sqrt(x * x + y * y + z * z + w * w);
    }

    public  double x;
    public  double y;
    public  double z;
    public  double w;

  };

  ///////////////////////////////
  // Quaternion to Euler
  ///////////////////////////////
  public enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};

  void twoaxisrot(double r11, double r12, double r21, double r31, double r32, ref double[] res){
    res[0] = Math.Atan2(r11, r12);
    res[1] = Math.Acos(r21);
    res[2] = Math.Atan2(r31, r32);
  }

  void threeaxisrot(double r11, double r12, double r21, double r31, double r32, ref double[] res){
    res[0] = Math.Atan2(r31, r32);
    res[1] = Math.Asin(r21);
    res[2] = Math.Atan2(r11, r12);
  }



  // note:
  // return values of res[] depends on rotSeq.
  // i.e.
  // for rotSeq zyx,
  // x = res[0], y = res[1], z = res[2]
  // for rotSeq xyz
  // z = res[0], y = res[1], x = res[2]
  // ...
  void quaternion2Euler(Quaternion q, ref double[] res, RotSeq rotSeq)
  {
    switch(rotSeq){

      case RotSeq.zyx:
        threeaxisrot(2 * (q.x * q.y + q.w * q.z),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          -2 * (q.x * q.z - q.w * q.y),
          2 * (q.y * q.z + q.w * q.x),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          ref res);
        break;

      case RotSeq.zyz:
        twoaxisrot(2 * (q.y * q.z - q.w * q.x),
          2 * (q.x * q.z + q.w * q.y),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          2 * (q.y * q.z + q.w * q.x),
          -2 * (q.x * q.z - q.w * q.y),
          ref res);
        break;

      case RotSeq.zxy:
        threeaxisrot(-2 * (q.x * q.y - q.w * q.z),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          2 * (q.y * q.z + q.w * q.x),
          -2 * (q.x * q.z - q.w * q.y),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          ref res);
        break;

      case RotSeq.zxz:
        twoaxisrot(2 * (q.x * q.z + q.w * q.y),
          -2 * (q.y * q.z - q.w * q.x),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          2 * (q.x * q.z - q.w * q.y),
          2 * (q.y * q.z + q.w * q.x),
          ref res);
        break;

      case RotSeq.yxz:
        threeaxisrot(2 * (q.x * q.z + q.w * q.y),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          -2 * (q.y * q.z - q.w * q.x),
          2 * (q.x * q.y + q.w * q.z),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          ref res);
        break;

      case RotSeq.yxy:
        twoaxisrot(2 * (q.x * q.y - q.w * q.z),
          2 * (q.y * q.z + q.w * q.x),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          2 * (q.x * q.y + q.w * q.z),
          -2 * (q.y * q.z - q.w * q.x),
          ref res);
        break;

      case RotSeq.yzx:
        threeaxisrot(-2 * (q.x * q.z - q.w * q.y),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          2 * (q.x * q.y + q.w * q.z),
          -2 * (q.y * q.z - q.w * q.x),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          ref res);
        break;

      case RotSeq.yzy:
        twoaxisrot(2 * (q.y * q.z + q.w * q.x),
          -2 * (q.x * q.y - q.w * q.z),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          2 * (q.y * q.z - q.w * q.x),
          2 * (q.x * q.y + q.w * q.z),
          ref res);
        break;

      case RotSeq.xyz:
        threeaxisrot(-2 * (q.y * q.z - q.w * q.x),
          q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z,
          2 * (q.x * q.z + q.w * q.y),
          -2 * (q.x * q.y - q.w * q.z),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          ref res);
        break;

      case RotSeq.xyx:
        twoaxisrot(2 * (q.x * q.y + q.w * q.z),
          -2 * (q.x * q.z - q.w * q.y),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          2 * (q.x * q.y - q.w * q.z),
          2 * (q.x * q.z + q.w * q.y),
          ref res);
        break;

      case RotSeq.xzy:
        threeaxisrot(2 * (q.y * q.z + q.w * q.x),
          q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
          -2 * (q.x * q.y - q.w * q.z),
          2 * (q.x * q.z + q.w * q.y),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          ref res);
        break;

      case RotSeq.xzx:
        twoaxisrot(2 * (q.x * q.z - q.w * q.y),
          2 * (q.x * q.y + q.w * q.z),
          q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
          2 * (q.x * q.z + q.w * q.y),
          -2 * (q.x * q.y - q.w * q.z),
          ref res);
        break;

      default:
        //std::cout << "Unknown rotation sequence" << std::endl;
        break;


    }
  }





  ///////////////////////////////
  // Helper functions
  ///////////////////////////////
  public static Quaternion Multiply(Quaternion q1, Quaternion q2){
    Quaternion q = new Quaternion(0, 0, 0, 0);
    q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
    q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
    q.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
    q.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
    return q;
  }

  double rad2deg(double rad){
    return Math.Abs(rad * 180.0 / Math.PI+360)%360; 
  }
1 Like