Ejemplo n.º 1
0
            /// <summary>
            /// Convert into an array of polygons
            /// </summary>
            /// <remarks>
            /// The polytree will nest deeply if solids are inside of holes.  But Polygon2D would treat the solids inside of holes as their own
            /// independent isntances
            /// 
            /// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/PolyTree/_Body.htm
            /// </remarks>
            private static Polygon2D[] ConvertOutput(PolyTree solution, double scaleInverse)
            {
                List<Polygon2D> retVal = new List<Polygon2D>();

                // Walk the tree, and get all parents (need to look at contour count so that the root gets skipped)
                foreach (PolyNode parent in ((PolyNode)solution).Descendants(o => o.Childs).Where(o => !o.IsHole && o.Contour.Count > 0))
                {
                    // Convert the parent polygon
                    Point[] points = parent.Contour.Select(o => new Point(o.X * scaleInverse, o.Y * scaleInverse)).ToArray();

                    if (parent.Childs.Count == 0)
                    {
                        // No holes
                        retVal.Add(new Polygon2D(points));
                    }
                    else
                    {
                        List<Point[]> holes = new List<Point[]>();

                        foreach (PolyNode child in parent.Childs)
                        {
                            if (!child.IsHole)
                            {
                                throw new ApplicationException("Expected the child of a non hole to be a hole");
                            }

                            // Convert the hole polygon
                            holes.Add(child.Contour.Select(o => new Point(o.X * scaleInverse, o.Y * scaleInverse)).ToArray());
                        }

                        // Store with holes
                        retVal.Add(new Polygon2D(points, holes.ToArray()));
                    }
                }

                // Exit Function
                return retVal.ToArray();
            }
Ejemplo n.º 2
0
            public static Polygon2D[] GetPolyUnion(Point[][] polygons)
            {
                if (polygons == null || polygons.Length == 0)
                {
                    return new Polygon2D[0];
                }

                double scale = GetScale(polygons);
                var convertedPolys = ConvertInput(polygons, scale);

                Clipper clipper = new Clipper();
                clipper.AddPolygons(convertedPolys, PolyType.ptSubject);        // when doing union, I don't think it matters what is subject and what is union
                //clipper.ForceSimple = true;

                // Here is a page describing PolyFillType (nonzero is what you intuitively think of for a union)
                // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm

                PolyTree solution = new PolyTree();
                if (!clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero))
                {
                    return new Polygon2D[0];
                }

                return ConvertOutput(solution, 1d / scale);
            }
Ejemplo n.º 3
0
        //------------------------------------------------------------------------------

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

        private void BuildResult2(PolyTree polytree)
        {
            polytree.Clear();

            //add each output polygon/contour to polytree ...
            polytree.m_AllPolys.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                int cnt = PointCount(outRec.pts);
                if (cnt < 3) continue;
                FixHoleLinkage(outRec);
                PolyNode pn = new PolyNode();
                polytree.m_AllPolys.Add(pn);
                outRec.polyNode = pn;
                pn.m_polygon.Capacity = cnt;
                OutPt op = outRec.pts;
                for (int j = 0; j < cnt; j++)
                {
                    pn.m_polygon.Add(op.pt);
                    op = op.prev;
                }
            }

            //fixup PolyNode links etc ...
            polytree.m_Childs.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                if (outRec.polyNode == null) continue;
                if (outRec.FirstLeft == null)
                    polytree.AddChild(outRec.polyNode);
                else
                    outRec.FirstLeft.polyNode.AddChild(outRec.polyNode);
            }
        }
Ejemplo n.º 5
0
        //------------------------------------------------------------------------------

        public bool Execute(ClipType clipType, PolyTree polytree)
        {
            return Execute(clipType, polytree,
                PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
        }
Ejemplo n.º 6
0
        //------------------------------------------------------------------------------

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