public static V3f Original(Rot3f r)
            {
                var test = r.W * r.Y - r.X * r.Z;

                if (test > 0.5f - Constant <float> .PositiveTinyValue) // singularity at north pole
                {
                    return(new V3f(
                               2 * Fun.Atan2(r.X, r.W),
                               (float)Constant.PiHalf,
                               0));
                }
                if (test < -0.5f + Constant <float> .PositiveTinyValue) // singularity at south pole
                {
                    return(new V3f(
                               2 * Fun.Atan2(r.X, r.W),
                               -(float)Constant.PiHalf,
                               0));
                }
                // From Wikipedia, conversion between quaternions and Euler angles.
                return(new V3f(
                           Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),
                                     1 - 2 * (r.X * r.X + r.Y * r.Y)),
                           Fun.AsinClamped(2 * test),
                           Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),
                                     1 - 2 * (r.Y * r.Y + r.Z * r.Z))));
            }
示例#2
0
        public static void FromInto()
        {
            TrafoTesting.GenericTest(rnd =>
            {
                var dir   = rnd.UniformV3d().Normalized;
                var rotId = Rot3d.RotateInto(dir, dir);
                var matId = (M33d)rotId;

                Assert.IsTrue(matId.IsIdentity(0));

                var rot    = Rot3d.RotateInto(dir, -dir);
                var invDir = rot.Transform(dir);

                Assert.IsTrue(invDir.ApproximateEquals(-dir, 1e-14));

                var dirF   = rnd.UniformV3f().Normalized;
                var rotIdF = Rot3f.RotateInto(dirF, dirF);
                var matIdF = (M33f)rotIdF;

                Assert.IsTrue(matIdF.IsIdentity(0));

                var rotF    = Rot3f.RotateInto(dirF, -dirF);
                var invDirF = rotF.Transform(dirF);

                Assert.IsTrue(invDirF.ApproximateEquals(-dirF, 1e-6f));
            });
        }
示例#3
0
        /// <summary>
        /// Spherical linear interpolation.
        ///
        /// Assumes q1 and q2 are normalized and that t in [0,1].
        ///
        /// This method does interpolate along the shortest arc
        /// between q1 and q2.
        /// </summary>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <param name="t">[0,1]</param>
        /// <returns>Interpolant</returns>
        public static Rot3f SlerpShortest(
            Rot3f q1, Rot3f q2, double t
            )
        {
            Rot3f q3       = q2;
            float cosomega = Fun.Clamp(Rot3f.Dot(q1, q3), -1, 1);

            if (cosomega < 0.0)
            {
                cosomega = -cosomega;
                q3      *= -1; //q3 = -q3;
            }

            if (cosomega >= 1.0)
            {
                // Special case: q1 and q2 are the same, so just return one of them.
                // This also catches the case where cosomega is very slightly > 1.0

                return(q1);
            }

            double sinomega = System.Math.Sqrt(1 - cosomega * cosomega);

            Rot3f result = new Rot3f();

            if (sinomega * double.MaxValue > 1)
            {
                double omega = System.Math.Acos(cosomega);
                float  s1    = (float)(System.Math.Sin((1.0 - t) * omega) / sinomega);
                float  s2    = (float)(System.Math.Sin(t * omega) / sinomega);

                result = s1 * q1 + s2 * q3;
            }
            else if (cosomega > 0)
            {
                // omega == 0

                float s1 = 1.0f - (float)t;
                float s2 = (float)t;

                result = s1 * q1 + s2 * q3;
            }
            else
            {
                // omega == -pi

                result.X = -q1.Y;
                result.Y = q1.X;
                result.Z = -q1.W;
                result.W = q1.Z;

                float s1 = (float)System.Math.Sin((0.5 - t) * System.Math.PI);
                float s2 = (float)System.Math.Sin(t * System.Math.PI);

                result = s1 * q1 + s2 * result;
            }

            return(result);
        }
示例#4
0
 /// <summary>
 /// Multiplies 2 Similarity transformations.
 /// This concatenates the two similarity transformations into a single one, first b is applied, then a.
 /// Attention: Multiplication is NOT commutative!
 /// </summary>
 public static Similarity3f Multiply(Similarity3f a, Similarity3f b)
 {
     //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans
     return(new Similarity3f(a.Scale * b.Scale, new Euclidean3f(
                                 Rot3f.Multiply(a.Rot, b.Rot),
                                 a.Trans + a.Rot.TransformDir(a.Scale * b.Trans))
                             ));
 }
示例#5
0
        public static void RotIntoCornerCase()
        {
            TrafoTesting.GenericTest(rnd =>
            {
                // some vectors will not normalize to 1.0 -> provoke numerical issues in Rot3d
                var vecd  = new V3d(0, 0, -rnd.UniformDouble());
                var rotd  = Rot3d.RotateInto(V3d.OOI, vecd.Normalized);
                var testd = rotd.Transform(V3d.OOI);
                Assert.True((testd + V3d.OOI).Length < 1e-8);

                var vecf  = new V3f(0, 0, -rnd.UniformDouble());
                var rotf  = Rot3f.RotateInto(V3f.OOI, vecf.Normalized);
                var testf = rotf.Transform(V3f.OOI);
                Assert.True((testf + V3f.OOI).Length < 1e-5);
            });
        }
