Beispiel #1
0
        public void Execute(ref List <List <IntPoint> > solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);
            Clipper clipper = new Clipper(0);

            clipper.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0.0)
            {
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         bounds = ClipperBase.GetBounds(m_destPolys);
                List <IntPoint> list   = new List <IntPoint>(4);
                list.Add(new IntPoint(bounds.left - 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.top - 10));
                list.Add(new IntPoint(bounds.left - 10, bounds.top - 10));
                clipper.AddPath(list, PolyType.ptSubject, true);
                clipper.ReverseSolution = true;
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                if (solution.Count > 0)
                {
                    solution.RemoveAt(0);
                }
            }
        }
Beispiel #2
0
        public static Polygons GetCorrectedWinding(this Polygons polygonsToFix)
        {
            polygonsToFix = Clipper.CleanPolygons(polygonsToFix);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToFix);

            bounds.minX -= 10;
            bounds.minY -= 10;
            bounds.maxY += 10;
            bounds.maxX += 10;

            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY));
            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY));

            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);
        }
Beispiel #3
0
        public static Ngons MinkowskiSumSegment(Ngon pattern, IntPoint p1, IntPoint p2, bool flip_pattern)
        {
            Clipper clipper = new Clipper();

            Ngon p1_c = pattern.Clone(p1.X, p1.Y, flip_pattern);

            if (p1 == p2)
            {
                return new Ngons()
                       {
                           p1_c
                       }
            }
            ;

            Ngon p2_c = pattern.Clone(p2.X, p2.Y, flip_pattern);

            Ngons full = new Ngons();

            clipper.AddPath(p1_c, PolyType.ptSubject, true);
            clipper.AddPath(p2_c, PolyType.ptSubject, true);
            clipper.AddPaths(Clipper.MinkowskiSum(pattern.Clone(0, 0, flip_pattern), new Ngon()
            {
                p1, p2
            }, false), PolyType.ptSubject, true);
            clipper.Execute(ClipType.ctUnion, full, PolyFillType.pftNonZero);

            return(full);
        }
Beispiel #4
0
        /// <summary>
        /// Checks if polygons are intersecting
        /// </summary>
        /// <param name="p1">Subject polygon</param>
        /// <param name="p2">Clip polygon(s)</param>
        /// <returns>true if intersects</returns>
        public static bool IsIntersects(Paths p1, params Paths[] p2)
        {
            Clipper c        = new Clipper();
            Paths   solution = new Paths();

            c.AddPaths(p1, PolyType.ptSubject, true);

            for (int i = 0; i < p2.Length; i++)
            {
                c.AddPaths(p2[i], PolyType.ptClip, true);
            }

            c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(solution.Count != 0);
        }
Beispiel #5
0
        private Polygons FixWinding(Polygons polygonsToPathAround)
        {
            polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToPathAround);

            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(polygonsToPathAround, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            PolyTree intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            Clipper.ReversePaths(outputPolygons);

            return(outputPolygons);
        }
Beispiel #6
0
        /// <summary>
        /// Add the 2D projection of the given arc
        /// to the current element outline union
        /// </summary>
        static public bool AddToUnion(
            Polygons union,
            VertexLookup vl,
            Clipper c,
            Arc arc)
        {
            IList <XYZ> pts = arc.Tessellate();
            int         n   = pts.Count;

            Polygons faces  = new Polygons(1);
            Polygon  face2d = new Polygon(n);

            IntPoint a = vl.GetOrAdd(pts[0]);

            face2d.Add(a);

            for (int i = 1; i < n; ++i)
            {
                IntPoint b = vl.GetOrAdd(pts[i]);

                if (b != a)
                {
                    face2d.Add(b);
                    a = b;
                }
            }
            faces.Add(face2d);

            return(c.AddPaths(faces, PolyType.ptSubject, true));
        }
