예제 #1
0
            // returns distance, 1e20 if nohit
            public double intersect(ref Ray r)
            {
                // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0
                Vec    op  = p.Sub(ref r.o);
                double b   = op.Dot(ref r.d);
                double det = b * b - op.Dot(ref op) + sqRad;
                double eps = 1e-4;

                if (det < 0)
                {
                    return(1e20);
                }
                else
                {
                    double dets = MathSqrt(det);

                    if (b - dets > eps)
                    {
                        return(b - dets);
                    }
                    else if (b + dets > eps)
                    {
                        return(b + dets);
                    }
                    else
                    {
                        return(1e20);
                    }
                }
            }
예제 #2
0
        /// <summary>
        /// Construct ellipse from two conjugate diameters, and set
        /// Axis0 to the major axis and Axis1 to the minor axis.
        /// The algorithm was constructed from first principles.
        /// Also computes the squared lengths of the major and minor
        /// half axis.
        /// </summary>
        public static __et__ FromConjugateDiameters(__vt__ center, /*# if (d == 3) { */ __vt__ normal, /*# } */ __vt__ a, __vt__ b,
                                                    out double major2, out double minor2)
        {
            var    ab = Vec.Dot(a, b);
            double a2 = a.LengthSquared, b2 = b.LengthSquared;

            if (ab.IsTiny())
            {
                if (a2 >= b2)
                {
                    major2 = a2; minor2 = b2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ a, b));
                }
                else
                {
                    major2 = b2; minor2 = a2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ b, a));
                }
            }
            else
            {
                var    t = 0.5 * Fun.Atan2(2 * ab, a2 - b2);
                double ct = Fun.Cos(t), st = Fun.Sin(t);
                __vt__ v0 = a * ct + b * st, v1 = b * ct - a * st;
                a2 = v0.LengthSquared; b2 = v1.LengthSquared;
                if (a2 >= b2)
                {
                    major2 = a2; minor2 = b2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ v0, v1));
                }
                else
                {
                    major2 = b2; minor2 = a2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ v1, v0));
                }
            }
        }
예제 #3
0
파일: VecTests.cs 프로젝트: lanicon/Macad3D
        public void Dot()
        {
            var p1 = new Vec(1, 2, 3);

            Assert.AreEqual(14, p1.Dot(new Vec(1, 2, 3)));
            Assert.AreEqual(0, p1.DotCross(new Vec(4, 5, 6), new Vec(4, 5, 6)));
        }
예제 #4
0
        /// <summary>
        /// Enumerates all vertex indexes at which
        /// both outgoing edges meet at an angle that
        /// is less than the given threshold.
        /// </summary>
        public static IEnumerable <int> GetSpikes(
            this Polygon3d self, double toleranceInDegrees = 0.1)
        {
            if (toleranceInDegrees < 0.0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var threshold = Conversion.RadiansFromDegrees(toleranceInDegrees).Cos();
            var edges     = self.GetEdgeArray();

            edges.Apply(e => e.Normalized);
            var ec = edges.Length;

            if (Vec.Dot(-edges[ec - 1], edges[0]) > threshold)
            {
                yield return(0);
            }
            for (int i = 1; i < ec; i++)
            {
                if (Vec.Dot(-edges[i - 1], edges[i]) > threshold)
                {
                    yield return(i);
                }
            }
        }
예제 #5
0
파일: Arc.cs 프로젝트: yasenRK/ThePipe
        public void TransformToPlane(Plane newPlane)
        {
            double eps = 1e-7;

            if (!PipeDataUtil.Equals(Vec.Dot(newPlane.Z, Plane.Z), 1, eps))
            {
                throw new InvalidOperationException("Cannot transform arc to a new plane");
            }
            if (Vec.Difference(newPlane.Origin, Plane.Origin).Length > eps)
            {
                throw new InvalidOperationException("The origins of the planes do not match");
            }

            double angle = Vec.AngleBetween(Plane.X, newPlane.X);

            if (angle < eps)
            {
                return;
            }
            if (Vec.Dot(Vec.Cross(Plane.X, newPlane.X), Plane.Z) < 0)
            {
                angle *= -1;
            }

            Plane = new Plane(Plane.Origin, Plane.X.RotateAbout(Plane.Z, angle),
                              Plane.Y.RotateAbout(Plane.Z, angle));
            StartAngle -= angle;
            EndAngle   -= angle;
        }
예제 #6
0
        public override bool Intersect(Ray ray, Intersection isec)
        {
            var a = 1;
            var b = 2 * ray.Direction.Dot(ray.Origin - Center);
            var c = Center.Dot(Center) + ray.Origin.Dot(ray.Origin) - 2 * (Center.Dot(ray.Origin)) - Radius * Radius;

            var d = b * b - 4 * a * c;

            if (d < 0)
            {
                return(false);
            }

            var sqrtd = (Prec)Math.Sqrt(d);

            var t1 = (-b - sqrtd) / 2;            //(2*a);
            var t2 = (-b + sqrtd) / 2;            //(2*a);

            var t = t1;

            if (t1 < 0)
            {
                if (t2 < 0)
                {
                    return(false);
                }
                t = t2;
            }
            else
            {
                if (t2 > 0 && t2 < t1)
                {
                    t = t2;
                }
            }

            var p = ray.Origin + ray.Direction * t;
            var n = (p - Center);

            n.Normalize();

            isec.Set(t, n, Material);

            return(true);
        }
예제 #7
0
        public static double ComputeUnscaledFormFactor(
            this Polygon3d polygon,
            V3d p, V3d n,
            double eps = 1e-6)
        {
            var vc = polygon.PointCount;

            V3d[] cpa = new V3d[vc + 1];

            var cc = 0;
            var pb = polygon[0] - p;
            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;

            if (hb >= -eps)
            {
                cpa[cc++] = pb;
            }
            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;

            for (int vi = 1; vi < vc; vi++)
            {
                var  p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);
                bool h1p = h1 > eps, h1n = h1 < -eps;
                if (h0p && h1n || h0n && h1p)
                {
                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));
                }
                if (h1 >= -eps)
                {
                    cpa[cc++] = p1;
                }
                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;
            }
            if (h0p && hbn || h0n && hbp)
            {
                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));
            }

            var cpr = cpa.Map(cc, v => v.Length);

            var    cv = Vec.Cross(cpa[0], cpa[cc - 1]);
            double ff = Vec.Dot(n, cv)
                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])
                                          / (cpr[0] * cpr[cc - 1]))
                        / cv.Length;

            for (int ci = 0; ci < cc - 1; ci++)
            {
                cv  = Vec.Cross(cpa[ci + 1], cpa[ci]);
                ff += Vec.Dot(n, cv)
                      * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])
                                        / (cpr[ci + 1] * cpr[ci]))
                      / cv.Length;
            }
            return(ff);
        }
            private static __mnnt__ Mgs(__mnnt__ m)
            {
                //# for (int j = 1; j < n; j++) {
                //# for (int k = 0; k < j; k++) {
                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;
                //# }

                //# }
                return(m);
            }
예제 #9
0
        public static IEnumerable <Pt> ClipPolygonToLine(Pt a, Pt b, IEnumerable <Pt> pts)
        {
            Vec    N = (b - a).Perp();
            double D = -N.Dot((Vec)a);
            bool   first = true;
            Pt     S = new Pt(), F = new Pt(); // compiler is unable to prove these don't need initialization here

            foreach (Pt P in pts)
            {
                double v1, v2;
                v2 = N.Dot((Vec)P) + D;
                if (first)
                {
                    S     = P;
                    F     = P;
                    first = false;
                }
                else
                {
                    v1 = N.Dot((Vec)S) + D;
                    if (v1 * v2 < 0)
                    {
                        yield return(S + (P - S) * v1 / (v1 - v2));
                    }
                    S = P;
                }
                if (v2 >= 0)
                {
                    yield return(P);
                }
            }
            if (!first)
            {
                double v1, v2;
                v2 = N.Dot((Vec)F) + D;
                v1 = N.Dot((Vec)S) + D;
                if (v1 * v2 < 0)
                {
                    yield return(S + (F - S) * v1 / (v1 - v2));
                }
            }
        }
예제 #10
0
 // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
 public static Rot3f HalfWayVec(V3f from, V3f into)
 {
     if (from.Dot(into).ApproximateEquals(-1))
     {
         return(new Rot3f(0, from.AxisAlignedNormal()));
     }
     else
     {
         V3f         half = Vec.Normalized(from + into);
         QuaternionF q    = new QuaternionF(Vec.Dot(from, half), Vec.Cross(from, half));
         return(new Rot3f(q.Normalized));
     }
 }
 // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
 public static __rot3t__ HalfWayVec(__v3t__ from, __v3t__ into)
 {
     if (from.Dot(into).ApproximateEquals(-1))
     {
         return(new __rot3t__(0, from.AxisAlignedNormal()));
     }
     else
     {
         __v3t__   half = Vec.Normalized(from + into);
         __quatt__ q    = new __quatt__(Vec.Dot(from, half), Vec.Cross(from, half));
         return(new __rot3t__(q.Normalized));
     }
 }
            private static __mnnt__ MgsNorm(__mnnt__ m)
            {
                m.C0 = m.C0.Normalized;

                //# for (int j = 1; j < n; j++) {
                //# for (int k = 0; k < j; k++) {
                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;
                //# }
                m.C__j__ = m.C__j__.Normalized;

                //# }
                return(m);
            }
예제 #13
0
            public static Rot3f HalfWayQuat(V3f from, V3f into)
            {
                var d = Vec.Dot(from, into);

                if (d.ApproximateEquals(-1))
                {
                    return(new Rot3f(0, from.AxisAlignedNormal()));
                }
                else
                {
                    QuaternionF q = new QuaternionF(d + 1, Vec.Cross(from, into));
                    return(new Rot3f(q.Normalized));
                }
            }
            public static __rot3t__ HalfWayQuat(__v3t__ from, __v3t__ into)
            {
                var d = Vec.Dot(from, into);

                if (d.ApproximateEquals(-1))
                {
                    return(new __rot3t__(0, from.AxisAlignedNormal()));
                }
                else
                {
                    __quatt__ q = new __quatt__(d + 1, Vec.Cross(from, into));
                    return(new __rot3t__(q.Normalized));
                }
            }