示例#6
0
        public void TrafoRotIntoCornerCase()
        {
            var rnd = new Random();

            for (int i = 0; i < 1000; i++)
            {
                // some vectors will not normalize to 1.0 -> provoke numerical issues in Rot3d
                var vecd  = new V3d(0, 0, -rnd.NextDouble());
                var rotd  = new Rot3d(V3d.OOI, vecd);
                var testd = rotd.TransformDir(V3d.OOI);
                Assert.True((testd + V3d.OOI).Length < 1e-7);

                var vecf  = new V3f(0, 0, -rnd.NextDouble());
                var rotf  = new Rot3f(V3f.OOI, vecf);
                var testf = rotf.TransformDir(V3f.OOI);
                Assert.True((testf + V3f.OOI).Length < 1e-3);
            }
        }
            public static Rot3f Original(V3f from, V3f into)
            {
                var angle = from.AngleBetween(into);

                if (angle < 1e-6f)
                {
                    return(Rot3f.Identity);
                }
                else if (Constant.PiF - angle < 1e-6f)
                {
                    return(new Rot3f(0, from.AxisAlignedNormal()));
                }
                else
                {
                    V3f axis = Vec.Cross(from, into).Normalized;
                    return(Rot3f.Rotation(axis, angle));
                }
            }
示例#8
0
        public static void FromIntoEpislon()
        {
            TrafoTesting.GenericTest((rnd, i) =>
            {
                var dir   = rnd.UniformV3d().Normalized;
                var eps   = rnd.UniformV3d() * (i / 100) * 1e-22;
                var rotId = Rot3d.RotateInto(dir, (dir + eps).Normalized);
                var matId = (M33d)rotId;

                Assert.IsTrue(matId.IsIdentity(1e-10));

                var dirF   = rnd.UniformV3f().Normalized;
                var epsF   = rnd.UniformV3f() * (i / 100) * 1e-12f;
                var rotIdF = Rot3f.RotateInto(dirF, (dirF + epsF).Normalized);
                var matIdF = (M33f)rotIdF;

                Assert.IsTrue(matIdF.IsIdentity(1e-7f));
            });
        }
            public static V3f CopySign(Rot3f r)
            {
                var test = r.W * r.Y - r.X * r.Z;

                if (test.Abs() >= 0.5f - Constant <float> .PositiveTinyValue)
                {
                    return(new V3f(
                               2 * Fun.Atan2(r.X, r.W),
                               Fun.CopySign((float)Constant.PiHalf, test),
                               0));
                }
                else
                {
                    return(new V3f(
                               Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),
                                         1 - 2 * (r.X * r.X + r.Y * r.Y)),
                               Fun.AsinClamped(2 * test),
                               Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),
                                         1 - 2 * (r.Y * r.Y + r.Z * r.Z))));
                }
            }
示例#10
0
        public DistanceRot3f()
        {
            var rnd = new RandomSystem(1);

            A.SetByIndex(i => RndRot(rnd));
            angles.SetByIndex(i =>
            {
                float a = 0;
                do
                {
                    a = RndAngle(rnd);
                }while (a == 0);

                return(a);
            });

            B.SetByIndex(i =>
            {
                var r = Rot3f.Rotation(RndAxis(rnd), angles[i]);
                return(r * A[i]);
            });
        }
示例#11
0
 /// <summary>
 /// Creates a rigid transformation from a rotation matrix <paramref name="rot"/> and a (subsequent) translation <paramref name="trans"/>.
 /// </summary>
 public Euclidean3f(M33f rot, V3f trans, float epsilon = 1e-5f)
 {
     Rot   = Rot3f.FromM33f(rot, epsilon);
     Trans = trans;
 }
示例#12
0
 public static M33f Multiply(Scale3f scale, Rot3f rot)
 {
     return(Scale3f.Multiply(scale, (M33f)rot));
 }
示例#13
0
 /// <summary>
 /// Creates rotational matrix from quaternion.
 /// </summary>
 /// <returns>Rotational matrix.</returns>
 public static M44f Rotation(Rot3f r)
 {
     return((M44f)r);
 }
示例#14
0
 private static Rot3f RndRot(RandomSystem rnd)
 => Rot3f.Rotation(RndAxis(rnd), RndAngle(rnd));
示例#15
0
 public static M34f Rotation(Rot3f q)
 {
     return((M34f)q);
 }
示例#16
0
 public void Write(Rot3f t)
 {
     Write(t.W); Write(t.V);
 }
示例#17
0
 /// <summary>
 /// Multiplies 2 Euclidean transformations.
 /// This concatenates the two rigid transformations into a single one, first b is applied, then a.
 /// Attention: Multiplication is NOT commutative!
 /// </summary>
 public static Euclidean3f Multiply(Euclidean3f a, Euclidean3f b)
 {
     //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans
     return(new Euclidean3f(Rot3f.Multiply(a.Rot, b.Rot), a.Trans + a.Rot.TransformDir(b.Trans)));
 }
示例#18
0
        public static Euclidean3f Parse(string s)
        {
            var x = s.NestedBracketSplitLevelOne().ToArray();

            return(new Euclidean3f(Rot3f.Parse(x[0]), V3f.Parse(x[1])));
        }
示例#19
0
 public static M33f Multiply(Rot2f rot2, Rot3f rot3)
 {
     return(Rot2f.Multiply(rot2, (M33f)rot3));
 }
示例#20
0
 /// <summary>
 /// Creates a rigid transformation from a rotation <paramref name="rot"/> and a (subsequent) translation <paramref name="trans"/>.
 /// </summary>
 public Euclidean3f(Rot3f rot, V3f trans)
 {
     Rot   = rot;
     Trans = trans;
 }
示例#21
0
 public static bool ApproxEqual(Euclidean3f r0, Euclidean3f r1, float angleTol, float posTol)
 {
     return(V3f.ApproxEqual(r0.Trans, r1.Trans, posTol) && Rot3f.ApproxEqual(r0.Rot, r1.Rot, angleTol));
 }