Beispiel #1
0
    public static void renderTree(ClipperLib.PolyNode node, List <Vector3> verts, List <Vector3> norms, List <Vector2> uvs, List <int> faces, ref int idx)
    {
        Poly2Tri.Polygon p = new Poly2Tri.Polygon(node.Contour.ConvertAll <Poly2Tri.PolygonPoint>(PP));
        //p.RemoveDuplicateNeighborPoints();
        //p.MergeParallelEdges(1e-3);

        foreach (ClipperLib.PolyNode child in node.Childs)
        {
            if (child.IsHole)
            {
                Poly2Tri.Polygon h = new Poly2Tri.Polygon(child.Contour.ConvertAll <Poly2Tri.PolygonPoint>(PP));
                h.RemoveDuplicateNeighborPoints();
                h.MergeParallelEdges(1e-3);

                p.AddHole(h);
            }
            else
            {
                renderTree(child, verts, norms, uvs, faces, ref idx);
            }
        }

        Poly2Tri.DTSweepContext ctx = new Poly2Tri.DTSweepContext();
        ctx.PrepareTriangulation(p);
        Poly2Tri.DTSweep.Triangulate(ctx);

        foreach (Poly2Tri.DelaunayTriangle dt in p.Triangles)
        {
            faces.Add(idx); uvs.Add(UV(dt.Points[2])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[2])); idx++;
            faces.Add(idx); uvs.Add(UV(dt.Points[1])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[1])); idx++;
            faces.Add(idx); uvs.Add(UV(dt.Points[0])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[0])); idx++;
        }
    }
Beispiel #2
0
 internal void AddChild(PolyNode Child)
 {
     int cnt = m_Childs.Count;
     m_Childs.Add(Child);
     Child.m_Parent = this;
     Child.m_Index = cnt;
 }
Beispiel #3
0
        //------------------------------------------------------------------------------
        public void AddPath(List<IntPoint> path, JoinType joinType, EndType endType)
        {
            int highI = path.Count - 1;
            if (highI < 0) return;
            PolyNode newNode = new PolyNode();
            newNode.m_jointype = joinType;
            newNode.m_endtype = endType;

            //strip duplicate points from path and also get index to the lowest point ...
            if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon)
                while (highI > 0 && path[0] == path[highI]) highI--;
            newNode.m_polygon.Capacity = highI + 1;
            newNode.m_polygon.Add(path[0]);
            int j = 0, k = 0;
            for (int i = 1; i <= highI; i++)
                if (newNode.m_polygon[j] != path[i])
                {
                    j++;
                    newNode.m_polygon.Add(path[i]);
                    if (path[i].Y > newNode.m_polygon[k].Y ||
                      (path[i].Y == newNode.m_polygon[k].Y &&
                      path[i].X < newNode.m_polygon[k].X)) k = j;
                }
            if (endType == EndType.etClosedPolygon && j < 2) return;

            m_polyNodes.AddChild(newNode);

            //if this path's lowest pt is lower than all the others then update m_lowest
            if (endType != EndType.etClosedPolygon) return;
            if (m_lowest.X < 0)
                m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
            else
            {
                IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y];
                if (newNode.m_polygon[k].Y > ip.Y ||
                  (newNode.m_polygon[k].Y == ip.Y &&
                  newNode.m_polygon[k].X < ip.X))
                    m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
            }
        }
        public List<DelaunayTriangle> TriangulateComplex(
         PolyTree polyTree,
         bool ignoreFills = false, bool ignoreHoles = true)
        {
            PolyNode rootNode;
             if (polyTree.Total == 0) {
            Console.WriteLine(0);
            rootNode = new PolyNode();
             } else {
            rootNode = polyTree.GetFirst().Parent;
             }

             // Equivalent to rootNode.Contour = bounds;
             var contourField = rootNode.GetType().GetField("m_polygon", BindingFlags.Instance | BindingFlags.NonPublic);
             if (contourField == null) {
            throw new Exception("Could not find field contour backing field.");
             }
             contourField.SetValue(rootNode, kTriangulatorBounds);

             var result = new List<DelaunayTriangle>();
             int i = 0;
             for (var currentNode = rootNode; currentNode != null; currentNode = currentNode.GetNext()) {
            if ((ignoreHoles && currentNode.IsHole) || (ignoreFills && !currentNode.IsHole)) continue;
            var polyline = DownscalePolygon(currentNode.Contour);
            var finalPolygon = new Polygon(polyline);
            foreach (var child in currentNode.Childs) {
               var shrunkContour = EdgeShrink(child.Contour);
               var holePoints = DownscalePolygon(shrunkContour);
               var holePoly = new Polygon(holePoints);
               finalPolygon.AddHole(holePoly);
            }
            P2T.Triangulate(finalPolygon);
            result.AddRange(finalPolygon.Triangles);
             }
             return result;
        }