예제 #15
0
        public void ValueType_Vec()
        {
            var p1 = new Vec(1, 0, 0);
            var p2 = new Vec(0, 1, 0);

            Assert.IsFalse(p1.IsEqual(p2, 0.99, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 1.01, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 0.99, Math.PI / 2));
            Assert.IsTrue(p1.IsNormal(p2, 0.1));
            Assert.IsFalse(p1.IsOpposite(p2, 0.1));
            Assert.IsTrue(p1.IsOpposite(p2, Math.PI / 2));
            Assert.IsFalse(p1.IsParallel(p2, 0.1));
            Assert.IsTrue(p1.IsParallel(p2, Math.PI / 2));

            p1 = new Vec(1, 2, 3);
            p2 = new Vec(4, 5, 6);

            Assert.AreEqual(14, p1.SquareMagnitude());
            Assert.AreEqual(Math.Sqrt(14), p1.Magnitude());

            p2 = p1;
            p2.Add(new Vec(1, 2, 3));
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Added(new Vec(1, 2, 3)));

            p2 = new Vec(1, 2, 3);
            p2.Subtract(new Vec(3, 2, 1));
            Assert.AreEqual(new Vec(-2, 0, 2), p2);
            Assert.AreEqual(new Vec(-2, 0, 2), p1.Subtracted(new Vec(3, 2, 1)));

            p2 = new Vec(1, 2, 3);
            p2.Cross(new Vec(3, 2, 1));
            Assert.AreEqual(new Vec(-4, 8, -4), p2);
            Assert.AreEqual(new Vec(-4, 8, -4), p1.Crossed(new Vec(3, 2, 1)));

            Assert.AreEqual(Math.Sqrt(96), p1.CrossMagnitude(new Vec(3, 2, 1)));
            Assert.AreEqual(96, p1.CrossSquareMagnitude(new Vec(3, 2, 1)));

            p2 = new Vec(1, 2, 3);
            p2.CrossCross(new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(-24, -6, 12), p2);
            Assert.AreEqual(new Vec(-24, -6, 12), p1.CrossCrossed(new Vec(1, 2, 3), new Vec(4, 5, 6)));

            p2 = new Vec(1, 2, 3);
            p2.Divide(2);
            Assert.AreEqual(new Vec(0.5, 1, 1.5), p2);
            Assert.AreEqual(new Vec(0.5, 1, 1.5), p1.Divided(2));

            Assert.AreEqual(14, p1.Dot(new Vec(1, 2, 3)));
            Assert.AreEqual(0, p1.DotCross(new Vec(4, 5, 6), new Vec(4, 5, 6)));

            p2 = new Vec(1, 2, 3);
            p2.Multiply(2);
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Multiplied(2));

            p2 = new Vec(1, 2, 3);
            p2.Scale(2);
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Scaled(2));

            p2 = new Vec(1, 2, 3);
            p2.Normalize();
            Assert.IsTrue(p2.IsEqual(new Vec(0.26726, 0.53452, 0.80178), 0.00001, 0.00001));
            Assert.IsTrue(p1.Normalized().IsEqual(new Vec(0.26726, 0.53452, 0.80178), 0.00001, 0.00001));

            p2 = new Vec(1, 2, 3);
            p2.Reverse();
            Assert.AreEqual(new Vec(-1, -2, -3), p2);
            Assert.AreEqual(new Vec(-1, -2, -3), p1.Reversed());

            p2.SetLinearForm(new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(5, 7, 9), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(6, 9, 12), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(14, 19, 24), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), new Vec(7, 8, 9));
            Assert.AreEqual(new Vec(21, 27, 33), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), 4, new Vec(7, 8, 9));
            Assert.AreEqual(new Vec(42, 51, 60), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), 4, new Vec(7, 8, 9), new Vec(10, 11, 12));
            Assert.AreEqual(new Vec(52, 62, 72), p2);

            p2 = new Vec(2, 0, 0);
            p2.Mirror(new Vec(0, 1, 0));
            Assert.AreEqual(new Vec(-2, 0, 0), p2);
            Assert.AreEqual(new Vec(2, 0, 0), p2.Mirrored(new Vec(0, 1, 0)));

            var m2 = new Ax1(new Pnt(-1, 2, -3), new Dir(-1, 0, 0));

            p2 = new Vec(2, 1, 3);
            Assert.AreEqual(new Vec(2, -1, -3), p2.Mirrored(m2));
            p2.Mirror(m2);
            Assert.AreEqual(new Vec(2, -1, -3), p2);

            var a2 = new Ax2(new Pnt(-1, 2, -3), new Dir(-1, 0, 0));

            p2 = new Vec(2, 1, 3);
            Assert.AreEqual("-2,1,3", p2.Mirrored(a2).ToString());
            p2.Mirror(a2);
            Assert.AreEqual("-2,1,3", p2.ToString());

            p2 = new Vec(2, 1, 3);
            Assert.IsTrue(new Vec(2, 3, -1).IsEqual(p2.Rotated(m2, Math.PI / 2), 0.0001, 0.0001));
            p2.Rotate(m2, Math.PI / 2);
            Assert.IsTrue(new Vec(2, 3, -1).IsEqual(p2, 0.0001, 0.0001));

            //TestContext.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", gp2.x, gp2.y, gp2.z));

            Trsf t1 = new Trsf();

            t1.SetRotation(Ax1.OZ, Math.PI / 2);
            p2 = new Vec(4, 5, 6);
            Assert.AreEqual("-5,4,6", p2.Transformed(t1).ToString());
            p2.Transform(t1);
            Assert.AreEqual("-5,4,6", p2.ToString());
        }
예제 #16
0
 /// <summary>
 /// Creates a plane from 3 independent points.
 /// A normalized normal vector is computed and stored.
 /// </summary>
 public Plane3d(V3d p0, V3d p1, V3d p2)
 {
     Normal   = Vec.Cross(p1 - p0, p2 - p0).Normalized;
     Distance = Vec.Dot(Normal, p0);
 }
예제 #17
0
 /// <summary>
 /// Creates plane from normal vector and point.
 /// IMPORTANT: The normal has to be normalized in order for all methods
 /// to work correctly, however if only relative height computations
 /// using the <see cref="Height"/> method are necessary, the normal
 /// vector need not be normalized.
 /// </summary>
 public Plane3d(V3d normalizedNormal, V3d point)
 {
     Normal   = normalizedNormal;
     Distance = Vec.Dot(normalizedNormal, point);
 }
예제 #18
0
 /// <summary>
 /// The signed height of the supplied point over the plane.
 /// </summary>
 public double Height(V3d p) => Vec.Dot(Normal, p - Point);
