I have a drawing made of many polylines with arcs. I need to draw circles that are tangent to each arc in the polylines. Doing this manually, I am drawing each circle by hovering by each arc, using the center snap command to draw the center of the circle and then the perp snap to bring the edge tangent to the line at that point.
This is taking forever and I’m hoping to write a script to iterate through each arc for each polyline. It’s been a few years since I scripted, so I’m a bit rusty on the functions. Thank you so much for any help!
Here is some pseudocode with the steps I think this will require
#Select polylines
id = rs.GetObject(“Select Polylines”) #Identify arcs on polylines #For each arc, find ArcCenterPoint #For each center point, draw a circle at this point with the edge at the point perp to that arc
Thank you so much for this. I haven’t used Grasshopper Python components before. Do I need to implement the script in Grasshopper or will it execute in Rhino without the additional integration?
You’re welcome. It can implemented in Grasshopper, but it needn’t be. It’s simpler to take out the try/finally and sc.doc and just use Rhino Python:
import Rhino
import rhinoscriptsyntax as rs
objs = rs.ObjectsByType(4)
for obj in objs:
if rs.IsArc(obj):
center = rs.ArcCenterPoint(obj)
radius = rs.ArcRadius(obj)
rs.AddCircle(center, radius)
# relies on "active construction plane"
This is so helpful, thanks! I tried to implement it, but think I have an issue because my objects are polylines made of arcs, but not arcs themselves. The IsArc() operation is false for all of my lines, but IsPolyCurve() is true.
Do you know how to identify each arc making up the polyline, and then execute the remaining code from there?
Ah right. Polylines are fine, so e.g. if you want a circle through the vertices of a polyline, there’s a circle from three points function that should do it easily (then you don’t ned to worry about the normal or plane).
But I’ve not used Polycurves, so if you want to sort of do something else, e.g. circumscribe the inside of a polyline, then I’m not sure how that geometry has a unique solution, so I need a more precise definition
Well, this might be a bit advanced, but… a little RhinoCommon is sometimes helpful.
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def AddCirclesToPolyCurve():
obj_ids=rs.GetObjects("Select polycurves to process",4,preselect=True)
if not obj_ids: return
for obj_id in obj_ids:
#get the RhinoCommon curve object geometry
crv=rs.coercecurve(obj_id)
#find all the subsegments
segs=crv.DuplicateSegments()
#loop and check each segment to see if it is an arc curve
for seg in segs:
if isinstance(seg,Rhino.Geometry.ArcCurve):
#segment is an arc curve, get underlying arc plane and radius
radius=seg.Arc.Radius
plane=seg.Arc.Plane
#make new circles with arc data
circle=Rhino.Geometry.Circle(plane,radius)
#add the circles to the document
sc.doc.Objects.AddCircle(circle)
sc.doc.Views.Redraw()
AddCirclesToPolyCurve()
Just in case, here is a rhinoscriptsyntax-only version which does not need any knowledge of RhinoCommon. Only difference is the segments are first duplicated and added to the document, then deleted at the end, which could take slightly longer if there are thousands, otherwise you probably won’t notice the difference.
import rhinoscriptsyntax as rs
def AddCirclesToPolyCurve():
obj_ids=rs.GetObjects("Select polycurves to process",4,preselect=True)
if not obj_ids: return
rs.EnableRedraw(False)
for obj_id in obj_ids:
seg_ids=rs.ExplodeCurves(obj_id) #makes a copy, doesn't delete original
for seg_id in seg_ids:
if rs.IsArc(seg_id):
#segment is an arc curve
radius=rs.ArcRadius(seg_id)
plane=rs.CurvePlane(seg_id)
#make new circles with arc data
circle_id=rs.AddCircle(plane,radius)
#delete the copied segments after
rs.DeleteObjects(seg_ids)
AddCirclesToPolyCurve()