Beispiel #7
0
        /// <summary>
        /// Constructs the geometric difference between this Polygon and the supplied Polygons.
        /// </summary>
        /// <param name="difPolys">The list of intersecting Polygons.</param>
        /// <returns>
        /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon.
        /// Returns null if the area of this Polygon is entirely subtracted.
        /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect.
        /// </returns>
        public IList <Polygon> Difference(IList <Polygon> difPolys)
        {
            var thisPath  = this.ToClipperPath();
            var polyPaths = new List <List <IntPoint> >();

            foreach (Polygon polygon in difPolys)
            {
                polyPaths.Add(polygon.ToClipperPath());
            }
            Clipper clipper = new Clipper();

            clipper.AddPath(thisPath, PolyType.ptSubject, true);
            clipper.AddPaths(polyPaths, PolyType.ptClip, true);
            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctDifference, solution);
            if (solution.Count == 0)
            {
                return(null);
            }
            var polygons = new List <Polygon>();

            foreach (List <IntPoint> path in solution)
            {
                polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList()));
            }
            return(polygons);
        }
Beispiel #8
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 KeyboardKeyDefinition UnionWith(IList <KeyboardKeyDefinition> 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 KeyboardKeyDefinition(
                       this.Id,
                       newBoundaries,
                       this.KeyCodes,
                       this.Text,
                       this.ShiftText,
                       this.ChangeOnCaps));
        }
Beispiel #9
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;
 }
Beispiel #10
0
        public void GenerateMarchingSquaresAndLines(Action <double, string> progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction)
        {
            if (image != null)
            {
                // Regenerate outline
                var marchingSquaresData = new MarchingSquaresByte(
                    image,
                    thresholdFunction.ZeroColor,
                    thresholdFunction.Threshold,
                    0);

                progressReporter?.Invoke(0, "Creating Outline");

                marchingSquaresData.CreateLineSegments();
                progressReporter?.Invoke(.1, null);

                int pixelsToIntPointsScale = 1000;
                var lineLoops = marchingSquaresData.CreateLineLoops(pixelsToIntPointsScale);

                progressReporter?.Invoke(.15, null);

                var min = new IntPoint(-10, -10);
                var max = new IntPoint(10 + image.Width * pixelsToIntPointsScale, 10 + image.Height * pixelsToIntPointsScale);

                var boundingPoly = new Polygon();
                boundingPoly.Add(min);
                boundingPoly.Add(new IntPoint(min.X, max.Y));
                boundingPoly.Add(max);
                boundingPoly.Add(new IntPoint(max.X, min.Y));

                // now clip the polygons to get the inside and outside polys
                var clipper = new Clipper();
                clipper.AddPaths(lineLoops, PolyType.ptSubject, true);
                clipper.AddPath(boundingPoly, PolyType.ptClip, true);

                var polygonShape = new Polygons();
                progressReporter?.Invoke(.3, null);

                clipper.Execute(ClipType.ctIntersection, polygonShape);

                progressReporter?.Invoke(.55, null);

                polygonShape = Clipper.CleanPolygons(polygonShape, 100);

                progressReporter?.Invoke(.75, null);

                VertexStorage rawVectorShape = polygonShape.PolygonToPathStorage();

                var aabb   = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox();
                var xScale = aabb.XSize / image.Width;

                var affine = Affine.NewScaling(1.0 / pixelsToIntPointsScale * xScale);
                affine *= Affine.NewTranslation(-aabb.XSize / 2, -aabb.YSize / 2);

                rawVectorShape.transform(affine);
                this.VertexSource = rawVectorShape;

                progressReporter?.Invoke(1, null);
            }
        }
Beispiel #11
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;
 }
