Instead of using FlowAlongSurface with only one target, with this script, you can select several targets.
Since FlowAlongSrf might run into trouble on high tolerances, I added custom tolerance input, with the default being 0.1.
# Flow geometry from reference surface to multiple target surfaces
# Works with Meshes, Breps, Curves, Points, PointClouds, and Extrusions
# Extrusions are converted to Breps before morphing
import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
import System
def get_tolerance_option(default_tol=0.1):
go = Rhino.Input.Custom.GetOption()
go.SetCommandPrompt("Tolerance ({})".format(default_tol))
go.AcceptNothing(True)
opt_map = [
("T1_0", 1.0),
("T0_1", 0.1),
("T0_01", 0.01),
("T0_001", 0.001),
("Doc", None),
]
for name, _ in opt_map:
go.AddOption(name)
while True:
res = go.Get()
if res == Rhino.Input.GetResult.Nothing:
return default_tol
if res == Rhino.Input.GetResult.Option:
idx = go.OptionIndex() - 1
if idx < 0 or idx >= len(opt_map):
return None
name, val = opt_map[idx]
return sc.doc.ModelAbsoluteTolerance if name == "Doc" else val
return None
def get_first_surface(obj_id):
brep = rs.coercebrep(obj_id)
if not brep or brep.Faces.Count < 1:
return None
return brep.Faces[0].UnderlyingSurface()
def add_geometry_to_doc(geom, atts):
if isinstance(geom, Rhino.Geometry.Mesh):
geom.Normals.ComputeNormals()
geom.Compact()
return sc.doc.Objects.AddMesh(geom, atts)
elif isinstance(geom, Rhino.Geometry.Brep):
return sc.doc.Objects.AddBrep(geom, atts)
elif isinstance(geom, Rhino.Geometry.Curve):
return sc.doc.Objects.AddCurve(geom, atts)
elif isinstance(geom, Rhino.Geometry.Point):
return sc.doc.Objects.AddPoint(geom.Location, atts)
elif isinstance(geom, Rhino.Geometry.PointCloud):
return sc.doc.Objects.AddPointCloud(geom, atts)
else:
return sc.doc.Objects.Add(geom, atts)
def flow_along_srf_rhinocommon_keep_props_and_groups():
geo_ids = rs.GetObjects(
"Select GeometryToFlow",
preselect=True
)
if not geo_ids:
return
rs.UnselectAllObjects()
ref_id = rs.GetObject(
"Select RefSurface / Base Surface",
rs.filter.surface | rs.filter.polysurface,
preselect=False
)
if not ref_id:
return
rs.UnselectAllObjects()
tgt_ids = rs.GetObjects(
"Select Target Surfaces",
rs.filter.surface | rs.filter.polysurface,
preselect=False
)
if not tgt_ids:
return
tol = get_tolerance_option(default_tol=0.1)
if tol is None:
return
ref_srf = get_first_surface(ref_id)
if not ref_srf:
print("Could not read reference surface.")
return
src_items = []
src_group_indices = set()
for gid in geo_ids:
rhobj = sc.doc.Objects.FindId(gid)
if not rhobj or not rhobj.Geometry:
continue
geom = rhobj.Geometry.Duplicate()
# Important: convert extrusions to Breps before morphing
if isinstance(geom, Rhino.Geometry.Extrusion):
geom = geom.ToBrep()
atts = rhobj.Attributes.Duplicate()
g_list = list(atts.GetGroupList()) if atts.GroupCount > 0 else []
for gi in g_list:
src_group_indices.add(gi)
src_items.append((geom, atts, g_list))
if not src_items:
print("No valid geometry found.")
return
for ti, tid in enumerate(tgt_ids, start=1):
tgt_srf = get_first_surface(tid)
if not tgt_srf:
print("Skipping invalid target surface.")
continue
morph = Rhino.Geometry.Morphs.SporphSpaceMorph(ref_srf, tgt_srf)
morph.Tolerance = tol
morph.PreserveStructure = False
morph.ConstrainNormal = Rhino.Geometry.Vector3d.Unset
group_map = {}
for src_gi in src_group_indices:
old_name = sc.doc.Groups.GroupName(src_gi) or "Group"
new_name = "{}__Flow_{:02d}".format(old_name, ti)
new_gi = sc.doc.Groups.Add(new_name)
group_map[src_gi] = new_gi
for geom, atts, g_list in src_items:
dup = geom.Duplicate()
if not dup:
continue
morph.Morph(dup)
new_atts = atts.Duplicate()
try:
new_atts.RemoveFromAllGroups()
except:
pass
new_id = add_geometry_to_doc(dup, new_atts)
if new_id == System.Guid.Empty:
print("Failed to add morphed object.")
continue
for src_gi in g_list:
new_gi = group_map.get(src_gi)
if new_gi is not None:
sc.doc.Groups.AddToGroup(new_gi, new_id)
sc.doc.Views.Redraw()
print("Flow complete.")
if __name__ == "__main__":
flow_along_srf_rhinocommon_keep_props_and_groups()
This post is related to: