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); }
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); }