Example #1
0
        /// <summary>
        /// Calculates the distance to the nearest edge from the point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <returns>The distance.</returns>
        public T GetDistanceToNearestEdge(Vector2D <T> point)
        {
            var dx = Scalar.Max(Scalar.Max(Scalar.Subtract(Min.X, point.X), Scalar <T> .Zero), Scalar.Subtract(point.X, Max.X));
            var dy = Scalar.Max(Scalar.Max(Scalar.Subtract(Min.Y, point.Y), Scalar <T> .Zero), Scalar.Subtract(point.Y, Max.Y));

            return(Scalar.Sqrt(Scalar.Add(Scalar.Multiply(dx, dx), Scalar.Multiply(dy, dy))));
        }
Example #2
0
        /// <summary>
        /// Calculates whether this circle contains another circle
        /// </summary>
        /// <param name="other">The circle.</param>
        /// <returns>True if this circle contains the given circle; False otherwise.</returns>
        /// <remarks>This does consider a circle that touches the edge contained.</remarks>
        public bool Contains(Circle <T> other)
        {
            var distanceSquared = Vector2D.DistanceSquared(Center, other.Center);
            var radiusDiff      = Scalar.Subtract(Radius, other.Radius);

            return(Scalar.LessThanOrEqual(distanceSquared, Scalar.Multiply(radiusDiff, radiusDiff)));
        }
Example #3
0
        /// <summary>Creates a rotation matrix from the given Quaternion rotation value.</summary>
        /// <param name="quaternion">The source Quaternion.</param>
        /// <returns>The rotation matrix.</returns>
        public static Matrix2X3 <T> CreateFromQuaternion <T>(Quaternion <T> quaternion)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix2X3 <T> result = Matrix2X3 <T> .Identity;

            T xx = Scalar.Multiply(quaternion.X, quaternion.X);
            T yy = Scalar.Multiply(quaternion.Y, quaternion.Y);
            T zz = Scalar.Multiply(quaternion.Z, quaternion.Z);

            T xy = Scalar.Multiply(quaternion.X, quaternion.Y);
            T wz = Scalar.Multiply(quaternion.Z, quaternion.W);
            T xz = Scalar.Multiply(quaternion.Z, quaternion.X);
            T wy = Scalar.Multiply(quaternion.Y, quaternion.W);
            T yz = Scalar.Multiply(quaternion.Y, quaternion.Z);
            T wx = Scalar.Multiply(quaternion.X, quaternion.W);

            result.M11 = Scalar.Subtract(Scalar <T> .One, Scalar.Multiply(Scalar <T> .Two, Scalar.Add(yy, zz)));
            result.M12 = Scalar.Multiply(Scalar <T> .Two, Scalar.Add(xy, wz));
            result.M13 = Scalar.Multiply(Scalar <T> .Two, Scalar.Subtract(xz, wy));

            result.M21 = Scalar.Multiply(Scalar <T> .Two, Scalar.Subtract(xy, wz));
            result.M22 = Scalar.Subtract(Scalar <T> .One, Scalar.Multiply(Scalar <T> .Two, Scalar.Add(zz, xx)));
            result.M23 = Scalar.Multiply(Scalar <T> .Two, Scalar.Add(yz, wx));

            return(result);
        }
        /// <summary>Attempts to invert the given matrix. If the operation succeeds, the inverted matrix is stored in the result parameter.</summary>
        /// <param name="matrix">The source matrix.</param>
        /// <param name="result">The output matrix.</param>
        /// <returns>True if the operation succeeded, False otherwise.</returns>
        public static bool Invert <T>(Matrix3X2 <T> matrix, out Matrix3X2 <T> result)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            T det = Scalar.Subtract(Scalar.Multiply(matrix.M11, matrix.M22), Scalar.Multiply(matrix.M21, matrix.M12));

            if (!Scalar.GreaterThanOrEqual(Scalar.Abs(det), Scalar <T> .Epsilon))
            {
                result = new(Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN, Scalar <T> .NaN);
                return(false);
            }

            T invDet = Scalar.Reciprocal(det);

            result = default;

            result.M11 = Scalar.Multiply(matrix.M22, invDet);
            result.M12 = Scalar.Negate(Scalar.Multiply(matrix.M12, invDet));

            result.M21 = Scalar.Negate(Scalar.Multiply(matrix.M21, invDet));
            result.M22 = Scalar.Multiply(matrix.M11, invDet);

            result.M31 = Scalar.Multiply(Scalar.Subtract(Scalar.Multiply(matrix.M21, matrix.M32), Scalar.Multiply(matrix.M31, matrix.M22)), invDet);
            result.M32 = Scalar.Multiply(Scalar.Subtract(Scalar.Multiply(matrix.M31, matrix.M12), Scalar.Multiply(matrix.M11, matrix.M32)), invDet);

            return(true);
        }
Example #5
0
        /// <summary>
        /// Calculates the distance to the nearest edge from the point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <returns>The distance.</returns>
        public T GetDistanceToNearestEdge(Vector3D <T> point)
        {
            var max = Max;
            var dx  = Scalar.Max(Scalar.Max(Scalar.Subtract(Origin.X, point.X), Scalar <T> .Zero), Scalar.Subtract(point.X, max.X));
            var dy  = Scalar.Max(Scalar.Max(Scalar.Subtract(Origin.Y, point.Y), Scalar <T> .Zero), Scalar.Subtract(point.Y, max.Y));
            var dz  = Scalar.Max(Scalar.Max(Scalar.Subtract(Origin.Z, point.Z), Scalar <T> .Zero), Scalar.Subtract(point.Z, max.Z));

            return(Scalar.Sqrt(Scalar.Add(Scalar.Add(Scalar.Multiply(dx, dx), Scalar.Multiply(dy, dy)), Scalar.Multiply(dz, dz))));
        }
Example #6
0
        /// <summary>Linearly interpolates between the corresponding values of two matrices.</summary>
        /// <param name="matrix1">The first source matrix.</param>
        /// <param name="matrix2">The second source matrix.</param>
        /// <param name="amount">The relative weight of the second source matrix.</param>
        /// <returns>The interpolated matrix.</returns>
        public static unsafe Matrix2X2<T> Lerp<T>(Matrix2X2<T> matrix1, Matrix2X2<T> matrix2, T amount) where T : unmanaged, IFormattable, IEquatable<T>, IComparable<T>
        {
            Matrix2X2<T> result = default;

            // First row
            result.M11 = Scalar.Add(matrix1.M11, Scalar.Multiply(Scalar.Subtract(matrix2.M11, matrix1.M11), amount));
            result.M12 = Scalar.Add(matrix1.M12, Scalar.Multiply(Scalar.Subtract(matrix2.M12, matrix1.M12), amount));

            // Second row
            result.M21 = Scalar.Add(matrix1.M21, Scalar.Multiply(Scalar.Subtract(matrix2.M21, matrix1.M21), amount));
            result.M22 = Scalar.Add(matrix1.M22, Scalar.Multiply(Scalar.Subtract(matrix2.M22, matrix1.M22), amount));

            return result;
        }
        /// <summary>Creates a matrix that rotates around an arbitrary vector.</summary>
        /// <param name="axis">The axis to rotate around.</param>
        /// <param name="angle">The angle to rotate around the given axis, in radians.</param>
        /// <returns>The rotation matrix.</returns>
        public static Matrix3X3 <T> CreateFromAxisAngle <T>(Vector3D <T> axis, T angle)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            // a: angle
            // x, y, z: unit vector for axis.
            //
            // Rotation matrix M can compute by using below equation.
            //
            //        T               T
            //  M = uu + (cos a)( I-uu ) + (sin a)S
            //
            // Where:
            //
            //  u = ( x, y, z )
            //
            //      [  0 -z  y ]
            //  S = [  z  0 -x ]
            //      [ -y  x  0 ]
            //
            //      [ 1 0 0 ]
            //  I = [ 0 1 0 ]
            //      [ 0 0 1 ]
            //
            //
            //     [  xx+cosa*(1-xx)   yx-cosa*yx-sina*z zx-cosa*xz+sina*y ]
            // M = [ xy-cosa*yx+sina*z    yy+cosa(1-yy)  yz-cosa*yz-sina*x ]
            //     [ zx-cosa*zx-sina*y zy-cosa*zy+sina*x   zz+cosa*(1-zz)  ]
            //
            T x = axis.X, y = axis.Y, z = axis.Z;
            T sa = Scalar.Sin(angle), ca = Scalar.Cos(angle);
            T xx = Scalar.Multiply(x, x), yy = Scalar.Multiply(y, y), zz = Scalar.Multiply(z, z);
            T xy = Scalar.Multiply(x, y), xz = Scalar.Multiply(x, z), yz = Scalar.Multiply(y, z);

            Matrix3X3 <T> result = Matrix3X3 <T> .Identity;

            result.M11 = Scalar.Add(xx, Scalar.Multiply(ca, Scalar.Subtract(Scalar <T> .One, xx)));
            result.M12 = Scalar.Add(Scalar.Subtract(xy, Scalar.Multiply(ca, xy)), Scalar.Multiply(sa, z));
            result.M13 = Scalar.Subtract(Scalar.Subtract(xz, Scalar.Multiply(ca, xz)), Scalar.Multiply(sa, y));

            result.M21 = Scalar.Subtract(Scalar.Subtract(xy, Scalar.Multiply(ca, xy)), Scalar.Multiply(sa, z));
            result.M22 = Scalar.Add(yy, Scalar.Multiply(ca, Scalar.Subtract(Scalar <T> .One, yy)));
            result.M23 = Scalar.Add(Scalar.Subtract(yz, Scalar.Multiply(ca, yz)), Scalar.Multiply(sa, x));

            result.M31 = Scalar.Add(Scalar.Subtract(xz, Scalar.Multiply(ca, xz)), Scalar.Multiply(sa, y));
            result.M32 = Scalar.Subtract(Scalar.Subtract(yz, Scalar.Multiply(ca, yz)), Scalar.Multiply(sa, x));
            result.M33 = Scalar.Add(zz, Scalar.Multiply(ca, Scalar.Subtract(Scalar <T> .One, zz)));

            return(result);
        }
        /// <summary>Creates a scale matrix that scales uniformly with the given scale with an offset from the given center.</summary>
        /// <param name="scale">The uniform scale to use.</param>
        /// <param name="centerPoint">The center offset.</param>
        /// <returns>A scaling matrix.</returns>
        public static Matrix3X2 <T> CreateScale <T>(T scale, Vector2D <T> centerPoint)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            T tx = Scalar.Multiply(centerPoint.X, Scalar.Subtract(Scalar <T> .One, scale));
            T ty = Scalar.Multiply(centerPoint.Y, Scalar.Subtract(Scalar <T> .One, scale));

            result.M11 = scale;
            result.M22 = scale;
            result.M31 = tx;
            result.M32 = ty;

            return(result);
        }