Beispiel #5
0
        //------------------------------------------------------------------------------

        public void AddPath(List <IntPoint> path, JoinType joinType, EndType endType)
        {
            int highI = path.Count - 1;

            if (highI < 0)
            {
                return;
            }
            PolyNode newNode = new PolyNode();

            newNode.m_jointype = joinType;
            newNode.m_endtype  = endType;

            //strip duplicate points from path and also get index to the lowest point ...
            if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon)
            {
                while (highI > 0 && path[0] == path[highI])
                {
                    highI--;
                }
            }
            newNode.m_polygon.Capacity = highI + 1;
            newNode.m_polygon.Add(path[0]);
            int j = 0, k = 0;

            for (int i = 1; i <= highI; i++)
            {
                if (newNode.m_polygon[j] != path[i])
                {
                    j++;
                    newNode.m_polygon.Add(path[i]);
                    if (path[i].Y > newNode.m_polygon[k].Y ||
                        (path[i].Y == newNode.m_polygon[k].Y &&
                         path[i].X < newNode.m_polygon[k].X))
                    {
                        k = j;
                    }
                }
            }
            if (endType == EndType.etClosedPolygon && j < 2)
            {
                return;
            }

            m_polyNodes.AddChild(newNode);

            //if this path's lowest pt is lower than all the others then update m_lowest
            if (endType != EndType.etClosedPolygon)
            {
                return;
            }
            if (m_lowest.X < 0)
            {
                m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
            }
            else
            {
                IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y];
                if (newNode.m_polygon[k].Y > ip.Y ||
                    (newNode.m_polygon[k].Y == ip.Y &&
                     newNode.m_polygon[k].X < ip.X))
                {
                    m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
                }
            }
        }