Beispiel #12
0
        private void Clip(NavigationPolygon floor, NavigationPolygons staticObjects)
        {
            Clipper clipper = new Clipper();

            if (!clipper.AddPath(floor, PolyType.ptSubject, true))
            {
                throw new Exception("Can't add Paths (Subject).");
            }

            if (staticObjects.Count > 0 && !clipper.AddPaths(staticObjects, PolyType.ptClip, true))
            {
                throw new Exception("Can't add Paths (Clip).");
            }

            // we do it twice (it's easier than deep copy the polygons), since this is loading screen time... We don't mind performance too much here
            if (!clipper.Execute(ClipType.ctDifference, floorWithStaticObjects, PolyFillType.pftNonZero))
            {
                throw new Exception("Can't clip floorWithStaticObjects.");
            }

            if (!clipper.Execute(ClipType.ctDifference, FloorWithDynamicObjects, PolyFillType.pftNonZero))
            {
                throw new Exception("Can't clip floorWithStaticObjects.");
            }

            clipper.Reset();
        }
Beispiel #13
0
        //------------------------------------------------------------------------------

        public void Execute(ref Paths sol, double delta)
        {
            sol.Clear();
            if (nodes.Count == 0)
            {
                return;
            }

            GetLowestPolygonIdx();
            bool negate = (lowestIdx >= 0 && Area(nodes[lowestIdx].path) < 0);

            //if polygon orientations are reversed, then 'negate' ...
            if (negate)
            {
                this.delta = -delta;
            }
            else
            {
                this.delta = delta;
            }
            DoOffset(this.delta);

            //now clean up 'corners' ...
            Clipper clpr = new Clipper();

            clpr.AddPaths(solution, PathType.Subject);
            if (negate)
            {
                clpr.Execute(ClipType.Union, sol, FillRule.Negative);
            }
            else
            {
                clpr.Execute(ClipType.Union, sol, FillRule.Positive);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Constructs the geometric difference between this Polygon and the supplied Polygons.
        /// </summary>
        /// <param name="difPolys">The list of intersecting Polygons.</param>
        /// <param name="tolerance">An optional tolerance value.</param>
        /// <returns>
        /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon.
        /// Returns null if the area of this Polygon is entirely subtracted.
        /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect.
        /// </returns>
        public IList <Polygon> Difference(IList <Polygon> difPolys, double tolerance = Vector3.EPSILON)
        {
            var thisPath  = this.ToClipperPath(tolerance);
            var polyPaths = new List <List <IntPoint> >();

            foreach (Polygon polygon in difPolys)
            {
                polyPaths.Add(polygon.ToClipperPath(tolerance));
            }
            Clipper clipper = new Clipper();

            clipper.AddPath(thisPath, PolyType.ptSubject, true);
            clipper.AddPaths(polyPaths, PolyType.ptClip, true);
            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctDifference, solution);
            if (solution.Count == 0)
            {
                return(null);
            }
            var polygons = new List <Polygon>();

            foreach (List <IntPoint> path in solution)
            {
                try
                {
                    polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList(), tolerance));
                }
                catch
                {
                    // swallow invalid polygons
                }
            }
            return(polygons);
        }
Beispiel #15
0
        public static Polygons GetCorrectedWinding(this Polygons polygonsToFix)
        {
            polygonsToFix = Clipper.CleanPolygons(polygonsToFix);
            var     boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToFix);

            bounds.left   -= 10;
            bounds.top    -= 10;
            bounds.bottom += 10;
            bounds.right  += 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));

            var clipper = new Clipper();

            clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            var intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            return(outputPolygons);
        }
        private Polygons FixWinding(Polygons polygonsToPathAround)
        {
            polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToPathAround);

            bounds.minX -= 10;
            bounds.maxY += 10;
            bounds.maxX += 10;
            bounds.minY -= 10;

            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY));
            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY));

            Clipper clipper = new Clipper();

            clipper.AddPaths(polygonsToPathAround, 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);
        }
