Exemplo n.º 1
0
        //------------------------------------------------------------------------------

        public static void AddPolyNodeToPolygons(PolyNode polynode, PolygonsClp polygons)
        {
            if (polynode.Contour.Count > 0)
                polygons.Add(polynode.Contour);
            foreach (PolyNode pn in polynode.Childs)
                AddPolyNodeToPolygons(pn, polygons);
        }
Exemplo n.º 2
0
        //------------------------------------------------------------------------------

        public bool AddPolygons(PolygonsClp ppg, PolyType polyType)
        {
            bool result = false;
            for (int i = 0; i < ppg.Count; ++i)
                if (AddPolygon(ppg[i], polyType)) result = true;
            return result;
        }
Exemplo n.º 3
0
        //------------------------------------------------------------------------------

        public static PolygonsClp CleanPolygons(PolygonsClp polys,
            double distance = 1.415)
        {
            PolygonsClp result = new PolygonsClp(polys.Count);
            for (int i = 0; i < polys.Count; i++)
                result.Add(CleanPolygon(polys[i], distance));
            return result;
        }
Exemplo n.º 4
0
        //------------------------------------------------------------------------------

        public static void PolyTreeToPolygons(PolyTree polytree, PolygonsClp polygons)
        {
            polygons.Clear();
            polygons.Capacity = polytree.Total;
            AddPolyNodeToPolygons(polytree, polygons);
        }
Exemplo n.º 5
0
        //------------------------------------------------------------------------------

        public static PolygonsClp OffsetPolyLines(PolygonsClp lines,
          double delta, JoinType jointype, EndType endtype,
          double limit)
        {
            PolygonsClp result = new PolygonsClp();

            //automatically strip duplicate points because it gets complicated with
            //open and closed lines and when to strip duplicates across begin-end ...
            PolygonsClp pts = new PolygonsClp(lines);
            for (int i = 0; i < pts.Count; ++i)
            {
                for (int j = pts[i].Count - 1; j > 0; j--)
                    if (PointsEqual(pts[i][j], pts[i][j - 1]))
                        pts[i].RemoveAt(j);
            }

            if (endtype == EndType.etClosed)
            {
                int sz = pts.Count;
                pts.Capacity = sz * 2;
                for (int i = 0; i < sz; ++i)
                {
                    PolygonClp line = new PolygonClp(pts[i]);
                    line.Reverse();
                    pts.Add(line);
                }
                new PolyOffsetBuilder(pts, result, true, delta, jointype, endtype, limit);
            }
            else
                new PolyOffsetBuilder(pts, result, false, delta, jointype, endtype, limit);

            return result;
        }
Exemplo n.º 6
0
        //------------------------------------------------------------------------------

        public static PolygonsClp SimplifyPolygons(PolygonsClp polys,
            PolyFillType fillType = PolyFillType.pftEvenOdd)
        {
            PolygonsClp result = new PolygonsClp();
            Clipper c = new Clipper();
            c.ForceSimple = true;
            c.AddPolygons(polys, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, result, fillType, fillType);
            return result;
        }
Exemplo n.º 7
0
        //------------------------------------------------------------------------------

        public static PolygonsClp OffsetPolygons(PolygonsClp poly, double delta, JoinType jointype)
        {
            return OffsetPolygons(poly, delta, jointype, 0, true);
        }
Exemplo n.º 8
0
        //------------------------------------------------------------------------------

        public static PolygonsClp OffsetPolygons(PolygonsClp poly, double delta)
        {
            return OffsetPolygons(poly, delta, JoinType.jtSquare, 0, true);
        }
Exemplo n.º 9
0
        //------------------------------------------------------------------------------

        public static PolygonsClp OffsetPolygons(PolygonsClp poly, double delta,
            JoinType jointype, double MiterLimit, bool AutoFix)
        {
            PolygonsClp result = new PolygonsClp();

            //AutoFix - fixes polygon orientation if necessary and removes 
            //duplicate vertices. Can be set false when you're sure that polygon
            //orientation is correct and that there are no duplicate vertices.
            if (AutoFix)
            {
                int Len = poly.Count, botI = 0;
                while (botI < Len && poly[botI].Count == 0) botI++;
                if (botI == Len) return result;

                //botPt: used to find the lowermost (in inverted Y-axis) & leftmost point
                //This point (on pts[botI]) must be on an outer polygon ring and if 
                //its orientation is false (counterclockwise) then assume all polygons 
                //need reversing ...
                IntPoint botPt = poly[botI][0];
                for (int i = botI; i < Len; ++i)
                {
                    if (poly[i].Count == 0) continue;
                    if (UpdateBotPt(poly[i][0], ref botPt)) botI = i;
                    for (int j = poly[i].Count - 1; j > 0; j--)
                    {
                        if (PointsEqual(poly[i][j], poly[i][j - 1]))
                            poly[i].RemoveAt(j);
                        else if (UpdateBotPt(poly[i][j], ref botPt))
                            botI = i;
                    }
                }
                if (!Orientation(poly[botI]))
                    ReversePolygons(poly);
            }

            new PolyOffsetBuilder(poly, result, true, delta, jointype, EndType.etClosed, MiterLimit);
            return result;
        }
