/// <summary> /// Gets the intersection points between us and a generalized circle. /// </summary> public Vector3D[] GetIntersectionPoints(Circle line) { List <Vector3D> iPoints = new List <Vector3D>(); for (int i = 0; i < NumSides; i++) { iPoints.AddRange(line.GetIntersectionPoints(Segments[i])); } return(iPoints.ToArray()); }
private static bool SlicePolygonInternal(Polygon p, Circle c, out List <Polygon> output) { // Our approach: // (1) Find the intersection points, and splice them into the polygon. (splicing in is the main diff from old algorithm.) // (2) From each intersection point, walk the polygon. // (3) When you are at an intersection point, always turn left, which may involve adding a new segment of the slicing circle. // (4) We'll have to check for duplicate polygons in the resulting list, and remove them. output = new List <Polygon>(); // We must be a digon at a minimum. if (p.NumSides < 2) { return(false); } // XXX - Code assumes well-formed polygon: closed (has connected segments), // no repeated vertices. Assert all this? // Code also assumes CCW orientation. if (!p.Orientation) { p.Reverse(); } // Cycle through our segments and splice in all the intersection points. Polygon diced = new Polygon(); List <IntersectionPoint> iPoints = new List <IntersectionPoint>(); for (int i = 0; i < p.NumSides; i++) { Segment s = p.Segments[i]; Vector3D[] intersections = c.GetIntersectionPoints(s); if (intersections == null) { continue; } switch (intersections.Length) { case 0: { diced.Segments.Add(s); break; } case 1: { // ZZZ - check here to see if it is a tangent iPoint? Not sure if we need to do this. diced.Segments.Add(SplitHelper(s, intersections[0], diced, iPoints)); break; } case 2: { // We need to ensure the intersection points are ordered correctly on the segment. Vector3D i1 = intersections[0], i2 = intersections[1]; if (!s.Ordered(i1, i2)) { Utils.SwapPoints(ref i1, ref i2); } Segment secondToSplit = SplitHelper(s, i1, diced, iPoints); Segment segmentToAdd = SplitHelper(secondToSplit, i2, diced, iPoints); diced.Segments.Add(segmentToAdd); break; } default: Debug.Assert(false); return(false); } } // NOTE: We've been careful to avoid adding duplicates to iPoints. // Are we done? (no intersections) if (0 == iPoints.Count) { output.Add(p); return(true); } // We don't yet deal with tangengies, // but we're going to let this case slip through as unsliced. if (1 == iPoints.Count) { output.Add(p); return(true); } // We don't yet deal with tangencies. // We're going to fail on this case, because it could be more problematic. if (Utils.Odd(iPoints.Count)) { Debug.Assert(false); return(false); } if (iPoints.Count > 2) { // We may need our intersection points to all be reorded by 1. // This is so that when walking from i1 -> i2 along c, we will be moving through the interior of the polygon. // ZZZ - This may need to change when hack in SplicedArc is improved. int dummy = 0; Segment testArc = SmallerSplicedArc(c, iPoints, ref dummy, true, ref dummy); Vector3D midpoint = testArc.Midpoint; if (!p.IsPointInsideParanoid(midpoint)) { IntersectionPoint t = iPoints[0]; iPoints.RemoveAt(0); iPoints.Add(t); } } // // From each intersection point, walk the polygon. // int numPairs = iPoints.Count / 2; for (int i = 0; i < numPairs; i++) { int pair = i; output.Add(WalkPolygon(p, diced, c, pair, iPoints, true)); output.Add(WalkPolygon(p, diced, c, pair, iPoints, false)); } // // Recalc centers. // foreach (Polygon poly in output) { poly.Center = poly.CentroidApprox; } // // Remove duplicate polygons. // output = output.Distinct(new PolygonEqualityComparer()).ToList(); return(true); }