Пример #1
0
        /// <summary>
        /// L2 norm of matrix column elemnts including start and excluding end.
        /// </summary>
        private static double ColNorm2(
            this double[] matrix, long m0, long mx, long my, long col, long start, long end)
        {
            m0 += col * mx;
            var norm = 0.0;

            for (long mi = m0 + start * my, me = m0 + end * my; mi != me; mi += my)
            {
                norm += matrix[mi] * matrix[mi];
            }
            return(Fun.Sqrt(norm));
        }
Пример #2
0
        /// <summary>
        /// L2 norm of matrix row elemnts including start and excluding end.
        /// </summary>
        private static double RowNorm2(
            this double[] matrix, long m0, long mx, long my, long row, long start, long end)
        {
            m0 += row * my;
            var norm = 0.0;

            for (long mi = m0 + start * mx, me = m0 + end * mx; mi != me; mi += mx)
            {
                norm += matrix[mi] * matrix[mi];
            }
            return(Fun.Sqrt(norm));
        }
Пример #3
0
        /// <summary>
        /// Creates a quaternion from a rotation matrix
        /// </summary>
        /// <param name="m"></param>
        /// <param name="epsilon"></param>
        public static __rot3t__ From__m33t__(__m33t__ m, __ft__ epsilon = (__ft__)1e-6)
        {
            if (!m.IsOrthonormal(epsilon))
            {
                throw new ArgumentException("Matrix is not orthonormal.");
            }
            var t = 1 + m.M00 + m.M11 + m.M22;

            if (t > epsilon)
            {
                __ft__ s = t.Sqrt() * 2;
                __ft__ x = (m.M21 - m.M12) / s;
                __ft__ y = (m.M02 - m.M20) / s;
                __ft__ z = (m.M10 - m.M01) / s;
                __ft__ w = s / 4;
                return(new __rot3t__(w, x, y, z).Normalized);
            }
            else
            {
                if (m.M00 > m.M11 && m.M00 > m.M22)
                {
                    __ft__ s = Fun.Sqrt(1 + m.M00 - m.M11 - m.M22) * 2;
                    __ft__ x = s / 4;
                    __ft__ y = (m.M01 + m.M10) / s;
                    __ft__ z = (m.M02 + m.M20) / s;
                    __ft__ w = (m.M21 - m.M12) / s;
                    return(new __rot3t__(w, x, y, z).Normalized);
                }
                else if (m.M11 > m.M22)
                {
                    __ft__ s = Fun.Sqrt(1 + m.M11 - m.M00 - m.M22) * 2;
                    __ft__ x = (m.M01 + m.M10) / s;
                    __ft__ y = s / 4;
                    __ft__ z = (m.M12 + m.M21) / s;
                    __ft__ w = (m.M20 - m.M02) / s;
                    return(new __rot3t__(w, x, y, z).Normalized);
                }
                else
                {
                    __ft__ s = Fun.Sqrt(1 + m.M22 - m.M00 - m.M11) * 2;
                    __ft__ x = (m.M20 + m.M02) / s;
                    __ft__ y = (m.M12 + m.M21) / s;
                    __ft__ z = s / 4;
                    __ft__ w = (m.M01 - m.M10) / s;
                    return(new __rot3t__(w, x, y, z).Normalized);
                }
            }
        }
Пример #4
0
        public static List <int[]> ComputeNonConcaveSubPolygons(
            this Polygon3d polygon, double absoluteEpsilon)
        {
            V3d    normal = polygon.ComputeDoubleAreaNormal();
            double len2   = normal.LengthSquared;

            if (len2 < absoluteEpsilon * absoluteEpsilon)
            {
                return(new int[polygon.PointCount].SetByIndex(i => i).IntoList());
            }

            M44d.NormalFrame(V3d.Zero, normal * (1.0 / Fun.Sqrt(len2)), out M44d local2global, out M44d global2local);
            var polygon2d = polygon.ToPolygon2d(p => global2local.TransformPos(p).XY);

            return(polygon2d.ComputeNonConcaveSubPolygons(absoluteEpsilon));
        }