Example #9
0
        public static Plane <T> Transform <T>(Plane <T> plane, Quaternion <T> rotation)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            // Compute rotation matrix.
            T x2 = Scalar.Add(rotation.X, rotation.X);
            T y2 = Scalar.Add(rotation.Y, rotation.Y);
            T z2 = Scalar.Add(rotation.Z, rotation.Z);

            T wx2 = Scalar.Multiply(rotation.W, x2);
            T wy2 = Scalar.Multiply(rotation.W, y2);
            T wz2 = Scalar.Multiply(rotation.W, z2);
            T xx2 = Scalar.Multiply(rotation.X, x2);
            T xy2 = Scalar.Multiply(rotation.X, y2);
            T xz2 = Scalar.Multiply(rotation.X, z2);
            T yy2 = Scalar.Multiply(rotation.Y, y2);
            T yz2 = Scalar.Multiply(rotation.Y, z2);
            T zz2 = Scalar.Multiply(rotation.Z, z2);

            T m11 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, yy2), zz2);
            T m21 = Scalar.Subtract(xy2, wz2);
            T m31 = Scalar.Add(xz2, wy2);

            T m12 = Scalar.Add(xy2, wz2);
            T m22 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, xx2), zz2);
            T m32 = Scalar.Subtract(yz2, wx2);

            T m13 = Scalar.Subtract(xz2, wy2);
            T m23 = Scalar.Add(yz2, wx2);
            T m33 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, xx2), yy2);

            T x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z;

            return(new(
                       Scalar.Add(Scalar.Add(Scalar.Multiply(x, m11), Scalar.Multiply(y, m21)), Scalar.Multiply(z, m31)),
                       Scalar.Add(Scalar.Add(Scalar.Multiply(x, m12), Scalar.Multiply(y, m22)), Scalar.Multiply(z, m32)),
                       Scalar.Add(Scalar.Add(Scalar.Multiply(x, m13), Scalar.Multiply(y, m23)), Scalar.Multiply(z, m33)),
                       plane.Distance));
        }