Beispiel #17
0
        public void RemoveHoles(float maxPerimiter)
        {
            Paths    keep = new Paths();
            PolyNode node = polyTree.GetFirst();

            while (node != null)
            {
                if (node.IsHole && node.ChildCount == 0)
                {
                    var   line   = LineStripFromPolygon(node.Contour);
                    float length = line.Length(LineStrip.Type.Closed);
                    if (length < maxPerimiter)
                    {
                        // Remove it
                    }
                    else
                    {
                        keep.Add(node.Contour);
                    }
                }
                else
                {
                    keep.Add(node.Contour);
                }
                node = node.GetNext();
            }
            Clipper c = new Clipper();

            c.Clear();
            c.AddPaths(keep, PolyType.ptSubject, true);
            polyTree = new PolyTree();
            c.Execute(ClipType.ctUnion, polyTree);
        }
Beispiel #18
0
        private Polygons CreateTravelPath(Polygons polygonsToPathAround, Polygons travelPolysLine)
        {
            Clipper clipper = new Clipper();

            clipper.AddPaths(travelPolysLine, PolyType.ptSubject, false);
            clipper.AddPaths(polygonsToPathAround, PolyType.ptClip, true);

            PolyTree clippedLine = new PolyTree();

            //List<List<IntPoint>> intersectedPolys = new List<List<IntPoint>>();
            //clipper.Execute(ClipType.ctDifference, intersectedPolys);

            clipper.Execute(ClipType.ctDifference, clippedLine);

            return(Clipper.OpenPathsFromPolyTree(clippedLine));
        }
Beispiel #19
0
        /// <summary>
        ///     Checks if polygons are intersecting
        /// </summary>
        /// <param name="p1">Subject polygon</param>
        /// <param name="p2">Clip polygon(s)</param>
        /// <returns>true if intersects</returns>
        public static bool IsIntersects(Paths p1, params Paths[] p2)
        {
            var c        = new Clipper();
            var solution = new Paths();

            c.AddPaths(p1, PolyType.ptSubject, true);

            foreach (Paths t in p2)
            {
                c.AddPaths(t, PolyType.ptClip, true);
            }

            c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(solution.Count != 0);
        }
Beispiel #20
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="booleanMode">The operation to apply: Union, Difference, Intersection, or XOr</param>
        /// <param name="voidTreatment">Optional setting for how to process the polygons in each set: either treat polygons inside others as voids, or treat them all as solid (thereby ignoring internal polygons).</param>
        /// <param name="tolerance">Optional override of the tolerance for determining if two polygons are identical.</param>
        private static IList <Polygon> BooleanTwoSets(IList <Polygon> subjectPolygons, IList <Polygon> clippingPolygons, BooleanMode booleanMode, VoidTreatment voidTreatment = VoidTreatment.PreserveInternalVoids, double tolerance = Vector3.EPSILON)
        {
            var     subjectPaths = subjectPolygons.Select(s => s.ToClipperPath(tolerance)).ToList();
            var     clipPaths    = clippingPolygons.Select(s => s.ToClipperPath(tolerance)).ToList();
            Clipper clipper      = new Clipper();

            clipper.AddPaths(subjectPaths, PolyType.ptSubject, true);
            clipper.AddPaths(clipPaths, PolyType.ptClip, true);
            var solution      = new List <List <IntPoint> >();
            var executionMode = ClipType.ctDifference;
            var polyFillType  = PolyFillType.pftEvenOdd;

            if (voidTreatment == VoidTreatment.IgnoreInternalVoids)
            {
                polyFillType = PolyFillType.pftNonZero;
            }
            switch (booleanMode)
            {
            case BooleanMode.Difference:
                executionMode = ClipType.ctDifference;
                break;

            case BooleanMode.Union:
                executionMode = ClipType.ctUnion;
                break;

            case BooleanMode.Intersection:
                executionMode = ClipType.ctIntersection;
                break;

            case BooleanMode.XOr:
                executionMode = ClipType.ctXor;
                break;
            }
            clipper.Execute(executionMode, solution, polyFillType);
            if (solution.Count == 0)
            {
                return(null);
            }
            var polygons = new List <Polygon>();

            foreach (List <IntPoint> path in solution)
            {
                polygons.Add(PolygonExtensions.ToPolygon(path, tolerance));
            }
            return(polygons);
        }
