public List <Vector2[]> TriangulateClipperSolution(ClipperLib.PolyTree solution)
        {
            var tess = new Tess();

            tess.NoEmptyPolygons = true;

            // Add a contour for each part of the solution tree
            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    // Add a new countor. Holes are automatically generated.
                    var vertices = node.Contour.Select(pt => new ContourVertex {
                        Position = new Vec3 {
                            X = pt.X, Y = pt.Y, Z = 0
                        }
                    }).ToArray();
                    tess.AddContour(vertices);
                }
                node = node.GetNext();
            }

            return(TrianglesFromTessellator(tess));
        }
Exemplo n.º 2
0
        private static void ClipperPolyTreeToPolygonListRecursively(ClipperLib.PolyNode node, HashSet <ClipperLib.IntPoint> sharpPoints, HashSet <ClipperLib.IntPoint> allPoints, List <PolygonClosedD2D> polygonList, IDictionary <ClipperLib.PolyNode, PolygonClosedD2D> dictClipperNodeToNode)
        {
            if (node.Contour != null && node.Contour.Count != 0)
            {
                var pointsInThisPolygon      = node.Contour.Select(clipperPt => new PointD2D(clipperPt.X / 65536.0, clipperPt.Y / 65536.0));
                var sharpPointsInThisPolygon = node.Contour.Where(clipperPt => sharpPoints.Contains(clipperPt)).Select(clipperPt => new PointD2D(clipperPt.X / 65536.0, clipperPt.Y / 65536.0));

                var polygon = new PolygonClosedD2D(pointsInThisPolygon.ToArray(), new HashSet <PointD2D>(sharpPointsInThisPolygon))
                {
                    IsHole = node.IsHole
                };
                polygonList.Add(polygon);

                if (node.IsHole)
                {
                    polygon.Parent = dictClipperNodeToNode[node.Parent];
                }

                dictClipperNodeToNode.Add(node, polygon);
            }

            if (0 != node.ChildCount)
            {
                foreach (var childNode in node.Childs)
                {
                    ClipperPolyTreeToPolygonListRecursively(childNode, sharpPoints, allPoints, polygonList, dictClipperNodeToNode);
                }
            }
        }
Exemplo n.º 3
0
        private List <Poly2Tri.DelaunayTriangle> GetTriangleListFromClipperSolution(ClipperLib.PolyTree solution)
        {
            Func <ClipperLib.IntPoint, Poly2Tri.PolygonPoint> xfToPolygonPoint = (p) => new Poly2Tri.PolygonPoint(p.X, p.Y);

            Poly2Tri.PolygonSet polygonSet = new Poly2Tri.PolygonSet();

            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    if (node.IsHole)
                    {
                        if (polygonSet.Polygons.Count() > 0)
                        {
                            // Add hole to last polygon entered
                            var polyPoints        = node.Contour.Select(xfToPolygonPoint).ToArray();
                            Poly2Tri.Polygon hole = new Poly2Tri.Polygon(polyPoints);

                            Poly2Tri.Polygon polygon = polygonSet.Polygons.Last();
                            polygon.AddHole(hole);
                        }
                    }
                    else
                    {
                        // Add a new polygon to the set
                        var polyPoints           = node.Contour.Select(xfToPolygonPoint).ToList();
                        Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(polyPoints);
                        polygonSet.Add(polygon);
                    }
                }
                node = node.GetNext();
            }

            // Now triangulate the whole set
            Poly2Tri.P2T.Triangulate(polygonSet);

            // Combine all the triangles into one list
            List <Poly2Tri.DelaunayTriangle> triangles = new List <Poly2Tri.DelaunayTriangle>();

            foreach (var polygon in polygonSet.Polygons)
            {
                triangles.AddRange(polygon.Triangles);
            }

            return(triangles);
        }
Exemplo n.º 4
0
        private void ExtractOutlines(ClipperLib.PolyNode tree, List <IShape> shapes)
        {
            if (tree.Contour.Any())
            {
                // convert the Clipper Contour from scaled ints back down to the origional size (this is going to be lossy but not significantly)
                var pointCount = tree.Contour.Count;
                var vectors    = new Vector2[pointCount];
                for (var i = 0; i < pointCount; i++)
                {
                    var p = tree.Contour[i];
                    vectors[i] = new Vector2(p.X, p.Y) / ClipperScaleFactor;
                }

                var polygon = new Polygon(new LinearLineSegment(vectors));

                shapes.Add(polygon);
            }

            foreach (var c in tree.Childs)
            {
                this.ExtractOutlines(c, shapes);
            }
        }
Exemplo n.º 5
0
        public List <PointF[]> Triangulate(ClipperLib.PolyTree solution)
        {
            List <PointF[]> triangles = new List <PointF[]>();

            var tess = new LibTessDotNet.Tess();

            tess.NoEmptyPolygons = true;

            // Transformation function from ClipperLip Point to LibTess contour vertex
            Func <ClipperLib.IntPoint, LibTessDotNet.ContourVertex> xfToContourVertex = (p) => new LibTessDotNet.ContourVertex()
            {
                Position = new LibTessDotNet.Vec3 {
                    X = p.X, Y = p.Y, Z = 0
                }
            };

            // Add a contour for each part of the solution tree
            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    // Add a new countor. Holes are automatically generated.
                    var vertices = node.Contour.Select(xfToContourVertex).ToArray();
                    tess.AddContour(vertices);
                }
                node = node.GetNext();
            }

            // Do the tessellation
            tess.Tessellate(LibTessDotNet.WindingRule.EvenOdd, LibTessDotNet.ElementType.Polygons, 3);

            // Extract the triangles
            int numTriangles = tess.ElementCount;

            for (int i = 0; i < numTriangles; i++)
            {
                var v0 = tess.Vertices[tess.Elements[i * 3 + 0]].Position;
                var v1 = tess.Vertices[tess.Elements[i * 3 + 1]].Position;
                var v2 = tess.Vertices[tess.Elements[i * 3 + 2]].Position;

                List <PointF> triangle = new List <PointF>()
                {
                    new PointF(v0.X, v0.Y),
                    new PointF(v1.X, v1.Y),
                    new PointF(v2.X, v2.Y),
                };

                // Assre each triangle needs to be CCW
                float cross = Geometry.Math.Cross(triangle[0], triangle[1], triangle[2]);
                if (cross > 0)
                {
                    triangle.Reverse();
                }

                triangles.Add(triangle.ToArray());
            }

            return(triangles);
        }