def render_attribute(self, points, bool_inside): ### Render Attribute-Values render = [] pts_weighting = [] for i in xrange(len(points)): pp = points[i] bb = bool_inside[i] sub_render = [] for j in xrange(len(pp)): p = pp[j] b = bb[j] if b: sub_render.append(rs.AddCircle(p, 0.5)) pts_weighting.append(p) else: sub_render.append(rs.AddCircle(p, 4)) render.append(sub_render) return render, pts_weighting
def createPipe(self, first, mid, last, text): first_fillet = rs.AddFilletCurve(first, mid, 0.25) fillet_points = rs.CurveFilletPoints(first, mid, 0.25) first_circle = rs.AddCircle(fillet_points[2], 0.125) first_cp = rs.CurveClosestPoint(first, fillet_points[0]) first_domain = rs.CurveDomain(first) nfirst = rs.TrimCurve(first, (first_domain[0], first_cp), False) second_cp = rs.CurveClosestPoint(mid, fillet_points[1]) second_domain = rs.CurveDomain(mid) nmid = rs.TrimCurve(mid, (second_cp, second_domain[1]), False) second_fillet = rs.AddFilletCurve(mid, last, 0.25) fillet_points = rs.CurveFilletPoints(mid, last, 0.25) second_circle = rs.AddCircle(fillet_points[2], 0.125) first_cp = rs.CurveClosestPoint(mid, fillet_points[0]) first_domain = rs.CurveDomain(mid) nmid = rs.TrimCurve(nmid, (first_domain[0], first_cp), False) second_cp = rs.CurveClosestPoint(last, fillet_points[1]) second_domain = rs.CurveDomain(last) nlast = rs.TrimCurve(last, (second_cp, second_domain[1]), False) curve = rs.JoinCurves( [nfirst, first_fillet, nmid, second_fillet, nlast]) print curve pipe = rs.AddPipe(curve, 0, 0.09375, 0, 1) points = [ rs.CurveStartPoint(first), rs.CurveEndPoint(first), rs.CurveStartPoint(last), rs.CurveEndPoint(last) ] self.copyAndMover(first, mid, last, points, text)
def imageToCircles(): filter = "Text file (*.jpg)|*.jpg|All Files (*.*)|*.*||" filename = rs.OpenFileName("Open Image", filter) if not filename: return image = System.Drawing.Bitmap.FromFile(filename) image.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipY) gridScale = image.Width / gridColumns outputX = 0 outputY = 0 imageX = 0 imageY = 0 rs.EnableRedraw(False) for imageX in range (0, image.Width, int(gridScale)): outputX = outputX+gridGapSize outputY = 0 for imageY in range (0, image.Height, int(gridScale)): outputY = outputY + gridGapSize pixel = image.GetPixel(imageX, imageY) diameter = (pixel.GetBrightness()* gridGapSize)* brightnessFactor if (diameter > minCircleSize): if (diameter > maxCircleSize): rs.AddCircle((outputX, outputY, 0), (maxCircleSize/2)) else: rs.AddCircle((outputX, outputY, 0), (diameter/2)) rs.EnableRedraw(True)
def make_jigs(b, diam, bdiam): jig_base_height = 4. / 12 jig_clearance = .25 / 12 # for s in [b.tof[i] for i in [0,2,5,7]]: for s in b.tof: r = 90 width = 5 * b.deckString.thickness height = s.keel_hab + 2 * b.deckString.width + jig_base_height p = [s.section, 0, 0] rect = x_rectangle_cut_out( p, width, height, b.deckString.thickness + 2 * jig_clearance, height - jig_base_height + jig_clearance + b.deckString.width) rect = [rs.MoveObject(rect, [0, 0, -jig_base_height])] plane = rs.PlaneFromNormal([s.section, 0, 0], [1, 0, 0]) holes = [ rs.MoveObject(rs.AddCircle(plane, diam / 2), [ 0, 1.5 * b.deckString.thickness, s.keel_hab + b.deckString.width ]) ] holes.extend(rs.MirrorObjects(holes, p, ss(p, [1, 0, 0]), copy=True)) bhole = rs.MoveObject(rs.AddCircle(plane, bdiam / 2), [0, 0, 47. / 64 / 12 - jig_base_height]) holes.extend([bhole, rs.CopyObject(bhole, [0, 0, 1.5 / 12])]) rs.RotateObjects(rect + holes, p, 90, [0, 1, 0])
def draw_tree(): x_coordinate = [] y_coordinate = [] r = 2 R = 100 n = 1000 for a in range(0, n): if a == 0: x = rd.uniform(-1, 1) * R rs.AddCircle((x, r, 0), r) x_coordinate.append(x) y_coordinate.append(r) else: x = rd.uniform(-1, 1) * R b = len(x_coordinate) - 1 y_contact = [] while (b != -1): if x_coordinate[b] - r * 2 <= x <= x_coordinate[b] + r * 2: y = ma.sqrt((r * 2)**2 - (x_coordinate[b] - x)**2) + y_coordinate[b] y_contact.append(y) b -= 1 else: b -= 1 else: if 1 <= len(y_contact): c = max(y_contact) x_coordinate.append(x) y_coordinate.append(c) rs.AddCircle((x, c, 0), r) else: rs.AddCircle((x, r, 0), r) x_coordinate.append(x) y_coordinate.append(r)
def renderSubTree(self, startRadius, growthFactor, curveDegree): #start radius is the radius at the tip of the smallest branches #growth Factor is the factor by which the start radius grows #as it moves towards the root, node by node #curveDegree is the degree of the curves of the tree treeID = rs.AddGroup() while True: deepCh = self.deepestChild() startNode = deepCh[0] if startNode == None: #this is the case where the whole tree is rendered #later return the group id of the group #that contains the whole tree from here return treeID curNode = startNode nodeList = [startNode] while (not curNode.parent is None) and (not curNode.isDone): nodeList.append(curNode.parent) curNode = curNode.parent posList = [] i = 0 while i < len(nodeList): posList.append(nodeList[i].pos) i += 1 curveID = rs.AddCurve(posList,curveDegree) curDom = rs.CurveDomain(curveID) node1 = rs.EvaluateCurve(curveID, curDom[0]) node2 = rs.EvaluateCurve(curveID, curDom[1]) tan1 = rs.CurveTangent(curveID, curDom[0]) tan2 = rs.CurveTangent(curveID, curDom[1]) plane1 = rs.PlaneFromNormal(node1, tan1) plane2 = rs.PlaneFromNormal(node2, tan2) radius1 = startRadius radius2 = (growthFactor**len(nodeList))*startRadius circles = [] circles.append(rs.AddCircle(plane1, radius1)) circles.append(rs.AddCircle(plane2, radius2)) branch = rs.AddSweep1(curveID, circles, True) rs.AddObjectToGroup(branch, treeID) rs.DeleteObjects(circles) rs.DeleteObject(curveID) for nd in nodeList: nd.isDone = True
def copyAndMover(self, first, mid, last, points, text): plane = rs.PlaneFromPoints(points[0], points[1], points[2]) uv1 = rs.PlaneClosestPoint(plane, points[1], False) uv2 = rs.PlaneClosestPoint(plane, points[2], False) distHor = abs(uv1[0] - uv2[0]) distVert = abs(uv1[1] - uv2[1]) key = 'len{0}{1}'.format(distHor, distVert) key = re.sub(r'\.', '', key) if key in self.partsHash: self.partsHash[key].append(text) else: self.partsHash[key] = [] self.partsHash[key].append(text) ypos = len(self.partsHash.keys()) + len(self.partsHash.keys()) rs.AddText(key, [0, ypos, 0], 0.3) newPoints = [ rs.AddPoint(0, ypos, 0), rs.AddPoint(self.FLAT_LENGTH, ypos, 0), rs.AddPoint(self.FLAT_LENGTH + distHor, ypos + distVert, 0), rs.AddPoint((self.FLAT_LENGTH * 2) + distHor, ypos + distVert, 0) ] first = rs.OrientObject(first, points, newPoints, 1) mid = rs.OrientObject(mid, points, newPoints, 1) last = rs.OrientObject(last, points, newPoints, 1) first_fillet = rs.AddFilletCurve(first, mid, 0.09375) fillet_points = rs.CurveFilletPoints(first, mid, 0.09375) first_circle = rs.AddCircle(fillet_points[2], 0.09375) first_cp = rs.CurveClosestPoint(first, fillet_points[0]) first_domain = rs.CurveDomain(first) first = rs.TrimCurve(first, (first_domain[0], first_cp), True) second_cp = rs.CurveClosestPoint(mid, fillet_points[1]) second_domain = rs.CurveDomain(mid) mid = rs.TrimCurve(mid, (second_cp, second_domain[1]), True) second_fillet = rs.AddFilletCurve(mid, last, 0.09375) fillet_points = rs.CurveFilletPoints(mid, last, 0.09375) second_circle = rs.AddCircle(fillet_points[2], 0.09375) first_cp = rs.CurveClosestPoint(mid, fillet_points[0]) first_domain = rs.CurveDomain(mid) mid = rs.TrimCurve(mid, (first_domain[0], first_cp), True) second_cp = rs.CurveClosestPoint(last, fillet_points[1]) second_domain = rs.CurveDomain(last) last = rs.TrimCurve(last, (second_cp, second_domain[1]), True) curve = rs.JoinCurves( [first, first_fillet, mid, second_fillet, last]) rs.AddCircle([0, ypos - 0.125 - 0.09375, 0], 0.09375) rs.AddCircle([(self.FLAT_LENGTH * 2) + distHor, ypos + distVert + 0.125 + 0.09375, 0], 0.09375)
def PlaceRing(x, y, r0, r1, layer): if (layer != 1) and (layer != 16): return None c0 = rs.AddCircle((x, y, 0), r0) c1 = rs.AddCircle((x, y, 0), r1) e0 = rs.ExtrudeCurveStraight(c0, (0, 0, 0), (0, 0, 0.1)) e1 = rs.ExtrudeCurveStraight(c1, (0, 0, 0), (0, 0, 0.1)) curves = [c0, c1] top = rs.AddPlanarSrf(curves) bot = rs.CopyObject(top, (0, 0, 0.1)) object = rs.JoinSurfaces([top, e0, e1, bot], True) rs.DeleteObjects(curves) ColorAndMove(object, layer) return object
def MakePerpLineCS(lineIn, pIn): rad1 = min(dist(pIn, lineIn[0]), dist(pIn, lineIn[1])) circ = rs.AddCircle(pIn, rad1) lineSegment = rs.AddLine(lineIn[0], lineIn[1]) pInt = findIntersection(lineSegment, circ) if pInt != None: #AddPointList(pInt) rad2 = dist(pIn, pInt[0]) + 0.1 circ1 = rs.AddCircle(pInt[0], rad2) circ2 = rs.AddCircle(pInt[1], rad2) pInt2 = findIntersection(circ1, circ2) if pInt2 != None: #AddPointList(pInt2) rs.AddLine(pInt2[0], pInt2[1]) rs.DeleteObjects([circ, circ1, circ2])
def test_SimpleWithSurfaceAndDefaults(self): id = rs.AddCircle((0, 0, 0), 20) srf_id = rs.AddPlanarSrf(id) pt_ids = rs.AddPoints([(-20, 0, 0), (0, 20, 0), (20, 0, 0)]) id = rs.AddPatch(pt_ids, srf_id) brep = rs.coercebrep(id, True) self.assertTrue(brep.IsSurface)
def ellipse(self, xheight, yheight, direction): centerPoint = rs.AddPoint(self.point) if direction == 'right': centerPoint = rs.MoveObject( centerPoint, rs.VectorScale(rs.VectorCreate([1, 0, 0], [0, 0, 0]), xheight / 2)) if direction == 'left': centerPoint = rs.MoveObject( centerPoint, rs.VectorScale(rs.VectorCreate([-1, 0, 0], [0, 0, 0]), xheight / 2)) if direction == 'top': centerPoint = rs.MoveObject( centerPoint, rs.VectorScale(rs.VectorCreate([0, 1, 0], [0, 0, 0]), xheight / 2)) if direction == 'bottom': centerPoint = rs.MoveObject( centerPoint, rs.VectorScale(rs.VectorCreate([0, -1, 0], [0, 0, 0]), xheight / 2)) newEllipse = rs.AddCircle(centerPoint, xheight / 2) yScaleFactor = yheight / xheight rs.ScaleObject(newEllipse, self.point, [1, yScaleFactor, 0]) rs.DeleteObject(centerPoint) return (newEllipse)
def drawTriTab(self, net): holeRadius = net.holeRadius mesh = net.mesh flatVerts = net.flatVerts flatFaces = net.flatFaces minArea = (holeRadius**2.0) * math.pi * 30 # print "minArea: " + str(minArea) flatFace = self.getConnectToFace(flatFaces, mesh) area = flatFace.getArea(flatVerts) pntA, pntC = self.get_coordinates(island) pntB = self.tabFaceCenter points = [pntA, pntB, pntC] polyline = Rhino.Geometry.PolylineCurve([pntA, pntB, pntC, pntA]) props = Rhino.Geometry.AreaMassProperties.Compute(polyline) if area > minArea: centerPnt = props.Centroid else: rs.AddTextDot("o", pntB) centerPnt = flatFaces[self.fromFace].getCenterPoint( flatVerts, True) hole = rs.AddCircle(centerPnt, holeRadius) polyGuid = rs.AddPolyline(points) self.geom.append(polyGuid) self.geom.append(hole) return polyGuid
def cxc(crv, pt, r, onlyNext=True): trash = [] xc = rs.AddCircle(pt, r) xx = rs.CurveCurveIntersection(crv, xc) xpts = [] if xx is None: return None #print('xx len:',len(xx)) for xxe in xx: if xxe[0] == 1: xpts.append(xxe[1]) rs.DeleteObject(xc) dom = rs.CurveDomain(crv) # endT=rs.CurveClosestPoint(crv,rs.CurveEndPoint(crv)) # print('endT :'endT) if onlyNext: centerT = rs.CurveClosestPoint(crv, pt) maxT = dom[0] maxI = 0 for i in range(0, len(xpts)): p = xpts[i] t = rs.CurveClosestPoint(crv, p) if t > maxT: maxT = t maxI = i # print(dom[1],centerT,t) if maxT > dom[1] or maxT < centerT: return None return xpts[maxI] return xpts
def ImportPoints(): #prompt the user for a file to import filter = "Text file (*.txt)|*.txt|All Files (*.*)|*.*||" filename = rs.OpenFileName("Open Point File", filter) if not filename: return #read each line from the file file = open(filename, "r") contents = file.readlines() file.close() # local helper function def __point_from_string(text): items = text.strip("()\n").split(",") center_x = float(items[0]) center_y = float(items[1]) r = float(items[2]) return center_x, center_y, r for entry in contents: if entry != "&\n": info = __point_from_string(entry) center = (info[0], info[1]) radius = info[2] rs.AddCircle(center, radius)
def filterObjects(objs): new_list = [] for obj in objs: if rs.LayerVisible( rs.ObjectLayer(obj) ): # only export visible layers if rs.IsCurve(obj): new_list.append(obj) elif rs.IsPoint(obj): # convert to circle layer = rs.ObjectLayer(obj) point=rs.coerce3dpoint(obj) circle = rs.AddCircle(rs.WorldXYPlane(),3) rs.ObjectLayer(circle, layer) rs.MoveObject(circle, [point.X, point.Y, point.Z]) new_list.append(circle) rs.DeleteObject(obj) # rs.DeleteObject(point) else: # remove from obj list rs.DeleteObject(obj) else: # remove from obj list rs.DeleteObject(obj) return new_list
def DistributeCirclesOnSphere(): sphere_radius = rs.GetReal("Radius of sphere", 10.0, 0.01) if not sphere_radius: return circle_radius = rs.GetReal("Radius of packing circles", 0.05 * sphere_radius, 0.001, 0.5 * sphere_radius) if not circle_radius: return vertical_count = int((math.pi * sphere_radius) / (2 * circle_radius)) rs.EnableRedraw(False) phi = -0.5 * math.pi phi_step = math.pi / vertical_count while phi < 0.5 * math.pi: horizontal_count = int((2 * math.pi * math.cos(phi) * sphere_radius) / (2 * circle_radius)) if horizontal_count == 0: horizontal_count = 1 theta = 0 theta_step = 2 * math.pi / horizontal_count while theta < 2 * math.pi - 1e-8: circle_center = (sphere_radius * math.cos(theta) * math.cos(phi), sphere_radius * math.sin(theta) * math.cos(phi), sphere_radius * math.sin(phi)) circle_normal = rs.PointSubtract(circle_center, (0, 0, 0)) circle_plane = rs.PlaneFromNormal(circle_center, circle_normal) rs.AddCircle(circle_plane, circle_radius) theta += theta_step phi += phi_step rs.EnableRedraw(True)
def RunCommand(is_interactive): ringSize = rs.GetReal("Ring size", 8.5, 0, 16) center = rs.GetPoint("Location") plane = rs.MovePlane(rs.ViewCPlane(), center) radius = (11.63 + 0.8128 * ringSize) * 0.5 objId = rs.AddCircle(plane, radius) rs.SelectObject(objId)
def spin(): line = rs.AddLine((0, 0, 0), (5, 0, 0)) circle = rs.AddCircle((5, 0, 0), 1) for i in range(30): time.sleep(0.1) rs.RotateObjects((line, circle), (0, 0, 0), 15) # call wait to ensure Rhino "catches-up" with drawing Rhino.RhinoApp.Wait()
def cutPlate(): center = rs.GetPoint("center point:") radius = 250 circle = rs.AddCircle(center, radius) rs.AddPlanarSrf(circle) rs.DeleteObject(circle)
def splitModel(objs, cutLevel): point = Rhino.Geometry.Point3d(0,0,cutLevel) belowDir = rs.AddLine(point, [0,0,-9999]) aboveDir = rs.AddLine(point, [0,0,9999]) circle = rs.AddCircle(point, 9999) circleSrf = rs.AddPlanarSrf(circle) aboveGroup = rs.AddGroup("Above") belowGroup = rs.AddGroup("Below") for obj in objs: ptBtm = rs.BoundingBox(obj)[0] ptTop = rs.BoundingBox(obj)[6] if ptBtm[2]>cutLevel: intersecting = False rs.AddObjectToGroup(obj, "Above") #print "Object Above" elif ptTop[2]<cutLevel: intersecting = False rs.AddObjectToGroup(obj, "Below") #print "Object Below" else: intersecting = True if intersecting: if rs.IsBrep(obj): closed = False if rs.IsPolysurfaceClosed(obj): closed = True try: copy = rs.CopyObject(obj) splitSrfs = rs.SplitBrep(obj, circleSrf, True) for splitSrf in splitSrfs: #print "looping" if closed: rs.CapPlanarHoles(splitSrf) rs.MatchObjectAttributes(splitSrf, copy) ptBtm = rs.BoundingBox(splitSrf)[0] ptTop = rs.BoundingBox(splitSrf)[6] mdPtZ = (ptBtm[2] + ptTop[2]) / 2 if mdPtZ>cutLevel: rs.AddObjectToGroup(splitSrf, "Above") else: rs.AddObjectToGroup(splitSrf, "Below") rs.DeleteObject(copy) rs.DeleteObject(obj) except: None if rs.IsBlockInstance(obj): contents = rs.ExplodeBlockInstance(obj) for content in contents: objs.append(content) rs.DeleteObject(belowDir) rs.DeleteObject(aboveDir) rs.DeleteObject(circle) rs.DeleteObject(circleSrf)
def Previewmark(crvs, dict, index):# 線の目印を作る pt_o = rs.DivideCurve(crvs[dict[index][0]], 10) pt_x = rs.DivideCurve(crvs[dict[index][1]], 10) mark_o = [rs.AddCircle(cen, mark) for cen in pt_o] mark_x1 = [rs.AddLine((cen[0] - mark,cen[1],cen[2]), (cen[0] + mark,cen[1],cen[2])) for cen in pt_x] mark_x2 = [rs.AddLine((cen[0],cen[1] - mark,cen[2]), (cen[0],cen[1] + mark,cen[2])) for cen in pt_x] a = mark_o b = mark_x1 + mark_x2 return (a, b)
def add_count(self): self.circle = rs.AddCircle(self.point, self.radius) self.group_list.append(self.circle) self.hatch = rs.AddHatch(self.circle, hatch_pattern="SOLID") self.group_list.append(self.hatch) self.group_name = rs.AddGroup(group_name=self.id) objs = [self.circle, self.hatch] rs.AddObjectsToGroup(objs, self.id) self.check_center()
def SentidoNo(cirDir, no, Plano, cirRaio): pOr, eX, eY, eZ = Plano planoAux = rs.PlaneFromNormal(no, eZ) Circulo = rs.AddCircle(planoAux, cirRaio) dir1 = rs.ClosedCurveOrientation(cirDir, eZ) dir2 = rs.ClosedCurveOrientation(Circulo, eZ) if not dir1 == dir2: rs.ReverseCurve(Circulo) return Circulo
def drawFaceHole(self, flatVerts, flatFaces, holeRadius): pntA, pntC = self.get_coordinates(island) pntB = flatFaces[self.fromFace].getCenterPoint(flatVerts, True) pnts = [pntA, pntB, pntC, pntA] polyline = Rhino.Geometry.PolylineCurve(pnts) props = Rhino.Geometry.AreaMassProperties.Compute(polyline) centerPnt = props.Centroid hole = rs.AddCircle(centerPnt, holeRadius) self.geom.append(hole)
def Circles(pt, r): if num == 0: return 0 else: for i in range(0, num): r = r + 1 * i * i rs.AddCircle(pt, r) pt.Y = pt.Y + 1 pt.Z = pt.Z + 1 * i * 4
def CreatingBeam(Crv, Rad): EndPt = rs.CurveEndPoint(Crv) StPt = rs.CurveStartPoint(Crv) DirVec = EndPt - StPt StPl = rs.PlaneFromNormal(StPt, DirVec) EndPl = rs.PlaneFromNormal(EndPt, DirVec) CirEd = rs.AddCircle(EndPl, Rad) CirSt = rs.AddCircle(StPl, Rad) IdsList = [] IdsList.append(CirSt) IdsList.append(CirEd) BeamGeometry = rs.AddLoftSrf(IdsList) return BeamGeometry
def CreatingNodeFun(Pt, Lines, BeamRad, BeamLength): Beams = [] for i in Lines: MidPt = rs.CurveMidPoint(i) DirVe = MidPt - Pt DirVecUni = rs.VectorUnitize(DirVe) TrVec = rs.VectorScale(DirVecUni, BeamLength) PtToMove = rs.AddPoint(pt) EndPt = rs.MoveObject(PtToMove, TrVec) Plane01 = rs.PlaneFromNormal(pt, DirVe) Plane02 = rs.PlaneFromNormal(PtToMove, DirVe) Ids = [] Cir01 = rs.AddCircle(Plane01, BeamRad) Cir02 = rs.AddCircle(Plane02, BeamRad) Ids.append(Cir01) Ids.append(Cir02) Beam = rs.AddLoftSrf(Ids) Beams.append(Beam) return Beams
def ellipse(self, xheight, yheight, placement='center', angle=0): centerPoint = rs.AddPoint(self.point) if placement == 'edge': centerPoint = rs.MoveObject( centerPoint, rs.VectorScale(rs.VectorCreate([1, 0, 0], [0, 0, 0]), xheight / 2)) newEllipse = rs.AddCircle(centerPoint, xheight / 2) ScaleFactor = yheight / xheight rs.ScaleObject(newEllipse, self.point, [1, ScaleFactor, 0]) newEllipse = rs.RotateObject(newEllipse, self.point, angle) rs.DeleteObject(centerPoint)
def rivet_tab(self, pntJ, pntI, prev_point, left_side): radius = self.rivet_diameter / 2.0 + self.tab_padding a, b, c, d, e = edgeGeom.get_arc_rod_points(pntI, pntJ, radius, not left_side) arc = rs.AddArc3Pt(b, d, c) line_ab = rs.AddLine(a, b) line_de = rs.AddLine(d, e) hole = rs.AddCircle(rs.PlaneFromNormal(pntI, self.normal), self.rivet_diameter / 2.0) line_connect = rs.AddLine(prev_point, a) self.geom_temp.extend([line_connect, line_ab, arc, line_de, hole]) return a, e
def dogbone(curves, diam, diam_barrenos, tol): for curve in curves: if rs.CloseCurve(curve): centroid = rs.CurveAreaCentroid(curve)[0] else: centroid = rs.CurveMidPoint(curve) if diam_barrenos == -1: rs.AddPoint(centroid) elif diam_barrenos == 0: pass else: rs.AddCircle(centroid, diam_barrenos * .5) curve = rs.ConvertCurveToPolyline(curve, delete_input=True) tol_curve = rs.OffsetCurve(curve, centroid, -tol) if tol else curve ocurve = rs.OffsetCurve(tol_curve, rs.CurveAreaCentroid(curve)[0], diam * .3) circles = [rs.AddCircle(i, diam / 2) for i in rs.CurvePoints(ocurve)] rs.CurveBooleanUnion(circles + [tol_curve]) rs.DeleteObjects([ocurve, tol_curve] + circles) if curve: rs.DeleteObject(curve)