Пример #5
0
        /// <summary>
        /// Create from Rodrigues axis-angle vactor
        /// </summary>
        public static __rot3t__ FromAngleAxis(__v3t__ angleAxis)
        {
            __ft__ theta2 = angleAxis.LengthSquared;

            if (theta2 > Constant <__ft__> .PositiveTinyValue)
            {
                var theta     = Fun.Sqrt(theta2);
                var thetaHalf = theta / 2;
                var k         = Fun.Sin(thetaHalf) / theta;
                return(new __rot3t__(Fun.Cos(thetaHalf), k * angleAxis));
            }
            else
            {
                return(new __rot3t__(1, 0, 0, 0));
            }
        }
Пример #6
0
        /// <summary>
        /// Returns the Rodrigues angle-axis vector of the quaternion.
        /// </summary>
        public __v3t__ ToAngleAxis()
        {
            var sinTheta2 = V.LengthSquared;

            if (sinTheta2 > Constant <__ft__> .PositiveTinyValue)
            {
                __ft__ sinTheta = Fun.Sqrt(sinTheta2);
                __ft__ cosTheta = W;
                __ft__ twoTheta = 2 * (cosTheta < 0 ? Fun.Atan2(-sinTheta, -cosTheta)
                                                    : Fun.Atan2(sinTheta, cosTheta));
                return(V * (twoTheta / sinTheta));
            }
            else
            {
                return(__v3t__.Zero);
            }
        }
Пример #7
0
        public static bool IsTrueFor(long value)
        {
            if (value < 0)
            {
                return(false);
            }
            if (value < isPrimeArray.Length)
            {
                return(isPrimeArray[value]);
            }

            int root           = (int)Fun.Sqrt(value);
            int directMaxPrime = Fun.Min(primeArray[primeCount - 1], root);
            int pi;

            for (pi = 0; primeArray[pi] <= directMaxPrime; pi++)
            {
                if (value % primeArray[pi] == 0)
                {
                    return(false);
                }
            }

            if (directMaxPrime == root)
            {
                return(true);
            }

            while (true)
            {
                int p = Prime.WithIndex(pi);
                if (p > root)
                {
                    break;
                }
                if (value % p == 0)
                {
                    return(false);
                }
                pi++;
            }
            return(true);
        }
Пример #8
0
        /// <summary>
        /// Return real roots of: x^4 + c3 x^3 + c2 x^2 + c1 x + c0 = 0.
        /// Double and triple solutions are returned as replicated values.
        /// Imaginary and non existing solutions are returned as NaNs.
        /// </summary>
        public static Quad <double> RealRootsOfNormed(
            double c3, double c2, double c1, double c0)
        {
            // eliminate cubic term (x = y - c3/4):  x^4 + p x^2 + q x + r = 0
            double e = c3 * c3;
            double p = -3 / 8.0 * e + c2;
            double q = (1 / 8.0 * e - 1 / 2.0 * c2) * c3 + c1;
            double r = (1 / 16.0 * c2 - 3 / 256.0 * e) * e - 1 / 4.0 * c3 * c1 + c0;

            if (Fun.IsTiny(r)) // ---- no absolute term: y (y^3 + p y + q) = 0
            {
                return(MergeSortedAndShift(
                           RealRootsOfDepressed(p, q), 0.0, -1 / 4.0 * c3));
            }
            // ----------------------- take one root of the resolvent cubic...
            double z = OneRealRootOfNormed(
                -1 / 2.0 * p, -r, 1 / 2.0 * r * p - 1 / 8.0 * q * q);
            // --------------------------- ...to build two quadratic equations
            double u = z * z - r;
            double v = 2.0 * z - p;

            if (u < Constant <double> .PositiveTinyValue) // +tiny instead of 0
            {
                u = 0.0;                                  // improves unique
            }
            else                                          // root accuracy by a
            {
                u = Fun.Sqrt(u);                          // factor of 10^5!
            }
            if (v < Constant <double> .PositiveTinyValue) // values greater than
            {
                v = 0.0;                                  // +tiny == 4 * eps
            }
            else                                          // do not seem to
            {
                v = Fun.Sqrt(v);                          // improve accuraccy!
            }
            double q1 = q < 0 ? -v : v;

            return(MergeSortedAndShift(RealRootsOfNormed(q1, z - u),
                                       RealRootsOfNormed(-q1, z + u),
                                       -1 / 4.0 * c3));
        }