Exemplo n.º 10
0
        //------------------------------------------------------------------------------

        public static PolygonsClp OffsetPolygons(PolygonsClp poly, double delta,
            JoinType jointype, double MiterLimit)
        {
            return OffsetPolygons(poly, delta, jointype, MiterLimit, true);
        }
Exemplo n.º 11
0
            //------------------------------------------------------------------------------

            public PolyOffsetBuilder(PolygonsClp pts, PolygonsClp solution, bool isPolygon, double delta,
                JoinType jointype, EndType endtype, double limit = 0)
            {
                //precondition: solution != pts

                if (delta == 0) { solution = pts; return; }
                m_p = pts;
                m_delta = delta;
                m_rmin = 0.5;

                if (jointype == JoinType.jtMiter)
                {
                    if (limit > 2) m_rmin = 2.0 / (limit * limit);
                    limit = 0.25; //just in case endtype == etRound
                }
                else
                {
                    if (limit <= 0) limit = 0.25;
                    else if (limit > Math.Abs(delta)) limit = Math.Abs(delta);
                }

                double deltaSq = delta * delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len == 0 || (len < 3 && delta <= 0))
                        continue;
                    else if (len == 1)
                    {
                        currentPoly = new PolygonClp();
                        currentPoly = BuildArc(pts[m_i][0], 0, 2 * Math.PI, delta, limit);
                        solution.Add(currentPoly);
                        continue;
                    }

                    bool forceClose = PointsEqual(pts[m_i][0], pts[m_i][len - 1]);
                    if (forceClose) len--;

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len - 1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j + 1]));
                    if (isPolygon || forceClose)
                        normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));
                    else
                        normals.Add(new DoublePoint(normals[len - 2]));

                    currentPoly = new PolygonClp();
                    if (isPolygon || forceClose)
                    {
                        m_k = len - 1;
                        for (m_j = 0; m_j < len; ++m_j)
                            OffsetPoint(jointype, limit);
                        solution.Add(currentPoly);
                        if (!isPolygon)
                        {
                            currentPoly = new PolygonClp();
                            m_delta = -m_delta;
                            m_k = len - 1;
                            for (m_j = 0; m_j < len; ++m_j)
                                OffsetPoint(jointype, limit);
                            m_delta = -m_delta;
                            currentPoly.Reverse();
                            solution.Add(currentPoly);
                        }
                    }
                    else
                    {
                        m_k = 0;
                        for (m_j = 1; m_j < len - 1; ++m_j)
                            OffsetPoint(jointype, limit);

                        IntPoint pt1;
                        if (endtype == EndType.etButt)
                        {
                            m_j = len - 1;
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X + normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y + normals[m_j].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X - normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y - normals[m_j].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_j = len - 1;
                            m_k = len - 2;
                            normals[m_j].X = -normals[m_j].X;
                            normals[m_j].Y = -normals[m_j].Y;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }

                        //re-build Normals ...
                        for (int j = len - 1; j > 0; j--)
                        {
                            normals[j].X = -normals[j - 1].X;
                            normals[j].Y = -normals[j - 1].Y;
                        }
                        normals[0].X = -normals[1].X;
                        normals[0].Y = -normals[1].Y;

                        m_k = len - 1;
                        for (m_j = m_k - 1; m_j > 0; --m_j)
                            OffsetPoint(jointype, limit);

                        if (endtype == EndType.etButt)
                        {
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X - normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y - normals[0].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X + normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y + normals[0].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_k = 1;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }
                        solution.Add(currentPoly);
                    }
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    PolygonClp outer = new PolygonClp(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.ReverseSolution = true;
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0) solution.RemoveAt(0);
                }
            }
Exemplo n.º 12
0
        //------------------------------------------------------------------------------

        private void BuildResult(PolygonsClp polyg)
        {
            polyg.Clear();
            polyg.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                if (outRec.pts == null) continue;
                OutPt p = outRec.pts;
                int cnt = PointCount(p);
                if (cnt < 3) continue;
                PolygonClp pg = new PolygonClp(cnt);
                for (int j = 0; j < cnt; j++)
                {
                    pg.Add(p.pt);
                    p = p.prev;
                }
                polyg.Add(pg);
            }
        }
Exemplo n.º 13
0
        //------------------------------------------------------------------------------

        public static void ReversePolygons(PolygonsClp polys)
        {
            polys.ForEach(delegate(PolygonClp poly) { poly.Reverse(); });
        }
Exemplo n.º 14
0
        //------------------------------------------------------------------------------

        public bool Execute(ClipType clipType, PolygonsClp solution)
        {
            return Execute(clipType, solution,
                PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
        }
Exemplo n.º 15
0
        //------------------------------------------------------------------------------

        public bool Execute(ClipType clipType, PolygonsClp solution,
            PolyFillType subjFillType, PolyFillType clipFillType)
        {
            if (m_ExecuteLocked) return false;
            m_ExecuteLocked = true;
            solution.Clear();
            m_SubjFillType = subjFillType;
            m_ClipFillType = clipFillType;
            m_ClipType = clipType;
            m_UsingPolyTree = false;
            bool succeeded = ExecuteInternal();
            //build the return polygons ...
            if (succeeded) BuildResult(solution);
            m_ExecuteLocked = false;
            return succeeded;
        }