Example #10
0
        public static Plane <T> Normalize <T>(Plane <T> value)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            /*if (Vector.IsHardwareAccelerated)
             * {
             *  T normalLengthSquared = value.Normal.LengthSquared();
             *  if (MathF.Abs(normalLengthSquared - 1.0f) < NormalizeEpsilon)
             *  {
             *      // It already normalized, so we don't need to farther process.
             *      return value;
             *  }
             *  T normalLength = MathF.Sqrt(normalLengthSquared);
             *  return new Plane(
             *      value.Normal / normalLength,
             *      value.D / normalLength);
             * }
             * else*/
            {
                T f = Scalar.Add(
                    Scalar.Add(Scalar.Multiply(value.Normal.X, value.Normal.X),
                               Scalar.Multiply(value.Normal.Y, value.Normal.Y)),
                    Scalar.Multiply(value.Normal.Z, value.Normal.Z));

                if (!Scalar.GreaterThanOrEqual(Scalar.Abs(Scalar.Subtract(f, Scalar <T> .One)), Scalar.As <float, T>(NormalizeEpsilon)))
                {
                    return(value); // It already normalized, so we don't need to further process.
                }

                T fInv = Scalar.Reciprocal(Scalar.Sqrt(f));

                return(new(
                           Scalar.Multiply(value.Normal.X, fInv),
                           Scalar.Multiply(value.Normal.Y, fInv),
                           Scalar.Multiply(value.Normal.Z, fInv),
                           Scalar.Multiply(value.Distance, fInv)));
            }
        }
