public static List <Polyline> DelaunayTriangulation(this Polyline outerCurve, List <Polyline> innerCurves = null, double offsetDistance = -0.001, bool conformingDelaunay = true) { if (outerCurve == null) { BH.Engine.Base.Compute.RecordError("Cannot perform Delaunay Triangulation on an outer curve that is set to null."); return(new List <Polyline>()); } // Create a zero length list if no holes input if (innerCurves == null) { innerCurves = new List <Polyline>(); } double area = outerCurve.Area(); for (int x = 0; x < innerCurves.Count; x++) { Polyline pLine = outerCurve.BooleanDifference(new List <Polyline> { innerCurves[x] })[0]; if (pLine.Area() != area) { //The boolean difference returned a different polyline - offset this inner curve innerCurves[x] = innerCurves[x].Offset(offsetDistance); } } // Get the transformation matrix Plane plane = outerCurve.IFitPlane(); Vector normal = plane.Normal; List <Point> vertices = outerCurve.IDiscontinuityPoints(); Point refPoint = vertices.Min(); Point refPointP = BH.Engine.Geometry.Create.Point(refPoint.X, refPoint.Y, 0); Vector zVector = BH.Engine.Geometry.Create.Vector(0, 0, 1); Vector rotationVector = normal.CrossProduct(zVector).Normalise(); double rotationAngle = normal.Angle(zVector); TransformMatrix transformMatrix = BH.Engine.Geometry.Create.RotationMatrix(vertices.Min(), rotationVector, rotationAngle); // Get the translation vector Vector translateVector = refPointP - refPoint; // Transform the original input curve/s Polyline transformedCurve = Modify.Translate(outerCurve.Transform(transformMatrix), translateVector); List <Polyline> transformedHole = new List <Polyline>(); foreach (Polyline h in innerCurves) { if (h.IsCoplanar(outerCurve)) { transformedHole.Add(Modify.Translate(h.Transform(transformMatrix), translateVector)); } } // Convert geometry to Triangle inputs TriangleNet.Geometry.Polygon parentPolygon = new TriangleNet.Geometry.Polygon(); List <TriangleNet.Geometry.Vertex> parentVertices = new List <TriangleNet.Geometry.Vertex>(); foreach (Point point in transformedCurve.IDiscontinuityPoints()) { parentPolygon.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); parentVertices.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); } TriangleNet.Geometry.Contour parentContour = new TriangleNet.Geometry.Contour(parentVertices); parentPolygon.Add(parentContour); foreach (Polyline h in transformedHole) { List <TriangleNet.Geometry.Vertex> childVertices = new List <TriangleNet.Geometry.Vertex>(); foreach (Point point in h.IDiscontinuityPoints()) { childVertices.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); } TriangleNet.Geometry.Contour childContour = new TriangleNet.Geometry.Contour(childVertices); Point childCentroid = h.PointInRegion(); parentPolygon.Add(childContour, new TriangleNet.Geometry.Point(childCentroid.X, childCentroid.Y)); } // Triangulate TriangleNet.Meshing.ConstraintOptions options = new TriangleNet.Meshing.ConstraintOptions() { ConformingDelaunay = conformingDelaunay, }; TriangleNet.Meshing.QualityOptions quality = new TriangleNet.Meshing.QualityOptions() { }; TriangleNet.Mesh mesh = (TriangleNet.Mesh)TriangleNet.Geometry.ExtensionMethods.Triangulate(parentPolygon, options, quality); // Convert triangulations back to BHoM geometry List <Polyline> translatedPolylines = new List <Polyline>(); foreach (var face in mesh.Triangles) { // List points defining the triangle List <Point> pts = new List <Point>(); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(0).X, face.GetVertex(0).Y)); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(1).X, face.GetVertex(1).Y)); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(2).X, face.GetVertex(2).Y)); pts.Add(pts.First()); translatedPolylines.Add(BH.Engine.Geometry.Create.Polyline(pts)); } // Translate back to original plane List <Polyline> meshPolylines = new List <Polyline>(); foreach (Polyline pl in translatedPolylines) { TransformMatrix matrixTransposed = transformMatrix.Invert(); Polyline meshPolyline = pl.Translate(-translateVector).Transform(transformMatrix.Invert()); meshPolylines.Add(meshPolyline); } return(meshPolylines); }