/// <summary> /// Constructs the geometric difference between this Polygon and the supplied Polygons. /// </summary> /// <param name="difPolys">The list of intersecting Polygons.</param> /// <returns> /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon. /// Returns null if the area of this Polygon is entirely subtracted. /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect. /// </returns> public IList <Polygon> Difference(IList <Polygon> difPolys) { var thisPath = this.ToClipperPath(); var polyPaths = new List <List <IntPoint> >(); foreach (Polygon polygon in difPolys) { polyPaths.Add(polygon.ToClipperPath()); } Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, true); clipper.AddPaths(polyPaths, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctDifference, solution); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList())); } return(polygons); }
/// <summary> /// Constructs the geometric difference between this Polygon and the supplied Polygons. /// </summary> /// <param name="difPolys">The list of intersecting Polygons.</param> /// <param name="tolerance">An optional tolerance value.</param> /// <returns> /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon. /// Returns null if the area of this Polygon is entirely subtracted. /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect. /// </returns> public IList <Polygon> Difference(IList <Polygon> difPolys, double tolerance = Vector3.EPSILON) { var thisPath = this.ToClipperPath(tolerance); var polyPaths = new List <List <IntPoint> >(); foreach (Polygon polygon in difPolys) { polyPaths.Add(polygon.ToClipperPath(tolerance)); } Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, true); clipper.AddPaths(polyPaths, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctDifference, solution); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { try { polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList(), tolerance)); } catch { // swallow invalid polygons } } return(polygons); }
internal static Profile ToProfile(this PolyNode node, double tolerance = Vector3.EPSILON) { var perimeter = PolygonExtensions.ToPolygon(node.Contour, tolerance); if (perimeter == null) { return(null); } List <Polygon> voidCrvs = new List <Polygon>(); if (node.ChildCount > 0) { foreach (var child in node.Childs) { var voidCrv = PolygonExtensions.ToPolygon(child.Contour, tolerance); if (voidCrv != null) { voidCrvs.Add(voidCrv); } } } var profile = new Profile(perimeter, voidCrvs, Guid.NewGuid(), null); return(profile); }
/// <summary> /// Apply a boolean operation (Union, Difference, Intersection, or XOr) to two lists of Polygons. /// </summary> /// <param name="subjectPolygons">Polygons to clip</param> /// <param name="clippingPolygons">Polygons with which to clip</param> /// <param name="booleanMode">The operation to apply: Union, Difference, Intersection, or XOr</param> /// <param name="voidTreatment">Optional setting for how to process the polygons in each set: either treat polygons inside others as voids, or treat them all as solid (thereby ignoring internal polygons).</param> /// <param name="tolerance">Optional override of the tolerance for determining if two polygons are identical.</param> private static IList <Polygon> BooleanTwoSets(IList <Polygon> subjectPolygons, IList <Polygon> clippingPolygons, BooleanMode booleanMode, VoidTreatment voidTreatment = VoidTreatment.PreserveInternalVoids, double tolerance = Vector3.EPSILON) { var subjectPaths = subjectPolygons.Select(s => s.ToClipperPath(tolerance)).ToList(); var clipPaths = clippingPolygons.Select(s => s.ToClipperPath(tolerance)).ToList(); Clipper clipper = new Clipper(); clipper.AddPaths(subjectPaths, PolyType.ptSubject, true); clipper.AddPaths(clipPaths, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); var executionMode = ClipType.ctDifference; var polyFillType = PolyFillType.pftEvenOdd; if (voidTreatment == VoidTreatment.IgnoreInternalVoids) { polyFillType = PolyFillType.pftNonZero; } switch (booleanMode) { case BooleanMode.Difference: executionMode = ClipType.ctDifference; break; case BooleanMode.Union: executionMode = ClipType.ctUnion; break; case BooleanMode.Intersection: executionMode = ClipType.ctIntersection; break; case BooleanMode.XOr: executionMode = ClipType.ctXor; break; } clipper.Execute(executionMode, solution, polyFillType); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path, tolerance)); } return(polygons); }
/// <summary> /// Returns Polygons representing the symmetric difference between this Polygon and the supplied Polygon. /// </summary> /// <param name="polygon">The intersecting polygon.</param> /// <param name="tolerance">An optional tolerance.</param> /// <returns> /// Returns a list of Polygons representing the symmetric difference of this Polygon and the supplied Polygon. /// Returns a representation of this Polygon and the supplied Polygon if the Polygons do not intersect. /// </returns> public IList <Polygon> XOR(Polygon polygon, double tolerance = Vector3.EPSILON) { var thisPath = this.ToClipperPath(tolerance); var polyPath = polygon.ToClipperPath(tolerance); Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, true); clipper.AddPath(polyPath, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctUnion, solution); var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path, tolerance)); } return(polygons); }
/// <summary> /// Apply a boolean operation (Union, Difference, Intersection, or XOr) to two lists of Polygons. /// </summary> /// <param name="subjectPolygons">Polygons to clip</param> /// <param name="clippingPolygons">Polygons with which to clip</param> /// <param name="mode">The operation to apply: Union, Difference, Intersection, or XOr</param> /// <returns></returns> private static IList <Polygon> BooleanTwoSets(IList <Polygon> subjectPolygons, IList <Polygon> clippingPolygons, BooleanMode mode) { var subjectPaths = subjectPolygons.Select(s => s.ToClipperPath()).ToList(); var clipPaths = clippingPolygons.Select(s => s.ToClipperPath()).ToList(); Clipper clipper = new Clipper(); clipper.AddPaths(subjectPaths, PolyType.ptSubject, true); clipper.AddPaths(clipPaths, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); var executionMode = ClipType.ctDifference; switch (mode) { case BooleanMode.Difference: executionMode = ClipType.ctDifference; break; case BooleanMode.Union: executionMode = ClipType.ctUnion; break; case BooleanMode.Intersection: executionMode = ClipType.ctIntersection; break; case BooleanMode.XOr: executionMode = ClipType.ctXor; break; } clipper.Execute(executionMode, solution); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path)); } return(polygons); }
/// <summary> /// Constructs the geometric difference between this Polygon and the supplied Polygon. /// </summary> /// <param name="polygon">The intersecting Polygon.</param> /// <param name="tolerance">An optional tolerance value.</param> /// <returns> /// Returns a list of Polygons representing the subtraction of the supplied Polygon from this Polygon. /// Returns null if the area of this Polygon is entirely subtracted. /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect. /// </returns> public IList <Polygon> Difference(Polygon polygon, double tolerance = Vector3.EPSILON) { var thisPath = this.ToClipperPath(tolerance); var polyPath = polygon.ToClipperPath(tolerance); Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, true); clipper.AddPath(polyPath, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctDifference, solution, PolyFillType.pftNonZero); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path, tolerance)); } return(polygons); }
/// <summary> /// Constructs the Polygon intersections between this Polygon and the supplied Polygon. /// </summary> /// <param name="polygon">The intersecting Polygon.</param> /// <returns> /// Returns a list of Polygons representing the intersection of this Polygon with the supplied Polygon. /// Returns null if the two Polygons do not intersect. /// </returns> public IList <Polygon> Intersection(Polygon polygon) { var thisPath = this.ToClipperPath(); var polyPath = polygon.ToClipperPath(); Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, true); clipper.AddPath(polyPath, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctIntersection, solution); if (solution.Count == 0) { return(null); } var polygons = new List <Polygon>(); foreach (List <IntPoint> path in solution) { polygons.Add(PolygonExtensions.ToPolygon(path)); } return(polygons); }