Пример #1
0
        private double IntersectRayDisk(Disk disk, Vector O, Vector D)
        {
            O = new Vector(O.D1 - disk.Position.D1, O.D2 - disk.Position.D2, O.D3 - disk.Position.D3);
            if (disk.Rotation != null)
            {
                D = D.MultiplyMatrix(disk.Rotation.Rotation);
                O = O.MultiplyMatrix(disk.Rotation.Rotation);
            }

            var t = -O.D3 / D.D3;

            var x = D.D1 * t + O.D1;
            var y = D.D2 * t + O.D2;

            if (x * x / disk.A + y * y / disk.B < disk.R2)
            {
                return(t);
            }

            return(double.PositiveInfinity);
        }
Пример #2
0
        private double IntersectRayTorus(Torus torus, Vector O, Vector D)
        {
            var o = O;
            var d = D;

            var r = torus.TubeRadius;
            var R = torus.SweptRadius;

            o = new Vector(o.D1 - torus.Position.D1, o.D2 - torus.Position.D2, o.D3 - torus.Position.D3);

            if (torus.Rotation != null)
            {
                d = d.MultiplyMatrix(torus.Rotation.Rotation);
                o = o.MultiplyMatrix(torus.Rotation.Rotation);
            }

            var intersectBox = IntersectRayBox(o, d.Invert(), torus.AroundBox);

            if (double.IsNaN(intersectBox) || double.IsPositiveInfinity(intersectBox))
            {
                return(double.NaN);
            }

            var ox = o.D1;
            var oy = o.D2;
            var oz = o.D3;

            var dx = d.D1;
            var dy = d.D2;
            var dz = d.D3;

            var rPow2  = r * r;
            var RPow2  = R * R;
            var dyPow2 = dy * dy;
            var oyPow2 = oy * oy;

            // define the coefficients of the quartic equation
            var sum_d_sqrd = dx * dx + dyPow2 + dz * dz;
            var e          = ox * ox + oyPow2 + oz * oz -
                             RPow2 - rPow2;
            var f           = ox * dx + oy * dy + oz * dz;
            var four_a_sqrd = 4.0 * RPow2;

            var coeffs = new[]
            {
                sum_d_sqrd *sum_d_sqrd,
                4.0 *sum_d_sqrd *f,
                2.0 *sum_d_sqrd *e + 4.0 *f *f + four_a_sqrd *dyPow2,
                4.0 *f *e + 2.0 *four_a_sqrd *oy *dy,
                e *e - four_a_sqrd *(rPow2 - oyPow2)
            };

            var solve = RealPolynomialRootFinder.FindRoots(coeffs);

            if (solve == null)
            {
                return(double.PositiveInfinity);
            }

            var min = double.PositiveInfinity;

            for (var i = 0; i < solve.Count; i++)
            {
                if (solve[i].IsReal() && solve[i].Real > 0.0001 && solve[i].Real < min)
                {
                    min = solve[i].Real;
                }
            }

            return(min);
        }
Пример #3
0
        private double IntersectRaySurface(Surface surface, Vector O, Vector D)
        {
            var origO = new Vector(O);
            var origD = new Vector(D);

            var a = surface.A;
            var b = surface.B;
            var c = surface.C;
            var d = surface.D;
            var e = surface.E;
            var f = surface.F;

            O = new Vector(O.D1 - surface.Position.D1, O.D2 - surface.Position.D2, O.D3 - surface.Position.D3);

            if (surface.Rotation != null)
            {
                D = D.MultiplyMatrix(surface.Rotation.Rotation);
                O = O.MultiplyMatrix(surface.Rotation.Rotation);
            }

            var d1 = D.D1;
            var d2 = D.D2;
            var d3 = D.D3;
            var o1 = O.D1;
            var o2 = O.D2;
            var o3 = O.D3;

            var p1 = 2 * a * d1 * o1 + 2 * b * d2 * o2 + 2 * c * d3 * o3 + d * d3 + d2 * e;
            var p2 = a * d1.Pow2() + b * d2.Pow2() + c * d3.Pow2();
            var p3 = a * o1.Pow2() + b * o2.Pow2() + c * o3.Pow2() + d * o3 + e * o2 + f;
            var p4 = Math.Sqrt(p1.Pow2() - 4 * p2 * p3);

            //division by zero
            if (Math.Abs(p2) < 1e-20)
            {
                var t = -p3 / p1;
                return(t);
            }

            var min = double.PositiveInfinity;
            var max = double.PositiveInfinity;

            var t1 = (-p1 - p4) / (2 * p2);
            var t2 = (-p1 + p4) / (2 * p2);

            var epsilon = 1e-4;

            if (t1 > epsilon && t1 < min)
            {
                min = t1;
                max = t2;
            }

            if (t2 > epsilon && t2 < min)
            {
                min = t2;
                max = t1;
            }

            var vMin = new Vector(surface.XMin, surface.YMin, surface.ZMin);
            var vMax = new Vector(surface.XMax, surface.YMax, surface.ZMax);

            if (!CheckSurfaceEdges(origD, origO, ref min, ref max, vMin, vMax, epsilon))
            {
                return(double.PositiveInfinity);
            }

            return(min);
        }