public SplitType SplitWithPlane(Plane3D plane, out Polygon3D front, out Polygon3D back, bool veryPrecise) { Vector3D intersection; front = null; back = null; double dist = 0; double maxDist = 0; double minDist = 0; double prevDist; double threshold; VType status; VType prevStatus = VType.Either; // double scale if (veryPrecise) { threshold = 0.01; } else { threshold = 0.25; } for (int i = 0; i < vertices.Count; i++) { dist = plane.GetDistanceToPoint(vertices[i]); if (i == 0 || dist > maxDist) { maxDist = dist; } if (i == 0 || dist < minDist) { minDist = dist; } if (dist > +threshold) { prevStatus = VType.Front; } else if (dist < -threshold) { prevStatus = VType.Back; } } if (maxDist < threshold && minDist > -threshold) { return(SplitType.SP_Coplanar); } else if (maxDist < threshold) { return(SplitType.SP_Back); } else if (minDist > -threshold) { return(SplitType.SP_Front); } else { front = Clone(); front.vertices.Clear(); back = Clone(); back.vertices.Clear(); int j = vertices.Count - 1; for (int i = 0; i < vertices.Count; i++) { prevDist = dist; dist = plane.GetDistanceToPoint(vertices[i]); if (dist > +threshold) { status = VType.Front; } else if (dist < -threshold) { status = VType.Back; } else { status = prevStatus; } if (status != prevStatus) { // Crossing. Either Front-to-Back or Back-To-Front. // Intersection point is naturally on both front and back polys. if ((dist >= -threshold) && (dist < +threshold)) { // This point lies on plane. if (prevStatus == VType.Front) { front.vertices.Add(vertices[i]); back.vertices.Add(vertices[i]); } else { back.vertices.Add(vertices[i]); front.vertices.Add(vertices[i]); } } else if ((prevDist >= -threshold) && (prevDist < +threshold)) { // Previous point lies on plane. if (status == VType.Front) { front.vertices.Add(vertices[j]); front.vertices.Add(vertices[i]); } else { back.vertices.Add(vertices[j]); back.vertices.Add(vertices[i]); } } else { // Intersection point is in between. intersection = plane.LineIntersection(vertices[j], vertices[i]); if (prevStatus == VType.Front) { front.vertices.Add(intersection); back.vertices.Add(intersection); back.vertices.Add(vertices[i]); } else { back.vertices.Add(intersection); front.vertices.Add(intersection); front.vertices.Add(vertices[i]); } } } else { if (status == VType.Front) { front.vertices.Add(vertices[i]); } else { back.vertices.Add(vertices[i]); } } j = i; prevStatus = status; } // Handle possibility of sliver polys due to precision errors. if (front.Fix() < 3) { return(SplitType.SP_Back); } else if (back.Fix() < 3) { return(SplitType.SP_Front); } else { return(SplitType.SP_Split); } } }