Пример #9
0
        /// <summary>
        /// One real root of the equation: x^3 + c2 x^2 + c1 x + c0 = 0.
        /// </summary>
        public static double OneRealRootOfNormed(
            double c2, double c1, double c0
            )
        {
            // ------ eliminate quadric term (x = y - c2/3): x^3 + p x + q = 0
            double d   = c2 * c2;
            double p3  = 1 / 3.0 * /* p */ (-1 / 3.0 * d + c1);
            double q2  = 1 / 2.0 * /* q */ ((2 / 27.0 * d - 1 / 3.0 * c1) * c2 + c0);
            double p3c = p3 * p3 * p3;

            d = q2 * q2 + p3c;
            if (d < 0) // -------------- casus irreducibilis: three real roots
            {
                return(2 * Fun.Sqrt(-p3) * Fun.Cos(1 / 3.0
                                                   * Fun.Acos(-q2 / Fun.Sqrt(-p3c))) - 1 / 3.0 * c2);
            }
            d = Fun.Sqrt(d);  // one triple root or a single and a double root
            return(Fun.Cbrt(d - q2) - Fun.Cbrt(d + q2) - 1 / 3.0 * c2);
        }
Пример #10
0
        /// <summary>
        /// Return real roots of the equation x^2 + px + q = 0.
        /// Double roots are returned as a pair of identical values.
        /// If no real roots exists, then both entries are NaN.
        /// </summary>
        public static Pair <double> RealRootsOfNormed(double p, double q)
        {
            double p2 = p / 2.0;
            double d  = p2 * p2 - q;

            if (d < 0)
            {
                return(Pair.Create(double.NaN, double.NaN));
            }
            if (p2 > 0.0)                                              // prevent cancellation
            {
                double r = -(p2 + Fun.Sqrt(d));
                return(Pair.Create(r, q / r));
            }
            else
            {
                double r = Fun.Sqrt(d) - p2;
                return(Pair.Create(q / r, r));
            }
        }
Пример #11
0
 public void ReportValue(int verbosity, string name)
 {
     using (Report.Job(verbosity, name))
     {
         if ((m_options & StatsOptions.Count) != 0)
         {
             Report.Value(verbosity, "count", Count);
         }
         if ((m_options & StatsOptions.Sum) != 0)
         {
             Report.Value(verbosity, "sum", Sum);
         }
         if ((m_options & StatsOptions.Min) != 0)
         {
             Report.Value(verbosity, "minimum", Min);
         }
         if ((m_options & StatsOptions.Max) != 0)
         {
             Report.Value(verbosity, "maximum", Max);
         }
         if ((m_options & StatsOptions.Mean) != 0)
         {
             Report.Value(verbosity, "mean", Mean);
         }
         if ((m_options & StatsOptions.NeedsSumOfSquares) != 0)
         {
             double variance = Variance;
             if ((m_options & StatsOptions.Variance) != 0)
             {
                 Report.Value(verbosity, "variance", variance);
             }
             if ((m_options & StatsOptions.Variance) != 0)
             {
                 Report.Value(verbosity, "standard deviation", Fun.Sqrt(variance));
             }
         }
     }
 }
Пример #12
0
        /// <summary>
        /// Return real roots of the equation: x^3 + p x + q = 0
        /// Double and triple solutions are returned as replicated values.
        /// Imaginary and non existing solutions are returned as NaNs.
        /// </summary>
        public static Triple <double> RealRootsOfDepressed(
            double p, double q)
        {
            double p3 = 1 / 3.0 * p, q2 = 1 / 2.0 * q;
            double p3c = p3 * p3 * p3, d = q2 * q2 + p3c;

            if (d < 0) // ---------- casus irreducibilis: three real solutions
            {
                double phi = 1 / 3.0 * Fun.Acos(-q2 / Fun.Sqrt(-p3c));
                double t   = 2 * Fun.Sqrt(-p3);
                double r0  = t * Fun.Cos(phi);
                double r1  = -t *Fun.Cos(phi + Constant.Pi / 3.0);

                double r2 = -t *Fun.Cos(phi - Constant.Pi / 3.0);

                return(Triple.CreateAscending(r0, r1, r2));
            }
            d = Fun.Sqrt(d);  // one triple root or a single and a double root
            double s0 = Fun.Cbrt(d - q2) - Fun.Cbrt(d + q2);
            double s1 = -0.5 * s0;

            return(s0 < s1?Triple.Create(s0, s1, s1)
                       : Triple.Create(s1, s1, s0));
        }
