<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Calculate Euler Angles from BlockReference.Transform - Matrix3d in .NET Forum</title>
    <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6755868#M33465</link>
    <description>&lt;P&gt;It is look like you using wrong algorithm. Maybe this algorithm help you: &lt;A href="http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf" target="_blank"&gt;http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;But if matrix has nonuniform scaling that algorithm also wrong.&lt;/P&gt;</description>
    <pubDate>Sat, 17 Dec 2016 14:54:02 GMT</pubDate>
    <dc:creator>Alexander.Rivilis</dc:creator>
    <dc:date>2016-12-17T14:54:02Z</dc:date>
    <item>
      <title>Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6754904#M33464</link>
      <description>&lt;P&gt;I'm having trouble calculating the Euler Angles (Yaw, Pitch, Roll) for a given block's Transform member. Assuming WCS = Matrix3d.Identity and ignoring UCS I have the following code for calculating the rotation about each axis stored in the Matrix3d:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;    Public Shared Function CalculateEulerAngles(Transform As Matrix3d) As Vector3d
        Dim x As Double = Math.Atan2(Transform.ElementAt(3, 2), Transform.ElementAt(3, 3))
        Dim y As Double = Math.Atan2(-Transform.ElementAt(3, 1), Math.Sqrt(Transform.ElementAt(3, 2) ^ 2 + Transform.ElementAt(3, 3) ^ 2))
        Dim z As Double = Math.Atan2(Transform.ElementAt(2, 1), Transform.ElementAt(1, 1))
        Return New Vector3d(x, y, z)
    End Function&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This calculation is obviously incorrect from the results I receive.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Kevin&lt;/P&gt;</description>
      <pubDate>Fri, 16 Dec 2016 19:30:50 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6754904#M33464</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2016-12-16T19:30:50Z</dc:date>
    </item>
    <item>
      <title>Re: Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6755868#M33465</link>
      <description>&lt;P&gt;It is look like you using wrong algorithm. Maybe this algorithm help you: &lt;A href="http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf" target="_blank"&gt;http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;But if matrix has nonuniform scaling that algorithm also wrong.&lt;/P&gt;</description>
      <pubDate>Sat, 17 Dec 2016 14:54:02 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6755868#M33465</guid>
      <dc:creator>Alexander.Rivilis</dc:creator>
      <dc:date>2016-12-17T14:54:02Z</dc:date>
    </item>
    <item>
      <title>Re : Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6755895#M33466</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Assuming you're trying to get the rotation angles about Z, Y&amp;nbsp;and X&amp;nbsp;axis (respectively yaw, pitch and roll) as defined in the specific Euler angles definition called Tait-Bryan angles using the z-y'-x" convention (see &lt;A href="https://en.wikipedia.org/wiki/Euler_angles" target="_blank"&gt;here&lt;/A&gt; and &lt;A href="http://planning.cs.uiuc.edu/node102.html" target="_blank"&gt;there&lt;/A&gt;), in other words, the angles along the X, Y and Z axes of an object that would have undergone rotations, first along the X axis, then along the Y axis and finally along the Z axis.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Maybe you can get some inspiration from this little class.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using System;
using static System.Math;

namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Describes a 3d rotation with Yaw Pitch and Roll
    /// (i.e. a specific Euler angles called Tait-Ryan angles with z-y'-x" convention).
    /// &amp;lt;/summary&amp;gt;
    public class TaitBryan
    {
        /// &amp;lt;summary&amp;gt;
        /// Get the transformation matrix.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Transform { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about Z axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Yaw { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about Y axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Pitch { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about X axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Roll { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about Z axis.
        /// &amp;lt;/summary&amp;gt;
        public double Alpha { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about Y axis.
        /// &amp;lt;/summary&amp;gt;
        public double Beta { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about X axis.
        /// &amp;lt;/summary&amp;gt;
        public double Gamma { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="xform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public TaitBryan(Matrix3d xform)
        {
            if (!xform.IsUniscaledOrtho())
                throw new ArgumentException("Non uniscaled ortho matrix.");

            Transform = xform;
            Alpha = Atan2(xform[1, 0], xform[0, 0]);
            Beta = Atan2(-xform[2, 0], Sqrt(xform[2, 1] * xform[2, 1] + xform[2, 2] * xform[2, 2]));
            Gamma = Atan2(xform[2, 1], xform[2, 2]);
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
        }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Rotation angle about Z axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Rotation angle about Y axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"Rotation angle about X axis.&amp;gt;&amp;lt;/param&amp;gt;
        public TaitBryan(double alpha, double beta, double gamma)
        {
            Alpha = alpha;
            Beta = beta;
            Gamma = gamma;
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
            Transform = Yaw * Pitch * Roll;
        }
    }
}
&lt;/PRE&gt;</description>
      <pubDate>Sat, 17 Dec 2016 15:20:36 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6755895#M33466</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2016-12-17T15:20:36Z</dc:date>
    </item>
    <item>
      <title>Re : Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6756048#M33467</link>
      <description>&lt;P&gt;Oops!...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The link provided by &lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/481027"&gt;@Alexander.Rivilis&lt;/a&gt; made me see I forgot the cases of rotations of 90° or -90° about Y axis which may cause a 'divide by zero' error.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's a safer implementation&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using System;
using static System.Math;

namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Describes a 3d rotation with Yaw Pitch and Roll
    /// (i.e. a specific Euler angles called Tait-Ryan angles with z-y'-x" convention).
    /// &amp;lt;/summary&amp;gt;
    public class TaitBryan
    {
        /// &amp;lt;summary&amp;gt;
        /// Get the transformation matrix.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Transform { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about Z axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Yaw { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about Y axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Pitch { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation matrix about X axis.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Roll { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about Z axis.
        /// &amp;lt;/summary&amp;gt;
        public double Alpha { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about Y axis.
        /// &amp;lt;/summary&amp;gt;
        public double Beta { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation angle about X axis.
        /// &amp;lt;/summary&amp;gt;
        public double Gamma { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="xform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public TaitBryan(Matrix3d xform)
        {
            if (!xform.IsUniscaledOrtho())
                throw new ArgumentException("Non uniscaled ortho matrix.");

            Transform = xform;
            Beta = -Asin(xform[2, 0] / xform.GetScale());
            if (Abs(Beta - PI * 0.5) &amp;lt; 1e-7)
            {
                Beta = PI * 0.5;
                Alpha = Atan2(xform[1, 2], xform[1, 1]);
                Gamma = 0.0;
            }
            else if (Abs(Beta + PI * 0.5) &amp;lt; 1e-7)
            {
                Beta = -PI * 0.5;
                Alpha = Atan2(-xform[1, 2], xform[1, 1]);
                Gamma = 0.0;
            }
            else
            {
                Alpha = Atan2(xform[1, 0], xform[0, 0]);
                Gamma = Atan2(xform[2, 1], xform[2, 2]);
            }
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
        }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Rotation angle about Z axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Rotation angle about Y axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"Rotation angle about X axis.&amp;gt;&amp;lt;/param&amp;gt;
        public TaitBryan(double alpha, double beta, double gamma)
        {
            Alpha = alpha;
            Beta = beta;
            Gamma = gamma;
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
            Transform = Yaw * Pitch * Roll;
        }
    }
}
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 17 Dec 2016 17:35:55 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6756048#M33467</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2016-12-17T17:35:55Z</dc:date>
    </item>
    <item>
      <title>Re : Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6756596#M33468</link>
      <description>&lt;P&gt;Here's an implementation which illustrates the diffeence between proper&amp;nbsp;Euler angles&amp;nbsp;(Z-X'-Z")&amp;nbsp;and Tait-Bryan angles (Z-Y'-X").&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Abstract base class&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;

namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Base class for Euler angles descriptions.
    /// &amp;lt;/summary&amp;gt;
    public abstract class EulerAngles
    {
        protected double psi, theta, phi;
        protected Matrix3d xform;

        /// &amp;lt;summary&amp;gt;
        /// Gets the precession angle.
        /// &amp;lt;/summary&amp;gt;
        public double Alpha =&amp;gt; psi;

        /// &amp;lt;summary&amp;gt;
        /// Gets the nutation angle.
        /// &amp;lt;/summary&amp;gt;
        public double Beta =&amp;gt; theta;

        /// &amp;lt;summary&amp;gt;
        /// Gets the spin angle.
        /// &amp;lt;/summary&amp;gt;
        public double Gamma =&amp;gt; phi;

        /// &amp;lt;summary&amp;gt;
        /// Get the transformation matrix.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Transform =&amp;gt; xform;

        /// &amp;lt;summary&amp;gt;
        /// Base constructor.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="transform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public EulerAngles(Matrix3d transform)
        {
            xform = transform;
        }

        /// &amp;lt;summary&amp;gt;
        /// Base constructor.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Precession angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Nutation angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Intrinsic rotation.&amp;lt;/param&amp;gt;
        public EulerAngles(double alpha, double beta, double gamma)
        {
            psi = alpha;
            theta = beta;
            phi = gamma;
        }
    }
}
&lt;/PRE&gt;
&lt;P&gt;Proper Euler angles.&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using System;
using static System.Math;

namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Describes a 3d rotation with precession, nutation and intrinsic rotation
    /// (i.e. a proper Euler angles with z-x'-z" convention).
    /// &amp;lt;/summary&amp;gt;
    public class ProperEuler : EulerAngles
    {
        /// &amp;lt;summary&amp;gt;
        /// Gets the precession rotation matrix (Z).
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Precession { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the nutation rotation matrix (X').
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Nutation { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the spin rotation matrix (Z").
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Spin { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of ProperEuler.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="xform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public ProperEuler(Matrix3d xform) : base(xform)
        {
            if (!xform.IsUniscaledOrtho())
                throw new ArgumentException("Non uniscaled ortho matrix.");

            theta = Acos(xform[2, 2] / xform.GetScale());
            if (Abs(theta) &amp;lt; 1e-7)
            {
                theta = 0.0;
                psi = Atan2(xform[1, 0], xform[1, 1]);
                phi = 0.0;
            }
            else
            {
                psi = Atan2(xform[0, 2], -xform[1, 2]);
                phi = Atan2(xform[2, 0], xform[2, 1]);
            }
            Precession = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Nutation = Matrix3d.Rotation(Beta, Vector3d.XAxis, Point3d.Origin);
            Spin = Matrix3d.Rotation(Gamma, Vector3d.ZAxis, Point3d.Origin);
        }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of ProperEuler.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Precession angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Nutation angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Intrinsic rotation angle.&amp;lt;/param&amp;gt;
        public ProperEuler(double alpha, double beta, double gamma) : base(alpha, beta, gamma)
        {
            Precession = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Nutation = Matrix3d.Rotation(Beta, Vector3d.XAxis, Point3d.Origin);
            Spin = Matrix3d.Rotation(Gamma, Vector3d.ZAxis, Point3d.Origin);
            xform = Precession * Nutation * Spin;
        }
    }
}
&lt;/PRE&gt;
&lt;P&gt;Tait-Bryan angles.&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using System;
using static System.Math;

namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Describes a 3d rotation with Yaw Pitch and Roll
    /// (i.e. a specific Euler angles called Tait-Ryan angles with z-y'-x" convention).
    /// &amp;lt;/summary&amp;gt;
    public class TaitBryan : EulerAngles
    {
        /// &amp;lt;summary&amp;gt;
        /// Gets the yaw rotation matrix (Z).
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Yaw { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the pitch rotation matrix (Y').
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Pitch { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets roll the rotation matrix (X").
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Roll { get; private set; }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="xform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public TaitBryan(Matrix3d xform) : base(xform)
        {
            if (!xform.IsUniscaledOrtho())
                throw new ArgumentException("Non uniscaled ortho matrix.");

            theta = -Asin(xform[2, 0] / xform.GetScale());
            if (Abs(theta - PI * 0.5) &amp;lt; 1e-7)
            {
                theta = PI * 0.5;
                psi = Atan2(xform[1, 2], xform[1, 1]);
                phi = 0.0;
            }
            else if (Abs(Beta + PI * 0.5) &amp;lt; 1e-7)
            {
                theta = -PI * 0.5;
                psi = Atan2(-xform[1, 2], xform[1, 1]);
                phi = 0.0;
            }
            else
            {
                psi = Atan2(xform[1, 0], xform[0, 0]);
                phi = Atan2(xform[2, 1], xform[2, 2]);
            }
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
        }

        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Rotation angle about Z axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Rotation angle about Y axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Rotation angle about X axis.&amp;lt;/param&amp;gt;
        public TaitBryan(double alpha, double beta, double gamma) : base(alpha, beta, gamma)
        {
            Yaw = Matrix3d.Rotation(Alpha, Vector3d.ZAxis, Point3d.Origin);
            Pitch = Matrix3d.Rotation(Beta, Vector3d.YAxis, Point3d.Origin);
            Roll = Matrix3d.Rotation(Gamma, Vector3d.XAxis, Point3d.Origin);
            xform = Yaw * Pitch * Roll;
        }
    }
}
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 18 Dec 2016 10:35:58 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6756596#M33468</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2016-12-18T10:35:58Z</dc:date>
    </item>
    <item>
      <title>Re : Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6757349#M33469</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Playing a little further with this, i notice that the ProperEuler type makes it easy to establish a relationship between the Euler angle and how AutoCAD exposes a 3d rotation using a vector (Normal) and an angle (Rotation).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So,&amp;nbsp;here's one more new implementation (I removed the (IMHO unsefull) rotation 3d matrices properties).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The&amp;nbsp;&lt;SPAN&gt;base 'EulerAngles' abstract class.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using static System.Math;
 
namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Base class for Euler angles defintions.
    /// &amp;lt;/summary&amp;gt;
    public abstract class EulerAngles
    {
        protected double psi, theta, phi;
        protected Matrix3d xform;
 
        /// &amp;lt;summary&amp;gt;
        /// Gets the angle alpha (or psi).
        /// &amp;lt;/summary&amp;gt;
        public double Alpha =&amp;gt; psi;
 
        /// &amp;lt;summary&amp;gt;
        /// Gets the angle beta (or theta).
        /// &amp;lt;/summary&amp;gt;
        public double Beta =&amp;gt; theta;
 
        /// &amp;lt;summary&amp;gt;
        /// Gets the angle gamma (or phi).
        /// &amp;lt;/summary&amp;gt;
        public double Gamma =&amp;gt; phi;
 
        /// &amp;lt;summary&amp;gt;
        /// Get the transformation matrix.
        /// &amp;lt;/summary&amp;gt;
        public Matrix3d Transform =&amp;gt; xform;
 
        /// &amp;lt;summary&amp;gt;
        /// Base constructor.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="transform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public EulerAngles(Matrix3d transform)
        {
            if (!transform.IsUniscaledOrtho())
                throw new System.ArgumentException("Non uniscaled ortho matrix.");
            xform = transform;
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Base constructor.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Precession angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Nutation angle.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Intrinsic rotation.&amp;lt;/param&amp;gt;
        public EulerAngles(double alpha, double beta, double gamma)
        {
            psi = Wrap(alpha);
            theta = Wrap(beta);
            phi = Wrap(gamma);
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Equality operator.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="x"&amp;gt;Left operand.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="y"&amp;gt;Right operand.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;true if the values of its operands are equal, false otherwise.&amp;lt;/returns&amp;gt;
        public static bool operator ==(EulerAngles x, EulerAngles y) =&amp;gt; x.Equals(y);
 
        /// &amp;lt;summary&amp;gt;
        /// Inequality operator.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="x"&amp;gt;Left operand.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="y"&amp;gt;Right operand.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;true if the values of its operands are not equal, false otherwise.&amp;lt;/returns&amp;gt;
        public static bool operator !=(EulerAngles x, EulerAngles y) =&amp;gt; !x.Equals(y);
 
        /// &amp;lt;summary&amp;gt;
        /// Determines whether the specified object is equal to the current object.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="obj"&amp;gt;The object to compare with the current object.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;true if the specified object is equal to the current object; otherwise, false.&amp;lt;/returns&amp;gt;
        public override bool Equals(object obj)
        {
            var other = obj as EulerAngles;
            return psi == other?.psi &amp;amp;&amp;amp; theta == other.theta &amp;amp;&amp;amp; phi == other.phi;
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Serves as hash function.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;A hash code for the current object.&amp;lt;/returns&amp;gt;
        public override int GetHashCode() =&amp;gt; psi.GetHashCode() ^ theta.GetHashCode() ^ phi.GetHashCode();
 
        /// &amp;lt;summary&amp;gt;
        /// Returns a string that represents the current object.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;A string that represents the current object.&amp;lt;/returns&amp;gt;
        public override string ToString() =&amp;gt; $"({Alpha}, {Beta}, {Gamma})";
 
        /// &amp;lt;summary&amp;gt;
        /// Return the angle in [0,2*PI) range.
        /// &amp;lt;/summary&amp;gt;
        private double Wrap(double angle) =&amp;gt; 
            0.0 &amp;lt;= angle &amp;amp;&amp;amp; angle &amp;lt; 2 * PI ? angle : Asin(Sin(angle));
    }
}&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;The 'ProperEuler' class (can also be used with Normal and Rotation)&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;Transform = Rotation_Z(Alpha) * Rotation_X(Beta) * Rotation_Z(Gamma)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using static System.Math;
 
namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Defines the relations between a transformation matrix and Euler angles
    /// (proper Euler angles using z-x'-z" convention).
    /// &amp;lt;/summary&amp;gt;
    public class ProperEuler : EulerAngles
    {
        Matrix3d planeToWorld;
 
        /// &amp;lt;summary&amp;gt;
        /// Gets the normal of the plane.
        /// &amp;lt;/summary&amp;gt;
        public Vector3d Normal =&amp;gt; planeToWorld.CoordinateSystem3d.Zaxis;
 
        /// &amp;lt;summary&amp;gt;
        /// Gets the rotation on the plane;
        /// &amp;lt;/summary&amp;gt;
        public double Rotation =&amp;gt; phi;
 
        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of ProperEuler.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="transform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public ProperEuler(Matrix3d transform) : base(transform)
        {
            theta = Acos(xform[2, 2] / xform.GetScale());
            if (Abs(theta) &amp;lt; 1e-7)
            {
                theta = 0.0;
                psi = Atan2(xform[1, 0], xform[1, 1]);
                phi = 0.0;
            }
            else
            {
                psi = Atan2(xform[0, 2], -xform[1, 2]);
                phi = Atan2(xform[2, 0], xform[2, 1]);
            }
            planeToWorld = 
                Matrix3d.Rotation(psi, Vector3d.ZAxis, Point3d.Origin) *
                Matrix3d.Rotation(theta, Vector3d.XAxis, Point3d.Origin);
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of ProperEuler.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Rotation angle around the Z axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Rotation angle around the X' axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Rotation angle around the Z" axis.&amp;lt;/param&amp;gt;
        public ProperEuler(double alpha, double beta, double gamma) : base(alpha, beta, gamma)
        {
            planeToWorld =
                Matrix3d.Rotation(alpha, Vector3d.ZAxis, Point3d.Origin) *
                Matrix3d.Rotation(beta, Vector3d.XAxis, Point3d.Origin);
            xform = planeToWorld * 
                Matrix3d.Rotation(gamma, Vector3d.ZAxis, Point3d.Origin);
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of ProperEuler.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="normal"&amp;gt;Plane normal.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="rotation"&amp;gt;Proper rotation.&amp;lt;/param&amp;gt;
        public ProperEuler(Vector3d normal, double rotation)
            : this(Matrix3d.PlaneToWorld(normal) *
                   Matrix3d.Rotation(rotation, Vector3d.ZAxis, Point3d.Origin))
        { }
 
    /// &amp;lt;summary&amp;gt;
    /// Determines whether the specified object is equal to the current object.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="obj"&amp;gt;The object to compare with the current object.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;true if the specified object is equal to the current object; otherwise, false.&amp;lt;/returns&amp;gt;
    public override bool Equals(object obj) =&amp;gt; obj is ProperEuler &amp;amp;&amp;amp; base.Equals(obj);
 
        /// &amp;lt;summary&amp;gt;
        /// Serves as hash function.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;A hash code for the current object.&amp;lt;/returns&amp;gt;
        public override int GetHashCode() =&amp;gt; base.GetHashCode();
    }
}&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;The TaitBryan class (yaw,pitch, roll)&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;Transform = Rotation_Z(Alpha) * Rotation_Y(Beta) * Rotation_X(Gamma)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;using Autodesk.AutoCAD.Geometry;
using static System.Math;
 
namespace Gile.AutoCAD.Geometry
{
    /// &amp;lt;summary&amp;gt;
    /// Defines the relations between a transformation matrix and Euler angles
    /// (specific Euler angles called Tait-Ryan angles using z-y'-x" convention).
    /// &amp;lt;/summary&amp;gt;
    public class TaitBryan : EulerAngles
    {
        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="transform"&amp;gt;Transformation matrix.&amp;lt;/param&amp;gt;
        public TaitBryan(Matrix3d transform) : base(transform)
        {
            theta = -Asin(xform[2, 0] / xform.GetScale());
            if (Abs(theta - PI * 0.5) &amp;lt; 1e-7)
            {
                theta = PI * 0.5;
                psi = Atan2(xform[1, 2], xform[1, 1]);
                phi = 0.0;
            }
            else if (Abs(Beta + PI * 0.5) &amp;lt; 1e-7)
            {
                theta = -PI * 0.5;
                psi = Atan2(-xform[1, 2], xform[1, 1]);
                phi = 0.0;
            }
            else
            {
                psi = Atan2(xform[1, 0], xform[0, 0]);
                phi = Atan2(xform[2, 1], xform[2, 2]);
            }
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Create a new intance of TaitBryan.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="alpha"&amp;gt;Rotation angle around the Z axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="beta"&amp;gt;Rotation angle around the Y' axis.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="gamma"&amp;gt;Rotation angle around the X" axis.&amp;lt;/param&amp;gt;
        public TaitBryan(double alpha, double beta, double gamma) : base(alpha, beta, gamma)
        {
            xform = 
                Matrix3d.Rotation(alpha, Vector3d.ZAxis, Point3d.Origin) *
                Matrix3d.Rotation(beta, Vector3d.YAxis, Point3d.Origin) *
                Matrix3d.Rotation(gamma, Vector3d.XAxis, Point3d.Origin);
        }
 
        /// &amp;lt;summary&amp;gt;
        /// Determines whether the specified object is equal to the current object.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="obj"&amp;gt;The object to compare with the current object.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;true if the specified object is equal to the current object; otherwise, false.&amp;lt;/returns&amp;gt;
        public override bool Equals(object obj) =&amp;gt; obj is TaitBryan &amp;amp;&amp;amp; base.Equals(obj);
 
        /// &amp;lt;summary&amp;gt;
        /// Serves as hash function.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;A hash code for the current object.&amp;lt;/returns&amp;gt;
        public override int GetHashCode() =&amp;gt; base.GetHashCode();
    }
}&lt;/PRE&gt;</description>
      <pubDate>Mon, 19 Dec 2016 07:29:35 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6757349#M33469</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2016-12-19T07:29:35Z</dc:date>
    </item>
    <item>
      <title>Re : Calculate Euler Angles from BlockReference.Transform - Matrix3d</title>
      <link>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6758828#M33470</link>
      <description>&lt;P&gt;Your code worked perfectly. I thank you from the bottom of my heart :).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best Regards,&lt;/P&gt;&lt;P&gt;Kevin&lt;/P&gt;</description>
      <pubDate>Mon, 19 Dec 2016 19:00:48 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/calculate-euler-angles-from-blockreference-transform-matrix3d/m-p/6758828#M33470</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2016-12-19T19:00:48Z</dc:date>
    </item>
  </channel>
</rss>

