def mapping(discretization_spacing, surface_guid, curve_features_guids = [], point_features_guids = []): """Creates planar polylines from the boundaries of a NURBS surface, NURBS curves and point on the NURBS surface by using the UV parameterisation with a user-input discretisation spacing. Parameters ---------- discretization_spacing: real Spacing value for discretisation of NURBS surface borders and curves into polylines. surface: Rhino surface guid Untrimmed or trimmed Rhino NURBS surface. curve_features: Rhino curve guid Rhino NURBS curve on the surface. point_features: Rhino point guid Rhino point on the surface. Returns ------- output: list Planar parameterised geometrical output: boundary, holes, polyline features and point features. Raises ------ - """ boundaries = surface_borders(surface_guid, border_type = 1) boundary_polylines = [curve_discretisation(boundary, discretization_spacing) for boundary in boundaries] uv_boundary_polylines = [[rs.SurfaceClosestPoint(surface_guid, vertex) for vertex in rs.PolylineVertices(boundary_polyline)] for boundary_polyline in boundary_polylines] planar_boundary_polylines = [[[u, v, 0] for u, v in uv_boundary_polyline] for uv_boundary_polyline in uv_boundary_polylines] planar_boundary_polyline = [] for polyline in planar_boundary_polylines: planar_boundary_polyline += polyline[: -1] planar_boundary_polyline.append(planar_boundary_polyline[0]) rs.DeleteObjects(boundaries) rs.DeleteObjects(boundary_polylines) holes = surface_borders(surface_guid, border_type = 2) if len(holes) > 1: holes = rs.JoinCurves(holes, delete_input = True) hole_polylines = [curve_discretisation(hole, discretization_spacing) for hole in holes] uv_hole_polylines = [[rs.SurfaceClosestPoint(surface_guid, vertex) for vertex in rs.PolylineVertices(hole_polyline)] for hole_polyline in hole_polylines] planar_hole_polylines = [[[u, v, 0] for u, v in hole] for hole in uv_hole_polylines] rs.DeleteObjects(holes) rs.DeleteObjects(hole_polylines) polyline_features = [curve_discretisation(curve_features_guid, discretization_spacing) for curve_features_guid in curve_features_guids] uv_polyline_features = [[rs.SurfaceClosestPoint(surface_guid, vertex) for vertex in rs.PolylineVertices(polyline_feature)] for polyline_feature in polyline_features] planar_polyline_features = [[[u, v, 0] for u, v in feature] for feature in uv_polyline_features] rs.DeleteObjects(polyline_features) uv_point_features = [rs.SurfaceClosestPoint(surface_guid, point) for point in point_features_guids] planar_point_features = [[u, v, 0] for u, v in uv_point_features] return planar_boundary_polyline, planar_hole_polylines, planar_polyline_features, planar_point_features
def depressCrvs(srf, crvs, paths, startPt, radius, sd): newCrvs = [] for i in range(len(crvs)): divPts = rs.DivideCurve(crvs[i], 400) for j in range(len(divPts)): path = rs.PointClosestObject(divPts[j], paths)[0] param = rs.CurveClosestPoint(path, divPts[j]) close = rs.EvaluateCurve(path, param) srfParam = rs.SurfaceClosestPoint(srf, close) vec = rs.SurfaceNormal(srf, srfParam) dist = rs.Distance(close, divPts[j]) vec = rs.VectorUnitize(vec) border = 1 entry = 1 if j > len(divPts) / 2: border = rs.Distance(rs.CurveEndPoint(crvs[i]), divPts[j]) else: border = rs.Distance(rs.CurveStartPoint(crvs[i]), divPts[j]) if border < sd * 3: border = border / (sd * 3) else: border = 1 entryDist = rs.Distance(startPt, divPts[j]) if entryDist < sd * 10: entry = entryDist / (sd * 10) else: entry = 1 if dist < sd * 2: val = radius * (bellCrv(dist, sd)) divPts[j] = rs.PointAdd(divPts[j], vec * val * border * entry) newCrvs.append(rs.AddCurve(divPts)) return divPts
def offsetext(): def RepresentsInt(s): try: int(s) return True except ValueError: return False viste = rs.ViewNames() for viewport in viste: rs.ViewDisplayMode(viewport,"Shaded") diametro = rs.StringBox("dimensione della punta","10","scontornatura") if RepresentsInt(diametro): diametro = int(diametro) else: diametro = 10 brep = rs.GetObjects("dammi un solido",16) brepexp = rs.ExplodePolysurfaces(brep) get_val = rs.GetEdgeCurves("dammi le curve") surf_edge = [] for i in get_val: surf_edge.append(i[0]) surf_edge = rs.coerceguidlist(surf_edge) if len(surf_edge)>1: surf_edge = rs.JoinCurves(surf_edge,True) surface = rs.GetObjects("conferma la selezione",8,False,True,1,1) print surf_edge uv= [] temp_edge = rs.ExplodeCurves(surf_edge,False) new_surface = rs.CopyObject(surface,(0,0,0)) list_evpt =[] for i in temp_edge: evpt =rs.CurveMidPoint(i) print evpt list_evpt.append(evpt) for i in list_evpt: bord= rs.SurfaceClosestPoint(new_surface,i) uv.append(bord) for i in uv: rs.ExtendSurface(new_surface,i,diametro*10) edge = rs.OffsetCurveOnSurface(surf_edge,new_surface,-diametro) print edge if rs.CurveLength(edge)<rs.CurveLength(surf_edge): rs.DeleteObject(edge) edge = rs.OffsetCurveOnSurface(surf_edge,new_surface,diametro) surf_edge = rs.ExplodeCurves(surf_edge,True) print edge rs.ObjectColor(edge,(0,0,255)) for i in brepexp: rs.DeleteObject(i) for i in temp_edge: rs.DeleteObject(i) for i in surf_edge: rs.DeleteObject(i) rs.DeleteObjects([new_surface,surface])
def get_dist(p): param = rs.SurfaceClosestPoint(surf, p) cp = rs.EvaluateSurface(surf, param[0], param[1]) #n = rs.SurfaceNormal(surf,param) #dv = map_values(param,axis.Domain[0],axis.Domain[1],0,1) #r = (1-dv)*start_radius + dv*end_radius d = rs.Distance(p, cp) - thickness / 2.0 return d
def divCrv(srf, pts, uv, vec, eq): param = map(lambda x: rs.SurfaceClosestPoint(srf, x), pts) railcrv = map(lambda x: rs.ExtractIsoCurve(srf, x, trp.intFlipBool(uv)), param) frames = map(lambda x, y, z: sweepRail(srf, x, vec, y, z), railcrv, param, pts) # rs.DeleteObject(domaincrv) return railcrv
def getSrfFrame(srf): domainU = rs.SurfaceDomain(srf, 0) domainV = rs.SurfaceDomain(srf, 1) u = domainU[1] / 2.0 v = domainV[1] / 2.0 point = rs.EvaluateSurface(srf, u, v) param = rs.SurfaceClosestPoint(srf, point) return rs.SurfaceFrame(srf, param)
def evaluatedeviation( surface_id, threshold, sample ): r2point = rs.SurfaceClosestPoint(surface_id, sample)#Returns the UV parameter of the point on a surface that is closest to a test point. if not r2point: return r3point = rs.EvaluateSurface(surface_id, r2point[0], r2point[1])#evaluates the surface with UV parameters(U=[0] and v[1]) if not r3point: return deviation = rs.Distance(r3point, sample)#sample refers to the previous point if deviation<=threshold: return#if deviation is less than threshold do nothing rs.AddPoint(sample)#if deviation is more than threshold add point rs.AddLine(sample, r3point)#if deviation is more than threshold add line
def extframe(srf): crv = rs.DuplicateSurfaceBorder(srf, type=1) point = rs.EvaluateCurve(crv, 0) parameter = rs.SurfaceClosestPoint(srf, point) plane = rs.SurfaceFrame(srf, parameter) direction = rs.CurveTangent(crv, 0) newplane = rs.PlaneFromNormal(point, direction, plane.ZAxis) frame = sweepSec(crv, newplane, vec1) if crv: rs.DeleteObjects(crv) return frame
def getr2PathOnSurface(surface, segments, prompt1, prompt2): startPt = rs.GetPointOnSurface(surface, prompt1) if not startPt: return endPt = rs.GetPointOnSurface(surface, prompt2) if not endPt: return #if our start and end points are coincedents, why bother? if rs.Distance(startPt, endPt) == 0.0: return #GetPointOnSurface returns a Point3D, to get the UV coords, we need to SCP to the Point3D uva = rs.SurfaceClosestPoint(surface, startPt) uvb = rs.SurfaceClosestPoint(surface, endPt) #store our new vertices for the path in a list path = [] #the shortest path between two points is a straight line, but in our case this #needs to follow the contours of the surface. We divide the straight path into #segments and check each vertex of the segments and find the closest corrisponding point #on the surface itself #range is non inclusive in python, I had to add 1 here to get the last point to align #with the last point selected for i in range(segments + 1): #we will decompose the UV r2 space into U and V r1 spaces and find where we #are using a single parameter at each segment vertex t = i / segments # U and V parameters are calculated by taking the individual U and V domains # and multiplying them by the t value. The t paramter is added to the start of #both domains. SCP will return a list of values [0] is the U and [1] is the V u = uva[0] + t * (uvb[0] - uva[0]) v = uva[1] + t * (uvb[1] - uva[1]) #get that closes point on the surface and add it to the path list of vertices pt = rs.EvaluateSurface(surface, u, v) path.append(pt) return path
def isHorizontalUpSrf(srf,tolerance=TOLERANCE): boundary=rs.DuplicateSurfaceBorder(srf) if type(boundary is list):boundary=boundary[0] sp=rs.CurveStartPoint(boundary) uv=rs.SurfaceClosestPoint(srf,sp) normal=rs.SurfaceNormal(srf,uv) normal=rs.VectorUnitize(normal) nz=normal[2] rs.DeleteObject(boundary) if abs(nz-1)<tolerance:return True return False
def getr2pathonsurface(surface_id, segments, prompt1, prompt2): start_point = rs.GetPointOnSurface(surface_id, prompt1) if not start_point: return end_point = rs.GetPointOnSurface(surface_id, prompt2) if not end_point: return if rs.Distance(start_point, end_point) == 0.0: return uva = rs.SurfaceClosestPoint(surface_id, start_point) uvb = rs.SurfaceClosestPoint(surface_id, end_point) path = [] for i in range(segments): t = i / segments u = uva[0] + t * (uvb[0] - uva[0]) v = uva[1] + t * (uvb[1] - uva[1]) pt = rs.EvaluateSurface(surface_id, u, v) path.append(pt) return path
def isoframe(srf, uv, spacing, vec): points = intervalpts(srf, uv, spacing) sweeps = [] for i in points: point = rs.EvaluateSurface(srf, i[0], i[1]) parameter = rs.SurfaceClosestPoint(srf, point) plane = rs.SurfaceFrame(srf, parameter) crv = rs.ExtractIsoCurve(srf, parameter, flipBool(uv)) direction = rs.CurveTangent(crv, 0) newplane = rs.PlaneFromNormal(point, direction, plane.ZAxis) sweeps.append(sweepSec(crv, newplane, vec)) return sweeps
def getCurvatureOfClosestPoint(pt, srf, scale=None): if scale is None: global curvatureScale scale = curvatureScale u, v = rs.SurfaceClosestPoint(srf, pt) c = rs.SurfaceCurvature(srf, (u, v)) if c is None: return 0 else: return c[7] * scale
def evaluatedeviation( surface_id, threshold, sample ): r2point = rs.SurfaceClosestPoint(surface_id, sample) if not r2point: return r3point = rs.EvaluateSurface(surface_id, r2point[0], r2point[1]) if not r3point: return deviation = rs.Distance(r3point, sample) if deviation<=threshold: return rs.AddPoint(sample) rs.AddLine(sample, r3point)
def MovePt2PtBasedOnSrf(fromPt, toPt, toSrf): u, v = rs.SurfaceClosestPoint(toSrf, toPt) vt = rs.VectorCreate(toPt, fromPt) vt = rs.VectorUnitize(vt) c = rs.SurfaceCurvature(toSrf, (u, v)) c = c[7] vt = rs.VectorScale(vt, 10 * c) return rs.PointAdd(toPt, vt)
def ConvertToUVW(srf_id, xyz_points): uvw_points = [] for point in xyz_points: Suv = rs.SurfaceClosestPoint(srf_id, point) Sxyz = rs.EvaluateSurface(srf_id, Suv) Snormal = rs.SurfaceNormal(srf_id, Suv) dirPos = rs.PointAdd(Sxyz, Snormal) dirNeg = rs.PointSubtract(Sxyz, Snormal) Sdist = rs.Distance(Sxyz, point) if rs.Distance(point, dirPos) > rs.Distance(point, dirNeg): Sdist = -Sdist uvw_points.append((Suv(0), Suv(1), Sdist)) return uvw_points
def XYZ_To_UVW(srf_id, pXYZ): pUVW = [] for point in pXYZ: uvClosest = rs.SurfaceClosestPoint(srf_id, point) ptClosest = rs.EvaluateSurface(srf_id, uvClosest) srfNormal = rs.SurfaceNormal(srf_id, uvClosest) pPositive = rs.PointAdd(ptClosest, srfNormal) pNegative = rs.PointSubtract(ptClosest, srfNormal) fDistance = rs.Distance(ptClosest, point) if rs.Distance(point,pPositive) > rs.Distance(point, pNegative): fDistance = -fDistance pUVW.append( (uvClosest[0], uvClosest[1], fDistance) ) return pUVW
def isHorizonalSrf(srf,return_dir=False,tolerance=TOLERANCE): boundary=rs.DuplicateSurfaceBorder(srf) if type(boundary is list):boundary=boundary[0] sp=rs.CurveStartPoint(boundary) uv=rs.SurfaceClosestPoint(srf,sp) normal=rs.SurfaceNormal(srf,uv) normal=rs.VectorUnitize(normal) direct=normal[2] nz=abs(normal[2]) rs.DeleteObject(boundary) if abs(nz-1)<tolerance: if return_dir:return True,direct return True if return_dir:return False,direct return False
def point_xyz_to_uv(self, xyz): """Return the UV point from the mapping of a XYZ point based on the UV parameterisation of the surface. Parameters ---------- xyz : list (x, y, z) coordinates. Returns ------- list The (u, v, 0) coordinates of the mapped point. """ return rs.SurfaceClosestPoint(self.guid, xyz) + (0., )
def closest_point(self, xyz): """Return the XYZ coordinates of the closest point on the surface from input XYZ-coordinates. Parameters ---------- xyz : list XYZ coordinates. Returns ------- list The XYZ coordinates of the closest point on the surface. """ return rs.EvaluateSurface(self.guid, *rs.SurfaceClosestPoint(self.guid, xyz))
def MapCurvatureStep(srf_id, uvPt, max, reverse, accuracy): data_curvature = rs.SurfaceCurvature(srf_id, uvPt) if not data_curvature: return vec = data_curvature[5] if max: vec = data_curvature[3] if reverse: vec = rs.VectorReverse(vec) vec = rs.VectorUnitize(vec) vec = rs.VectorScale(vec, accuracy) dPoint = rs.VectorAdd(data_curvature[0], vec) nPoint = rs.SurfaceClosestPoint(srf_id, dPoint) mPoint = rs.EvaluateSurface(srf_id, nPoint) if rs.Distance(mPoint, data_curvature[0])< (0.5*accuracy): return return nPoint
def extframe(srf, vec): frames = [] crv = rs.DuplicateSurfaceBorder(srf, type=1) rs.SimplifyCurve(crv) domain = rs.CurveDomain(crv) param = (domain[0] + domain[1]) / 2.0 rs.CurveSeam(crv, param) point = rs.EvaluateCurve(crv, 0) parameter = rs.SurfaceClosestPoint(srf, point) plane = rs.SurfaceFrame(srf, parameter) direction = rs.CurveTangent(crv, 0) newplane = rs.PlaneFromNormal(point, direction, plane.ZAxis) frame.append(sweepSec(crv, newplane, vec)) if crv: rs.DeleteObjects(crv) return frames
def GetTimberSectionLenght(tim_srf, base_point): closest_pra = rs.SurfaceClosestPoint(tim_srf.Faces[0], base_point) V = rs.SurfaceDomain(tim_srf.Faces[0], 1) if V[0] < 0: divide_V = abs(V[0] / 10) else: divide_V = abs(V[1] / 10) list_point = [] for i in range(10): point = rs.EvaluateSurface(tim_srf.Faces[0], closest_pra[0], V[0] + divide_V * i) list_point.append(point) length = rs.Distance(list_point[0], list_point[5]) return length
def offset_vector(self, point, cross_section_index, point_index): modulo = len(self.point_lists[cross_section_index - 1]) prev_point_1 = self.point_lists[cross_section_index - 1][ (point_index - 2) % modulo] if cross_section_index % 2 == 0 else self.point_lists[ cross_section_index - 1][(point_index - 1) % modulo] prev_point_2 = self.point_lists[cross_section_index - 1][ (point_index - 1) % modulo] if cross_section_index % 2 == 0 else self.point_lists[ cross_section_index - 1][point_index] in_between_vector = rs.VectorAdd(rs.VectorCreate(prev_point_1, point), rs.VectorCreate(prev_point_2, point)) normal_vector = rs.SurfaceNormal( self.brep, rs.SurfaceClosestPoint(self.brep, point)) plane = rs.PlaneFromFrame(point, in_between_vector, normal_vector) vector = rs.SurfaceNormal(rs.AddPlaneSurface(plane, 1, 1), [0, 0]) unit_vector = rs.VectorUnitize(vector) return [rs.VectorScale(unit_vector, 2), in_between_vector]
def HorizPlaneFromSurface(srf): rhsrf = rs.coercesurface(srf) centerPoint = utils.FindMostDistantPointOnSrf(srf) u, v = rs.SurfaceClosestPoint(srf, centerPoint) origPlane = rhsrf.FrameAt(u,v)[1] if abs(origPlane.Normal.Z) == 1: #SURFACE HORIZONTAL plane = rs.WorldXYPlane() plane.Origin = centerPoint return plane else: #SURFACE NOT HORIZONTAL upVec = utils.GetUphillVectorFromPlane(srf) ptUp = rc.Geometry.Point3d.Add(centerPoint, upVec) line1 = rc.Geometry.Line(centerPoint, ptUp) ptY = rc.Geometry.Point3d.Add(centerPoint, origPlane.YAxis) line2 = rc.Geometry.Line(centerPoint, ptY) angle = math.radians(min(rs.Angle2(line1, line2))) origPlane.Rotate(angle, origPlane.Normal, centerPoint) return origPlane
def main(): rs.AddLayer("laydown") while True: panel, face = getsubsurface.GetSubSurface("select down face") if panel is None or face is None: break # compute the plane normal = rs.VectorUnitize(rs.SurfaceNormal(face, (0.5,0.5))) plane = rs.PlaneFromNormal(rs.EvaluateSurface(face, 0.5, 0.5), normal) rs.ViewCPlane(plane=plane) box = rs.BoundingBox(face, rs.ViewCPlane(), in_world_coords=True) proj_coords = [rs.SurfaceClosestPoint(face, coord) + (0,) for coord in box] laydown = rs.OrientObject(panel, box[0:3], proj_coords[0:3], flags=1) rs.ObjectLayer(laydown, "laydown") rs.DeleteObject(face) rs.HideObject(panel)
def offsetCurveOnSurface(): curve = rs.GetObject("sel curve", 4) num = rs.GetReal("Offset Distance:", 200) points = rs.DivideCurve(curve, num) surface = rs.GetObject("sel surface", 8) offset_ptsA0 = [] offset_ptsA1 = [] offset_ptsB0 = [] offset_ptsB1 = [] rs.EnableRedraw(False) for point in points: parameter = rs.SurfaceClosestPoint(surface, point) crv = rs.ExtractIsoCurve(surface, parameter, 2) #create sphere at end try: offsetEndPtsA = offsetCrvEndPt(crv[0], num) rs.DeleteObject(crv[0]) except IndexError: offsetEndPtsA = None try: offsetEndPtsB = offsetCrvEndPt(crv[1], num) rs.DeleteObject(crv[1]) except IndexError: offsetEndPtsB = None #offset_points.append(offset_point) if not (offsetEndPtsA is None): offset_ptsA0.append(offsetEndPtsA[0]) offset_ptsA1.append(offsetEndPtsA[1]) if not (offsetEndPtsB is None): offset_ptsB0.append(offsetEndPtsB[0]) offset_ptsB1.append(offsetEndPtsB[1]) rs.EnableRedraw(True) rs.AddInterpCurve(offset_ptsA0) rs.AddInterpCurve(offset_ptsA1) rs.AddInterpCurve(offset_ptsB0) rs.AddInterpCurve(offset_ptsB1)
def convert_to_uv_space(srf,pts): tol = rs.UnitAbsoluteTolerance() uv_pts = [] for pt in pts: #need for issues in cases points lie on a seam if not rs.IsPointOnSurface (srf, pt): pts_dis = [] pts_dis.append((pt[0]+tol,pt[1],pt[2])) pts_dis.append((pt[0]-tol,pt[1],pt[2])) pts_dis.append((pt[0],pt[1]+tol,pt[2])) pts_dis.append((pt[0],pt[1]-tol,pt[2])) pts_dis.append((pt[0],pt[1],pt[2]+tol)) pts_dis.append((pt[0],pt[1],pt[2]-tol)) for pt_dis in pts_dis: data= rs.BrepClosestPoint(srf,pt_dis) if rs.IsPointOnSurface(srf,data[0]): pt = data[0] break u,v = rs.SurfaceClosestPoint(srf,pt) uv_pts.append((u,v,0)) #rs.AddTextDot(str(data[2] ) + " / " + str(rs.IsPointOnSurface (srf, pt)) + " / " + str(u) + " / " + str(v),pt) return uv_pts
def splitSrfVerticallyByPts(srf,pts): normals=[] up=(0,0,1000000000) half=(0,0,500000000) cutters=[] for p in pts: uv=rs.SurfaceClosestPoint(srf,p) normal=rs.SurfaceNormal(srf,uv) normal=rs.VectorScale(normal,1000) normals.append(normal) botStart=rs.VectorAdd(rs.VectorSubtract(p,half),normal) botEnd=rs.VectorSubtract(rs.VectorSubtract(p,half),normal) l=rs.AddLine(botStart,botEnd) path=rs.AddLine(botStart,rs.VectorAdd(botStart,up)) cutter=rs.ExtrudeCurve(l,path) rs.DeleteObjects([l,path]) #print(rs.IsBrep(cutter)) #print(cutter) cutters.append(cutter) # rs.SelectObjects(cutters) srfs=splitSrfBySrfs(srf,cutters) return srfs
def main(): global inner_curves, outer_curves, curve_coords # save for later orig_hidden_objects = rs.HiddenObjects() # we put reference points in the dogbone-ref layer, so create it if it doesn't exist rs.AddLayer("dogbone-ref") panel, face = getsubsurface.GetSubSurface("select dogbone face") diameter = rs.GetReal("enter cutter diameter", number=0.25) diameter = diameter * 1.1 rs.EnableRedraw(False) # compute the plane normal = rs.VectorUnitize(rs.SurfaceNormal(face, (0.5, 0.5))) plane = rs.PlaneFromNormal(rs.EvaluateSurface(face, 0.5, 0.5), normal) rs.ViewCPlane(plane=plane) rs.ProjectOsnaps(True) outer_curves = rs.DuplicateSurfaceBorder(face, 1) inner_curves = rs.DuplicateSurfaceBorder(face, 2) # make a dict mapping each curve to the coords in that curve curve_coords = dict() for curve in outer_curves + inner_curves: coords = rs.CurvePoints(curve)[:-1] curve_coords[curve] = coords # make a dict mapping each curve to the z component of its cross product at each index curve_cross_zs = dict() for curve, coords in curve_coords.items(): proj_coords = [rs.SurfaceClosestPoint(face, coord) for coord in coords] cross_zs = [] for idx in range(len(proj_coords)): triplet = [ proj_coords[(idx + 1) % len(proj_coords)], proj_coords[idx], proj_coords[(idx - 1) % len(proj_coords)] ] v0 = (triplet[1][0] - triplet[0][0], triplet[1][1] - triplet[0][1], 0) v1 = (triplet[2][0] - triplet[1][0], triplet[2][1] - triplet[1][1], 0) cross_z = rs.VectorCrossProduct(v0, v1)[2] cross_zs.append(cross_z) curve_cross_zs[curve] = cross_zs points = [] bones = [] temp_points = [] rs.EnableRedraw(True) while True: coord = rs.GetPoint("select corner") if coord is None: break try: curve, idx = get_curve_and_idx_for_coord(coord) point = rs.AddPoint(coord) rs.ObjectColor(point, (255, 0, 0)) temp_points.append(point) bones.append((curve, idx)) except ValueError: print "invalid curve point" continue rs.EnableRedraw(False) rs.DeleteObjects(temp_points) # try to automatically identify dogbone points if user selected none if len(bones) == 0: for curve, coords in curve_coords.items(): proj_coords = [ rs.SurfaceClosestPoint(face, coord) for coord in coords ] for idx in range(len(proj_coords)): triplet = [ proj_coords[(idx + 1) % len(proj_coords)], proj_coords[idx], proj_coords[(idx - 1) % len(proj_coords)] ] if curve_cross_zs[curve][idx] > 0: bones.append((curve, idx)) # make the bones extrusions = [] for bone in bones: curve, idx = bone coords = curve_coords[curve] point = rs.AddPoint(coords[idx]) rs.ObjectLayer(point, "dogbone-ref") triplet = [ coords[(idx + 1) % len(coords)], coords[idx], coords[(idx - 1) % len(coords)], ] angle = rs.Angle2( (triplet[1], triplet[0]), (triplet[1], triplet[2]), ) angle = angle[0] # This is a hacky method to determine the handedness of the curve # the cross product SHOULD have worked here, but for some reason # it did not. v0 = triplet[2][0] - triplet[1][0], triplet[2][1] - triplet[1][1], 0 v1 = triplet[1][0] - triplet[0][0], triplet[1][1] - triplet[0][1], 0 _angle = math.degrees( math.atan2(v0[1], v0[0]) - math.atan2(v1[1], v1[0])) while _angle > 180: _angle -= 360 while _angle < -180: _angle += 360 if math.copysign(1, angle) != math.copysign(1, _angle): angle -= 180 point = rs.VectorAdd( triplet[1], rs.VectorRotate( 0.5 * diameter * rs.VectorUnitize(rs.VectorSubtract(triplet[2], triplet[1])), angle / 2, (0, 0, 1))) circle = rs.AddCircle((point.X, point.Y, -10), diameter / 2.0) circle_srf = rs.AddPlanarSrf(circle) p0 = (point.X, point.Y, -10) p1 = (point.X, point.Y, 10) line = rs.AddLine(p0, p1) extrusion = rs.ExtrudeSurface(circle_srf, line) extrusions.append(extrusion) rs.DeleteObjects([circle, circle_srf, line]) rs.BooleanDifference([panel], extrusions, delete_input=True) rs.DeleteObject(panel) rs.DeleteObjects(extrusions) rs.DeleteObjects(points) rs.DeleteObjects(inner_curves) rs.DeleteObjects(outer_curves) rs.DeleteObject(face) rs.ShowObject(rs.AllObjects()) rs.HideObjects(orig_hidden_objects) rs.EnableRedraw(True)