Script asks for geometry in Set A and Set B.
Then selects the geometry in Set A intersected by the geometry in Set B.
This time I had to debug the script a few times.
Tested on 2000 geometries, for meshes, curves, surfaces, polysurfaces.
# -*- coding: utf-8 -*-
import Rhino
import Rhino.Geometry as rg
import rhinoscriptsyntax as rs
import scriptcontext as sc
def to_brep_from_id(obj_id):
"""
Try to turn any supported object into a Brep.
- Brep / polysurface / surface / extrusion: via rs.coercebrep
- Mesh: via Brep.CreateFromMesh
Returns a Brep or None.
"""
if not obj_id:
return None
geo = rs.coercegeometry(obj_id)
if geo is None:
return None
# Mesh → Brep
if isinstance(geo, rg.Mesh):
brep = rg.Brep.CreateFromMesh(geo, True)
return brep
# Brep / Surface / Extrusion etc.
brep = rs.coercebrep(obj_id)
return brep
def objects_clash(id_a, id_b, tol):
"""
True geometric clash test between two objects.
Uses BrepBrep intersection only.
No bounding box filtering involved.
"""
brep_a = to_brep_from_id(id_a)
brep_b = to_brep_from_id(id_b)
# If we can't convert either to a Brep, skip
if brep_a is None or brep_b is None:
return False
# Real clash: BrepBrep intersection
rc, curves, points = rg.Intersect.Intersection.BrepBrep(brep_a, brep_b, tol)
if not rc:
return False
has_curves = curves is not None and len(curves) > 0
has_points = points is not None and len(points) > 0
return has_curves or has_points
def main():
tol = sc.doc.ModelAbsoluteTolerance
# First set: GeoA (can be preselected)
geo_a_ids = rs.GetObjects(
"Select GeoA (objects that will be filtered by clash)",
preselect=True,
select=False
)
if not geo_a_ids:
print("No GeoA objects selected.")
return
# Second set: GeoB (clashing objects)
geo_b_ids = rs.GetObjects(
"Select GeoB (objects that may clash with GeoA)",
preselect=False,
select=False
)
if not geo_b_ids:
print("No GeoB objects selected.")
return
clashing_ids = []
count_a = len(geo_a_ids)
count_b = len(geo_b_ids)
for i, id_a in enumerate(geo_a_ids):
# Optional: progress feedback for large sets:
# print("Testing {}/{} from GeoA...".format(i+1, count_a))
for id_b in geo_b_ids:
if objects_clash(id_a, id_b, tol):
clashing_ids.append(id_a)
break # already found a clash, no need to test more GeoB
rs.UnselectAllObjects()
if clashing_ids:
rs.SelectObjects(clashing_ids)
print("Found {} clashing object(s) in GeoA (out of {} GeoA, {} GeoB).".format(
len(clashing_ids), count_a, count_b))
print("They are now selected.")
else:
print("No clashes found between GeoA and GeoB.")
if __name__ == "__main__":
main()