Beispiel #6
0
        //------------------------------------------------------------------------------

        private void DoOffset(double delta)
        {
            m_destPolys = new List <List <IntPoint> >();
            m_delta     = delta;

            //if Zero offset, just copy any CLOSED polygons to m_p and return ...
            if (ClipperBase.near_zero(delta))
            {
                m_destPolys.Capacity = m_polyNodes.ChildCount;
                for (int i = 0; i < m_polyNodes.ChildCount; i++)
                {
                    PolyNode node = m_polyNodes.Childs[i];
                    if (node.m_endtype == EndType.etClosedPolygon)
                    {
                        m_destPolys.Add(node.m_polygon);
                    }
                }
                return;
            }

            //see offset_triginometry3.svg in the documentation folder ...
            if (MiterLimit > 2)
            {
                m_miterLim = 2 / (MiterLimit * MiterLimit);
            }
            else
            {
                m_miterLim = 0.5;
            }

            double y;

            if (ArcTolerance <= 0.0)
            {
                y = def_arc_tolerance;
            }
            else if (ArcTolerance > Math.Abs(delta) * def_arc_tolerance)
            {
                y = Math.Abs(delta) * def_arc_tolerance;
            }
            else
            {
                y = ArcTolerance;
            }
            //see offset_triginometry2.svg in the documentation folder ...
            double steps = Math.PI / Math.Acos(1 - y / Math.Abs(delta));

            m_sin         = Math.Sin(two_pi / steps);
            m_cos         = Math.Cos(two_pi / steps);
            m_StepsPerRad = steps / two_pi;
            if (delta < 0.0)
            {
                m_sin = -m_sin;
            }

            m_destPolys.Capacity = m_polyNodes.ChildCount * 2;
            for (int i = 0; i < m_polyNodes.ChildCount; i++)
            {
                PolyNode node = m_polyNodes.Childs[i];
                m_srcPoly = node.m_polygon;

                int len = m_srcPoly.Count;

                if (len == 0 || (delta <= 0 && (len < 3 ||
                                                node.m_endtype != EndType.etClosedPolygon)))
                {
                    continue;
                }

                m_destPoly = new List <IntPoint>();

                if (len == 1)
                {
                    if (node.m_jointype == JoinType.jtRound)
                    {
                        double X = 1.0, Y = 0.0;
                        for (int j = 1; j <= steps; j++)
                        {
                            m_destPoly.Add(new IntPoint(
                                               Round(m_srcPoly[0].X + X * delta),
                                               Round(m_srcPoly[0].Y + Y * delta)));
                            double X2 = X;
                            X = X * m_cos - m_sin * Y;
                            Y = X2 * m_sin + Y * m_cos;
                        }
                    }
                    else
                    {
                        double X = -1.0, Y = -1.0;
                        for (int j = 0; j < 4; ++j)
                        {
                            m_destPoly.Add(new IntPoint(
                                               Round(m_srcPoly[0].X + X * delta),
                                               Round(m_srcPoly[0].Y + Y * delta)));
                            if (X < 0)
                            {
                                X = 1;
                            }
                            else if (Y < 0)
                            {
                                Y = 1;
                            }
                            else
                            {
                                X = -1;
                            }
                        }
                    }
                    m_destPolys.Add(m_destPoly);
                    continue;
                }

                //build m_normals ...
                m_normals.Clear();
                m_normals.Capacity = len;
                for (int j = 0; j < len - 1; j++)
                {
                    m_normals.Add(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1]));
                }
                if (node.m_endtype == EndType.etClosedLine ||
                    node.m_endtype == EndType.etClosedPolygon)
                {
                    m_normals.Add(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0]));
                }
                else
                {
                    m_normals.Add(new DoublePoint(m_normals[len - 2]));
                }

                if (node.m_endtype == EndType.etClosedPolygon)
                {
                    int k = len - 1;
                    for (int j = 0; j < len; j++)
                    {
                        OffsetPoint(j, ref k, node.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                }
                else if (node.m_endtype == EndType.etClosedLine)
                {
                    int k = len - 1;
                    for (int j = 0; j < len; j++)
                    {
                        OffsetPoint(j, ref k, node.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                    m_destPoly = new List <IntPoint>();
                    //re-build m_normals ...
                    DoublePoint n = m_normals[len - 1];
                    for (int j = len - 1; j > 0; j--)
                    {
                        m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
                    }
                    m_normals[0] = new DoublePoint(-n.X, -n.Y);
                    k            = 0;
                    for (int j = len - 1; j >= 0; j--)
                    {
                        OffsetPoint(j, ref k, node.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                }
                else
                {
                    int k = 0;
                    for (int j = 1; j < len - 1; ++j)
                    {
                        OffsetPoint(j, ref k, node.m_jointype);
                    }

                    IntPoint pt1;
                    if (node.m_endtype == EndType.etOpenButt)
                    {
                        int j = len - 1;
                        pt1 = new IntPoint((int)Round(m_srcPoly[j].X + m_normals[j].X *
                                                      delta), (int)Round(m_srcPoly[j].Y + m_normals[j].Y * delta));
                        m_destPoly.Add(pt1);
                        pt1 = new IntPoint((int)Round(m_srcPoly[j].X - m_normals[j].X *
                                                      delta), (int)Round(m_srcPoly[j].Y - m_normals[j].Y * delta));
                        m_destPoly.Add(pt1);
                    }
                    else
                    {
                        int j = len - 1;
                        k            = len - 2;
                        m_sinA       = 0;
                        m_normals[j] = new DoublePoint(-m_normals[j].X, -m_normals[j].Y);
                        if (node.m_endtype == EndType.etOpenSquare)
                        {
                            DoSquare(j, k);
                        }
                        else
                        {
                            DoRound(j, k);
                        }
                    }

                    //re-build m_normals ...
                    for (int j = len - 1; j > 0; j--)
                    {
                        m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
                    }

                    m_normals[0] = new DoublePoint(-m_normals[1].X, -m_normals[1].Y);

                    k = len - 1;
                    for (int j = k - 1; j > 0; --j)
                    {
                        OffsetPoint(j, ref k, node.m_jointype);
                    }

                    if (node.m_endtype == EndType.etOpenButt)
                    {
                        pt1 = new IntPoint((int)Round(m_srcPoly[0].X - m_normals[0].X * delta),
                                           (int)Round(m_srcPoly[0].Y - m_normals[0].Y * delta));
                        m_destPoly.Add(pt1);
                        pt1 = new IntPoint((int)Round(m_srcPoly[0].X + m_normals[0].X * delta),
                                           (int)Round(m_srcPoly[0].Y + m_normals[0].Y * delta));
                        m_destPoly.Add(pt1);
                    }
                    else
                    {
                        k      = 1;
                        m_sinA = 0;
                        if (node.m_endtype == EndType.etOpenSquare)
                        {
                            DoSquare(0, 1);
                        }
                        else
                        {
                            DoRound(0, 1);
                        }
                    }
                    m_destPolys.Add(m_destPoly);
                }
            }
        }
Beispiel #7
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 ((outRec.IsOpen && cnt < 2) ||
                  (!outRec.IsOpen && 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.Prev;
                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;
                else if (outRec.IsOpen)
                {
                    outRec.PolyNode.IsOpen = true;
                    polytree.AddChild(outRec.PolyNode);
                }
                else if (outRec.FirstLeft != null &&
                  outRec.FirstLeft.PolyNode != null)
                    outRec.FirstLeft.PolyNode.AddChild(outRec.PolyNode);
                else
                    polytree.AddChild(outRec.PolyNode);
            }
        }
Beispiel #8
0
 private void DoOffset(double delta)
 {
     m_destPolys = new List <List <IntPoint> >();
     m_delta     = delta;
     if (ClipperBase.near_zero(delta))
     {
         m_destPolys.Capacity = m_polyNodes.ChildCount;
         for (int i = 0; i < m_polyNodes.ChildCount; i++)
         {
             PolyNode polyNode = m_polyNodes.Childs[i];
             if (polyNode.m_endtype == EndType.etClosedPolygon)
             {
                 m_destPolys.Add(polyNode.m_polygon);
             }
         }
     }
     else
     {
         if (MiterLimit > 2.0)
         {
             m_miterLim = 2.0 / (MiterLimit * MiterLimit);
         }
         else
         {
             m_miterLim = 0.5;
         }
         double num  = (ArcTolerance <= 0.0) ? 0.25 : ((!(ArcTolerance > Math.Abs(delta) * 0.25)) ? ArcTolerance : (Math.Abs(delta) * 0.25));
         double num2 = 3.1415926535897931 / Math.Acos(1.0 - num / Math.Abs(delta));
         m_sin         = Math.Sin(6.2831853071795862 / num2);
         m_cos         = Math.Cos(6.2831853071795862 / num2);
         m_StepsPerRad = num2 / 6.2831853071795862;
         if (delta < 0.0)
         {
             m_sin = 0.0 - m_sin;
         }
         m_destPolys.Capacity = m_polyNodes.ChildCount * 2;
         for (int j = 0; j < m_polyNodes.ChildCount; j++)
         {
             PolyNode polyNode2 = m_polyNodes.Childs[j];
             m_srcPoly = polyNode2.m_polygon;
             int count = m_srcPoly.Count;
             if (count != 0 && (!(delta <= 0.0) || (count >= 3 && polyNode2.m_endtype == EndType.etClosedPolygon)))
             {
                 m_destPoly = new List <IntPoint>();
                 if (count == 1)
                 {
                     if (polyNode2.m_jointype == JoinType.jtRound)
                     {
                         double num3 = 1.0;
                         double num4 = 0.0;
                         for (int k = 1; (double)k <= num2; k++)
                         {
                             m_destPoly.Add(new IntPoint(Round((double)m_srcPoly[0].X + num3 * delta), Round((double)m_srcPoly[0].Y + num4 * delta)));
                             double num5 = num3;
                             num3 = num3 * m_cos - m_sin * num4;
                             num4 = num5 * m_sin + num4 * m_cos;
                         }
                     }
                     else
                     {
                         double num6 = -1.0;
                         double num7 = -1.0;
                         for (int l = 0; l < 4; l++)
                         {
                             m_destPoly.Add(new IntPoint(Round((double)m_srcPoly[0].X + num6 * delta), Round((double)m_srcPoly[0].Y + num7 * delta)));
                             if (num6 < 0.0)
                             {
                                 num6 = 1.0;
                             }
                             else if (num7 < 0.0)
                             {
                                 num7 = 1.0;
                             }
                             else
                             {
                                 num6 = -1.0;
                             }
                         }
                     }
                     m_destPolys.Add(m_destPoly);
                 }
                 else
                 {
                     m_normals.Clear();
                     m_normals.Capacity = count;
                     for (int m = 0; m < count - 1; m++)
                     {
                         m_normals.Add(GetUnitNormal(m_srcPoly[m], m_srcPoly[m + 1]));
                     }
                     if (polyNode2.m_endtype == EndType.etClosedLine || polyNode2.m_endtype == EndType.etClosedPolygon)
                     {
                         m_normals.Add(GetUnitNormal(m_srcPoly[count - 1], m_srcPoly[0]));
                     }
                     else
                     {
                         m_normals.Add(new DoublePoint(m_normals[count - 2]));
                     }
                     if (polyNode2.m_endtype == EndType.etClosedPolygon)
                     {
                         int k2 = count - 1;
                         for (int n = 0; n < count; n++)
                         {
                             OffsetPoint(n, ref k2, polyNode2.m_jointype);
                         }
                         m_destPolys.Add(m_destPoly);
                     }
                     else if (polyNode2.m_endtype == EndType.etClosedLine)
                     {
                         int k3 = count - 1;
                         for (int num8 = 0; num8 < count; num8++)
                         {
                             OffsetPoint(num8, ref k3, polyNode2.m_jointype);
                         }
                         m_destPolys.Add(m_destPoly);
                         m_destPoly = new List <IntPoint>();
                         DoublePoint doublePoint = m_normals[count - 1];
                         for (int num9 = count - 1; num9 > 0; num9--)
                         {
                             m_normals[num9] = new DoublePoint(0.0 - m_normals[num9 - 1].X, 0.0 - m_normals[num9 - 1].Y);
                         }
                         m_normals[0] = new DoublePoint(0.0 - doublePoint.X, 0.0 - doublePoint.Y);
                         k3           = 0;
                         for (int num10 = count - 1; num10 >= 0; num10--)
                         {
                             OffsetPoint(num10, ref k3, polyNode2.m_jointype);
                         }
                         m_destPolys.Add(m_destPoly);
                     }
                     else
                     {
                         int k4 = 0;
                         for (int num11 = 1; num11 < count - 1; num11++)
                         {
                             OffsetPoint(num11, ref k4, polyNode2.m_jointype);
                         }
                         if (polyNode2.m_endtype == EndType.etOpenButt)
                         {
                             int      index = count - 1;
                             IntPoint item  = new IntPoint(Round((double)m_srcPoly[index].X + m_normals[index].X * delta), Round((double)m_srcPoly[index].Y + m_normals[index].Y * delta));
                             m_destPoly.Add(item);
                             item = new IntPoint(Round((double)m_srcPoly[index].X - m_normals[index].X * delta), Round((double)m_srcPoly[index].Y - m_normals[index].Y * delta));
                             m_destPoly.Add(item);
                         }
                         else
                         {
                             int num12 = count - 1;
                             k4               = count - 2;
                             m_sinA           = 0.0;
                             m_normals[num12] = new DoublePoint(0.0 - m_normals[num12].X, 0.0 - m_normals[num12].Y);
                             if (polyNode2.m_endtype == EndType.etOpenSquare)
                             {
                                 DoSquare(num12, k4);
                             }
                             else
                             {
                                 DoRound(num12, k4);
                             }
                         }
                         for (int num13 = count - 1; num13 > 0; num13--)
                         {
                             m_normals[num13] = new DoublePoint(0.0 - m_normals[num13 - 1].X, 0.0 - m_normals[num13 - 1].Y);
                         }
                         m_normals[0] = new DoublePoint(0.0 - m_normals[1].X, 0.0 - m_normals[1].Y);
                         k4           = count - 1;
                         for (int num14 = k4 - 1; num14 > 0; num14--)
                         {
                             OffsetPoint(num14, ref k4, polyNode2.m_jointype);
                         }
                         if (polyNode2.m_endtype == EndType.etOpenButt)
                         {
                             IntPoint item = new IntPoint(Round((double)m_srcPoly[0].X - m_normals[0].X * delta), Round((double)m_srcPoly[0].Y - m_normals[0].Y * delta));
                             m_destPoly.Add(item);
                             item = new IntPoint(Round((double)m_srcPoly[0].X + m_normals[0].X * delta), Round((double)m_srcPoly[0].Y + m_normals[0].Y * delta));
                             m_destPoly.Add(item);
                         }
                         else
                         {
                             k4     = 1;
                             m_sinA = 0.0;
                             if (polyNode2.m_endtype == EndType.etOpenSquare)
                             {
                                 DoSquare(0, 1);
                             }
                             else
                             {
                                 DoRound(0, 1);
                             }
                         }
                         m_destPolys.Add(m_destPoly);
                     }
                 }
             }
         }
     }
 }
Beispiel #9
0
        private void RecursiveDrawPolytree(PolyNode tree, Color drawColor,Matrix4x4 matrix)
        {
            if (tree == null)
                return;

            DrawPointListLine(tree.Contour, drawColor, matrix, true);

            foreach (PolyNode cTree in tree.Childs)
            {
                RecursiveDrawPolytree(cTree, drawColor, matrix);
            }
        }
Beispiel #10
0
        //------------------------------------------------------------------------------

        public static void AddPolyNodeToPolygons(PolyNode polynode, Polygons polygons)
        {
            if (polynode.Contour.Count > 0) 
                polygons.Add(polynode.Contour);
            foreach (PolyNode pn in polynode.Childs)
                AddPolyNodeToPolygons(pn, polygons);
        }
Beispiel #11
0
        void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node)
        {
            foreach (PolyNode childNode in node.Childs)
            {
                int startIndex = pointIndex;

                foreach (ControlPoint point in childNode.Contour)
                {
                    inputGeometry.AddPoint(point.X, point.Y);
                    if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex);
                    pointIndex++;
                }
                inputGeometry.AddSegment(pointIndex - 1, startIndex);

                if (childNode.IsHole)
                {
                    for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++)
                    {
                        ControlPoint a1 = childNode.Contour[k];
                        ControlPoint a2 = childNode.Contour[j];
                        ControlPoint a3 = childNode.Contour[i];

                        if (ControlPoint.VectorProduct(a2 - a1, a3 - a1) < 0)
                        {
                            ControlPoint c = ((a1 + a3) / 2) - a2;
                            double x = 2;
                            ControlPoint hole;
                            do
                            {
                                x /= 2;
                                hole = a2 + (c * x);
                            } while (!IsInside(childNode, hole));

                            inputGeometry.AddHole(hole.X, hole.Y);
                            break;
                        }
                    }
                }

                SearchTree(inputGeometry, ref pointIndex, childNode);
            }
        }
Beispiel #12
0
        bool IsInside(PolyNode node, ControlPoint point)
        {
            foreach (PolyNode childNode in node.Childs)
                if (Contains(childNode.Contour, point)) return false;

            return Contains(node.Contour, point);
        }
        static void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node)
        {
            foreach (PolyNode childNode in node.Childs)
            {
                int startIndex = pointIndex;

                foreach (Vector2 point in childNode.Contour)
                {
                    inputGeometry.AddPoint(point.X, point.Y);
                    if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex);
                    pointIndex++;
                }
                inputGeometry.AddSegment(pointIndex - 1, startIndex);

                if (childNode.IsHole)
                {
                    for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++)
                    {
                        Vector2 a1 = childNode.Contour[k];
                        Vector2 a2 = childNode.Contour[j];
                        Vector2 a3 = childNode.Contour[i];
                        
                        if (Vector2.VectorProduct(a2 - a1, a3 - a1) < 0)
                        {
                            Vector2 c = (a1 + a3) / 2;
                            Vector2 d = a2 - c;
                            float x = c.Length * 2;
                            Vector2 hole;
                            do
                            {
                                x /= 2;
                                hole = c + (1 - x) * d;
                            } while (!IsInside(childNode, hole));
                            x /= 512;
                            hole = c + (1 - x) * d;
                            inputGeometry.AddHole(hole.X, hole.Y);
                            break;
                        }
                    }
                    
                }

                SearchTree(inputGeometry, ref pointIndex, childNode);
            }
        }
 static bool IsInside(PolyNode node, Vector2 point)
 {
     foreach (PolyNode childNode in node.Childs)
     {
         var polygon = new Polygon(childNode.Contour);
         if (polygon.Contains(point)) return false;
     }
     return new Polygon(node.Contour).Contains(point);
 }
 static void TransformRecursiveley(PolyNode node, Matrix2x3 matrix)
 {
     foreach (PolyNode childNode in node.Childs)
     {
         childNode.Contour = matrix.ApplyTo(childNode.Contour).ToList();
         TransformRecursiveley(childNode, matrix);
     }
 }
