Skip to content

Instantly share code, notes, and snippets.

@ian-quinn
Last active May 13, 2021 08:17
Show Gist options
  • Save ian-quinn/89b72eb09797726cb3aa9050008fc58d to your computer and use it in GitHub Desktop.
Save ian-quinn/89b72eb09797726cb3aa9050008fc58d to your computer and use it in GitHub Desktop.
[component_ghpython] Useful GH_Python components #grasshopper #python
# Switch on and off of the global timer
# Needs update with Rhino 7
import Grasshopper as gh
# Get the Grasshopper document and objects
ghDoc = ghenv.Component.OnPingDocument()
ghObjects = ghDoc.Objects
# Iterate the GH objects, check type and reset data recorders
for obj in ghObjects:
if type(obj) is gh.Kernel.Special.GH_Timer:
if Toggle:
obj.Locked = True
obj.ExpireSolution(True)
else:
obj.Locked = False
obj.ExpireSolution(True)
# RegionContainment defines enumerated values for curve relationships but I just don't get it.
# https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_RegionContainment.htm
from Rhino.Geometry import *
from Rhino.RhinoDoc import ActiveDoc as rhdoc
tol = rhdoc.ModelAbsoluteTolerance
ids = range(len(crvs))
# initialize with dictionary of sets containing its own key
# i.e all curves in separate clusters
clusters = {i: set([i]) for i in ids}
rtree = RTree()
for i, crv in enumerate(crvs):
# populate the RTree with bounding boxes
rtree.Insert(crv.GetBoundingBox(True), i)
def check_containment(crvA, crvB):
# checks if either A contains B or B contains A
# relatively expensive, so further optimizations can be made here eg. for polylines
rg = Curve.PlanarClosedCurveRelationship(crvA, crvB, Plane.WorldXY, tol)
return (rg in (RegionContainment.AInsideB, RegionContainment.BInsideA))
def callback(sender, e):
a, b = e.Id, e.IdB
if a == b:
return
if b in clusters[a] or a in clusters[b]:
return
if check_containment(crvs[a], crvs[b]):
clusters[a].add(b)
clusters[b].add(a)
RTree.SearchOverlaps(rtree, rtree, 0.01, callback) # O(n)
# iterate through the clusters from the highest to lowest index
for i in reversed(ids):
# still O(n) despite nested for loop, because inner loop is ~O(1)
for j in list(clusters[i]): # create new list to avoid changing the iterable
# merge with sets of a greater index
if j > i:
try:
clusters[i].update(clusters.pop(j))
except KeyError: # j has already been popped
pass
mapping = [0] * len(crvs)
for k, vals in clusters.items():
for v in vals:
mapping[v] = k
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment