I’m trying to get the naked boundary (closed polyline) from two meshes with multiple open faces… I’m getting satisfactory results within geometry, but as I increase the mesh resolution, the time processing rises a lot.
Computing with more straightforward methods or some plugin components is much faster. Still, it doesn’t get the completely accurate naked boundary polyline, or they don’t appear in the same topology for later processes like lofting them.
(The following steps to consider…I’m doing a mesh loft in between the two sets of polylines and joining the meshes to get a close mesh)
in the IMG below you can visualize the black segements which are missing in the faster process to get the polylines.
import Rhino
from collections import defaultdict
def pt3f_pt3d(pt3f):
return Rhino.Geometry.Point3d(pt3f.X, pt3f.Y, pt3f.Z)
def naked_boundary(mesh):
e_dict = defaultdict(int)
naked_e = []
for face in mesh.Faces:
indices = [face.A, face.B, face.C]
if face.IsQuad:
indices.append(face.D)
num_vx = 4 if face.IsQuad else 3
for i in range(num_vx):
v1 = indices[i]
v2 = indices[(i + 1) % num_vx]
e = tuple(sorted((v1, v2)))
e_dict[e] += 1
for e, count in e_dict.iteritems():
if count == 1:
v1, v2 = e
pt1_f = mesh.Vertices[v1]
pt2_f = mesh.Vertices[v2]
pt1 = pt3f_pt3d(pt1_f)
pt2 = pt3f_pt3d(pt2_f)
naked_e.append((pt1, pt2))
edges = naked_e[:]
pl = []
while edges:
current_pl = []
current_e = edges.pop(0)
current_pl.extend(current_e)
extended = True
while extended:
extended = False
tol = Rhino.RhinoMath.SqrtEpsilon
st_pt = current_pl[0]
for i, edge in enumerate(edges):
if edge[1].DistanceTo(st_pt) <= tol:
current_pl.insert(0, edge[0])
del edges[i]
extended = True
break
elif edge[0].DistanceTo(st_pt) <= tol:
current_pl.insert(0, edge[1])
del edges[i]
extended = True
break
if extended:
continue
end_pt = current_pl[-1]
for i, edge in enumerate(edges):
if edge[0].DistanceTo(end_pt) <= tol:
current_pl.append(edge[1])
del edges[i]
extended = True
break
elif edge[1].DistanceTo(end_pt) <= tol:
current_pl.append(edge[0])
del edges[i]
extended = True
break
unique_pl = [current_pl[0]]
for pt in current_pl[1:]:
if not pt.Equals(unique_pl[-1]):
unique_pl.append(pt)
if len(unique_pl) >= 2:
polyline = Rhino.Geometry.Polyline(unique_pl)
if polyline.IsValid:
pl_curve = Rhino.Geometry.PolylineCurve(polyline)
pl.append(pl_curve)
return pl
if mesh and mesh.IsValid:
nb = naked_boundary(mesh)
crv = nb
else:
crv = "Invalid or NO input"