Beispiel #21
0
        public bool CheckForOverLaps(Polygon otherPolygon)
        {
            var subj = new List <List <IntPoint> >();
            var clip = new List <List <IntPoint> >();

            subj.Add(ToClipperPath());
            clip.Add(otherPolygon.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.ctIntersection, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            return(solution.Count != 0);
        }
Beispiel #22
0
        private static Polygon ClipPolygon(Polygon subject, Polygon clip, ClipType operation)
        {
            Paths clprResult = new Paths();
            // Convert to library structure
            Paths clprSubject = PolygonToClprPaths(subject);
            Paths clprClip    = PolygonToClprPaths(clip);

            // Execute clip action
            lock (ClipperEngine) {
                ClipperEngine.Clear();
                ClipperEngine.AddPaths(clprSubject, PolyType.ptSubject, true);
                ClipperEngine.AddPaths(clprClip, PolyType.ptClip, true);
                ClipperEngine.Execute(operation, clprResult);
            }
            // Convert back to common polygon
            return(ClprPathsToPolygon(clprResult));
        }
Beispiel #23
0
        static public IPolygon Clip(this IPolygon clippee, Envelope clipper)
        {
            var clippeePolygons = clippee.ToClipperPolygons();
            var clipperPolygons = clipper.ToPolygon().ToClipperPolygons();

            var c = new Clipper();
            c.AddPaths(clippeePolygons, PolyType.ptSubject, true);
            c.AddPaths(clipperPolygons, PolyType.ptClip, true);

            ClipperPolygons result = new ClipperPolygons();
            if (c.Execute(ClipType.ctIntersection, result) == true)
            {
                return result.ToPolygon();
            }

            return clippee;
        }
Beispiel #24
0
        /// <summary>
        /// Constructs the geometric intersections between two supplied Lists of Polygons.
        /// </summary>
        /// <param name="polygons">List of subject Polygons for the difference calculation.</param>
        /// <param name="inters">List of clipping Polygons for the difference calculation.</param>
        /// <returns>
        /// A List of Polygons representing the subtraction of the clipping Polygons from the subject Polygons.
        /// </returns>
        public static List <Polygon> Intersections(List <Polygon> polygons, List <Polygon> inters, double tolerance = 0.01)
        {
            var resultPolygons = new List <Polygon>();

            if (polygons == null || polygons.Count == 0 ||
                inters == null || inters.Count == 0)
            {
                return(resultPolygons);
            }
            var polyPaths = new List <List <IntPoint> >();
            var intrPaths = new List <List <IntPoint> >();

            foreach (Polygon polygon in polygons)
            {
                polyPaths.Add(polygon.PolygonToClipper());
            }
            foreach (Polygon polygon in inters)
            {
                intrPaths.Add(polygon.PolygonToClipper());
            }
            Clipper clipper = new Clipper();

            clipper.AddPaths(polyPaths, PolyType.ptSubject, true);
            clipper.AddPaths(intrPaths, PolyType.ptClip, true);
            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctIntersection, 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.Where(p => p.Area() >= tolerance).OrderByDescending(p => p.Area()).ToList());
        }