예제 #19
0
        public static unsafe Vec radiance(ref Ray r, int depth, ref RandomLCG rand)
        {
            double  t;                                          // distance to intersection
            Sphere *obj = intersect(ref r, out t);

            if (obj == null)
            {
                return(Vec_Zero);                // if miss, return black
            }
            else
            {
                int  newDepth   = depth + 1;
                bool isMaxDepth = newDepth > 100;

                // Russian roulette for path termination
                bool isUseRR = newDepth > 5;
                bool isRR    = isUseRR && rand.NextNumber() < obj->maxC;

                if (isMaxDepth || (isUseRR && !isRR))
                {
                    return(obj->e);
                }
                else
                {
                    Vec f    = (isUseRR && isRR) ? obj->cc : obj->c;
                    var tmp1 = r.d.Mul(t);
                    Vec x    = r.o.Add(ref tmp1);
                    Vec n    = (x.Sub(ref obj->p)).Norm();
                    Vec nl   = n.Dot(ref r.d) < 0 ? n : n.Mul(-1);

                    if (obj->refl == MatType.DIFF)
                    {                     // Ideal DIFFUSE reflection
                        double r1  = 2 * M_PI * rand.NextNumber();
                        double r2  = rand.NextNumber();
                        double r2s = MathSqrt(r2);

                        Vec w  = nl;
                        Vec wo = w.x <-0.1 || w.x> 0.1 ? Vec_YAxis : Vec_XAxis;
                        Vec u  = (wo.Cross(ref w)).Norm();
                        Vec v  = w.Cross(ref u);

                        var tmp2 = v.Mul(MathSin(r1)).Mul(r2s);
                        var tmp3 = w.Mul(MathSqrt(1 - r2));
                        Vec d    = (u.Mul(MathCos(r1)).Mul(r2s).Add(ref tmp2).Add(ref tmp3)).Norm();

                        var tmp4 = new Ray(ref x, ref d);
                        var tmp5 = radiance(ref tmp4, newDepth, ref rand);
                        var tmp6 = f.Mul(ref tmp5);
                        return(obj->e.Add(ref tmp6));
                    }
                    else if (obj->refl == MatType.SPEC)                     // Ideal SPECULAR reflection
                    {
                        var tmp8  = n.Mul(2 * (n.Dot(ref r.d)));
                        var tmp9  = r.d.Sub(ref tmp8);
                        var tmp7  = new Ray(ref x, ref tmp9);
                        var tmp10 = radiance(ref tmp7, newDepth, ref rand);
                        var tmp11 = f.Mul(ref tmp10);
                        return(obj->e.Add(ref tmp11));
                    }
                    else
                    {                     // Ideal dielectric REFRACTION
                        var    tmp100  = n.Mul(2 * (n.Dot(ref r.d)));
                        var    tmp101  = r.d.Sub(ref tmp100);
                        Ray    reflRay = new Ray(ref x, ref tmp101);
                        bool   into    = n.Dot(ref nl) > 0;                     // Ray from outside going in?
                        double nc      = 1;
                        double nt      = 1.5;
                        double nnt     = into ? nc / nt : nt / nc;
                        double ddn     = r.d.Dot(ref nl);
                        double cos2t   = 1 - nnt * nnt * (1 - ddn * ddn);

                        if (cos2t < 0)                         // Total internal reflection
                        {
                            var tmp12 = radiance(ref reflRay, newDepth, ref rand);
                            var tmp13 = f.Mul(ref tmp12);
                            return(obj->e.Add(ref tmp13));
                        }
                        else
                        {
                            var    tmp14 = n.Mul((into ? 1 : -1) * (ddn * nnt + MathSqrt(cos2t)));
                            Vec    tdir  = (r.d.Mul(nnt).Sub(ref tmp14)).Norm();
                            double a     = nt - nc;
                            double b     = nt + nc;
                            double R0    = (a * a) / (b * b);
                            double c     = 1 - (into ? -ddn : tdir.Dot(ref n));
                            double Re    = R0 + (1 - R0) * c * c * c * c * c;
                            double Tr    = 1 - Re;
                            double P     = .25 + .5 * Re;
                            double RP    = Re / P;
                            double TP    = Tr / (1 - P);

                            Vec result;
                            if (newDepth > 2)
                            {
                                // Russian roulette and splitting for selecting reflection and/or refraction
                                if (rand.NextNumber() < P)
                                {
                                    result = radiance(ref reflRay, newDepth, ref rand).Mul(RP);
                                }
                                else
                                {
                                    var tmp15 = new Ray(ref x, ref tdir);
                                    result = radiance(ref tmp15, newDepth, ref rand).Mul(TP);
                                }
                            }
                            else
                            {
                                var tmp16 = new Ray(ref x, ref tdir);
                                var tmp17 = radiance(ref tmp16, newDepth, ref rand).Mul(Tr);
                                result = radiance(ref reflRay, newDepth, ref rand).Mul(Re).Add(ref tmp17);
                            }

                            var tmp18 = f.Mul(ref result);
                            return(obj->e.Add(ref tmp18));
                        }
                    }
                }
            }
        }
