/// <summary> /// Tests if the supplied Polygon and this Polygon are coincident in any way when compared on a shared plane. /// </summary> /// <param name="polygon">The Polygon to compare to this Polygon.</param> /// <returns> /// Returns true if the supplied Polygon do not intersect or touch this Polygon when compared on a shared plane or if the supplied Polygon is null. /// </returns> public bool Disjoint(Polygon polygon) { if (polygon == null) { return(true); } var thisPath = this.ToClipperPath(); var polyPath = polygon.ToClipperPath(); foreach (IntPoint vertex in thisPath) { if (Clipper.PointInPolygon(vertex, polyPath) != 0) { return(false); } } foreach (IntPoint vertex in polyPath) { if (Clipper.PointInPolygon(vertex, thisPath) != 0) { return(false); } } return(true); }
/// <summary> /// Tests if the supplied Polygon is within this Polygon with or without edge coincident vertices when compared on a shared plane. /// </summary> /// <param name="polygon">The Polygon to compare to this Polygon.</param> /// <returns> /// Returns true if every vertex of the supplied Polygon is within this Polygon or coincident with an edge when compared on a shared plane. Returns false if any vertex of the supplied Polygon is outside this Polygon, or if the supplied Polygon is null. /// </returns> public bool Covers(Polygon polygon) { if (polygon == null) { return(false); } var clipper = new Clipper(); var solution = new List <List <IntPoint> >(); clipper.AddPath(this.ToClipperPath(), PolyType.ptSubject, true); clipper.AddPath(polygon.ToClipperPath(), PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, solution); if (solution.Count != 1) { return(false); } return(solution.First().ToPolygon().Area == polygon.ToClipperPath().ToPolygon().Area); }
/// <summary> /// Constructs the geometric union between this Polygon and the supplied Polygon. /// </summary> /// <param name="polygon">The Polygon to be combined with this Polygon.</param> /// <param name="tolerance">An optional tolerance.</param> /// <returns> /// Returns a single Polygon from a successful union. /// Returns null if a union cannot be performed on the two Polygons. /// </returns> public Polygon Union(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); if (solution.Count > 1) { return(null); } return(solution.First().ToPolygon(tolerance)); }
/// <summary> /// Tests if at least one point of an edge of the supplied Polygon is shared with an edge of this Polygon without the Polygons interesecting when compared on a shared plane. /// </summary> /// <param name="polygon">The Polygon to compare to this Polygon.</param> /// <param name="tolerance">An optional tolerance.</param> /// <returns> /// Returns true if the supplied Polygon shares at least one edge point with this Polygon without the Polygons intersecting when compared on a shared plane. Returns false if the Polygons intersect, are disjoint, or if the supplied Polygon is null. /// </returns> public bool Touches(Polygon polygon, double tolerance = Vector3.EPSILON) { if (polygon == null || this.Intersects(polygon)) { return(false); } var thisPath = this.ToClipperPath(tolerance); var polyPath = polygon.ToClipperPath(tolerance); foreach (IntPoint vertex in thisPath) { if (Clipper.PointInPolygon(vertex, polyPath) == -1) { return(true); } } return(false); }
/// <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> /// Tests if the supplied Polygon is within this Polygon with or without edge coincident vertices when compared on a shared plane. /// </summary> /// <param name="polygon">The Polygon to compare to this Polygon.</param> /// <returns> /// Returns true if every vertex of the supplied Polygon is within this Polygon or coincident with an edge when compared on a shared plane. Returns false if any vertex of the supplied Polygon is outside this Polygon, or if the supplied Polygon is null. /// </returns> public bool Covers(Polygon polygon) { if (polygon == null) { return(false); } if (this.IsClockWise() != polygon.IsClockWise()) { polygon = polygon.Reversed(); } var clipper = new Clipper(); var solution = new List <List <IntPoint> >(); clipper.AddPath(this.ToClipperPath(), PolyType.ptSubject, true); clipper.AddPath(polygon.ToClipperPath(), PolyType.ptClip, true); clipper.Execute(ClipType.ctUnion, solution); if (solution.Count != 1) { return(false); } return(Math.Abs(solution.First().ToPolygon().Area() - this.ToClipperPath().ToPolygon().Area()) <= 0.0001); }
/// <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); }