public static List<List<IntPoint>> ClipPolygons(List<Polygon> polygons) { var subj = new List<List<IntPoint>>(polygons.Count); var clip = new List<List<IntPoint>>(polygons.Count); foreach (var polygon in polygons) { subj.Add(polygon.ToClipperPath()); clip.Add(polygon.ToClipperPath()); } var solution = new List<List<IntPoint>>(); var c = new Clipper(); c.AddPaths(subj, PolyType.PtSubject, true); c.AddPaths(clip, PolyType.PtClip, true); c.Execute(ClipType.CtUnion, solution, PolyFillType.PftPositive, PolyFillType.PftEvenOdd); return solution; }
/// <summary>Intersects the current clipping path with the given path.</summary> /// <remarks> /// Intersects the current clipping path with the given path. /// <strong>Note:</strong> Coordinates of the given path should be in /// the transformed user space. /// </remarks> /// <param name="path">The path to be intersected with the current clipping path.</param> /// <param name="fillingRule"> /// The filling rule which should be applied to the given path. /// It should be either /// <see cref="iText.Kernel.Pdf.Canvas.PdfCanvasConstants.FillingRule.EVEN_ODD"/> /// or /// <see cref="iText.Kernel.Pdf.Canvas.PdfCanvasConstants.FillingRule.NONZERO_WINDING"/> /// </param> public virtual void Clip(Path path, int fillingRule) { if (clippingPath == null || clippingPath.IsEmpty()) { return; } Path pathCopy = new Path(path); pathCopy.CloseAllSubpaths(); Clipper clipper = new Clipper(); ClipperBridge.AddPath(clipper, clippingPath, PolyType.SUBJECT); ClipperBridge.AddPath(clipper, pathCopy, PolyType.CLIP); PolyTree resultTree = new PolyTree(); clipper.Execute(ClipType.INTERSECTION, resultTree, PolyFillType.NON_ZERO, ClipperBridge.GetFillType(fillingRule )); clippingPath = ClipperBridge.ConvertToPath(resultTree); }
public static Paths ClipPolygons(List <Polygon> polygons) { var subj = new Paths(polygons.Count); var clip = new Paths(polygons.Count); foreach (var polygon in polygons) { subj.Add(polygon.ToClipperPath()); clip.Add(polygon.ToClipperPath()); } var solution = new Paths(); var c = new Clipper(); c.AddPaths(subj, PolyType.ptSubject, true); c.AddPaths(clip, PolyType.ptClip, true); c.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftEvenOdd); return(solution); }
IMoveableSection GetCutPolygon(List <Point2D> CuttingRectanglePoints) { #region GPC ////Cutting polygon //Polygon CuttingPoly = new Polygon(); //CuttingPoly.AddContour(CuttingRectanglePoints, false); ////Original polygon //Polygon OriginalPoly = new Polygon(); //OriginalPoly.AddContour(Vertices, false); //Polygon result = OriginalPoly.Clip(GpcOperation.Intersection, CuttingPoly); //GenericShape shape = new GenericShape(result); //return shape; #endregion #region Clipper Paths subj = GetPolyPaths(Vertices); Paths clip = GetPolyPaths(CuttingRectanglePoints); Paths solution = new Paths(); Clipper c = new Clipper(); c.AddPaths(subj, PolyType.ptSubject, true); c.AddPaths(clip, PolyType.ptClip, true); c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); if (solution.Count == 0) { return(null); } else { PolygonShape shape = new PolygonShape(solution, true); return(shape); } #endregion }
public static void calculateInfillSegments() { Logger.logProgress("Calculating infill segments"); //To calculate the segments that need normal infill we need to go through each island in each layer, we then need to subtract the //top or bottom segments from the outline shape polygons of the layer and we then have the segments that need normal infill for (int i = Global.Values.layerCount - 1; i >= 0; i--) { foreach (Island island in Global.Values.layerComponentList[i].islandList) { Clipper islandClipper = new Clipper(); //Add the outline shape polygons as the subject islandClipper.AddPaths(island.outlinePolygons, PolyType.ptSubject, true); //Then add existing segments such as top or bottom and outline as the clip foreach (LayerSegment segment in island.segmentList) { //We do not want to subtract outline segments because we already use the overall outline of the island if (segment.segmentType == SegmentType.OutlineSegment) { continue; } islandClipper.AddPaths(segment.outlinePolygons, PolyType.ptClip, true); } Polygons infillSegments = new Polygons(); //We then need to perform a difference operation to determine the infill segments islandClipper.Execute(ClipType.ctDifference, infillSegments); LayerSegment infillSegment = new LayerSegment(SegmentType.InfillSegment); infillSegment.outlinePolygons = infillSegments; infillSegment.segmentType = SegmentType.InfillSegment; infillSegment.segmentSpeed = Global.Values.layerComponentList[i].infillSpeed; island.segmentList.Add(infillSegment); } } }
/// <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> /// <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 mode, 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; 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, tolerance)); } return(polygons); }
/// <summary> /// Determines if the two polygons overlap. /// Polygons that touch at a vertex or along an edge are considered overlapping. /// </summary> public static bool OverlappingPolygons(string polygonWkt1, string polygonWkt2) { //Note: the clipper library uses 2D geometry while we have spherical coordinates. But it should be near enough for our purposes. var points1 = ConvertAndValidatePolygon(polygonWkt1); var points2 = ConvertAndValidatePolygon(polygonWkt2); //Simple bounding box check first. if (!BoundingBoxesOverlap(points1, points2)) { return(false); } // The clipper library doesn't work as expected for touching polygons so check. // Check both ways as a vertex of one polygon may be touching an edge of the other. foreach (var point in points1) { if (PointOnPolygonEdge(points2, point.X, point.Y)) { return(true); } } foreach (var point in points2) { if (PointOnPolygonEdge(points1, point.X, point.Y)) { return(true); } } // Now do the clipper polygon intersection check. var polygon1 = ClipperPolygon(points1); var polygon2 = ClipperPolygon(points2); var clipper = new Clipper(); clipper.AddPolygon(polygon1, PolyType.ptSubject); clipper.AddPolygon(polygon2, PolyType.ptClip); var intersectingPolygons = new List <List <IntPoint> >(); var succeeded = clipper.Execute(ClipType.ctIntersection, intersectingPolygons); return(succeeded && intersectingPolygons.Count > 0); }
public static Paths Clip_Paths(Paths subjpaths, bool blnSubjClosed, Paths clippaths, bool blnClipClosed, ClipType pClipType) { Clipper pClipper = new Clipper(); if (pClipper.AddPaths(subjpaths, PolyType.ptSubject, blnSubjClosed) == false || pClipper.AddPaths(clippaths, PolyType.ptClip, blnClipClosed) == false) { throw new ArgumentException("failed to add paths!"); } Paths clippedPaths = new Paths(); if (pClipper.Execute(pClipType, clippedPaths) == false) { throw new ArgumentException("failed to cut!"); } return(clippedPaths); }
/// <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> private static bool Covers(Polygon cover, Polygon polygon) { if (polygon == null) { return(false); } var clipper = new Clipper(); var solution = new List <List <IntPoint> >(); clipper.AddPath(cover.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 - cover.ToClipperPath().ToPolygon().Area) <= 0.0001); //return Math.Abs(solution.First().ToPolygon().Area - polygon.ToClipperPath().ToPolygon().Area) <= 0.0001; //return solution.First().ToPolygon().Area == polygon.ToClipperPath().ToPolygon().Area; }
public static bool IsPolyOperation(List <IntPoint> poly, List <List <IntPoint> > polys, ClipType cType) { Clipper c = new Clipper(); c.AddPolygons(new List <List <IntPoint> >() { poly }, PolyType.ptSubject); c.AddPolygons(polys, PolyType.ptClip); var solution = new List <List <IntPoint> >(); try { c.Execute(cType, solution, PolyFillType.pftPositive, PolyFillType.pftPositive); } catch (Exception) { } return(solution.Count != 0); }
private VertexStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType) { List <List <IntPoint> > aPolys = VertexSourceToClipperPolygons.CreatePolygons(a); List <List <IntPoint> > bPolys = VertexSourceToClipperPolygons.CreatePolygons(b); Clipper clipper = new Clipper(); clipper.AddPaths(aPolys, PolyType.ptSubject, true); clipper.AddPaths(bPolys, PolyType.ptClip, true); List <List <IntPoint> > intersectedPolys = new List <List <IntPoint> >(); clipper.Execute(clipType, intersectedPolys); VertexStorage output = VertexSourceToClipperPolygons.CreateVertexStorage(intersectedPolys); output.Add(0, 0, ShapePath.FlagsAndCommand.Stop); return(output); }
public void Clip(Vector2 center, float radius) { center.x *= MAP_SCALE_INV; center.y *= MAP_SCALE_INV; radius *= MAP_SCALE_INV; Path clip = new Path(); for (int th = 0; th < 360; th += 20) { clip.Add(new IntPoint((int)(center.x + radius * Mathf.Cos(th * Mathf.Deg2Rad)), (int)(center.y + radius * Mathf.Sin(th * Mathf.Deg2Rad)))); } Clipper c = new Clipper(); c.AddPaths(this.polygons, PolyType.ptSubject, true); c.AddPath(clip, PolyType.ptClip, true); c.Execute(ClipType.ctDifference, polygons); dirty = true; }
public static Ngons MinkowskiSumBoundary(Ngon pattern, Ngons path, bool flip_pattern) { Clipper clipper = new Clipper(); Ngons full = new Ngons(); for (int i = 0; i < path.Count; i++) { Ngons seg = MinkowskiSumBoundary(pattern, path[i], flip_pattern); clipper.AddPaths(full, PolyType.ptSubject, true); clipper.AddPaths(seg, PolyType.ptSubject, true); Ngons res = new Ngons(); clipper.Execute(ClipType.ctUnion, res, PolyFillType.pftNonZero); full = res; clipper.Clear(); } return(full); }
public static IEnumerable <IEnumerable <Vector2> > inverseWithOffset(IEnumerable <Vector2> subject, IEnumerable <IEnumerable <Vector2> > clips, float offset) { ClipperLibPolygons result = new ClipperLibPolygons(); Clipper c = new Clipper(); c.ReverseSolution = true; c.AddPaths(clips.Select(createPolygon).ToList(), PolyType.ptClip, true); c.AddPath(createPolygon(subject), PolyType.ptSubject, true); c.Execute(ClipType.ctDifference, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero); ClipperLibPolygons offsetResult = new ClipperLibPolygons(); ClipperOffset co = new ClipperOffset(); co.ArcTolerance = 0.25f * multiplier; co.AddPaths(result, JoinType.jtRound, EndType.etClosedPolygon); co.Execute(ref offsetResult, offset * multiplier); Clipper.ReversePaths(offsetResult); return(offsetResult.Select(createPoints)); }
public static XYPolygon GetIntersection(XYPolygon pol1, XYPolygon pol2) { List <List <IntPoint> > subj = new List <List <IntPoint> >(); subj.Add(new List <IntPoint>(pol1.Points.Count)); foreach (var p in pol1.Points) { subj[0].Add(new IntPoint(p.X, p.Y)); } List <List <IntPoint> > clip = new List <List <IntPoint> >(); clip.Add(new List <IntPoint>(pol2.Points.Count)); foreach (var p in pol2.Points) { clip[0].Add(new IntPoint(p.X, p.Y)); } List <List <IntPoint> > solution = new List <List <IntPoint> >(); Clipper c = new Clipper(); c.AddPaths(subj, PolyType.ptSubject, true); c.AddPaths(clip, PolyType.ptClip, true); c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); XYPolygon ToReturn = new XYPolygon(); if (solution.Count > 0) { foreach (var p in solution[0]) { ToReturn.Points.Add(new XYPoint(p.X, p.Y)); } } return(ToReturn); }
public double ComputeArea() { if (SubPolygons.Count == 0) { return(Polygon.GetArea()); } Clipper c = new Clipper(); Path polyPath = new Path(); foreach (Point2 point in Polygon.Points) { polyPath.Add(new IntPoint(point.X, point.Y)); } c.AddPath(polyPath, PolyType.ptSubject, true); foreach (Polygon poly in SubPolygons) { polyPath = new Path(); foreach (Point2 point in poly.Points) { polyPath.Add(new IntPoint(point.X, point.Y)); } c.AddPath(polyPath, PolyType.ptSubject, true); } Paths solution = new Paths(); c.Execute(ClipType.ctXor, solution, PolyFillType.pftEvenOdd); double clipperArea = 0.0; foreach (Path p in solution) { clipperArea += Clipper.Area(p); } return(clipperArea); }
// Use this for initialization void Start() { //listPolygonPath subj = new listPolygonPath (2); //listPolygonPath subj = new listPolygonPath (1); subj.Add(new PolygonPath(4)); subj[0].Add(new IntPoint(-180, 200)); subj[0].Add(new IntPoint(-260, 200)); subj[0].Add(new IntPoint(-260, 150)); subj[0].Add(new IntPoint(-220, 100)); subj[0].Add(new IntPoint(-180, 150)); //subj.Add (new Path (3)); //subj[1].Add (new IntPoint (215, 160)); //subj[1].Add (new IntPoint (230, 190)); //subj[1].Add (new IntPoint (200, 190)); //listPolygonPath clip = new listPolygonPath (1); clip.Add(new PolygonPath(4)); clip[0].Add(new IntPoint(-190, 210)); clip[0].Add(new IntPoint(-215, 190)); clip[0].Add(new IntPoint(-240, 210)); clip[0].Add(new IntPoint(-240, 130)); clip[0].Add(new IntPoint(-190, 130)); //DrawPolygons (subj, Color.FromArgb (0x16, 0, 0, 0xFF), Color.FromArgb (0x60, 0, 0, 0xFF)); DrawPolygons(subj, "0x0000FF9A".hexToColor(), "0x6000009A".hexToColor()); //DrawPolygons (clip, Color.FromArgb (0x20, 0xFF, 0xFF, 0), Color.FromArgb (0x30, 0xFF, 0, 0)); DrawPolygons(clip, "0x00FF009A".hexToColor(), "0x30FF009A".hexToColor()); //listPolygonPath solution = new listPolygonPath (); c = new Clipper(); c.AddPaths(subj, PolyType.ptSubject, true); c.AddPaths(clip, PolyType.ptClip, true); c.Execute(clipType, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); Debug.Log("solution count:" + solution.Count + " points count: " + (solution.Count > 0 ? solution[0].Count.ToString() : "0")); //DrawPolygons (solution, Color.FromArgb (0x30, 0, 0xFF, 0), Color.FromArgb (0xFF, 0, 0x66, 0)); DrawPolygons(solution, "0xFF00009A".hexToColor(), "0xFF00669A".hexToColor(), true); }
public void removeShapeCollider(List <Vector2> points, Vector3 position) { points = new List <Vector2>(points); if (collider.pathCount == 0) { return; } updatePointList(points, position); List <List <IntPoint> > pathclip = filterCollider(Vector2ArrayToListIntPoint(points.ToArray())); if (pathclip.Count == 0) { return; } Clipper c = new Clipper(); foreach (List <IntPoint> p in pathclip) { c.AddPath(p, PolyType.ptClip, true); } for (int i = 0; i < collider.pathCount; i++) { c.AddPath(Vector2ArrayToListIntPoint(collider.GetPath(i)), PolyType.ptSubject, true); } List <List <IntPoint> > solution = new List <List <IntPoint> >(); c.Execute(ClipType.ctDifference, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero); collider.pathCount = solution.Count; for (int i = 0; i < solution.Count; i++) { collider.SetPath(i, ListIntPointToVector2Array(solution[i])); } }
public JsonResult GetBySponsor(ObjectId id) { var spots = Context.SponsorSpots.GetSpotsBySponsors(id); Clipper clipper = new Clipper(); var polygons = new List <List <IntPoint> >(); var scale = 100000000.0; foreach (var spot in spots) { var polygon = new List <IntPoint>(); foreach (var coord in spot.SpotShape) { polygon.Add(new IntPoint(coord.Longitude * scale, coord.Latitude * scale)); } polygons.Add(polygon); } var solution = new List <List <IntPoint> >(); clipper.AddPaths(polygons, PolyType.ptSubject, true); clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero); var results = new List <Spot>(); foreach (var shape in solution) { var resultShape = new Spot(); foreach (var item in shape) { resultShape.SpotShape.Add(new Coordinate { Latitude = item.Y / scale, Longitude = item.X / scale }); } results.Add(resultShape); } return(Json(new { success = true, results = results }, JsonRequestBehavior.AllowGet)); }
private double calcCoverage(List <IntPoint> subject, List <IntPoint> clipping) { var clipper = new Clipper(); clipper.StrictlySimple = true; var solution = new List <List <IntPoint> >(); clipper.AddPath(subject, PolyType.ptSubject, true); clipper.AddPath(clipping, PolyType.ptClip, true); if (clipper.Execute(ClipType.ctIntersection, solution) == false || solution.Count != 1) { return(0); } var areaIntersection = Clipper.Area(solution[0]); var areaSubject = Clipper.Area(subject); return(areaIntersection / areaSubject); }
public void Clip(double x0, double x1, double y0, double y1) { var p00 = new Point3d(x0, y0, 0.0); var p01 = new Point3d(x0, y1, 0.0); var p11 = new Point3d(x1, y1, 0.0); var p10 = new Point3d(x1, y0, 0.0); var clip = new[] { p00, p10, p11, p01, p00 }.ToPolygon(Plane.WorldXY, Unit); var clipper = new Clipper(); clipper.AddPaths(Polygons, PolyType.ptSubject, true); clipper.AddPath(clip, PolyType.ptClip, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); Polygons = solution; Curves = Polygons.ToCurves(Plane, Unit); }
public static List <Polygon> Execute( Polygon a, Polygon b, ClipType clipType) { Paths solution = new Paths(); Clipper clipper = new Clipper(); clipper.AddPath(a.GetPoints(), PolyType.ptSubject, true); clipper.AddPath(b.GetPoints(), PolyType.ptClip, true); clipper.Execute(clipType, solution); List <Polygon> solutionPolygons = new List <Polygon>(); foreach (Path path in solution) { Polygon polygon = new Polygon(path); solutionPolygons.Add(polygon); } return(solutionPolygons); }
public static List <Polygon> Merge(List <Polygon> polygons) { var resultPolygons = new List <Polygon>(); if (polygons == null || polygons.Count == 0) { return(resultPolygons); } var polyPaths = new List <List <IntPoint> >(); foreach (Polygon polygon in polygons) { polyPaths.Add(polygon.PolygonToClipper()); } Clipper clipper = new Clipper(); clipper.AddPaths(polyPaths, PolyType.ptClip, true); clipper.AddPaths(polyPaths, PolyType.ptSubject, true); var solution = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero); if (solution.Count == 0) { return(resultPolygons); } foreach (var solved in solution) { var polygon = solved.ToList().PolygonFromClipper(); if (polygon == null) { continue; } if (polygon.IsClockWise()) { polygon = polygon.Reversed(); } resultPolygons.Add(polygon); } return(resultPolygons.OrderByDescending(p => p.Area()).ToList()); }
public static void GenerateLinePaths(Polygons in_outline, ref Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0) { if (in_outline.Count > 0) { Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um); if (outlines.Count > 0) { PointMatrix matrix = new PointMatrix(-(rotation + 90)); // we are rotating the part so we rotate by the negative so the lines go the way we expect outlines.ApplyMatrix(matrix); Aabb boundary = new Aabb(outlines); boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing - rotationOffset; int xLineCount = (int)((boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing); Polygons unclipedPatern = new Polygons(); long firstX = boundary.min.X / lineSpacing * lineSpacing; for (int lineIndex = 0; lineIndex < xLineCount; lineIndex++) { Polygon line = new Polygon(); line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.min.Y)); line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.max.Y)); unclipedPatern.Add(line); } PolyTree ret = new PolyTree(); Clipper clipper = new Clipper(); clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false); clipper.AddPaths(outlines, PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd); Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret); PointMatrix inversematrix = new PointMatrix((rotation + 90)); newSegments.ApplyMatrix(inversematrix); result.AddRange(newSegments); } } }
/// <summary> /// can generate a Int64MapExceptionRange exception if double values can't fit into a In64 representation. /// In that case try with tolerances not too small. /// It is suggested to use a lenTol/10 to avoid lost of precision during domain conversions. /// </summary> public static IEnumerable <IEnumerable <Vector3D> > Boolean(this IEnumerable <Vector3D> polyA, double tol, IEnumerable <Vector3D> polyB, ClipType type, bool selfCheckInt64MapTolerance = true) { var intmap = new Int64Map(tol, polyA.SelectMany(x => x.Coordinates).Union(polyB.SelectMany(x => x.Coordinates)), selfCheckInt64MapTolerance); var clipper = new Clipper(); { var path = polyA.Select(p => new IntPoint(intmap.ToInt64(p.X), intmap.ToInt64(p.Y))).ToList(); clipper.AddPath(path, PolyType.ptSubject, true); } { var path = polyB.Select(p => new IntPoint(intmap.ToInt64(p.X), intmap.ToInt64(p.Y))).ToList(); clipper.AddPath(path, PolyType.ptClip, true); } var sol = new List <List <IntPoint> >(); clipper.Execute(type, sol); var res = sol.Select(s => s.Select(si => new Vector3D(intmap.FromInt64(si.X), intmap.FromInt64(si.Y), 0))); return(res); }
public static VertexStorage MergePaths(this IVertexSource a, IVertexSource b, ClipType clipType) { List <List <IntPoint> > aPolys = a.CreatePolygons(); List <List <IntPoint> > bPolys = b.CreatePolygons(); var clipper = new Clipper(); clipper.AddPaths(aPolys, PolyType.ptSubject, true); clipper.AddPaths(bPolys, PolyType.ptClip, true); var outputPolys = new List <List <IntPoint> >(); clipper.Execute(clipType, outputPolys); Clipper.CleanPolygons(outputPolys); VertexStorage output = outputPolys.CreateVertexStorage(); output.Add(0, 0, ShapePath.FlagsAndCommand.Stop); return(output); }
private PathStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType) { List <List <IntPoint> > aPolys = CreatePolygons(a); List <List <IntPoint> > bPolys = CreatePolygons(b); Clipper clipper = new Clipper(); clipper.AddPaths(aPolys, PolyType.ptSubject, true); clipper.AddPaths(bPolys, PolyType.ptClip, true); List <List <IntPoint> > intersectedPolys = new List <List <IntPoint> >(); clipper.Execute(clipType, intersectedPolys); PathStorage output = new PathStorage(); foreach (List <IntPoint> polygon in intersectedPolys) { bool first = true; foreach (IntPoint point in polygon) { if (first) { output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandMoveTo); first = false; } else { output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandLineTo); } } output.ClosePolygon(); } output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop); return(output); }
/// <summary> /// Updates the key definition to occupy a region of itself plus the specified other keys. /// </summary> /// <param name="keys">The keys to union with.</param> /// <returns>A new key definition with the updated region.</returns> private MouseKeyDefinition UnionWith(IList <MouseKeyDefinition> keys) { var newBoundaries = this.Boundaries.Select(b => new TPoint(b.X, b.Y)).ToList(); if (keys.Any()) { var cl = new Clipper(); cl.AddPath(this.GetPath(), PolyType.ptSubject, true); cl.AddPaths(keys.Select(x => x.GetPath()).ToList(), PolyType.ptClip, true); var union = new List <List <IntPoint> >(); cl.Execute(ClipType.ctUnion, union); if (union.Count > 1) { throw new ArgumentException("Cannot union two non-overlapping keys."); } newBoundaries = union.Single().ConvertAll <TPoint>(x => x); } return(new MouseKeyDefinition(this.Id, newBoundaries, this.KeyCodes.Single(), this.Text)); }
/// <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 union between this Polygon and the supplied list of Polygons. /// </summary> /// <param name="polygons">The list of Polygons 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 complete list of Polygons. /// </returns> public Polygon Union(IList <Polygon> polygons, double tolerance = Vector3.EPSILON) { var thisPath = this.ToClipperPath(tolerance); var polyPaths = new List <List <IntPoint> >(); foreach (Polygon polygon in polygons) { 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.ctUnion, solution); if (solution.Count > 1) { return(null); } return(solution.First().Distinct().ToList().ToPolygon(tolerance)); }
public void RectangularFillBetweenPolygons(ClipPaths paths, double cuttingdepth, double rapiddepth, double ystep, double x1, double x2, double y1, double y2, double stepdown) { ClipPaths clips = paths; // ClipPaths paths = new ClipPaths(); ClipperLib.Clipper cp = new Clipper(); //cp.add cp.AddPolygons(paths, PolyType.ptClip); for(double y = y1;y<y2;y+= ystep * 2) { ClipPath p = new ClipPath(); p.Add(new IntPoint() { X = (int)(x1 * 100000), Y = (int)(y * 100000) }); p.Add(new IntPoint() { X = (int)(x2 * 100000), Y = (int)(y * 100000) }); p.Add(new IntPoint() { X = (int)(x2 * 100000), Y = (int)((y+ystep) * 100000) }); p.Add(new IntPoint() { X = (int)(x1 * 100000), Y = (int)((y + ystep) * 100000) }); cp.AddPolygon(p, PolyType.ptSubject); } ClipPaths res = new ClipPaths(); cp.Execute(ClipType.ctDifference, res); AddClipperPolygonsToCarve(res, cuttingdepth, rapiddepth, stepdown); }
public static Polygons CreateLineIntersections(this Polygons polygons, Polygons other) { Clipper clipper = new Clipper(); clipper.AddPaths(other, PolyType.ptSubject, false); clipper.AddPaths(polygons, PolyType.ptClip, true); PolyTree clippedLines = new PolyTree(); clipper.Execute(ClipType.ctIntersection, clippedLines); return Clipper.OpenPathsFromPolyTree(clippedLines); }
public static List<Polygons> ProcessIntoSeparatIslands(this Polygons polygons) { List<Polygons> ret = new List<Polygons>(); Clipper clipper = new Clipper(); PolyTree resultPolyTree = new PolyTree(); clipper.AddPaths(polygons, PolyType.ptSubject, true); clipper.Execute(ClipType.ctUnion, resultPolyTree); polygons.ProcessPolyTreeNodeIntoSeparatIslands(resultPolyTree, ret); return ret; }
public static Polygons GetCorrectedWinding(this Polygons polygonsToFix) { polygonsToFix = Clipper.CleanPolygons(polygonsToFix); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToFix); bounds.left -= 10; bounds.bottom += 10; bounds.right += 10; bounds.top -= 10; boundsPolygon.Add(new IntPoint(bounds.left, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom)); boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom)); Clipper clipper = new Clipper(); clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); PolyTree intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); return outputPolygons; }
public static Polygons CreateLineDifference(this Polygons linePolygons, Polygons removePolygons) { Clipper clipper = new Clipper(); clipper.AddPaths(linePolygons, PolyType.ptSubject, false); clipper.AddPaths(removePolygons, PolyType.ptClip, true); PolyTree clippedLines = new PolyTree(); clipper.Execute(ClipType.ctDifference, clippedLines); return Clipper.OpenPathsFromPolyTree(clippedLines); }
private bool Intersect(Point2D[] rect1, Point2D[] rect2) { Clipper clipper = new Clipper(); AddRect(clipper, rect1, PolyType.ptSubject); AddRect(clipper, rect2, PolyType.ptClip); List<List<IntPoint>> paths = new List<List<IntPoint>>(); clipper.Execute(ClipType.ctIntersection, paths, PolyFillType.pftNonZero, PolyFillType.pftNonZero); return paths.Count != 0; }
/// <summary> /// Gets the union coordinates of specified district key. /// </summary> /// <returns>The coordinates.</returns> /// <param name="districtKeys">Array of district key.</param> public static IEnumerable<Coordinate> GetUnionCoordinates(String[] districtKeys) { // Using Clipper library to do polygon operation. var clipper = new Clipper(); foreach (var dk in districtKeys) { var polies = new List<List<IntPoint>>(); var areas = GetCoordinates(dk); foreach(var a in areas) { polies.Add(new List<IntPoint>()); foreach (var c in a) polies[0].Add(new IntPoint(Utils.ToLong(c.X), Utils.ToLong(c.Y))); } clipper.AddPaths(polies, PolyType.ptSubject, true); } var solution = new List<List<IntPoint>>(); clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); var coords = new List<Coordinate>(); foreach (var areas in solution) { foreach(var p in areas) { var c = new Coordinate() { X = Utils.ToDouble(p.X), Y = Utils.ToDouble(p.Y) }; coords.Add(c); } } return coords; }
public static Polygons ProcessEvenOdd(this Polygons polygons) { Polygons ret = new Polygons(); Clipper clipper = new Clipper(); clipper.AddPaths(polygons, PolyType.ptSubject, true); clipper.Execute(ClipType.ctUnion, ret); return ret; }
public static Polygons CreateUnion(this Polygons polygons, Polygons other) { Polygons ret = new Polygons(); Clipper clipper = new Clipper(); clipper.AddPaths(polygons, PolyType.ptSubject, true); clipper.AddPaths(other, PolyType.ptSubject, true); clipper.Execute(ClipType.ctUnion, ret, PolyFillType.pftNonZero, PolyFillType.pftNonZero); return ret; }
public static List<Polygons> CreateLayerOutlines(this Polygons polygons, LayerOpperation opperation) { List<Polygons> ret = new List<Polygons>(); Clipper clipper = new Clipper(); PolyTree resultPolyTree = new PolyTree(); clipper.AddPaths(polygons, PolyType.ptSubject, true); if (opperation == LayerOpperation.UnionAll) { clipper.Execute(ClipType.ctUnion, resultPolyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero); } else { clipper.Execute(ClipType.ctUnion, resultPolyTree); } polygons._processPolyTreeNode(resultPolyTree, ret); return ret; }
public static Polygons CreateIntersection(this Polygons polygons, Polygons other) { Polygons ret = new Polygons(); Clipper clipper = new Clipper(); clipper.AddPaths(polygons, PolyType.ptSubject, true); clipper.AddPaths(other, PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, ret); return ret; }
/** * Note: this method will close all unclosed subpaths of the passed path. * * @param fillingRule If the subpath is contour, pass any value. */ protected internal Path FilterFillPath(Path path, Matrix ctm, int fillingRule) { path.CloseAllSubpaths(); Clipper clipper = new Clipper(); AddPath(clipper, path); foreach (Rectangle rectangle in rectangles) { Point2D[] transfRectVertices = TransformPoints(ctm, true, GetVertices(rectangle)); AddRect(clipper, transfRectVertices, PolyType.ptClip); } PolyFillType fillType = PolyFillType.pftNonZero; if (fillingRule == PathPaintingRenderInfo.EVEN_ODD_RULE) { fillType = PolyFillType.pftEvenOdd; } PolyTree resultTree = new PolyTree(); clipper.Execute(ClipType.ctDifference, resultTree, fillType, PolyFillType.pftNonZero); return ConvertToPath(resultTree); }
/// <summary> /// Subtract 2 polygon coordinates by top - bottom. /// </summary> /// <returns>The subtracted coordinates.</returns> /// <param name="top">Top polygon coordinates.</param> /// <param name="bottom">Bottom polygon coordinates.</param> public static IEnumerable<Coordinate> Subtract(IEnumerable<Coordinate> top, IEnumerable<Coordinate> bottom) { // Using Clipper library to do polygon operation. var clipper = new Clipper(); var topPolies = new List<List<IntPoint>>(); topPolies.Add(new List<IntPoint>()); foreach(var c in top) { topPolies[0].Add( new IntPoint(Utils.ToLong(c.X), Utils.ToLong(c.Y))); } clipper.AddPaths(topPolies, PolyType.ptSubject, true); var bottomPolies = new List<List<IntPoint>>(); bottomPolies.Add(new List<IntPoint>()); foreach(var c in bottom) { bottomPolies[0].Add( new IntPoint(Utils.ToLong(c.X), Utils.ToLong(c.Y))); } clipper.AddPaths(bottomPolies, PolyType.ptClip, true); var solution = new List<List<IntPoint>>(); clipper.Execute(ClipType.ctXor, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); var coords = new List<Coordinate>(); foreach (var areas in solution) { foreach(var p in areas) { var c = new Coordinate() { X = Utils.ToDouble(p.X), Y = Utils.ToDouble(p.Y) }; coords.Add(c); } } return coords; }
//------------------------------------------------------------------------------ public List<List<Point>> Execute(double deltap, double eps = double.Epsilon) { var solution = new List<List<Point>>(); FixPerimeters(); DoOffset(deltap, eps); //now clean up 'corners' ... var clpr = new Clipper(); clpr.AddPaths(destPolys, PolyType.Subject); if (deltap > 0) { clpr.Execute(ClipType.Union, solution, PolyFillType.Positive, PolyFillType.Positive); } else { var r = destPolys.GetBounds(); var outer = new List<Point>(4) { new Point(r.Left - 10, r.Bottom + 10), new Point(r.Right + 10, r.Bottom + 10), new Point(r.Right + 10, r.Top - 10), new Point(r.Left - 10, r.Top - 10) }; clpr.AddPath(outer, PolyType.Subject); clpr.ReverseSolution = true; clpr.Execute(ClipType.Union, solution, PolyFillType.Negative, PolyFillType.Negative); if (solution.Count > 0) solution.RemoveAt(0); } return solution; }
public static void GenerateHexLinePaths(Polygons in_outline, ref Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotationDegrees, int layerIndex) { int extraRotationAngle = 0; if (in_outline.Count > 0) { Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um); if (outlines.Count > 0) { int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5); PointMatrix matrix = new PointMatrix(-(rotationDegrees + extraRotationAngle)); // we are rotating the part so we rotate by the negative so the lines go the way we expect outlines.ApplyMatrix(matrix); Aabb boundary = new Aabb(outlines); boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing; boundary.min.Y = ((boundary.min.Y / perIncrementOffset) - 2) * perIncrementOffset; boundary.max.X += lineSpacing; boundary.max.Y += perIncrementOffset; Polygons unclipedPatern = new Polygons(); foreach (IntPoint startPoint in StartPositionIterator(boundary, lineSpacing, layerIndex)) { Polygon attachedLine = new Polygon(); foreach (IntPoint center in IncrementPositionIterator(startPoint, boundary, lineSpacing, layerIndex)) { // what we are adding are the little plusses that define the points // | top // | // /\ center // left/ \ right // IntPoint left = center + new IntPoint(-lineSpacing / 2, -perIncrementOffset / 3); IntPoint right = center + new IntPoint(lineSpacing / 2, -perIncrementOffset / 3); IntPoint top = center + new IntPoint(0, perIncrementOffset * 2 / 3); switch (layerIndex % 3) { case 0: // left to right attachedLine.Add(left); attachedLine.Add(center); attachedLine.Add(center); attachedLine.Add(right); unclipedPatern.Add(new Polygon() { top, center }); break; case 1: // left to top attachedLine.Add(left); attachedLine.Add(center); attachedLine.Add(center); attachedLine.Add(top); unclipedPatern.Add(new Polygon() { center, right }); break; case 2: // top to right attachedLine.Add(top); attachedLine.Add(center); attachedLine.Add(center); attachedLine.Add(right); unclipedPatern.Add(new Polygon() { left, center }); break; } } if (attachedLine.Count > 0) { unclipedPatern.Add(attachedLine); } } PolyTree ret = new PolyTree(); Clipper clipper = new Clipper(); clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false); clipper.AddPaths(outlines, PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd); Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret); PointMatrix inversematrix = new PointMatrix((rotationDegrees + extraRotationAngle)); newSegments.ApplyMatrix(inversematrix); result.AddRange(newSegments); } } }