Exemplo n.º 1
0
 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
        }
Exemplo n.º 5
0
        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);
                }
            }
        }
Exemplo n.º 6
0
        /// <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);
        }
Exemplo n.º 7
0
        /// <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);
        }
Exemplo n.º 8
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);
        }
Exemplo n.º 9
0
        /// <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;
        }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
        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;
        }
Exemplo n.º 13
0
        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);
        }
Exemplo n.º 14
0
    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));
    }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
        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);
        }
Exemplo n.º 17
0
        // 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);
        }
Exemplo n.º 18
0
        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]));
            }
        }
Exemplo n.º 19
0
        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));
        }
Exemplo n.º 20
0
    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);
    }
Exemplo n.º 21
0
        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);
        }
Exemplo n.º 22
0
        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);
        }
Exemplo n.º 23
0
        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());
        }
Exemplo n.º 24
0
        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);
                }
            }
        }
Exemplo n.º 25
0
		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);
				}
			}
		}
Exemplo n.º 26
0
        /// <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);
        }
Exemplo n.º 27
0
    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);
    }
Exemplo n.º 28
0
        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);
        }
Exemplo n.º 29
0
        /// <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));
        }
Exemplo n.º 30
0
        /// <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);
        }
Exemplo n.º 31
0
        /// <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));
        }
Exemplo n.º 32
0
        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);
        }
Exemplo n.º 33
0
		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);
		}
Exemplo n.º 34
0
		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;
		}
Exemplo n.º 35
0
		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;
		}
Exemplo n.º 36
0
		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);
		}
Exemplo n.º 37
0
        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;
        }
Exemplo n.º 38
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;
		}
Exemplo n.º 39
0
 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;
 }
Exemplo n.º 40
0
 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;
 }
Exemplo n.º 41
0
        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;
        }
Exemplo n.º 42
0
 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;
 }
Exemplo n.º 43
0
        /**
         * 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);
        }
Exemplo n.º 44
0
		/// <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;
		}
Exemplo n.º 45
0
        //------------------------------------------------------------------------------
        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;
        }
Exemplo n.º 46
0
		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);
				}
			}
		}