And here it is.
As said, this method makes a check and remove edges if they start and ends from the same curve… but! I didn’t tought about convex shapes! So, before removing the edge, its midpoint is checked to be outside of the main shape or inside an internal shape (according to edge “birthplace”).
mesh_delanuay_holes_V1.gh (18.5 KB)
The script takes a list of curves as input. First curve must be the outer one.
The script doesn’t check for intersections and works on XY plane.
I’ve left inside 6 alternative of the same script: for loop, parallel loop (multithreaded), Curve or Polyline inclusion test and outputting points or not.
One of the two in the green box should be the best… probably the Curve one, for precision.
It seems to be 2x slower than original Delanuay component… not that bad, imho…
More tests needed.
Hope it helps!
Code of the Parallel.For, Curve inclusion test version:
using System.Linq;
using System.Threading.Tasks;
private void RunScript(List<Curve> Curves, ref object Mesh)
{
double t = this.RhinoDocument.ModelAbsoluteTolerance;
int cc = Curves.Count;
Rhino.Geometry.PolylineCurve[] polylines = new Rhino.Geometry.PolylineCurve[cc];
Rhino.Geometry.Point3d[][] pts = new Rhino.Geometry.Point3d[cc][];
int[] pc = new int[cc]; // Point count for each polyline
// Transforming each curve into a polyline, extracting the point array and counting them
//for(int i = 0;i < cc;i++){ // --- FOR --- //
Parallel.For(0, cc, (i) => { // --- PAR --- //
polylines[i] = Curves[i].ToPolyline(-1, -1, 0.2, 1, 100, 0.1, 0.1, 1, false);
pts[i] = polylines[i].ToPolyline().ToArray();
//polylines[i] = ClosePolylineCurve(polylines[i]); // Closing PolylineCurve for inclusion test
pc[i] = pts[i].Length;
}); // --- PAR --- //
//} // --- FOR --- //
int total = pc.Sum(); // Total amount of points
Rhino.Geometry.Point3d[] points = pts.SelectMany(x => x).ToArray();
int[] cis = new int[total];
int[] prevs = new int[total];
int[] nexts = new int[total];
int[] starts = new int[total];
int[] ends = new int[total];
int start = 0;
for(int k = 0;k < cc;k++){
//for(int i = 0;i < pc[k];i++){ // --- FOR --- //
Parallel.For(0, pc[k], (i) => { // --- PAR --- //
int w = start + i;
int prev;
int next;
Neighbors(w, i, pc[k], out prev, out next);
cis[w] = k;
prevs[w] = prev;
nexts[w] = next;
starts[w] = start;
ends[w] = start + pc[k];
}); // --- PAR --- //
//} // --- FOR --- //
start += pc[k];
}
Rhino.Geometry.Mesh mesh = Rhino.Geometry.Mesh.CreateFromTessellation(points, null, Plane.WorldXY, false);
Rhino.Geometry.Collections.MeshTopologyEdgeList topedges = mesh.TopologyEdges;
int[] faces = Enumerable.Repeat(-1, topedges.Count * 2).ToArray();
//for(int i = 0;i < topedges.Count;i++){ // --- FOR --- //
var result = Parallel.For(0, topedges.Count, (i) => { // --- PAR --- //
Rhino.IndexPair pair = topedges.GetTopologyVertices(i);
if(pair.J >= starts[pair.I] & pair.J <= ends[pair.I]){
if(!(pair.I == prevs[pair.J] || pair.I == nexts[pair.J])){
if(cis[pair.I] == 0){
if(Curves[0].Contains((points[pair.I] + points[pair.J]) / 2, Plane.WorldXY, t).Equals(PointContainment.Outside)){
//if(polylines[0].Contains((points[pair.I] + points[pair.J]) / 2, Plane.WorldXY, t).Equals(PointContainment.Outside)){
int asd = 0;
foreach(int f in topedges.GetConnectedFaces(i)){
faces[i * 2 + asd] = f;
asd++;
}
}
}
else{
if(Curves[cis[pair.I]].Contains((points[pair.I] + points[pair.J]) / 2, Plane.WorldXY, t).Equals(PointContainment.Inside)){
//if(polylines[cis[pair.I]].Contains((points[pair.I] + points[pair.J]) / 2, Plane.WorldXY, t).Equals(PointContainment.Inside)){
int asd = 0;
foreach(int f in topedges.GetConnectedFaces(i)){
faces[i * 2 + asd] = f;
asd++;
}
}
}
}
}
}); // --- PAR --- //
//} // --- FOR --- //
faces = faces.Distinct().OrderByDescending(f => f).ToArray();
foreach(int f in faces){
if(f > -1){
mesh.Faces.RemoveAt(f);
}
}
Mesh = mesh;
// Points = points;
}
// <Custom additional code>
public void Neighbors(int val, int index, int loopsize, out int previous, out int next){
loopsize += -1;
if(index == 0){ previous = val + loopsize; }
else{ previous = val - 1; }
if(index == loopsize){ next = val - loopsize;}
else{next = val + 1;}
}
public Rhino.Geometry.PolylineCurve ClosePolylineCurve(Rhino.Geometry.PolylineCurve p){
Rhino.Geometry.Polyline poly = p.ToPolyline();
poly.Add(p.PointAtStart);
p = poly.ToPolylineCurve();
return p;
}