예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <summary>Creates a matrix for rotating points around the Z-axis.</summary>
        /// <param name="radians">The amount, in radians, by which to rotate around the Z-axis.</param>
        /// <returns>The rotation matrix.</returns>
        public static Matrix3X3 <T> CreateRotationZ <T>(T radians)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X3 <T> result = Matrix3X3 <T> .Identity;

            T c = Scalar.Cos(radians);
            T s = Scalar.Sin(radians);

            // [  c  s  0  0 ]
            // [ -s  c  0  0 ]
            // [  0  0  1  0 ]
            // [  0  0  0  1 ]
            result.M11 = c;
            result.M12 = s;
            result.M21 = Scalar.Negate(s);
            result.M22 = c;

            return(result);
        }
예제 #3
0
        /// <summary>Creates a matrix for rotating points around the Y-axis.</summary>
        /// <param name="radians">The amount, in radians, by which to rotate around the Y-axis.</param>
        /// <returns>The rotation matrix.</returns>
        public static Matrix3X3 <T> CreateRotationY <T>(T radians)
            where T : unmanaged, IFormattable, IEquatable <T>, IComparable <T>
        {
            Matrix3X3 <T> result = Matrix3X3 <T> .Identity;

            T c = Scalar.Cos(radians);
            T s = Scalar.Sin(radians);

            // [  c  0 -s  0 ]
            // [  0  1  0  0 ]
            // [  s  0  c  0 ]
            // [  0  0  0  1 ]
            result.M11 = c;
            result.M13 = Scalar.Negate(s);
            result.M31 = s;
            result.M33 = c;

            return(result);
        }
예제 #4
0
        /// <summary>Creates a rotation matrix using the given rotation in radians.</summary>
        /// <param name="radians">The amount of rotation, in radians.</param>
        /// <returns>A rotation matrix.</returns>
        public static Matrix3X2 <T> CreateRotation <T>(T radians)
            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);
            }

            // [  c  s ]
            // [ -s  c ]
            // [  0  0 ]
            Matrix3X2 <T> result = Matrix3X2 <T> .Identity;

            result.M11 = c;
            result.M12 = s;
            result.M21 = Scalar.Negate(s);
            result.M22 = c;

            return(result);
        }
예제 #5
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)));
        }