bool IntersectsSegment(ref Plane3d plane, ref Triangle3d triangle, Vector3d end0, Vector3d end1)
        {
            // Compute the 2D representations of the triangle vertices and the
            // segment endpoints relative to the plane of the triangle.  Then
            // compute the intersection in the 2D space.

            // Project the triangle and segment onto the coordinate plane most
            // aligned with the plane normal.
            int    maxNormal = 0;
            double fmax      = Math.Abs(plane.Normal.x);
            double absMax    = Math.Abs(plane.Normal.y);

            if (absMax > fmax)
            {
                maxNormal = 1;
                fmax      = absMax;
            }
            absMax = Math.Abs(plane.Normal.z);
            if (absMax > fmax)
            {
                maxNormal = 2;
            }

            Triangle2d projTri = new Triangle2d();
            Vector2d   projEnd0 = Vector2d.Zero, projEnd1 = Vector2d.Zero;
            int        i;

            if (maxNormal == 0)
            {
                // Project onto yz-plane.
                for (i = 0; i < 3; ++i)
                {
                    projTri[i] = triangle[i].yz;
                    projEnd0.x = end0.y;
                    projEnd0.y = end0.z;
                    projEnd1.x = end1.y;
                    projEnd1.y = end1.z;
                }
            }
            else if (maxNormal == 1)
            {
                // Project onto xz-plane.
                for (i = 0; i < 3; ++i)
                {
                    projTri[i] = triangle[i].xz;
                    projEnd0.x = end0.x;
                    projEnd0.y = end0.z;
                    projEnd1.x = end1.x;
                    projEnd1.y = end1.z;
                }
            }
            else
            {
                // Project onto xy-plane.
                for (i = 0; i < 3; ++i)
                {
                    projTri[i] = triangle[i].xy;
                    projEnd0.x = end0.x;
                    projEnd0.y = end0.y;
                    projEnd1.x = end1.x;
                    projEnd1.y = end1.y;
                }
            }

            Segment2d             projSeg = new Segment2d(projEnd0, projEnd1);
            IntrSegment2Triangle2 calc    = new IntrSegment2Triangle2(projSeg, projTri);

            if (!calc.Find())
            {
                return(false);
            }

            Vector2dTuple2 intr = new Vector2dTuple2();

            if (calc.Type == IntersectionType.Segment)
            {
                Result   = IntersectionResult.Intersects;
                Type     = IntersectionType.Segment;
                Quantity = 2;
                intr.V0  = calc.Point0;
                intr.V1  = calc.Point1;
            }
            else
            {
                Debug.Assert(calc.Type == IntersectionType.Point);
                //"Intersection must be a point\n";
                Result   = IntersectionResult.Intersects;
                Type     = IntersectionType.Point;
                Quantity = 1;
                intr.V0  = calc.Point0;
            }

            // Unproject the segment of intersection.
            if (maxNormal == 0)
            {
                double invNX = ((double)1) / plane.Normal.x;
                for (i = 0; i < Quantity; ++i)
                {
                    double y = intr[i].x;
                    double z = intr[i].y;
                    double x = invNX * (plane.Constant - plane.Normal.y * y - plane.Normal.z * z);
                    Points[i] = new Vector3d(x, y, z);
                }
            }
            else if (maxNormal == 1)
            {
                double invNY = ((double)1) / plane.Normal.y;
                for (i = 0; i < Quantity; ++i)
                {
                    double x = intr[i].x;
                    double z = intr[i].y;
                    double y = invNY * (plane.Constant - plane.Normal.x * x - plane.Normal.z * z);
                    Points[i] = new Vector3d(x, y, z);
                }
            }
            else
            {
                double invNZ = ((double)1) / plane.Normal.z;
                for (i = 0; i < Quantity; ++i)
                {
                    double x = intr[i].x;
                    double y = intr[i].y;
                    double z = invNZ * (plane.Constant - plane.Normal.x * x - plane.Normal.y * y);
                    Points[i] = new Vector3d(x, y, z);
                }
            }

            return(true);
        }
Beispiel #2
0
        Circle UpdateSupport2(int i, int[] permutation, Support support)
        {
            var point = new Vector2dTuple2(
                Points[permutation[support.Index[0]]],                  // P0
                Points[permutation[support.Index[1]]]                   // P1
                );
            Vector2d P2 = Points[permutation[i]];

            // Permutations of type 2, used for calling ExactCircle2(..).
            int numType2 = 2;

            // Permutations of type 3, used for calling ExactCircle3(..).
            //int numType3 = 1;  // {0, 1, 2}

            Circle[] circle = circle_buf;
            int      indexCircle = 0;
            double   minRSqr = double.MaxValue;
            int      indexMinRSqr = -1;
            double   distDiff = 0, minDistDiff = double.MaxValue;
            int      indexMinDistDiff = -1;

            // Permutations of type 2.
            int j;

            for (j = 0; j < numType2; ++j, ++indexCircle)
            {
                circle[indexCircle] = ExactCircle2(point[type2_2[j, 0]], ref P2);
                if (circle[indexCircle].Radius < minRSqr)
                {
                    if (Contains(point[type2_2[j, 1]], ref circle[indexCircle], ref distDiff))
                    {
                        minRSqr      = circle[indexCircle].Radius;
                        indexMinRSqr = indexCircle;
                    }
                    else if (distDiff < minDistDiff)
                    {
                        minDistDiff      = distDiff;
                        indexMinDistDiff = indexCircle;
                    }
                }
            }

            // Permutations of type 3.
            circle[indexCircle] = ExactCircle3(point[0], point[1], ref P2);
            if (circle[indexCircle].Radius < minRSqr)
            {
                minRSqr      = circle[indexCircle].Radius;
                indexMinRSqr = indexCircle;
            }

            // Theoreticaly, indexMinRSqr >= 0, but floating-point round-off errors
            // can lead to indexMinRSqr == -1.  When this happens, the minimal sphere
            // is chosen to be the one that has the minimum absolute errors between
            // the sphere and points (barely) outside the sphere.
            if (indexMinRSqr == -1)
            {
                indexMinRSqr = indexMinDistDiff;
            }

            Circle minimal = circle[indexMinRSqr];

            switch (indexMinRSqr)
            {
            case 0:
                support.Index[1] = i;
                break;

            case 1:
                support.Index[0] = i;
                break;

            case 2:
                support.Quantity = 3;
                support.Index[2] = i;
                break;
            }

            return(minimal);
        }