def blendcorners(polyline_id, radius): # Fillets the corners of a polyline (from the McNeel website) if not polyline_id: return vertices = rs.PolylineVertices(polyline_id) if not vertices: return if radius is None: return between = lambda a, b: (a + b) / 2.0 newverts = [] for i in range(len(vertices) - 1): a = vertices[i] b = vertices[i + 1] segmentlength = rs.Distance(a, b) vec_segment = rs.PointSubtract(b, a) vec_segment = rs.VectorUnitize(vec_segment) if radius < (0.5 * segmentlength): vec_segment = rs.VectorScale(vec_segment, radius) else: vec_segment = rs.VectorScale(vec_segment, 0.5 * segmentlength) w1 = rs.PointAdd(a, vec_segment) w2 = rs.PointSubtract(b, vec_segment) newverts.append(a) newverts.append(between(a, w1)) newverts.append(w1) newverts.append(between(w1, w2)) newverts.append(w2) newverts.append(between(w2, b)) newverts.append(vertices[len(vertices) - 1]) CrvId = rs.AddCurve(newverts, 5) rs.DeleteObject(polyline_id) return CrvId
def blendcorners(): polyline_id = rs.GetObject("Polyline to blend", 4, True, True) if not polyline_id: return vertices = rs.PolylineVertices(polyline_id) if not vertices: return radius = rs.GetReal("Blend radius", 1.0, 0.0) if radius is None: return between = lambda a, b: (a + b) / 2.0 newverts = [] for i in range(len(vertices) - 1): a = vertices[i] b = vertices[i + 1] segmentlength = rs.Distance(a, b) vec_segment = rs.PointSubtract(b, a) vec_segment = rs.VectorUnitize(vec_segment) if radius < (0.5 * segmentlength): vec_segment = rs.VectorScale(vec_segment, radius) else: vec_segment = rs.VectorScale(vec_segment, 0.5 * segmentlength) w1 = rs.PointAdd(a, vec_segment) w2 = rs.PointSubtract(b, vec_segment) newverts.append(a) newverts.append(between(a, w1)) newverts.append(w1) newverts.append(between(w1, w2)) newverts.append(w2) newverts.append(between(w2, b)) newverts.append(vertices[len(vertices) - 1]) rs.AddCurve(newverts, 5) rs.DeleteObject(polyline_id)
def draw(p0, p1, n=4): if n == 0: rs.AddLine(p0, p1) elif n >= 1: p01 = rs.PointAdd(p0, rs.PointScale(rs.PointSubtract(p1, p0), 1 / 3)) p10 = rs.PointAdd(p0, rs.PointScale(rs.PointSubtract(p1, p0), 2 / 3)) p2 = rs.PointAdd( p01, rs.VectorRotate(rs.PointSubtract(p10, p01), 60, (0, 0, 1))) draw(p0, p01, n - 1) draw(p01, p2, n - 1) draw(p2, p10, n - 1) draw(p10, p1, n - 1)
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 main(): counts = [0, 0, 0] spacings = [10, 10, 10] rotations = [0, 0, 0] counts[0] = rs.GetInteger("number in x direction", minimum=1) # counts[1] = rs.GetInteger("number in y direction", minimum=1) # counts[2] = rs.GetInteger("number in z direction", minimum=1) spacings[0] = rs.GetReal("x spacing") # spacings[1] = rs.GetReal("y spacing") # spacings[2] = rs.GetReal("z spacing") rotations[0] = rs.GetReal("rotation of each object along x axis") # rotations[1] = rs.GetReal("y spacing") # rotations[2] = rs.GetReal("z spacing") print "count", counts print "spacing", spacings print "rotation", rotations for ix in range(counts[0]): newobj = rs.CopyObject(obj, [spacings[0] * ix, 0, 0]) bbox = rs.BoundingBox(newobj) if bbox: centroid = rs.PointSubtract(bbox[0], bbox[6]) print bbox[6], bbox[0] print centroid rs.AddPoint(centroid) else: print "no bbox"
def quad_rotate_point(point, center_point=(0, 0, 0), axis=(0, 0, 1)): _vec = rss.PointSubtract(point, center_point) return [ point, rss.PointAdd(center_point, rss.VectorRotate(_vec, 90.0, axis)), rss.PointAdd(center_point, rss.VectorRotate(_vec, 180.0, axis)), rss.PointAdd(center_point, rss.VectorRotate(_vec, -90.0, axis)), ]
def AddArcDir(ptStart, ptEnd, vecDir): vecBase = rs.PointSubtract(ptEnd, ptStart) if rs.VectorLength(vecBase)==0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize(vecBase) vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) dotProd = rs.VectorDotProduct(vecBisector, vecDir) midLength = (0.5*rs.Distance(ptStart, ptEnd))/dotProd vecBisector = rs.VectorScale(vecBisector, midLength) return rs.AddArc3Pt(ptStart, rs.PointAdd(ptStart, vecBisector), ptEnd)
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 DrawArcSED(): ptA = rs.GetPoint("Start of arc") if not ptA: return ptB = rs.GetPoint("End of arc") if not ptB: return ptD = rs.GetPoint("Direction of arc at start", ptA) if not ptD: return vecD = rs.PointSubtract(ptD, ptA) if rs.VectorLength(vecD) == 0.0: return AddArcDir(ptA, ptB, vecD)
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 draw_lpoint_triple(text, tail, head): """Receives label text and a list of point triples: str [<iter>, ...] Draws text dots with <text>-a, -b, -c """ line_vector = rs.PointSubtract(head, tail) offset_vector = line_vector * offset offset_tail = rs.VectorAdd(tail, offset_vector) offset_head = rs.VectorSubtract(head, offset_vector) axis = [0, 0, 1] angle = 90 rotated_offset_vector = rs.VectorRotate(offset_vector, angle, axis) offset_side = rs.VectorAdd(offset_tail, rotated_offset_vector) rs.AddTextDot(('%s-a' % text), offset_tail) rs.AddTextDot(('%s-b' % text), offset_head) rs.AddTextDot(('%s-c' % text), offset_side)
def addArc(startPt, endPt, vecDir): vecBase = rs.PointSubtract(endPt, startPt) if rs.VectorLength(vecBase) == 0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize(vecBase) vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) midlength = (0.5*rs.Distance(startPt, endPt)) / (rs.VectorDotProduct(vecBisector, vecDir)) vecBisector = rs.VectorScale(vecBisector, midlength) return rs.AddArc3Pt(startPt, endPt, rs.PointAdd(startPt, vecBisector))
def addArcDiv(ptStart, ptEnd, vecDir): vecBase = rs.PointSubtract(ptEnd, ptStart) # error handling if rs.VectorLength(vecBase) == 0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize( vecBase ) # normalize vector == force magnitude to 1 to just compare direction vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) dotProd = rs.VectorDotProduct(vecBisector, vecDir) midLength = (0.5 * rs.Distance(ptStart, ptEnd)) / dotProd vecBisector = rs.VectorScale(vecBisector, midLength) return rs.AddArc3Pt(ptStart, rs.PointAdd(pt.Start, vecBisector), ptEnd)
__author__ = "billpower" __version__ = "2020.01.15" import rhinoscriptsyntax as rs point = LocationPoint file = File x = [] y = [] z = [] xyz = [] rexyz = [] repoint = [] orpoint = [] f = open(file,'r') #使用open打开文件,r为只读模式 firstpoint = f.readline() #使用方法读取行,读到第一个换行符 subdistance = rs.PointSubtract(rs.AddPoint(firstpoint),point) #读取第一个行点坐标,建立点并与输入的定位点差,获取两点之间坐标的插值 for line in f.readlines(): #对文件内容进行迭代,读取所有行 lst = line.split(',') x.append(float(lst[0])) y.append(float(lst[1])) z.append(float(lst[2])) xyz.append((float(lst[0]),float(lst[1]),float(lst[2]))) #字符串坐标浮点数化,形成坐标值列表 orpoint.append(rs.AddPoint(float(lst[0]),float(lst[1]),float(lst[2]))) #根据原数据值建立点 rexyz.append(((float(lst[0])-subdistance[0]),(float(lst[1])-subdistance[1]),(float(lst[2])-subdistance[2]))) #计算新坐标,形成列表 repoint.append(rs.AddPoint((float(lst[0])-subdistance[0]),(float(lst[1])-subdistance[1]),(float(lst[2])-subdistance[2]))) #根据新坐标增加点 f.close() #关闭文件
arrBoxPoints = [[offsetX, offsetY, offsetZ],[offsetX + panelData[i][0].GetPanelProperty("PanelWidth"), offsetY, offsetZ],\ [offsetX, offsetY, offsetZ+panelData[i][0].GetPanelProperty("PanelHeight")],\ [offsetX + panelData[i][0].GetPanelProperty("PanelWidth"), offsetY, offsetZ+panelData[i][0].GetPanelProperty("PanelHeight")]] blockCount = len( panelData[i][0].GetPanelProperty("BlockInstances")) panelCounter += blockCount #create text info if drawGeometry: panelName = panelName.replace(" ", "\n\r", 1) prevLayer = rs.CurrentLayer() if not rs.IsLayer("GEO::_Canvas"): rs.AddLayer("GEO::_Canvas") rs.CurrentLayer("GEO::_Canvas") txtPlane = rs.PlaneFromFrame( rs.PointSubtract(arrBoxPoints[0], [0, 0, rowSeparation / 2]), (1, 0, 0), (0, 0, 1)) textTypes.append( rs.AddText(panelName + "\n\rCount: " + str(blockCount), txtPlane, fontHeight, font_style=fontStyle)) rs.CurrentLayer(prevLayer) #create panel copy Mockup_Bay.append(SGLibPanel()) Mockup_Bay[len(Mockup_Bay) - 1].Copy(panelData[i][0]) panelPoints = Mockup_Bay[len(Mockup_Bay) - 1].GetPanelProperty( "PanelCornerPoints") alignXform = rc.Geometry.Transform.Translation( -min(panelPoints[0].X, panelPoints[2].X), 0, 0) tmpBoxPts = rs.PointArrayTransform(arrBoxPoints, alignXform)
continue #skip custom panel if showCustom off else: fontHeight = .6 fontStyle = 1 arrBoxPoints = [[offsetX, offsetY, offsetZ],[offsetX + panelData[i][0].GetPanelProperty("PanelWidth"), offsetY, offsetZ],\ [offsetX, offsetY, offsetZ+panelData[i][0].GetPanelProperty("PanelHeight")],\ [offsetX + panelData[i][0].GetPanelProperty("PanelWidth"), offsetY, offsetZ+panelData[i][0].GetPanelProperty("PanelHeight")]] #create text info if drawGeometry: blockCount = len( panelData[i][0].GetPanelProperty("BlockInstances")) textTypes.append( rs.AddText(panelName + " Count: " + str(blockCount), rs.PointSubtract(arrBoxPoints[0], [0, 1, 0]), fontHeight, font_style=fontStyle)) rs.RotateObject( textTypes[len(textTypes) - 1], rs.TextObjectPoint(textTypes[len(textTypes) - 1]), 270) #create panel copy Mockup_Bay.append(SGLibPanel()) Mockup_Bay[len(Mockup_Bay) - 1].Copy(panelData[i][0]) Mockup_Bay[len(Mockup_Bay) - 1].MorphPanel(arrBoxPoints) #print i; print panelData Mockup_Bay[len(Mockup_Bay) - 1].Draw(drawGeometry) if drawBreps: Breps += Mockup_Bay[len(Mockup_Bay) - 1].GetBreps()
def _get_ordered_line_and_labeled_point_specs(cls, element_guids): """Receives: element_guids [guid, ...]. A list of the guids of (first) the frame instance and (then) the lines and labeled points Returns: ordered_line_and_labeled_point_specs ([line_spec, ...], [labeled_point_spec, ...]). A list of line specs ( (num, num, num), (num, num, num)) and a list of labeled point specs ( str, (num, num, num)) where the specs are relative to the frame instance, if successful None otherwise """ method_name = '_get_ordered_line_and_labeled_point_specs' try: if element_guids == []: raise ValueError except ValueError: message = "There is no frame instance" print("%s.%s\n %s" % (cls.__name__, method_name, message)) return_value = None else: line_specs, labeled_point_specs = [], [] frame_instance = element_guids.pop(0) frame_position = rs.BlockInstanceInsertPoint(frame_instance) curve_type, textdot_type = 4, 8192 for element_guid in element_guids: if rs.ObjectType(element_guid) == curve_type: p1_absolute = rs.CurveStartPoint(element_guid) p2_absolute = rs.CurveEndPoint(element_guid) p1_relative = rs.PointSubtract(p1_absolute, frame_position) p2_relative = rs.PointSubtract(p2_absolute, frame_position) p1_spec = tuple(p1_relative) p2_spec = tuple(p2_relative) if p1_spec < p2_spec: tail = p1_spec head = p2_spec elif p1_spec > p2_spec: tail = p2_spec head = p1_spec line_spec = (tail, head) line_specs.append(line_spec) elif rs.ObjectType(element_guid) == textdot_type: label = rs.TextDotText(element_guid) p_absolute = rs.TextDotPoint(element_guid) p_relative = rs.PointSubtract(p_absolute, frame_position) p_spec = tuple(p_relative) labeled_point_spec = (label, p_spec) labeled_point_specs.append(labeled_point_spec) else: pass ordered_line_and_labeled_point_specs = ( sorted(line_specs), sorted(labeled_point_specs)) return_value = ordered_line_and_labeled_point_specs finally: return return_value
def DistributeCirclesOnSphere(): #get a bunch of stuff from the user center_point = rs.GetPoint("Center of Sphere", (0, 0, 0)) if not center_point: print("Center Point Needed!") return sphere_radius = rs.GetReal("Radius of Sphere", 10.0, 0.01) if not sphere_radius: print("Sphere Radius Needed!") return circle_radius = rs.GetReal("Radius of Circles", 0.05 * sphere_radius, 0.001, 0.5 * sphere_radius) if not circle_radius: print("Circle Radius Needed!") return #this gives the number of circles that will fit along the seam. The centers of the seam #circles will also be the "bands" of circles around the sphere. The length of the seam #is half of the circumference (1/2C = pi * r). Divide that space by the diameter of the #circles we want to lay along it. Casting as INT drops the decimal (round down). vertical_count = int((math.pi * sphere_radius) / (2 * circle_radius)) rs.EnableRedraw(False) #phi is the variable that will set the elevation of the bands above and below #the equator. The domain of this space will be -0.5 pi to 0.5 pi. Each step #will be in an increment determined by the number of circles that fit along the seam. phi = -0.5 * math.pi phi_step = math.pi / vertical_count #step throught the "bands" around the sphere until we reach the bottom while phi < 0.5 * math.pi: #the number of circles we can fit in each "band" is the diameter of the sphere at each #angle of phi divided by the diameter of a single circle. Casting as an INT will drop #the decimals (round down) horizontal_count = int((2 * math.pi * math.cos(phi) * sphere_radius) / (2 * circle_radius)) #the only case to round UP is if we accidentially rounded down to 0 (we can't have 0 circles) if horizontal_count == 0: horizontal_count = 1 #theta is the angle around the center of the circle at the equator. We intitalize #for each "band" and determine the step increment based on the number of circles #we can fit in each band theta = 0 theta_step = 2 * math.pi / horizontal_count #this is where we look through all the positions on each "band" #the origianl author of this script subtracts a small value from 2 PI #to keep there from being an overlapped circle at the end. I am not #sure that it is needed here, but I am leaving it in as I have not #tested the script that much while theta < 2 * math.pi - 1e-8: #convert our spherical coordinates into cartesion that Rhino understands #this is 3D Pythagorean Theorum circle_center = (sphere_radius * math.cos(theta) * math.cos(phi) + center_point[0], sphere_radius * math.sin(theta) * math.cos(phi) + center_point[1], sphere_radius * math.sin(phi) + center_point[2]) #subtracting the point coordinates from the origin give us a vector that points #away from the center circle_normal = rs.PointSubtract(circle_center, center_point) #proxy place to place the circle, we don't care about orientation circle_plane = rs.PlaneFromNormal(circle_center, circle_normal) rs.AddCircle(circle_plane, circle_radius) #increment Theta angle theta += theta_step #increment Phi angle phi += phi_step rs.EnableRedraw(True)