def IsRectangle(obj): """ Checks if a curve is a rectangle. Must be closed, planar, 4 line segments, all 90 degrees. Uses UnitAngleTolerance inputs: obj (curve): curve to evaluate returns (list): [0] (Boolean): If rectangle [1] (String): explaination of why it failed """ explaination = '' tol = rs.UnitAngleTolerance() rhobj = rs.coercecurve(obj) if rs.IsCurveClosed(obj): if rs.IsCurvePlanar(obj): segments = rhobj.DuplicateSegments() if len(segments) == 4: for segment in segments: if segment.Degree != 1: explaination = "Not all segments are lines" return [False, explaination] for i in range(3): angle = rs.Angle2(segments[i], segments[i+1]) dist1 = abs(abs(180 - angle[0])-90) dist2 = abs(abs(180 - angle[1])-90) if dist1 > tol or dist2 > tol: explaination = "Angle not 90" return [False, explaination] angle = rs.Angle2(segments[-1], segments[0]) dist1 = abs(abs(180 - angle[0])-90) dist2 = abs(abs(180 - angle[1])-90) if dist1 > tol or dist2 > tol: explaination = "Final angle not 90" return [False, explaination] explaination = "ITS A RECTANGLE" return [True, explaination] else: explaination = "Curve does not have 4 sides" return [False, explaination] else: explaination = "Curve not planar" return [False, explaination] else: explaination = "Curve not closed" return [False, explaination]
def RunCommand(is_interactive): global params pitch_line = rs.GetObject(message="Select pitch line", filter=rs.filter.curve, preselect=True) if pitch_line is None: return 1 # Cancel if not rs.IsLine(pitch_line): print "Selected curve is not a line!" return 1 # Cancel rs.SelectObjects(pitch_line) m = rs.GetReal(message="Rack module", number=params["m"]) pa = rs.GetReal(message="Pressure angle", number=params["pa"], minimum=0, maximum=45) if m is None or pa is None: return 1 # Cancel params["m"] = m params["pa"] = pa pitch_line_center = rs.CurveMidPoint(pitch_line) pitch_line_start = rs.CurveStartPoint(pitch_line) pitch_line_end = rs.CurveEndPoint(pitch_line) angle, reflex_angle = rs.Angle2(line1=((0, 0, 0), (1, 0, 0)), line2=(pitch_line_start, pitch_line_end)) x_vector = rs.VectorCreate(pitch_line_end, pitch_line_start) y_vector = rs.VectorRotate(x_vector, 90.0, [0, 0, 1]) cplane = rs.PlaneFromFrame(origin=pitch_line_center, x_axis=x_vector, y_axis=y_vector) xform = rs.XformChangeBasis(cplane, rs.WorldXYPlane()) rs.EnableRedraw(False) old_plane = rs.ViewCPlane(plane=rs.WorldXYPlane()) rack = draw_rack(length=rs.CurveLength(pitch_line), module=params["m"], pressure_angle=params["pa"]) rs.ViewCPlane(plane=old_plane) rs.TransformObjects(rack, xform) rs.EnableRedraw(True) rs.UnselectAllObjects() rs.SelectObjects(rack) return 0 # Success
def main(): diameter = rs.GetReal("enter cutter diameter", number=0.25) diameter = diameter*1.1 # first, select objects in three orthogonal planes obj = rs.GetObject("select object", filter=4) # curve curve_points = rs.CurvePoints(obj)[:-1] circles = [] while True: point = rs.GetPoint("select point") if point is None: break try: idx = curve_points.index(point) print "clicked index", idx except ValueError: print "invalid point" continue points = [ curve_points[(idx+1)%len(curve_points)], curve_points[idx ], curve_points[(idx-1)%len(curve_points)], ] print points angle = rs.Angle2( (points[1], points[0]), (points[1], points[2]), ) angle = angle[0] point = rs.VectorAdd( points[1], rs.VectorRotate(0.5*diameter*rs.VectorUnitize(rs.VectorSubtract(points[2], points[1])), angle/2, (0,0,1)) ) #p0 = (point.X, point.Y, point.Z + 1000) #p1 = (point.X, point.Y, point.Z - 1000) circle = rs.AddCircle(point, diameter/2.0) circles.append(circle) #extrusion = rs.ExtrudeCurveStraight(circle, p0, p1) for circle in circles: before_obj = obj obj = rs.CurveBooleanDifference(obj, circle) rs.DeleteObject(before_obj) rs.DeleteObjects(circles)
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 get_internal_angles(pts): """get the internal angles of a set of pts representing a counter-clockwise polyline.""" angle_list = [] for i in xrange(0, len(pts)): start = (i - 1) % len(pts) mid = (i) % len(pts) end = (i + 1) % len(pts) line_a = [pts[mid], pts[end]] line_b = [pts[mid], pts[start]] angle = rs.Angle2(line_a, line_b) #returns [smaller,larger] angles. angle_index = 1 vect_a = rs.VectorCreate(line_a[0], line_a[1]) vect_b = rs.VectorCreate(line_b[0], line_b[1]) if wut.xprod(vect_a, vect_b) > 0: angle_index = 0 angle_list.append(angle[angle_index]) return angle_list
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)
def _TransformAirfoil(self, C): # Internal function. Given a normal airfoil, unit chord, nose in origin, # chord along x axis, applies scaling, rotations, positioning and smoothing # Smoothing for i in range(1, self.SmoothingIterations + 1): rs.FairCurve(C) # Find the actual leading edge point - the airfoil may have stretched as # as a result of the smoothing or it may have been incorrectly defined # through a series of coordinates RefLine = rs.AddLine((-100, 0, -100), (-100, 0, 100)) ClosestPoints = rs.CurveClosestObject(RefLine, C) P = rs.AddPoint(ClosestPoints[1]) MoveVec = rs.VectorCreate((0, 0, 0), P) rs.MoveObject(C, MoveVec) # Garbage collection rs.DeleteObjects((RefLine, P)) # Now find the trailing edge points PUpper = rs.CurveStartPoint(C) PLower = rs.CurveEndPoint(C) TECentre = ((PUpper[0] + PLower[0]) / 2, (PUpper[1] + PLower[1]) / 2, (PUpper[2] + PLower[2]) / 2) if PUpper[2] < PLower[2]: print "Warning: the upper and lower surface intersect at the TE." TECentrePoint = rs.AddPoint(TECentre) AxisOfRotation = rs.VectorCreate((0, 0, 0), (0, 1, 0)) L1 = rs.AddLine((0, 0, 0), (1, 0, 0)) L2 = rs.AddLine((0, 0, 0), TECentrePoint) AngRot = rs.Angle2(L1, L2) # The angle returned by Angle2 is always positive so: if TECentre[2] < 0: rs.RotateObject(C, (0, 0, 0), AngRot[0], AxisOfRotation) else: rs.RotateObject(C, (0, 0, 0), -AngRot[0], AxisOfRotation) # Garbage collection rs.DeleteObjects((TECentrePoint, L1, L2)) # Find the trailing edge point again after rotating it onto the x axis PUpper = rs.CurveStartPoint(C) PLower = rs.CurveEndPoint(C) TECentre = [(PUpper[0] + PLower[0]) / 2, (PUpper[1] + PLower[1]) / 2, (PUpper[2] + PLower[2]) / 2] ActualChordLength = TECentre[0] # Scale the airfoil to unit chord #rs.ScaleObject(C, (0,0,0), (1/ActualChordLength, 1, 1/ActualChordLength)) act.ScaleObjectWorld000( C, (1 / ActualChordLength, 1, 1 / ActualChordLength)) # Now we can assume that airfoil is normalised to the unit chord, with # its leading edge in the origin, trailing edge in (1,0,0) Chrd = rs.AddLine((0, 0, 0), (1, 0, 0)) # Scaling ScaleFact = (self.ChordLength, self.ChordLength, self.ChordLength) # same as rs.ScaleObject(C, (0,0,0), ScaleFact) act.ScaleObjectWorld000(C, ScaleFact) # same as rs.ScaleObject(Chrd, (0,0,0), ScaleFact) act.ScaleObjectWorld000(Chrd, ScaleFact) # Twist rs.RotateObject(C, (0, 0, 0), self.Twist, rs.VectorCreate((0, 0, 0), (0, 1, 0))) rs.RotateObject(Chrd, (0, 0, 0), self.Twist, rs.VectorCreate((0, 0, 0), (0, 1, 0))) # Dihedral rs.RotateObject(C, (0, 0, 0), -self.Rotation, rs.VectorCreate((0, 0, 0), (1, 0, 0))) rs.RotateObject(Chrd, (0, 0, 0), -self.Rotation, rs.VectorCreate((0, 0, 0), (1, 0, 0))) # 3d positioning MoveVec = rs.VectorCreate(self.LeadingEdgePoint, (0, 0, 0)) rs.MoveObject(C, MoveVec) rs.MoveObject(Chrd, MoveVec) return C, Chrd
sumAngle = 0 angles = [] angle180s = [] sp = [] # 与i点相连的顶点,有序,list[point3d] ihe = pmesh.Vertices.GetHalfedges(i) # 以i点为起点的半边的编号 for j in ihe: ih = pmesh.Halfedges[pmesh.Halfedges[j].NextHalfedge].StartVertex pp = pkg.RhinoSupport.ToPoint3d(pmesh.Vertices[ih]) sp.append(pp) valence = pmesh.Vertices.GetValence(i) valences.append(valence) if p0 in nakedVertices: bNakedPoints.append(True) nakedPoints.append(p0) for j in range(len(sp) - 1): angle = rs.Angle2((p0, sp[j]), (p0, sp[j + 1])) angles.append(angle[0]) sumAngle = angle[0] + sumAngle angleEqualIndexes0.append(-1) adjustedValence = valence + AddNakedValences(sumAngle, VOT) angle180Indexes0.append(-2) else: bNakedPoints.append(False) interiorPoints.append(p0) adjustedValence = valence for j in range(len(sp)): if j != (len(sp) - 1): angle = rs.Angle2((p0, sp[j]), (p0, sp[j + 1])) else: angle = rs.Angle2((p0, sp[len(sp) - 1]), (p0, sp[0])) angles.append(angle[0])
rs.AddLine(point,intersection[0]) lines4.append(dividedPoints[0]) x = rs.LineLineIntersection(lines1[0],lines2[7]) lines4.append(rs.AddPoint(x[0])) z = rs.LineLineIntersection(lines3[0],lines2[7]) lines4.append(rs.AddPoint(z[0])) y = rs.LineLineIntersection(lines1[7], lines2[9]) lines4.append(rs.AddPoint(y[0])) lines4.append(dividedPoints[0]) polylines = [] polyline = rs.AddCurve(lines4, 1) polylines.append(polyline) angle = rs.Angle2(lines3[0], lines3[1]) rotation = angle[0] #rs.ObjectColor(innerCircle, color=(255,0,0)) #rs.ObjectColor(outterCircle, color=(255,0,0)) for t in range(len(dividedPoints)): polylines.append(rs.RotateObject(polyline, point, rotation*t, axis=None, copy=True)) rs.ObjectColor(polyline, color=(255,0,0)) white = rs.CreateColor(255,255,255) translation = rs.VectorCreate(dividedPoints[1], dividedPointsInner[6]) rs.CopyObjects(polylines, translation) translation = rs.VectorCreate(dividedPoints[4], dividedPointsInner[9]) rs.CopyObjects(polylines, translation)