Beispiel #16
0
      //------------------------------------------------------------------------------

      internal static void AddPolyNodeToPaths(PolyNode polynode, NodeType nt, Paths paths)
      {
        bool match = true;
        switch (nt)
        {
          case NodeType.ntOpen: return;
          case NodeType.ntClosed: match = !polynode.IsOpen; break;
          default: break;
        }

        if (polynode.Contour.Count > 0 && match) 
          paths.Add(polynode.Contour);
        foreach (PolyNode pn in polynode.Childs)
          AddPolyNodeToPaths(pn, nt, paths);
      }
Beispiel #17
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);
            }
        }
Beispiel #18
0
        private void DoOffset(double delta)
        {
            m_destPolys = new List <List <IntPoint> >();
            m_delta     = delta;
            if (ClipperBase.near_zero(delta))
            {
                m_destPolys.Capacity = m_polyNodes.ChildCount;
                for (int i = 0; i < m_polyNodes.ChildCount; i++)
                {
                    PolyNode polyNode = m_polyNodes.Childs[i];
                    if (polyNode.m_endtype == EndType.etClosedPolygon)
                    {
                        m_destPolys.Add(polyNode.m_polygon);
                    }
                }
                return;
            }
            if (MiterLimit > 2.0)
            {
                m_miterLim = 2.0 / (MiterLimit * MiterLimit);
            }
            else
            {
                m_miterLim = 0.5;
            }
            double num  = (ArcTolerance <= 0.0) ? 0.25 : ((!(ArcTolerance > Math.Abs(delta) * 0.25)) ? ArcTolerance : (Math.Abs(delta) * 0.25));
            double num2 = 3.1415926535897931 / Math.Acos(1.0 - num / Math.Abs(delta));

            m_sin         = Math.Sin(6.2831853071795862 / num2);
            m_cos         = Math.Cos(6.2831853071795862 / num2);
            m_StepsPerRad = num2 / 6.2831853071795862;
            if (delta < 0.0)
            {
                m_sin = 0.0 - m_sin;
            }
            m_destPolys.Capacity = m_polyNodes.ChildCount * 2;
            IntPoint item = default(IntPoint);

            for (int j = 0; j < m_polyNodes.ChildCount; j++)
            {
                PolyNode polyNode2 = m_polyNodes.Childs[j];
                m_srcPoly = polyNode2.m_polygon;
                int count = m_srcPoly.Count;
                if (count == 0 || (delta <= 0.0 && (count < 3 || polyNode2.m_endtype != 0)))
                {
                    continue;
                }
                m_destPoly = new List <IntPoint>();
                if (count == 1)
                {
                    if (polyNode2.m_jointype == JoinType.jtRound)
                    {
                        double num3 = 1.0;
                        double num4 = 0.0;
                        for (int k = 1; (double)k <= num2; k++)
                        {
                            List <IntPoint> destPoly  = m_destPoly;
                            IntPoint        intPoint  = m_srcPoly[0];
                            long            x         = Round((double)intPoint.X + num3 * delta);
                            IntPoint        intPoint2 = m_srcPoly[0];
                            destPoly.Add(new IntPoint(x, Round((double)intPoint2.Y + num4 * delta)));
                            double num5 = num3;
                            num3 = num3 * m_cos - m_sin * num4;
                            num4 = num5 * m_sin + num4 * m_cos;
                        }
                    }
                    else
                    {
                        double num6 = -1.0;
                        double num7 = -1.0;
                        for (int l = 0; l < 4; l++)
                        {
                            List <IntPoint> destPoly2 = m_destPoly;
                            IntPoint        intPoint3 = m_srcPoly[0];
                            long            x2        = Round((double)intPoint3.X + num6 * delta);
                            IntPoint        intPoint4 = m_srcPoly[0];
                            destPoly2.Add(new IntPoint(x2, Round((double)intPoint4.Y + num7 * delta)));
                            if (num6 < 0.0)
                            {
                                num6 = 1.0;
                            }
                            else if (num7 < 0.0)
                            {
                                num7 = 1.0;
                            }
                            else
                            {
                                num6 = -1.0;
                            }
                        }
                    }
                    m_destPolys.Add(m_destPoly);
                    continue;
                }
                m_normals.Clear();
                m_normals.Capacity = count;
                for (int m = 0; m < count - 1; m++)
                {
                    m_normals.Add(GetUnitNormal(m_srcPoly[m], m_srcPoly[m + 1]));
                }
                if (polyNode2.m_endtype == EndType.etClosedLine || polyNode2.m_endtype == EndType.etClosedPolygon)
                {
                    m_normals.Add(GetUnitNormal(m_srcPoly[count - 1], m_srcPoly[0]));
                }
                else
                {
                    m_normals.Add(new DoublePoint(m_normals[count - 2]));
                }
                if (polyNode2.m_endtype == EndType.etClosedPolygon)
                {
                    int k2 = count - 1;
                    for (int n = 0; n < count; n++)
                    {
                        OffsetPoint(n, ref k2, polyNode2.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                    continue;
                }
                if (polyNode2.m_endtype == EndType.etClosedLine)
                {
                    int k3 = count - 1;
                    for (int num8 = 0; num8 < count; num8++)
                    {
                        OffsetPoint(num8, ref k3, polyNode2.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                    m_destPoly = new List <IntPoint>();
                    DoublePoint doublePoint = m_normals[count - 1];
                    for (int num9 = count - 1; num9 > 0; num9--)
                    {
                        List <DoublePoint> normals = m_normals;
                        int         index          = num9;
                        DoublePoint doublePoint2   = m_normals[num9 - 1];
                        double      x3             = 0.0 - doublePoint2.X;
                        DoublePoint doublePoint3   = m_normals[num9 - 1];
                        normals[index] = new DoublePoint(x3, 0.0 - doublePoint3.Y);
                    }
                    m_normals[0] = new DoublePoint(0.0 - doublePoint.X, 0.0 - doublePoint.Y);
                    k3           = 0;
                    for (int num10 = count - 1; num10 >= 0; num10--)
                    {
                        OffsetPoint(num10, ref k3, polyNode2.m_jointype);
                    }
                    m_destPolys.Add(m_destPoly);
                    continue;
                }
                int k4 = 0;
                for (int num11 = 1; num11 < count - 1; num11++)
                {
                    OffsetPoint(num11, ref k4, polyNode2.m_jointype);
                }
                if (polyNode2.m_endtype == EndType.etOpenButt)
                {
                    int         index2       = count - 1;
                    IntPoint    intPoint5    = m_srcPoly[index2];
                    double      num12        = intPoint5.X;
                    DoublePoint doublePoint4 = m_normals[index2];
                    long        x4           = Round(num12 + doublePoint4.X * delta);
                    IntPoint    intPoint6    = m_srcPoly[index2];
                    double      num13        = intPoint6.Y;
                    DoublePoint doublePoint5 = m_normals[index2];
                    item = new IntPoint(x4, Round(num13 + doublePoint5.Y * delta));
                    m_destPoly.Add(item);
                    IntPoint    intPoint7    = m_srcPoly[index2];
                    double      num14        = intPoint7.X;
                    DoublePoint doublePoint6 = m_normals[index2];
                    long        x5           = Round(num14 - doublePoint6.X * delta);
                    IntPoint    intPoint8    = m_srcPoly[index2];
                    double      num15        = intPoint8.Y;
                    DoublePoint doublePoint7 = m_normals[index2];
                    item = new IntPoint(x5, Round(num15 - doublePoint7.Y * delta));
                    m_destPoly.Add(item);
                }
                else
                {
                    int num16 = count - 1;
                    k4     = count - 2;
                    m_sinA = 0.0;
                    List <DoublePoint> normals2 = m_normals;
                    int         index3          = num16;
                    DoublePoint doublePoint8    = m_normals[num16];
                    double      x6           = 0.0 - doublePoint8.X;
                    DoublePoint doublePoint9 = m_normals[num16];
                    normals2[index3] = new DoublePoint(x6, 0.0 - doublePoint9.Y);
                    if (polyNode2.m_endtype == EndType.etOpenSquare)
                    {
                        DoSquare(num16, k4);
                    }
                    else
                    {
                        DoRound(num16, k4);
                    }
                }
                for (int num17 = count - 1; num17 > 0; num17--)
                {
                    List <DoublePoint> normals3 = m_normals;
                    int         index4          = num17;
                    DoublePoint doublePoint10   = m_normals[num17 - 1];
                    double      x7            = 0.0 - doublePoint10.X;
                    DoublePoint doublePoint11 = m_normals[num17 - 1];
                    normals3[index4] = new DoublePoint(x7, 0.0 - doublePoint11.Y);
                }
                List <DoublePoint> normals4      = m_normals;
                DoublePoint        doublePoint12 = m_normals[1];
                double             x8            = 0.0 - doublePoint12.X;
                DoublePoint        doublePoint13 = m_normals[1];
                normals4[0] = new DoublePoint(x8, 0.0 - doublePoint13.Y);
                k4          = count - 1;
                for (int num18 = k4 - 1; num18 > 0; num18--)
                {
                    OffsetPoint(num18, ref k4, polyNode2.m_jointype);
                }
                if (polyNode2.m_endtype == EndType.etOpenButt)
                {
                    IntPoint    intPoint9     = m_srcPoly[0];
                    double      num19         = intPoint9.X;
                    DoublePoint doublePoint14 = m_normals[0];
                    long        x9            = Round(num19 - doublePoint14.X * delta);
                    IntPoint    intPoint10    = m_srcPoly[0];
                    double      num20         = intPoint10.Y;
                    DoublePoint doublePoint15 = m_normals[0];
                    item = new IntPoint(x9, Round(num20 - doublePoint15.Y * delta));
                    m_destPoly.Add(item);
                    IntPoint    intPoint11    = m_srcPoly[0];
                    double      num21         = intPoint11.X;
                    DoublePoint doublePoint16 = m_normals[0];
                    long        x10           = Round(num21 + doublePoint16.X * delta);
                    IntPoint    intPoint12    = m_srcPoly[0];
                    double      num22         = intPoint12.Y;
                    DoublePoint doublePoint17 = m_normals[0];
                    item = new IntPoint(x10, Round(num22 + doublePoint17.Y * delta));
                    m_destPoly.Add(item);
                }
                else
                {
                    k4     = 1;
                    m_sinA = 0.0;
                    if (polyNode2.m_endtype == EndType.etOpenSquare)
                    {
                        DoSquare(0, 1);
                    }
                    else
                    {
                        DoRound(0, 1);
                    }
                }
                m_destPolys.Add(m_destPoly);
            }
        }
		private static void ProcessPolyTreeNodeIntoSeparatIslands(this Polygons polygonsIn, PolyNode node, List<Polygons> ret)
		{
			for (int n = 0; n < node.ChildCount; n++)
			{
				PolyNode child = node.Childs[n];
				Polygons polygons = new Polygons();
				polygons.Add(child.Contour);
				for (int i = 0; i < child.ChildCount; i++)
				{
					polygons.Add(child.Childs[i].Contour);
					polygonsIn.ProcessPolyTreeNodeIntoSeparatIslands(child.Childs[i], ret);
				}
				ret.Add(polygons);
			}
		}
Beispiel #20
0
        public void AddPath(List <IntPoint> path, JoinType joinType, EndType endType)
        {
            int num = path.Count - 1;

            if (num < 0)
            {
                return;
            }
            PolyNode polyNode = new PolyNode();

            polyNode.m_jointype = joinType;
            polyNode.m_endtype  = endType;
            if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon)
            {
                while (num > 0 && path[0] == path[num])
                {
                    num--;
                }
            }
            polyNode.m_polygon.Capacity = num + 1;
            polyNode.m_polygon.Add(path[0]);
            int num2 = 0;
            int num3 = 0;

            for (int i = 1; i <= num; i++)
            {
                if (!(polyNode.m_polygon[num2] != path[i]))
                {
                    continue;
                }
                num2++;
                polyNode.m_polygon.Add(path[i]);
                IntPoint intPoint  = path[i];
                long     y         = intPoint.Y;
                IntPoint intPoint2 = polyNode.m_polygon[num3];
                if (y <= intPoint2.Y)
                {
                    IntPoint intPoint3 = path[i];
                    long     y2        = intPoint3.Y;
                    IntPoint intPoint4 = polyNode.m_polygon[num3];
                    if (y2 != intPoint4.Y)
                    {
                        continue;
                    }
                    IntPoint intPoint5 = path[i];
                    long     x         = intPoint5.X;
                    IntPoint intPoint6 = polyNode.m_polygon[num3];
                    if (x >= intPoint6.X)
                    {
                        continue;
                    }
                }
                num3 = num2;
            }
            if ((endType == EndType.etClosedPolygon && num2 < 2) || (endType != 0 && num2 < 0))
            {
                return;
            }
            m_polyNodes.AddChild(polyNode);
            if (endType != 0)
            {
                return;
            }
            if (m_lowest.X < 0)
            {
                m_lowest = new IntPoint(0L, num3);
                return;
            }
            IntPoint intPoint7 = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y];
            IntPoint intPoint8 = polyNode.m_polygon[num3];

            if (intPoint8.Y <= intPoint7.Y)
            {
                IntPoint intPoint9 = polyNode.m_polygon[num3];
                if (intPoint9.Y != intPoint7.Y)
                {
                    return;
                }
                IntPoint intPoint10 = polyNode.m_polygon[num3];
                if (intPoint10.X >= intPoint7.X)
                {
                    return;
                }
            }
            m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, num3);
        }
		static private void GetAreasRecursive(PolyNode polyTreeForPlate, Polygons discreteAreas)
		{
			if (!polyTreeForPlate.IsHole)
			{
				discreteAreas.Add(polyTreeForPlate.Contour);
			}

			foreach (PolyNode child in polyTreeForPlate.Childs)
			{
				GetAreasRecursive(child, discreteAreas);
			}
		}
Beispiel #22
0
 private static List<Polygon> CreatePolygon(PolyNode polyNode)
 {
     List<Polygon> polyList = new List<Polygon>();
     Debug.Assert(polyNode.IsOpen == false);
     Debug.Assert(polyNode.IsHole == false);
     Polygon polygon = GetPolygon(polyNode.Contour);
     for (int i = 0; i < polyNode.Childs.Count; i++)
     {
         if (polyNode.Childs[i].IsHole)
         {
             polygon.AddHole(GetPolygon(polyNode.Childs[i].Contour));
         }
         else
         {
             polyList.AddRange(CreatePolygon(polyNode.Childs[i]));
         }
     }
     if (Triangulate(polygon))
     {
         polyList.Add(polygon);
     }
     return polyList;
 }