示例#1
0
        public static List <GeneralPolygon2d> ComputeOffsetPolygon(GeneralPolygon2d poly, double fOffset, bool bMiter = false)
        {
            double nIntScale = GetIntScale(poly);

            CPolygonList clipper_polys = new CPolygonList();

            clipper_polys.Add(ClipperUtil.ConvertToClipper(poly.Outer, nIntScale));
            foreach (Polygon2d hole in poly.Holes)
            {
                clipper_polys.Add(ClipperUtil.ConvertToClipper(hole, nIntScale));
            }

            CPolygonList dilate_solution = new CPolygonList();

            try {
                ClipperOffset co = new ClipperOffset();
                if (bMiter)
                {
                    co.AddPaths(clipper_polys, JoinType.jtMiter, EndType.etClosedPolygon);
                }
                else
                {
                    co.AddPaths(clipper_polys, JoinType.jtRound, EndType.etClosedPolygon);
                }
                co.Execute(ref dilate_solution, fOffset * nIntScale);
            } catch /*( Exception e )*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ComputeOffsetPolygon: Clipper threw exception: " + e.Message);
                return(new List <GeneralPolygon2d>());
            }

            List <GeneralPolygon2d> polys = ClipperUtil.ConvertFromClipper(dilate_solution, nIntScale);

            return(polys);
        }
示例#2
0
        /// <summary>
        /// Compute offset polygon from all input polys (ie separate islands may merge)
        /// </summary>
        public static List <GeneralPolygon2d> ComputeOffsetPolygon(IEnumerable <GeneralPolygon2d> polys,
                                                                   double fOffset, bool bMiter = false, double minArea = -1)
        {
            double nIntScale = GetIntScale(polys);

            if (minArea < 0)
            {
                minArea = DiscardMinArea;
            }

            ClipperOffset co   = new ClipperOffset();
            PolyTree      tree = new PolyTree();

            try {
                foreach (GeneralPolygon2d poly in polys)
                {
                    CPolygonList clipper_poly = ConvertToClipper(poly, nIntScale);
                    if (bMiter)
                    {
                        co.AddPaths(clipper_poly, JoinType.jtMiter, EndType.etClosedPolygon);
                    }
                    else
                    {
                        co.AddPaths(clipper_poly, JoinType.jtRound, EndType.etClosedPolygon);
                    }
                }
                co.Execute(ref tree, fOffset * nIntScale);

                List <GeneralPolygon2d> result = new List <GeneralPolygon2d>();
                for (int ci = 0; ci < tree.ChildCount; ++ci)
                {
                    Convert(tree.Childs[ci], result, nIntScale, minArea);
                }
                return(result);
            } catch /*(Exception e)*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ComputeOffsetPolygon: Clipper threw exception: " + e.Message);
                return(new List <GeneralPolygon2d>());
            }
        }
示例#3
0
        public static List <GeneralPolygon2d> ComputeOffsetPolygon(Polygon2d poly, double fOffset, bool bSharp = false)
        {
            double nIntScale = GetIntScale(poly.Vertices);

            List <IntPoint> clipper_poly  = ClipperUtil.ConvertToClipper(poly, nIntScale);
            CPolygonList    clipper_polys = new CPolygonList()
            {
                clipper_poly
            };

            CPolygonList dilate_solution = new CPolygonList();

            try {
                ClipperOffset co = new ClipperOffset();
                if (bSharp)
                {
                    co.AddPaths(clipper_polys, JoinType.jtMiter, EndType.etClosedPolygon);
                }
                else
                {
                    co.AddPaths(clipper_polys, JoinType.jtRound, EndType.etClosedPolygon);
                }
                co.Execute(ref dilate_solution, fOffset * nIntScale);
            } catch /*( Exception e )*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ComputeOffsetPolygon: Clipper threw exception: " + e.Message);
                return(new List <GeneralPolygon2d>());
            }

            if (dilate_solution.Count == 0)
            {
                return(new List <GeneralPolygon2d>());
            }

            List <GeneralPolygon2d> polys = ClipperUtil.ConvertFromClipper(dilate_solution, nIntScale);

            return(polys);
        }
示例#4
0
        /// <summary>
        /// remove portions of polyline that are inside set of solids
        /// </summary>
        public static List <PolyLine2d> ClipAgainstPolygon(IEnumerable <GeneralPolygon2d> solids, PolyLine2d polyline, bool bIntersect = false)
        {
            double            nIntScale = Math.Max(GetIntScale(solids), GetIntScale(polyline.Vertices));
            List <PolyLine2d> result    = new List <PolyLine2d>();

            Clipper  clip = new Clipper();
            PolyTree tree = new PolyTree();

            try {
                foreach (GeneralPolygon2d poly in solids)
                {
                    CPolygonList clipper_poly = ConvertToClipper(poly, nIntScale);
                    clip.AddPaths(clipper_poly, PolyType.ptClip, true);
                }

                CPolyPath path = ConvertToClipper(polyline, nIntScale);
                clip.AddPath(path, PolyType.ptSubject, false);

                if (bIntersect)
                {
                    clip.Execute(ClipType.ctIntersection, tree);
                }
                else
                {
                    clip.Execute(ClipType.ctDifference, tree);
                }

                for (int ci = 0; ci < tree.ChildCount; ++ci)
                {
                    if (tree.Childs[ci].IsOpen == false)
                    {
                        continue;
                    }
                    PolyLine2d clippedPath = ConvertFromClipperPath(tree.Childs[ci].Contour, nIntScale);

                    // clipper just cuts up the polylines, we still have to figure out containment ourselves.
                    // Currently just checking based on point around middle of polyline...
                    // [TODO] can we get clipper to not return the inside ones?
                    Vector2d qp = (clippedPath.VertexCount > 2) ?
                                  clippedPath[clippedPath.VertexCount / 2] : clippedPath.Segment(0).Center;
                    bool inside = false;
                    foreach (var poly in solids)
                    {
                        if (poly.Contains(qp))
                        {
                            inside = true;
                            break;
                        }
                    }
                    if (inside == bIntersect)
                    {
                        result.Add(clippedPath);
                    }
                }
            } catch /*(Exception e)*/ {
                // [TODO] what to do here?
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ClipAgainstPolygon: Clipper threw exception: " + e.Message);
                return(new List <PolyLine2d>());
            }

            return(result);
        }