Beispiel #25
0
        /// <summary>
        /// process the difference between this and other
        /// </summary>
        /// <param name="other"></param>
        /// <param name="type">http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/ClipType.htm</param>
        /// <returns></returns>
        public List <Vector2> Clip(Polygon other, PolygonOps op)
        {
            var type = (ClipType)op;
            var subj = new Paths(1);

            subj.Add(ToClipper(this.points));
            var clip = new Paths(1);

            clip.Add(ToClipper(other.Points));
            Paths   solution = new Paths();
            Clipper clp      = new Clipper();

            clp.AddPaths(subj, PolyType.ptSubject, true);
            clp.AddPaths(clip, PolyType.ptClip, true);
            clp.Execute(type, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            return(solution.Count > 0 ? FromClipper(solution[0]) : null);
        }
Beispiel #26
0
        public static NFP[] intersection(NFP polygon, NFP polygon1, double offset, JoinType jType = JoinType.jtMiter, double clipperScale = 10000000, double curveTolerance = 0.72, double miterLimit = 4)
        {
            var p  = ToClipperCoordinates(new[] { polygon }, clipperScale).ToList();
            var p1 = ToClipperCoordinates(new[] { polygon1 }, clipperScale).ToList();

            Clipper clipper = new Clipper();

            clipper.AddPaths(p.Select(z => z.ToList()).ToList(), PolyType.ptClip, true);
            clipper.AddPaths(p1.Select(z => z.ToList()).ToList(), PolyType.ptSubject, true);

            List <List <IntPoint> > finalNfp = new List <List <IntPoint> >();

            if (clipper.Execute(ClipType.ctIntersection, finalNfp, PolyFillType.pftNonZero, PolyFillType.pftNonZero) && finalNfp != null && finalNfp.Count > 0)
            {
                return(finalNfp.Select(z => toNestCoordinates(z.ToArray(), clipperScale)).ToArray());
            }
            return(null);
        }
Beispiel #27
0
        public void createBasePolyTreeFromDescription()
        {
            // combine all paths
            polytree = new PolyTree();
            Clipper c = new Clipper(Clipper.ioPreserveCollinear);

            // sort paths for subj and holes


            c.AddPaths(paths, PolyType.ptSubject, true);
            if (clips.Count > 0)
            {
                //Debug.Log ("Have clip");
                c.AddPaths(paths, PolyType.ptClip, true);
            }

            c.Execute(ClipType.ctDifference, polytree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
        }
Beispiel #28
0
        public static List <XPolygon> Clip(ClipType clipType, List <XPolygon> subjects, List <XPolygon> clips, double scaleBy = 1000)
        {
            List <XPolygon> results = new List <XPolygon>();

            Paths subjPaths = ToPaths(subjects, scaleBy);
            Paths clipPaths = ToPaths(clips, scaleBy);

            Clipper clipper = new Clipper();

            clipper.AddPaths(clipPaths, PolyType.ptSubject, closed: true);
            clipper.AddPaths(subjPaths, PolyType.ptClip, closed: true);
            PolyTree result = new PolyTree();

            clipper.Execute(clipType, result, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            PathOrientation orientation = Clipper.Orientation(subjPaths.First()) == true ? PathOrientation.Anticlockwise : PathOrientation.Clockwise;

            return(FromPolyTree(result, orientation, scaleBy));
        }
Beispiel #29
0
        // perform union on a list of polygons
        public static Paths ClipperUnion(this 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.pftPositive);
            return(solution);
        }
Beispiel #30
0
        public static Polygons ProcessEvenOdd(this Polygons polygons)
        {
            var ret     = new Polygons();
            var clipper = new Clipper();

            clipper.AddPaths(polygons, PolyType.ptSubject, true);
            clipper.Execute(ClipType.ctUnion, ret);
            return(ret);
        }
Beispiel #31
0
        private static List <List <IntPoint> > ClipPolygons(IReadOnlyCollection <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);
        }
Beispiel #32
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);
				}
			}
		}
Beispiel #33
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;
        }
Beispiel #34
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;
		}
Beispiel #35
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;
		}
Beispiel #36
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;
 }
Beispiel #37
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;
 }
Beispiel #38
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;
        }
Beispiel #39
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;
 }
Beispiel #40
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);
				}
			}
		}
Beispiel #41
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);
		}
Beispiel #42
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;
		}
Beispiel #43
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;
		}
Beispiel #44
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);
		}