Example #11
0
        /// <summary>Transforms the given matrix by applying the given Quaternion rotation.</summary>
        /// <param name="value">The source matrix to transform.</param>
        /// <param name="rotation">The rotation to apply.</param>
        /// <returns>The transformed matrix.</returns>
        public static Matrix2X3 <T> Transform <T>(Matrix2X3 <T> value, Quaternion <T> rotation)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            // Compute rotation matrix.
            T x2 = Scalar.Add(rotation.X, rotation.X);
            T y2 = Scalar.Add(rotation.Y, rotation.Y);
            T z2 = Scalar.Add(rotation.Z, rotation.Z);

            T wx2 = Scalar.Multiply(rotation.W, x2);
            T wy2 = Scalar.Multiply(rotation.W, y2);
            T wz2 = Scalar.Multiply(rotation.W, z2);
            T xx2 = Scalar.Multiply(rotation.X, x2);
            T xy2 = Scalar.Multiply(rotation.X, y2);
            T xz2 = Scalar.Multiply(rotation.X, z2);
            T yy2 = Scalar.Multiply(rotation.Y, y2);
            T yz2 = Scalar.Multiply(rotation.Y, z2);
            T zz2 = Scalar.Multiply(rotation.Z, z2);

            T q11 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, yy2), zz2);
            T q21 = Scalar.Subtract(xy2, wz2);
            T q31 = Scalar.Add(xz2, wy2);

            T q12 = Scalar.Add(xy2, wz2);
            T q22 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, xx2), zz2);
            T q32 = Scalar.Subtract(yz2, wx2);

            T q13 = Scalar.Subtract(xz2, wy2);
            T q23 = Scalar.Add(yz2, wx2);
            T q33 = Scalar.Subtract(Scalar.Subtract(Scalar <T> .One, xx2), yy2);

            var q1 = new Vector3D <T>(q11, q12, q13);
            var q2 = new Vector3D <T>(q21, q22, q23);
            var q3 = new Vector3D <T>(q31, q32, q33);

            return(new(value.M11 * q1 + value.M12 * q2 + value.M13 * q3, value.M21 *q1 + value.M22 * q2 + value.M23 * q3));
        }
Example #12
0
 /// <summary>
 /// Calculates the squared distance to the nearest edge from the point.
 /// </summary>
 /// <param name="point">The point.</param>
 /// <returns>The distance squared.</returns>
 public T GetDistanceToNearestEdgeSquared(Vector2D <T> point)
 {
     return(Scalar.Subtract(Vector2D.DistanceSquared(Center, point), SquaredRadius));
 }
Example #13
0
        /// <summary>Creates a rotation matrix using the given rotation in radians and a center point.</summary>
        /// <param name="radians">The amount of rotation, in radians.</param>
        /// <param name="centerPoint">The center point.</param>
        /// <returns>A rotation matrix.</returns>
        public static Matrix3X2 <T> CreateRotation <T>(T radians, Vector2D <T> centerPoint)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            radians = Scalar.IEEERemainder(radians, Scalar <T> .Tau);

            T c, s;

            if (Scalar.GreaterThan(radians, Scalar.As <float, T>(-RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(RotationEpsilon)))
            {
                // Exact case for zero rotation.
                c = Scalar <T> .One;
                s = Scalar <T> .Zero;
            }
            else if (Scalar.GreaterThan(radians, Scalar.As <float, T>(
#if MATHF
                                            MathF.PI
#else
                                                ((float)Math.PI)
#endif
                                            / 2 - RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(
#if MATHF
                                                                                                      MathF.PI
#else
                                                                                                          ((float)Math.PI)
#endif
                                                                                                      / 2 + RotationEpsilon)))
            {
                // Exact case for 90 degree rotation.
                c = Scalar <T> .Zero;
                s = Scalar <T> .One;
            }
            else if (!Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(-
#if MATHF
                                                                              MathF.PI
#else
                                                                                  ((float)Math.PI)
#endif
                                                                              + RotationEpsilon)) || Scalar.GreaterThan(radians, Scalar.As <float, T>(
#if MATHF
                                                                                                                            MathF.PI
#else
                                                                                                                                ((float)Math.PI)
#endif
                                                                                                                            - RotationEpsilon)))
            {
                // Exact case for 180 degree rotation.
                c = Scalar <T> .MinusOne;
                s = Scalar <T> .Zero;
            }
            else if (Scalar.GreaterThan(radians, Scalar.As <float, T>(-
#if MATHF
                                                                      MathF.PI
#else
                                                                          ((float)Math.PI)
#endif
                                                                      / 2 - RotationEpsilon)) && !Scalar.GreaterThanOrEqual(radians, Scalar.As <float, T>(-
#if MATHF
                                                                                                                                                          MathF.PI
#else
                                                                                                                                                              ((float)Math.PI)
#endif
                                                                                                                                                          / 2 + RotationEpsilon)))
            {
                // Exact case for 270 degree rotation.
                c = Scalar <T> .Zero;
                s = Scalar <T> .MinusOne;
            }
            else
            {
                // Arbitrary rotation.
                c = Scalar.Cos(radians);
                s = Scalar.Sin(radians);
            }

            T x = Scalar.Add(Scalar.Multiply(centerPoint.X, Scalar.Subtract(Scalar <T> .One, c)), Scalar.Multiply(centerPoint.Y, s));
            T y = Scalar.Subtract(Scalar.Multiply(centerPoint.Y, Scalar.Subtract(Scalar <T> .One, c)), Scalar.Multiply(centerPoint.X, s));

            // [  c  s ]
            // [ -s  c ]
            // [  x  y ]
            return(new(
                       new(c, s),
                       new(Scalar.Negate(s), c),
                       new(x, y)));
        }