示例#5
0
        public static List <GeneralPolygon2d> PolygonBoolean(
            ICollection <GeneralPolygon2d> poly1, ICollection <GeneralPolygon2d> poly2,
            BooleanOp opType, double minArea = -1)
        {
            // handle cases where one list is empty
            if (poly1.Count == 0)
            {
                if (opType == BooleanOp.Difference || opType == BooleanOp.Intersection)
                {
                    return(new List <GeneralPolygon2d>());
                }
                else
                {
                    return(DeepCopy.List(poly2));
                }
            }
            else if (poly2.Count == 0)
            {
                if (opType == BooleanOp.Intersection)
                {
                    return(new List <GeneralPolygon2d>());
                }
                else
                {
                    return(DeepCopy.List(poly1));
                }
            }


            double nIntScale = Math.Max(GetIntScale(poly1), GetIntScale(poly2));

            if (minArea < 0)
            {
                minArea = DiscardMinArea;
            }

            try {
                Clipper clipper = new Clipper(Clipper.ioStrictlySimple);

                foreach (GeneralPolygon2d sub in poly1)
                {
                    CPolygonList cpoly = ConvertToClipper(sub, nIntScale);
                    clipper.AddPaths(cpoly, PolyType.ptSubject, true);
                }
                foreach (GeneralPolygon2d clip in poly2)
                {
                    CPolygonList cpoly = ConvertToClipper(clip, nIntScale);
                    clipper.AddPaths(cpoly, PolyType.ptClip, true);
                }

                ClipType cType = ClipType.ctUnion;
                if (opType == BooleanOp.Difference)
                {
                    cType = ClipType.ctDifference;
                }
                else if (opType == BooleanOp.Intersection)
                {
                    cType = ClipType.ctIntersection;
                }
                else if (opType == BooleanOp.Xor)
                {
                    cType = ClipType.ctXor;
                }

                PolyTree tree = new PolyTree();
                bool     bOK  = clipper.Execute(cType, tree);
                if (bOK == false)
                {
                    //System.Diagnostics.Debug.WriteLine("ClipperUtil.PolygonBoolean: Clipper failed");
                    return(new List <GeneralPolygon2d>());
                }

                List <GeneralPolygon2d> result = new List <GeneralPolygon2d>();
                for (int ci = 0; ci < tree.ChildCount; ++ci)
                {
                    Convert(tree.Childs[ci], result, nIntScale, minArea);
                }
                return(result);
            } catch /*(Exception e)*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.PolygonBoolean: Clipper threw exception: " + e.Message);
                return(new List <GeneralPolygon2d>());
            }
        }
示例#6
0
        public static List <GeneralPolygon2d> ConvertFromClipper(CPolygonList clipper_polys, double nIntScale)
        {
            List <GeneralPolygon2d> result = new List <GeneralPolygon2d>();

            try {
                // convert clipper polys to Polygon2d
                List <Polygon2d> polys = new List <Polygon2d>();
                int N = clipper_polys.Count;
                for (int i = 0; i < N; ++i)
                {
                    Polygon2d poly = ConvertFromClipper(clipper_polys[i], nIntScale);
                    if (poly != null)
                    {
                        polys.Add(poly);
                    }
                }

                // sort polygons into outer/holes
                // [TODO] clipper can figure this out for us...perhaps faster??


                // find the 'outer' polygons. Here we are assuming
                // that outer polygons are CCW...
                bool[] done = new bool[N];
                Array.Clear(done, 0, N);
                for (int i = 0; i < N; ++i)
                {
                    if (polys[i].IsClockwise == false)
                    {
                        GeneralPolygon2d gp = new GeneralPolygon2d();
                        gp.Outer = polys[i];
                        result.Add(gp);
                        done[i] = true;
                    }
                }

                // compute bboxes
                AxisAlignedBox2d[] outerBounds = new AxisAlignedBox2d[result.Count];
                for (int i = 0; i < result.Count; ++i)
                {
                    outerBounds[i] = result[i].Outer.GetBounds();
                }

                // remaining polygons are holes. Figure out which outer
                // they belong too. Only difficult if there is more than one option.
                for (int i = 0; i < N; ++i)
                {
                    if (done[i])
                    {
                        continue;
                    }
                    if (result.Count == 1)
                    {
                        result[0].AddHole(polys[i], false);
                        done[i] = true;
                        continue;
                    }

                    AxisAlignedBox2d box = polys[i].GetBounds();
                    for (int j = 0; j < result.Count; ++j)
                    {
                        if (outerBounds[j].Contains(box) == false)
                        {
                            continue;
                        }
                        if (result[j].Outer.Contains(polys[i]))
                        {
                            result[j].AddHole(polys[i], false);
                        }
                        done[i] = true;
                    }

                    // uh-oh...now what? perhaps should force a full N-pair test/sort if this happens?
                    if (done[i] == false)
                    {
                        System.Diagnostics.Debug.WriteLine("ClipperUtil.ConvertFromClipper: could not find parent for polygon " + i.ToString());
                    }
                }
            } catch /*( Exception e )*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ConvertFromClipper: caught exception: " + e.Message);
            }
            return(result);
        }