def surface_border_kinks(surface_guid): kinks = [] borders = surface_borders(surface_guid) for curve_guid in borders: start_tgt = rs.CurveTangent(curve_guid, rs.CurveParameter(curve_guid, 0)) end_tgt = rs.CurveTangent(curve_guid, rs.CurveParameter(curve_guid, 1)) if not rs.IsCurveClosed(curve_guid) or not rs.IsVectorParallelTo( start_tgt, end_tgt): start = rs.CurveStartPoint(curve_guid) end = rs.CurveEndPoint(curve_guid) if start not in kinks: kinks.append(start) if end not in kinks: kinks.append(end) return kinks
def kinks(self, threshold=1e-3): """Return the XYZ coordinates of kinks, i.e. tangency discontinuities, along the surface's boundaries. Returns ------- list The list of XYZ coordinates of surface boundary kinks. """ kinks = [] borders = self.borders(type=0) for border in borders: border = RhinoCurve(border) extremities = map( lambda x: rs.EvaluateCurve(border.guid, rs.CurveParameter(border.guid, x)), [0., 1.]) if border.is_closed(): start_tgt, end_tgt = border.tangents(extremities) if angle_vectors(start_tgt, end_tgt) > threshold: kinks += extremities else: kinks += extremities return list(set(kinks))
def transf_t(t, r, s): plane = rh.CurvePerpFrame(path, rh.CurveParameter(path, t)) xform = rh.XformChangeBasis(plane, geo.Plane.WorldXY) xform = rh.XformMultiply(xform, rh.XformScale(s)) xform = rh.XformMultiply( xform, geo.Transform.Rotation(r, geo.Vector3d(0, 0, 1), rawu0)) return rh.TransformObject(profile, xform, True)
def offsetLine(line, dist): norm = rs.VectorRotate(rs.CurveTangent(line, rs.CurveParameter(line, 0)), 90, [0, 0, 1]) norm = rs.VectorScale(rs.VectorUnitize(norm), dist) sideStPt = rs.VectorAdd(rs.CurveStartPoint(line), norm) sideEndPt = rs.VectorAdd(rs.CurveEndPoint(line), norm) newLine = rs.AddLine(sideStPt, sideEndPt) return newLine
def ColorBySize(): try: objs = rs.GetObjects("Select objects to color", 1073815613, preselect=True) if objs is None: return print "Select First Color" firstColor = rs.GetColor() if firstColor is None: return print "Select Second Color" secondColor = rs.GetColor(firstColor) if secondColor is None: return rs.EnableRedraw(False) colorLine = rs.AddLine(firstColor, secondColor) areas = [] for obj in objs: if rs.IsCurve(obj): if rs.IsCurveClosed(obj): areas.append(rs.CurveArea(obj)[0]) else: areas.append(rs.CurveLength(obj)) elif rs.IsSurface(obj): areas.append(rs.SurfaceArea(obj)[0]) elif rs.IsPolysurface(obj): if rs.IsPolysurfaceClosed(obj): areas.append(rs.SurfaceVolume(obj)[0]) elif rs.IsHatch(obj): areas.append(rs.Area(obj)) else: print "Only curves, hatches, and surfaces supported" return newAreas = list(areas) objAreas = zip(newAreas, objs) objAreas.sort() objSorted = [objs for newAreas, objs in objAreas] areas.sort() normalParams = utils.RemapList(areas, 0, 1) colors = [] for t in normalParams: param = rs.CurveParameter(colorLine, t) colors.append(rs.EvaluateCurve(colorLine, param)) for i, obj in enumerate(objSorted): rs.ObjectColor(obj, (colors[i].X, colors[i].Y, colors[i].Z)) rs.DeleteObject(colorLine) rs.EnableRedraw(True) return True except: return False
def automated_smoothing_constraints(mesh, points = None, curves = None, surface = None, mesh2 = None): """Apply automatically point, curve and surface constraints to the vertices of a mesh to smooth. Parameters ---------- mesh : Mesh The mesh to apply the constraints to for smoothing. points : list List of XYZ coordinates on which to constrain mesh vertices. Default is None. curves : list List of Rhino curve guids on which to constrain mesh vertices. Default is None. surface : Rhino surface guid A Rhino surface guid on which to constrain mesh vertices. Default is None. mesh2 : Rhino mesh guid A Rhino mesh guid on which to constrain mesh vertices. Default is None. Returns ------- constraints : dict A dictionary of mesh constraints for smoothing as vertex keys pointing to point, curve or surface objects. """ if surface: surface = RhinoSurface.from_guid(surface) if curves: curves = [RhinoCurve.from_guid(curve) for curve in curves] if mesh2: mesh2 = RhinoMesh.from_guid(mesh2) constraints = {} constrained_vertices = {} vertices = list(mesh.vertices()) vertex_coordinates = [mesh.vertex_coordinates(vkey) for vkey in mesh.vertices()] if points is not None and len(points) != 0: constrained_vertices.update({vertices[closest_point_in_cloud(rs.PointCoordinates(point), vertex_coordinates)[2]]: point for point in points}) if mesh2 is not None: constraints.update({vkey: mesh2.guid for vkey in mesh.vertices()}) if surface is not None: constraints.update({vkey: surface.guid for vkey in mesh.vertices()}) if curves is not None and len(curves) != 0: boundaries = [split_boundary for boundary in mesh.boundaries() for split_boundary in list_split(boundary, [boundary.index(vkey) for vkey in constrained_vertices.keys() if vkey in boundary])] boundary_midpoints = [Polyline([mesh.vertex_coordinates(vkey) for vkey in boundary]).point(t = .5) for boundary in boundaries] curve_midpoints = [rs.EvaluateCurve(curve, rs.CurveParameter(curve, .5)) for curve in curves] midpoint_map = {i: closest_point_in_cloud(boundary_midpoint, curve_midpoints)[2] for i, boundary_midpoint in enumerate(boundary_midpoints)} constraints.update({vkey: curves[midpoint_map[i]].guid for i, boundary in enumerate(boundaries) for vkey in boundary}) if points is not None: constraints.update(constrained_vertices) return constraints
def Main(): mesh = rs.GetObject("please select mesh", rs.filter.mesh) srcs = rs.GetObjects("please select paths", rs.filter.curve) end = rs.MeshAreaCentroid(mesh) length = 6 ang = 20 gen = 12 for i in range(len(srcs)): nParam = r.random() start = rs.EvaluateCurve(srcs[i], rs.CurveParameter(srcs[i], nParam)) vec = rs.VectorCreate(end, start) vec = rs.VectorUnitize(vec) vec = vec * length tree = vine(mesh, start, vec, ang) for n in range(gen): tree.grow()
def ColorObjsWithGradient2Pt(): result = True try: objs = rs.GetObjects("Select objects to color", 1073750077, preselect=True) if objs is None: return pt1 = rs.GetPoint("Select first color point") if pt1 is None: return firstColor = rs.GetColor() if firstColor is None: return pt2 = rs.GetPoint("Select second color point") if pt2 is None: return secondColor = rs.GetColor(firstColor) if secondColor is None: return rs.EnableRedraw(False) origLine = rs.AddLine(pt1, pt2) colorLine = rs.AddLine(firstColor, secondColor) try: for obj in objs: bboxpts = rs.BoundingBox(obj) ctrPt = (bboxpts[0] + bboxpts[6]) / 2 param = rs.CurveClosestPoint(origLine, ctrPt) normParam = rs.CurveNormalizedParameter(origLine, param) colorParam = rs.CurveParameter(colorLine, normParam) finalPt = rs.EvaluateCurve(colorLine, colorParam) color = (finalPt.X, finalPt.Y, finalPt.Z) rs.ObjectColor(obj, color) except: result = False rs.DeleteObject(colorLine) rs.DeleteObject(origLine) rs.EnableRedraw(True) except: result = False utils.SaveFunctionData( 'colors-Gradient', [firstColor, secondColor, len(objs), result]) return result
def sweepVolume(crv, tool_id, z_pos): tangent = rs.CurveTangent(crv, rs.CurveParameter(crv, 0)) origin = rs.CurveStartPoint(crv) block = rs.InsertBlock( tool_id, (0,0,0), scale=(1,1,1) ) # rs.DeleteObjects(objs) # pt2 = [origin.X, origin.Y + perp.XAxis[1], origin.Z] pt2 = [origin.X, origin.Y , origin.Z + 1] pt3 = [origin.X + tangent.X, origin.Y + tangent.Y , origin.Z + tangent.Z] ref = [(0,0,0),(0,1,0),(0,0,1)] target = [origin, pt2 ,pt3] block = rs.OrientObject(block, ref, target) objs = rs.ExplodeBlockInstance(block) profile = None for item in objs: if rs.ObjectLayer(item) == 'HULP::C_Toolcontours' or rs.ObjectLayer(item) == 'Hulp::C_Toolcontours': profile = rs.CopyObject(item) rs.DeleteObjects(objs) if not profile: rs.MessageBox('there is no layer named "C_Toolcontours" in block %s' % rs.BlockInstanceName(block)) return False profile = rs.OffsetCurve(profile, rs.CurveAreaCentroid(profile)[0], 0.001, style=1) # rs.MoveObject(profile, (0,0,z_pos)) # rail = obj # rail_crv = rs.coercecurve(rail) # if not rail_crv: return # # cross_sections = [profile] # if not cross_sections: return # cross_sections = [rs.coercecurve(crv) for crv in cross_sections] # # sweep = Rhino.Geometry.SweepOneRail() # sweep.AngleToleranceRadians = scriptcontext.doc.ModelAngleToleranceRadians # sweep.ClosedSweep = True # # sweep.MiterType = 2 # sweep.SweepTolerance = scriptcontext.doc.ModelAbsoluteTolerance # sweep.SetToRoadlikeTop() # breps = sweep.PerformSweep(rail_crv, cross_sections) # for brep in breps: scriptcontext.doc.Objects.AddBrep(brep) # scriptcontext.doc.Views.Redraw() # # # surface_id = rs.LastCreatedObjects() # METHOD1 surface_id = rs.AddSweep1( crv, profile, True ) rs.CapPlanarHoles(surface_id) pt = rs.CurveAreaCentroid(profile)[0] pt2 = (pt.X, pt.Y, pt.Z+1) rev = rs.AddRevSrf( profile, (pt, pt2) ) rs.MoveObject(surface_id, (0,0,z_pos)) rs.MoveObject(rev, (0,0,z_pos)) return [surface_id, rev] rs.UnselectAllObjects() rs.SelectObjects([crv, profile]) result = rs.Command("_-Sweep1 _Enter Style=RoadlikeTop _Enter", False) if result: rs.DeleteObject(profile) surface_id = rs.LastCreatedObjects() rs.CapPlanarHoles(surface_id) rs.DeleteObjects(objs) rs.MoveObject(surface_id, (0,0,z_pos)) return surface_id
def make_fingers(positive, negative, subdivisions): """ intersect two collections of planes subdivide the intersections assign each subdivision to a guid from which it will be subtracted """ # this vector is used to indicate axis of the intersection. # it needs to be parallel to the intersection # (there are other ways of doing this!) p0 = rs.GetPoint("select start of intersection") p1 = rs.GetPoint("select end of intersection") edge = rs.AddLine(p0, p1) vector = rs.VectorCreate(p0, p1) rs.EnableRedraw(False) # this dict maps a pair of planes (ps, ns) to their booleanintersection intersections = {} for ps in positive: for ns in negative: intersection = rs.BooleanIntersection(ps, ns, False) if intersection is not None: intersections[(ps, ns)] = intersection # here we construct some very large cylinders aligned with the axis you drew origins = [] cylinders = [] for i in range(subdivisions+1): origin = rs.EvaluateCurve(edge, rs.CurveParameter(edge, i * 1.0/(subdivisions))) origins.append(origin) rs.DeleteObject(edge) for i in range(subdivisions): plane = rs.PlaneFromNormal(origins[i], vector) circle = rs.AddCircle(plane, 100) planar_circle = rs.AddPlanarSrf(circle) extrusion_curve = rs.AddLine(origins[i], origins[i+1]) cylinders.append(rs.ExtrudeSurface(planar_circle, extrusion_curve)) rs.DeleteObject(circle) rs.DeleteObject(planar_circle) rs.DeleteObject(extrusion_curve) # we perform a boolean intersection between each intersection and # the cylinders to construct the fingers for key, intersection in intersections.items(): ps, ns = key for i, cylinder in enumerate(cylinders): print "intersection", intersection print "cylinder", cylinder objs = [brep for brep in rs.BooleanIntersection(intersection, cylinder, False) if rs.IsBrep(brep)] # assign the resulting fingers to either the positive or negative if i % 2 == 0: guid_to_difference[ps].extend(objs) else: guid_to_difference[ns].extend(objs) DeleteItemOrList(cylinders) DeleteItemOrList(intersections.values()) rs.EnableRedraw(True)
def evaluateCrv(crv, normalizedParameter): """Returns a point on a curve given a normalized parameter.""" crvParam = rs.CurveParameter(crv, normalizedParameter) crvPt = rs.EvaluateCurve(crv, crvParam) return crvPt
def automatic_constraints(mesh, surface_constraint, curve_constraints = [], point_constraints = []): """Defines the constraints on the vertices of the mesh on a point, a curve or a surface. Parameters ---------- mesh : Mesh A mesh. surface_constraint : Rhino surface guid A surface to project vertices. curve_constraints : Rhino curve guids Curve features on surface to constrain vertices. point_constraints : Rhino point guids Point features on surface to constrain vertices. Returns ------- constraints: dict Dictionary of constraints {vertex_key: (constraint_type, constraint_information)}. Raises ------ - """ constraints = {} surface_boundaries = surface_borders(surface_constraint, border_type = 0) # set point constraints at point feature, curve feature extremities and boundary curve corners constrained_points = [] for curve_guid in surface_boundaries: start_tgt = rs.CurveTangent(curve_guid, rs.CurveParameter(curve_guid, 0)) end_tgt = rs.CurveTangent(curve_guid, rs.CurveParameter(curve_guid, 1)) # add only if not closed or closed with a kink if not rs.IsCurveClosed(curve_guid) or not rs.IsVectorParallelTo(start_tgt, end_tgt): start = geometric_key(rs.CurveStartPoint(curve_guid)) end = geometric_key(rs.CurveEndPoint(curve_guid)) if start not in constrained_points: constrained_points.append(start) if end not in constrained_points: constrained_points.append(end) for vkey in mesh.vertices(): xyz = mesh.vertex_coordinates(vkey) geom_key = geometric_key(xyz) if geom_key in constrained_points: constraints[vkey] = ['point', xyz] # set boundary curve constraints split_vertices = [vkey for vkey, constraint in constraints.items() if constraint[0] == 'point'] split_mesh_boundaries = mesh_boundaries(mesh, vertex_splits = split_vertices) # constrain a mesh boundary to a surface boundary if the two extremities of the mesh boundary are on the surface boundary for mesh_bdry in split_mesh_boundaries: if mesh_bdry[0] == mesh_bdry[-1]: crv_cstr = None for vkey in mesh_bdry: xyz = mesh.vertex_coordinates(vkey) for srf_bdry in surface_boundaries: if is_point_on_curve(srf_bdry, xyz): crv_cstr = srf_bdry break if crv_cstr is not None: break if crv_cstr is not None: for vkey in mesh_bdry: xyz = mesh.vertex_coordinates(vkey) if is_point_on_curve(crv_cstr, xyz) and vkey not in constraints: constraints[vkey] = ['curve', crv_cstr] for i, vkey in enumerate(mesh_bdry): if vkey not in constraints: # find next contrained point n_plus = 1 norm_t_plus = None count = len(mesh_bdry) while count > 0: count -= 1 vkey_plus = mesh_bdry[i + n_plus - len(mesh_bdry)] if vkey_plus in constraints: norm_t_plus = rs.CurveNormalizedParameter(crv_cstr, rs.CurveClosestPoint(crv_cstr, mesh.vertex_coordinates(vkey_plus))) else: n_plus += 1 # find previous contrained point n_minus = 1 norm_t_minus = None count = len(mesh_bdry) while count > 0: count -= 1 vkey_minus = mesh_bdry[i - n_minus] if vkey_minus in constraints: norm_t_minus = rs.CurveNormalizedParameter(crv_cstr, rs.CurveClosestPoint(crv_cstr, mesh.vertex_coordinates(vkey_minus))) else: n_minus += 1 # calculate barycentric parameter and move to it # dichotomy required in case of curve seam being between the two parameters #print n_minus, norm_t_minus, n_plus, norm_t_plus if norm_t_minus == norm_t_plus: norm_t = (norm_t_plus + .5) % 1 elif norm_t_minus < norm_t_plus: norm_t = (n_minus * norm_t_plus + n_plus * norm_t_minus) / (n_minus + n_plus) else: norm_t_plus += 1 norm_t = (n_minus * norm_t_plus + n_plus * norm_t_minus) / (n_minus + n_plus) # update coordiantes t = rs.CurveParameter(crv_cstr, norm_t) x, y, z = rs.EvaluateCurve(crv_cstr, t) attr = mesh.vertex[vkey] attr['x'] = x attr['y'] = y attr['z'] = z # store constraint constraints[vkey] = ['curve', crv_cstr] else: for srf_bdry in surface_boundaries: start_xyz = mesh.vertex_coordinates(mesh_bdry[0]) end_xyz = mesh.vertex_coordinates(mesh_bdry[-1]) # if the mesh boundary extremities match the ones of the curve boundary... if is_point_on_curve(srf_bdry, start_xyz) and is_point_on_curve(srf_bdry, end_xyz): # ... and if there is an intermediary mesh boundary vertex on this curve boundary (needed for two-sided boundary elements) to_constrain = False for vkey in mesh_bdry[1 : -1]: if is_point_on_curve(srf_bdry, mesh.vertex_coordinates(vkey)): to_constrain = True if to_constrain: crv_cstr = srf_bdry for vkey in mesh_bdry: xyz = mesh.vertex_coordinates(vkey) if is_point_on_curve(crv_cstr, xyz) and vkey not in constraints: constraints[vkey] = ['curve', crv_cstr] for i, vkey in enumerate(mesh_bdry): if vkey not in constraints: # find next contrained point n_plus = 1 norm_t_plus = None count = len(mesh_bdry) while count > 0: count -= 1 vkey_plus = mesh_bdry[i + n_plus - len(mesh_bdry)] if vkey_plus in constraints: norm_t_plus = rs.CurveNormalizedParameter(crv_cstr, rs.CurveClosestPoint(crv_cstr, mesh.vertex_coordinates(vkey_plus))) else: n_plus += 1 # find previous contrained point n_minus = 1 norm_t_minus = None count = len(mesh_bdry) while count > 0: count -= 1 vkey_minus = mesh_bdry[i - n_minus] if vkey_minus in constraints: norm_t_minus = rs.CurveNormalizedParameter(crv_cstr, rs.CurveClosestPoint(crv_cstr, mesh.vertex_coordinates(vkey_minus))) else: n_minus += 1 # calculate barycentric parameter and move to it # dichotomy required in case of curve seam being between the two parameters #print n_minus, norm_t_minus, n_plus, norm_t_plus if norm_t_minus == norm_t_plus: norm_t = (norm_t_plus + .5) % 1 elif norm_t_minus < norm_t_plus: norm_t = (n_minus * norm_t_plus + n_plus * norm_t_minus) / (n_minus + n_plus) else: norm_t_plus += 1 norm_t = (n_minus * norm_t_plus + n_plus * norm_t_minus) / (n_minus + n_plus) # update coordiantes t = rs.CurveParameter(crv_cstr, norm_t) x, y, z = rs.EvaluateCurve(crv_cstr, t) attr = mesh.vertex[vkey] attr['x'] = x attr['y'] = y attr['z'] = z # store constraint constraints[vkey] = ['curve', crv_cstr] # constrain to point features point_constraints_keys = [geometric_key(rs.PointCoordinates(pt)) for pt in point_constraints] for vkey in mesh.vertices(): xyz = mesh.vertex_coordinates(vkey) geom_key = geometric_key(xyz) if geom_key in point_constraints_keys: constraints[vkey] = ['point', xyz] # constrain to curve features for crv in curve_constraints: # extremities start = rs.CurveStartPoint(crv) start_geom_key = geometric_key(start) end = rs.CurveEndPoint(crv) end_geom_key = geometric_key(end) for vkey in mesh.vertices(): xyz = mesh.vertex_coordinates(vkey) geom_key = geometric_key(xyz) if geom_key == start_geom_key: constraints[vkey] = ['point', xyz] start_key = vkey if geom_key == end_geom_key: constraints[vkey] = ['point', xyz] end_key = vkey # regular nodes path = [start_key] for nbr in mesh.vertex_neighbors(start_key): completed = False if mesh.is_vertex_on_boundary(nbr): continue path.append(nbr) count = len(list(mesh.vertices())) while count > 0: count -= 1 u, v = path[-2], path[-1] fkey = mesh.halfedge[u][v] x = mesh.face_vertex_descendant(fkey, v) fkey = mesh.halfedge[x][v] w = mesh.face_vertex_descendant(fkey, v) path.append(w) if w == end_key: completed = True break elif mesh.is_vertex_on_boundary(w) or len(mesh.vertex_neighbors(w)) != 4: break if completed: break else: path = [start_key] for vkey in path[1 : -1]: constraints[vkey] = ['curve', crv] # set surface constraints by default for the others for vkey in mesh.vertices(): if vkey not in constraints: constraints[vkey] = ['surface', surface_constraint] # udpdate drawn mesh layer = 'pattern_topology' mesh_guid = rs.ObjectsByLayer(layer)[0] rs.DeleteObject(mesh_guid) mesh_guid = draw_mesh(mesh) rs.ObjectLayer(mesh_guid, layer) return constraints, surface_boundaries
def stairHeight(route, width=48, height=120): """ Makes a stair to specified height. input: route(pline), width (num), height(num) returns: Geo """ try: rs.EnableRedraw(False) rs.SimplifyCurve(route) if route is None: print("ERROR: No path selected") return if (rs.UnitSystem() == 2): #if mm maxRiserHeight = 180 thickness = 200 if (rs.UnitSystem() == 4): #if m maxRiserHeight = .180 thickness = .200 if (rs.UnitSystem() == 8): #if in" maxRiserHeight = 7 thickness = 9 negativeBoo = False if (height < 0): #if the stair negativeBoo = True landingEdges = [] landings = [] segments = rs.ExplodeCurves(route) if len(segments) < 1: segments = [rs.CopyObject(route)] landingHeight = [] geometry = [] #Check that all segments are lines for i in range(0, len(segments)): if not (rs.IsLine(segments[i])): print( "ERROR: This function only accepts lines. No arcs or nurb curves." ) rs.DeleteObjects(segments) return #first landing edge norm = rs.VectorRotate(rs.CurveTangent(segments[0], 0), 90, [0, 0, 1]) norm = rs.VectorScale(rs.VectorUnitize(norm), width / 2) side1Pt = rs.VectorAdd(rs.CurveStartPoint(segments[0]), norm) side2Pt = rs.VectorAdd(rs.CurveStartPoint(segments[0]), -norm) landingEdges.append(rs.AddLine(side1Pt, side2Pt)) #middle landing edges for i in range(0, len(segments) - 1): edgeList, landing = rampIntersection(segments[i], segments[i + 1], width) landingEdges.append(edgeList[0]) landingEdges.append(edgeList[1]) landings.append(landing) #last landing edge norm = rs.VectorRotate( rs.CurveTangent(segments[-1], rs.CurveParameter(segments[-1], 1)), 90, [0, 0, 1]) norm = rs.VectorScale(rs.VectorUnitize(norm), width / 2) side1Pt = rs.VectorAdd(rs.CurveEndPoint(segments[-1]), norm) side2Pt = rs.VectorAdd(rs.CurveEndPoint(segments[-1]), -norm) landingEdges.append(rs.AddLine(side1Pt, side2Pt)) #Add risers riserCrvs = [] treadVecs = [] numRisersPerRun = [] numRisers = abs(int(math.ceil(height / maxRiserHeight))) risersSoFar = 0 totalRun = getTotalRun(landingEdges) optTreadDepth = totalRun / (numRisers - 1) #2R+T = 635 riserHeight = height / numRisers if (negativeBoo): curRiserHeight = 0 else: curRiserHeight = riserHeight for i in range(0, len(landingEdges), 2): #find numRisers in each run a = rs.CurveMidPoint(landingEdges[i]) b = rs.CurveMidPoint(landingEdges[i + 1]) runDist = rs.Distance(a, b) numRisersThisRun = int(round((runDist / optTreadDepth), 0)) if (numRisersThisRun == 0): numRisersThisRun = 1 if (i == len(landingEdges) - 2): #if last run, add the rest of the risers numRisersThisRun = numRisers - risersSoFar else: risersSoFar = risersSoFar + numRisersThisRun numRisersPerRun.append(numRisersThisRun) #Create Risers on Plan for i in range(0, len(landingEdges), 2): run = [] a = rs.CurveMidPoint(landingEdges[i]) b = rs.CurveMidPoint(landingEdges[i + 1]) centerStringer = rs.AddLine(a, b) runDist = rs.Distance(a, b) numRisersThisRun = numRisersPerRun[int(i / 2)] #risers in this run tarPts = rs.DivideCurve(centerStringer, numRisersThisRun, create_points=False) rs.DeleteObject(centerStringer) for j in range(0, numRisersThisRun + 1): if (j == 0): treadVecs.append(rs.VectorCreate(tarPts[0], tarPts[1])) transVec = rs.VectorCreate(tarPts[0], tarPts[j]) run.append(rs.CopyObject(landingEdges[i], -transVec)) riserCrvs.append(run) print('Flight {0} has {1} risers: {3}" tall, Treads: {2}" deep'. format( int(i / 2) + 1, numRisersThisRun, rs.VectorLength(treadVecs[int(i / 2)]), riserHeight)) #Move riser edges vertically for i in range(0, len(riserCrvs)): triangles = [] if (negativeBoo): for j in range(0, len(riserCrvs[i]) - 1): #if stairs descending rs.MoveObject( riserCrvs[i][j], rs.VectorAdd([0, 0, curRiserHeight], -treadVecs[i])) riserGeo = rs.ExtrudeCurveStraight(riserCrvs[i][j], [0, 0, 0], [0, 0, riserHeight]) treadGeo = rs.ExtrudeCurveStraight(riserCrvs[i][j], [0, 0, 0], treadVecs[i]) stPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][j])) pt1 = rs.CopyObject( stPt, [0, 0, riserHeight]) #first riser in run pt2 = rs.CopyObject(stPt, treadVecs[i]) #last riser in run triCrv = rs.AddPolyline([stPt, pt1, pt2, stPt]) triangles.append(rs.AddPlanarSrf(triCrv)) geometry.append(riserGeo) #riser geometry.append(treadGeo) #tread curRiserHeight = curRiserHeight + riserHeight rs.MoveObject(riserCrvs[i][j], treadVecs[i]) #cleanup rs.DeleteObject(triCrv) rs.DeleteObject(stPt) rs.DeleteObject(pt1) rs.DeleteObject(pt2) else: for j in range(0, len(riserCrvs[i]) - 1): #if stairs ascend rs.MoveObject(riserCrvs[i][j], [0, 0, curRiserHeight]) stPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][j])) pt1 = rs.CopyObject( stPt, [0, 0, -riserHeight]) #first riser in run pt2 = rs.CopyObject(stPt, -treadVecs[i]) #last riser in run triCrv = rs.AddPolyline([stPt, pt1, pt2, stPt]) triangles.append(rs.AddPlanarSrf(triCrv)) riserGeo = rs.ExtrudeCurveStraight(riserCrvs[i][j], [0, 0, 0], [0, 0, -riserHeight]) treadGeo = rs.ExtrudeCurveStraight(riserCrvs[i][j], [0, 0, 0], -treadVecs[i]) geometry.append(riserGeo) #riser geometry.append(treadGeo) #tread curRiserHeight = curRiserHeight + riserHeight #cleanup rs.DeleteObject(triCrv) rs.DeleteObject(stPt) rs.DeleteObject(pt1) rs.DeleteObject(pt2) #Make Stringer if (negativeBoo): firstStartPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][0])) lastStartPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][-2])) #rs.MoveObject(firstStartPt, [0,0,riserHeight]) #first riser in run rs.MoveObject(lastStartPt, -treadVecs[i]) #last riser in run rs.MoveObject(lastStartPt, [0, 0, riserHeight]) #last riser in run else: firstStartPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][0])) lastStartPt = rs.AddPoint(rs.CurveStartPoint(riserCrvs[i][-2])) rs.MoveObject(firstStartPt, [0, 0, -riserHeight]) #first riser in run rs.MoveObject(lastStartPt, -treadVecs[i]) #last riser in run stringerCrv = rs.AddLine(firstStartPt, lastStartPt) stringerSrf = rs.ExtrudeCurveStraight(stringerCrv, [0, 0, 0], [0, 0, -thickness]) triangles.append(stringerSrf) stringer = makeFace(triangles) stringerVec = rs.VectorCreate(rs.CurveEndPoint(riserCrvs[i][0]), rs.CurveStartPoint(riserCrvs[i][0])) underside = rs.ExtrudeCurveStraight( stringerCrv, rs.CurveStartPoint(riserCrvs[i][0]), rs.CurveEndPoint(riserCrvs[i][0])) geometry.append(rs.MoveObject(underside, [0, 0, -thickness])) geometry.append(rs.CopyObject(stringer, stringerVec)) geometry.append(stringer) #cleanup rs.DeleteObject(firstStartPt) rs.DeleteObject(lastStartPt) rs.DeleteObject(stringerCrv) rs.DeleteObject(stringerSrf) #Move Landings lastLandingHeight = 0 for i in range(0, len(segments) - 1): landingHeight = lastLandingHeight + numRisersPerRun[i] * riserHeight rs.MoveObject(landings[i], [0, 0, landingHeight]) landingTopSrf = rs.AddPlanarSrf(landings[i]) landingBtmSrf = rs.CopyObject(landingTopSrf, [0, 0, -thickness]) geometry.append(landingTopSrf) geometry.append(landingBtmSrf) lastLandingHeight = landingHeight landingEdgesToEx = rs.ExplodeCurves(landings[i]) geometry.append( rs.ExtrudeCurveStraight(landingEdgesToEx[1], [0, 0, 0], [0, 0, -thickness])) geometry.append( rs.ExtrudeCurveStraight(landingEdgesToEx[2], [0, 0, 0], [0, 0, -thickness])) rs.DeleteObjects(landingEdgesToEx) #Create final geometry joinedGeo = rs.JoinSurfaces(geometry, True) holes = rs.DuplicateSurfaceBorder(joinedGeo) cap = rs.AddPlanarSrf(holes) newGeo = rs.ExplodePolysurfaces(joinedGeo, True) for i in cap: newGeo.append(i) FinalGeo = rs.JoinSurfaces(newGeo, True) #cleanup try: rs.DeleteObjects(segments) except: rs.DeleteObject(segments) rs.DeleteObjects(holes) rs.DeleteObjects(landings) rs.DeleteObjects(landingEdges) for i in riserCrvs: rs.DeleteObjects(i) rs.EnableRedraw(True) return FinalGeo except: print "Error" return None