예제 #20
0
 /// <summary>
 /// Creates plane from point and normal vector. IMPORTANT: The
 /// supplied vector has to be normalized in order for all methods
 /// to work correctly, however if only relative height computations
 /// using the <see cref="Height"/> method are necessary, the normal
 /// vector need not be normalized.
 /// </summary>
 public Plane2d(V2d normalizedNormal, V2d point)
 {
     Normal   = normalizedNormal;
     Distance = Vec.Dot(normalizedNormal, point);
 }
예제 #21
0
 /// <summary>
 /// The signed height of the supplied point over the plane.
 /// </summary>
 public double Height(V3d p) => Vec.Dot(Normal, p) - Distance;
예제 #22
0
        public void RasterTest(uint raster)
        {
            int iraster = (int)raster;

            V3fCoder coder = new V3fCoder(raster);

            uint step  = 1;
            bool large = false;

            if (iraster > 52)
            {
                step = 7; large = true;
            }
            if (iraster > 591)
            {
                step = 63;
            }
            if (iraster > 6688)
            {
                step = 2039;
            }

            int bits = (int)Fun.Ceiling(Fun.Log2(coder.Count));

            Test.Begin("normal coder raster {0} ({1} bits)", iraster, bits);

            /*
             * Console.WriteLine("  raster = {0}", m_raster);
             * Console.WriteLine("  rasterMul2Sub1 = {0}", m_r2Sub1);
             * Console.WriteLine("  doubleRaster = {0}", m_doubleRaster);
             * Console.WriteLine("  invDoubleRaster = {0}", m_invDoubleRaster);
             * Console.WriteLine("  edgeBasis = {0}", m_edgeBasis);
             * Console.WriteLine("  cornerBasis = {0}", m_cornerBasis);
             */
            Test.Begin("testing {0} of {1} codes", 1 + ((long)coder.Count - 1) / (long)step, coder.Count);
            for (uint code = 0; code < coder.Count; code += step)
            {
                V3f  dir     = coder.Decode(code);
                uint newCode = coder.Encode(dir);
                Test.IsTrue(code == newCode);
            }
            Test.End();

            double minDot = 1.0;

            float eps = Constant <float> .PositiveTinyValue;

            float[] factorTable = { 1.0f - eps, 1.0f, 1.0f + eps };

            for (int sign = -1; sign < 2; sign += 2)
            {
                for (int axis = 0; axis < 3; axis++)
                {
                    float factor = factorTable[axis];

                    for (int xi = -2 * iraster; xi <= 2 * iraster; xi++)
                    {
                        if (large && (xi > 3 - 2 * iraster) && (xi < -3))
                        {
                            continue;
                        }
                        if (large && (xi < 2 * iraster - 3) && (xi > +3))
                        {
                            continue;
                        }
                        double x = (double)xi * factor / (2 * iraster);
                        #if (!V3FCODER_NO_WARP)
                        x = V3fCoder.SphericalOfBox(x);
                        #endif
                        for (int yi = -2 * iraster; yi <= 2 * iraster; yi++)
                        {
                            if (large && (yi > 3 - 2 * iraster) && (yi < -3))
                            {
                                continue;
                            }
                            if (large && (yi < 2 * iraster - 3) && (yi > +3))
                            {
                                continue;
                            }
                            double y = (double)yi * factor / (2 * iraster);

                            #if (!V3FCODER_NO_WARP)
                            y = V3fCoder.SphericalOfBox(y);
                            #endif
                            V3f n = new V3f(0, 0, 0); // init to make compiler h.
                            n[axis]           = sign;
                            n[(axis + 1) % 3] = (float)x;
                            n[(axis + 2) % 3] = (float)y;

                            n.Normalize();

                            uint code = coder.Encode(n);
                            V3f  newN = coder.Decode(code);

                            double newDot = Vec.Dot(n, newN);
                            if (newDot < minDot)
                            {
                                minDot = newDot;
                            }
                        }
                    }
                }
            }
            double maxErr = System.Math.Acos(minDot) * 180.0 / System.Math.PI;
            Report.Line("maximal error {0:g4} degrees", maxErr);
            Test.End();
        }