Example #14
0
        /// <summary>Attempts to extract the scale, translation, and rotation components from the given scale/rotation/translation matrix.
        /// If successful, the out parameters will contained the extracted values.</summary>
        /// <param name="matrix">The source matrix.</param>
        /// <param name="scale">The scaling component of the transformation matrix.</param>
        /// <param name="rotation">The rotation component of the transformation matrix.</param>
        /// <returns>True if the source matrix was successfully decomposed; False otherwise.</returns>
        public static bool Decompose <T>(Matrix3X3 <T> matrix, out Vector3D <T> scale, out Quaternion <T> rotation)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            bool result = true;

            unsafe
            {
                fixed(Vector3D <T> *scaleBase = &scale)
                {
                    T *pfScales = (T *)scaleBase;
                    T  det;

                    VectorBasis <T> vectorBasis;
                    Vector3D <T> ** pVectorBasis = (Vector3D <T> **) & vectorBasis;

                    Matrix3X3 <T>      matTemp         = Matrix3X3 <T> .Identity;
                    CanonicalBasis <T> canonicalBasis  = default;
                    Vector3D <T> *     pCanonicalBasis = &canonicalBasis.Row0;

                    canonicalBasis.Row0 = new Vector3D <T>(Scalar <T> .One, Scalar <T> .Zero, Scalar <T> .Zero);
                    canonicalBasis.Row1 = new Vector3D <T>(Scalar <T> .Zero, Scalar <T> .One, Scalar <T> .Zero);
                    canonicalBasis.Row2 = new Vector3D <T>(Scalar <T> .Zero, Scalar <T> .Zero, Scalar <T> .One);

                    pVectorBasis[0] = &matTemp.Row1;
                    pVectorBasis[1] = &matTemp.Row2;
                    pVectorBasis[2] = &matTemp.Row3;

                    *(pVectorBasis[0]) = new Vector3D <T>(matrix.M11, matrix.M12, matrix.M13);
                    *(pVectorBasis[1]) = new Vector3D <T>(matrix.M21, matrix.M22, matrix.M23);
                    *(pVectorBasis[2]) = new Vector3D <T>(matrix.M31, matrix.M32, matrix.M33);

                    scale.X = pVectorBasis[0]->Length;
                    scale.Y = pVectorBasis[1]->Length;
                    scale.Z = pVectorBasis[2]->Length;

                    uint a, b, c;

                    #region Ranking
                    T x = pfScales[0], y = pfScales[1], z = pfScales[2];
                    if (!Scalar.GreaterThanOrEqual(x, y))
                    {
                        if (!Scalar.GreaterThanOrEqual(y, z))
                        {
                            a = 2;
                            b = 1;
                            c = 0;
                        }
                        else
                        {
                            a = 1;

                            if (!Scalar.GreaterThanOrEqual(x, z))
                            {
                                b = 2;
                                c = 0;
                            }
                            else
                            {
                                b = 0;
                                c = 2;
                            }
                        }
                    }
                    else
                    {
                        if (!Scalar.GreaterThanOrEqual(x, z))
                        {
                            a = 2;
                            b = 0;
                            c = 1;
                        }
                        else
                        {
                            a = 0;

                            if (!Scalar.GreaterThanOrEqual(y, z))
                            {
                                b = 2;
                                c = 1;
                            }
                            else
                            {
                                b = 1;
                                c = 2;
                            }
                        }
                    }
                    #endregion

                    if (!Scalar.GreaterThanOrEqual(pfScales[a], Scalar.As <float, T>(DecomposeEpsilon)))
                    {
                        *(pVectorBasis[a]) = pCanonicalBasis[a];
                    }

                    *pVectorBasis[a] = Vector3D.Normalize(*pVectorBasis[a]);

                    if (!Scalar.GreaterThanOrEqual(pfScales[b], Scalar.As <float, T>(DecomposeEpsilon)))
                    {
                        uint cc;
                        T    fAbsX, fAbsY, fAbsZ;

                        fAbsX = Scalar.Abs(pVectorBasis[a]->X);
                        fAbsY = Scalar.Abs(pVectorBasis[a]->Y);
                        fAbsZ = Scalar.Abs(pVectorBasis[a]->Z);

                        #region Ranking
                        if (!Scalar.GreaterThanOrEqual(fAbsX, fAbsY))
                        {
                            if (!Scalar.GreaterThanOrEqual(fAbsY, fAbsZ))
                            {
                                cc = 0;
                            }
                            else
                            {
                                if (!Scalar.GreaterThanOrEqual(fAbsX, fAbsZ))
                                {
                                    cc = 0;
                                }
                                else
                                {
                                    cc = 2;
                                }
                            }
                        }
                        else
                        {
                            if (!Scalar.GreaterThanOrEqual(fAbsX, fAbsZ))
                            {
                                cc = 1;
                            }
                            else
                            {
                                if (!Scalar.GreaterThanOrEqual(fAbsY, fAbsZ))
                                {
                                    cc = 1;
                                }
                                else
                                {
                                    cc = 2;
                                }
                            }
                        }
                        #endregion

                        *pVectorBasis[b] = Vector3D.Cross(*pVectorBasis[a], *(pCanonicalBasis + cc));
                    }

                    *pVectorBasis[b] = Vector3D.Normalize(*pVectorBasis[b]);

                    if (!Scalar.GreaterThanOrEqual(pfScales[c], Scalar.As <float, T>(DecomposeEpsilon)))
                    {
                        *pVectorBasis[c] = Vector3D.Cross(*pVectorBasis[a], *pVectorBasis[b]);
                    }

                    *pVectorBasis[c] = Vector3D.Normalize(*pVectorBasis[c]);

                    det = matTemp.GetDeterminant();

                    // use Kramer's rule to check for handedness of coordinate system
                    if (!Scalar.GreaterThanOrEqual(det, Scalar <T> .Zero))
                    {
                        // switch coordinate system by negating the scale and inverting the basis vector on the x-axis
                        pfScales[a] = Scalar.Negate(pfScales[a]);
                        *pVectorBasis[a] = -(*pVectorBasis[a]);

                        det = Scalar.Negate(det);
                    }

                    det = Scalar.Subtract(det, Scalar <T> .One);
                    det = Scalar.Multiply(det, det);

                    if (!Scalar.GreaterThanOrEqual(Scalar.As <float, T>(DecomposeEpsilon), det))
                    {
                        // Non-SRT matrix encountered
                        rotation = Quaternion <T> .Identity;
                        result   = false;
                    }
                    else
                    {
                        // generate the quaternion from the matrix
                        rotation = Quaternion <T> .CreateFromRotationMatrix(matTemp);
                    }
                }
            }

            return(result);
        }