Пример #13
0
 /// <summary>
 /// Returns the Euclidean (or 2-) distance between two matrices.
 /// </summary>
 public static __ctype__ Distance2(__nmtype__ a, __nmtype__ b)
 {
     return /*# if (ctype != "double") {*/ ((__ctype__)/*# } */ Fun.Sqrt(/*# n.ForEach(i => { m.ForEach(j => { */
                                                Fun.Square(b.M__i____j__ - a.M__i____j__) /*# }, add); }, add); */));
 }
Пример #14
0
 public static float Dist2(this Vector <float> v0, Vector <float> v1)
 => Fun.Sqrt(v0.Dist2Squared(v1));
Пример #15
0
 public static double Dist2(this Vector <double> v0, Vector <double> v1)
 => Fun.Sqrt(v0.Dist2Squared(v1));
 public static __ft__ Dist2(this Vector <__ft__> v0, Vector <__ft__> v1)
 => Fun.Sqrt(v0.Dist2Squared(v1));
Пример #17
0
        public bool HitsCylinder(Cylinder3d cylinder,
                                 double tmin, double tmax,
                                 ref RayHit3d hit)
        {
            var axisDir = cylinder.Axis.Direction.Normalized;

            // Vector Cyl.P0 -> Ray.Origin
            var op = Origin - cylinder.P0;

            // normal RayDirection - CylinderAxis
            var normal     = Direction.Cross(axisDir);
            var unitNormal = normal.Normalized;

            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis
            var normal2 = op.Cross(axisDir);
            var t       = -normal2.Dot(unitNormal) / normal.Length;

            var radius = cylinder.Radius;

            if (cylinder.DistanceScale != 0)
            {   // cylinder gets bigger, the further away it is
                var pnt = GetPointOnRay(t);

                var dis = V3d.Distance(pnt, this.Origin);
                radius = ((cylinder.Radius / cylinder.DistanceScale) * dis) * 2;
            }

            // between enitre rays (caps are ignored)
            var shortestDistance = Fun.Abs(op.Dot(unitNormal));

            if (shortestDistance <= radius)
            {
                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);

                var t1 = t - s; // first hit of Cylinder shell
                var t2 = t + s; // second hit of Cylinder shell

                if (t1 > tmin && t1 < tmax)
                {
                    tmin = t1;
                }
                if (t2 < tmax && t2 > tmin)
                {
                    tmax = t2;
                }

                hit.T     = t1;
                hit.Point = GetPointOnRay(t1);

                // check if found point is outside of Cylinder Caps
                var bottomPlane  = new Plane3d(cylinder.Circle0.Normal, cylinder.Circle0.Center);
                var topPlane     = new Plane3d(cylinder.Circle1.Normal, cylinder.Circle1.Center);
                var heightBottom = bottomPlane.Height(hit.Point);
                var heightTop    = topPlane.Height(hit.Point);
                // t1 lies outside of caps => find closest cap hit
                if (heightBottom > 0 || heightTop > 0)
                {
                    hit.T = tmax;
                    // intersect with bottom Cylinder Cap
                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);
                    // intersect with top Cylinder Cap
                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);

                    // hit still close enough to cylinder axis?
                    var distance = cylinder.Axis.Ray3d.GetMinimalDistanceTo(hit.Point);

                    if (distance <= radius && (bottomHit || topHit))
                    {
                        return(true);
                    }
                }
                else
                {
                    return(true);
                }
            }

            hit.T     = tmax;
            hit.Point = V3d.NaN;
            return(false);
        }