#!/usr/bin/env python #Sam Calisch, calisch@mit.edu, 2012 #paddle geom generation from parameters from __future__ import division import rhinoscriptsyntax as rs from math import * from convenience import * def SetupLayers(): rs.AddLayer ("cross", green) rs.AddLayer ("outline", blue) #compute line-line intersection def Intersection2D(p0,v0,p1,v1): if v0[1] - v0[0]*v1[1]/v1[0] == 0: return -1 #no intersection elif v1[0] != 0: s = (p1[1]-p0[1] + v1[1]/v1[0]*(p0[0]-p1[0]))/(v0[1]-v0[0]*v1[1]/v1[0]) return ss(p0,sm(s,v0)) else: t = (p1[0]-p0[0] + v1[0]/v1[1]*(p0[1]-p1[1]))/(v0[0]-v0[1]*v1[0]/v1[1]) return ss(p0,sm(t,v0)) #def SimpleNurbs(pts): # degree = 2 # knots = range(len(pts)-1) # knots.insert(0,0) # knots.append(len(pts)-2) # return rs.AddNurbsCurve(pts,knots,degree) def DrawOutline(length, width, shaft_diam, collar_length, assym=0): objs = [] assym = pi*assym/180. p0 = [0,shaft_diam/2,0] p1 = [length/2,width/2,0] p3 = [length,0,0] p2 = Intersection2D(p1,[1,0,0],p3,[sin(assym),cos(assym),0]) p5 = [length/2,-width/2,0] p4 = Intersection2D(p5,[1,0,0],p3,[-sin(assym),-cos(assym),0]) p6 = [0,-shaft_diam/2,0] pts = [p0,ss(p0,[.5*collar_length,0,0]),ss(p0,[collar_length,0,0]),ss(p0,[1.5*collar_length,0,0]),p1,p2,p4,p5,ss(p6,[1.5*collar_length,0,0]),ss(p6,[collar_length,0,0]),ss(p6,[.5*collar_length,0,0]),p6] pl = rs.AddPolyline(pts) cl = rs.CurveLength(pl) rs.DeleteObject(pl) degree = 2 knots = range(len(pts)-1) knots.append(len(pts)-2) knots.insert(0,0) knots = [cl*i/len(pts) for i in knots] n = rs.AddNurbsCurve(pts,knots,degree) return n #dir is 1 for right, -1 for left def add_edge(p1,p2,dir=1): d = smag(sd(p1,p2)) p3 = ss( sm(.5, ss(p1,p2) ) , [0,.5*dir*d,0]) return rs.AddArc3Pt(p1,p2,p3) def DrawCrossSections(length, width, shaft_diam, outline, collar_length,dihedral, res=10): dihedral = dihedral*pi/180. lat_taper = 5 #linear fade within width/2 of end thickness = 3 taper_end = .75*(length-collar_length) + collar_length sections = [] for i in range(res): objs = [] x = i*length/res l = rs.AddLine([x,-width,0],[x,width,0]) #p = rs.PlaneFromNormal([x,0,0],[1,0,0]) result = rs.CurveCurveIntersection(outline,l) rs.DeleteObject(l) p0 = result[0][1] p0 = [p0.X,p0.Y,p0.Z] p1 = result[1][1] p1 = [p1.X,p1.Y,p1.Z] collar_ratio = min(1,(x-collar_length)/(.5*collar_length)) if (dihedral != 0): p0 = [p0[0],p0[1],-p0[1]*tan(dihedral)*collar_ratio] p1 = [p1[0],p1[1],p1[1]*tan(dihedral)*collar_ratio] p6 = ss(p0,[0,0,-thickness*collar_ratio]) p7 = ss(p1,[0,0,-thickness*collar_ratio]) r = .5*shaft_diam*(taper_end-(x-collar_length))/taper_end if collar_length < x < taper_end and r > lat_taper: ratio = (x-collar_length)/(taper_end-collar_length) p2 = [x,r-lat_taper*ratio,lat_taper*collar_ratio] p3 = [x,-r+lat_taper*ratio,lat_taper*collar_ratio] p4 = [x,r-lat_taper*ratio,-lat_taper*collar_ratio-thickness*collar_ratio] p5 = [x,-r+lat_taper*ratio,-lat_taper*collar_ratio-thickness*collar_ratio] objs.append(rs.AddArc3Pt(p2,p3,[x,0,r])) objs.append(rs.AddLine(p0,p2)) objs.append(rs.AddLine(p1,p3)) if -r < -lat_taper-thickness: objs.append(rs.AddArc3Pt(p4,p5,[x,0,-r])) else: objs.append(rs.AddLine(p4,p5)) objs.append(rs.AddLine(p6,p4)) objs.append(rs.AddLine(p7,p5)) #objs.append(rs.AddLine(p0,p6)) objs.append(add_edge(p0,p6,.8)) # objs.append(rs.AddLine(p1,p7)) objs.append(add_edge(p1,p7,-.8)) elif x < collar_length: objs.append(rs.AddArc3Pt([x,shaft_diam/2.,0],[x,-shaft_diam/2.,0],[x,0,shaft_diam/2.])) objs.append(rs.AddArc3Pt([x,shaft_diam/2.,0],[x,-shaft_diam/2.,0],[x,0,-shaft_diam/2.])) else: lt = lat_taper if x > length - width/2.: lt = lat_taper*(length-x)/(width/2.) objs.append(rs.AddLine(p0,[x,0,lt])) objs.append(rs.AddLine(p1,[x,0,lt])) objs.append(rs.AddLine(p6,[x,0,-lt-thickness])) objs.append(rs.AddLine(p7,[x,0,-lt-thickness])) # objs.append(rs.AddLine(p0,p6)) objs.append(add_edge(p0,p6,.8)) objs.append(add_edge(p1,p7,-.8)) # objs.append(rs.AddLine(p1,p7)) l = rs.JoinCurves(objs,delete_input=True) assert(len(l)==1) #test orientation n = rs.CurveNormal(l[0]) if( n[0] < 0): rs.ReverseCurve(l[0]) sections.append(l[0]) i=i+1 while True: objs = [] x = i*length/res l = rs.AddLine([x,-width,0],[x,width,0]); result = rs.CurveCurveIntersection(outline,l); rs.DeleteObject(l); if (not result): break # print 'found section at %d. '%i, result p0 = result[0][1] p0 = [p0.X,p0.Y,p0.Z] p1 = result[1][1] p1 = [p1.X,p1.Y,p1.Z] if (dihedral != 0): p0 = [p0[0],p0[1],-p0[1]*tan(dihedral)] p1 = [p1[0],p1[1],-p1[1]*tan(dihedral)] objs.append(rs.AddLine(p0,p1)) objs.append(rs.AddLine(ss(p0,[0,0,-thickness]),ss(p1,[0,0,-thickness]))) objs.append(add_edge(p1,ss(p1,[0,0,-thickness]),-.8)) objs.append(add_edge(ss(p0,[0,0,-thickness]),p0,.8)) l = rs.JoinCurves(objs,delete_input=True) assert(len(l)==1) sections.append(l[0]) i = i+1 return sections #loft = rs.CapPlanarHoles(rs.AddLoftSrf(sections)) #python loft is crappy def ExportControlPoints(crvs): filter = "Text File (*.txt)|*.txt|All files (*.*)|*.*||" filename = rs.SaveFileName("Save Control Points As", filter) if not filename: return file = open( filename, 'w' ) points = [] for crv in crvs: points.extend(rs.CurvePoints(crv)) #print 'point size = ',len(points) #if not points: return #i=1 print 'pts size = ',len(points) for pt in points: # print "At ", i, "Current file position : ", file.tell() # i=i+1 file.write( ','.join(map(str,[pt.X,pt.Y,pt.Z]))+'\n' ) file.close() if __name__ == '__main__': SetupLayers() length = 450 #length of blade in mm width = 160 #max width of blade in mm shaft_diam = 25 #diameter of shaft in mm assym = 15 #angle of assymetry in degrees dihedral = 0. #dihedral angle in degrees collar_length = 50 #length of straight cylinder collar segment for attaching to shaft rs.CurrentLayer('outline') outline = DrawOutline(length, width, shaft_diam, collar_length, assym) rs.CurrentLayer('cross') sections = DrawCrossSections(length, width, shaft_diam, outline, collar_length, dihedral, 500) for i,s in enumerate(sections): #objs = rs.ExplodeCurves(s,delete_input=True) #reb = [] #for c in objs: #if not rs.IsLine(c): # rs.RebuildCurve(c,degree=1,point_count=50) #reb.append(c) #cycle reb by z coordinate of curve start? #sections[i] = rs.JoinCurves(reb,delete_input=True) rs.RebuildCurve(s,degree=1,point_count=1000) ExportControlPoints(sections)