def LEDHolder(LEDDia = 5.5, thick=1.5, tol = 0.5, L=15, W=20): od = LEDDia+4 DLUtils.DeleteMesh("Sphere1") DLUtils.DeleteMesh("Sphere2") DLUtils.DeleteMesh("Base") DLUtils.DrawCylinder("LEDHole",LEDDia,0,10,64) DLUtils.MoveObject("LEDHole",mathutils.Vector((0,0,4.5))) DLUtils.DrawCylinder("LEDHole2",LEDDia+1,0,6,64) DLUtils.MoveObject("LEDHole2",mathutils.Vector((0,0,-3))) DLUtils.DrawBox("Base",L,1,W) DLUtils.MoveObject("Base",mathutils.Vector([0,-od/2,0])) DLUtils.DrawSphere("Sphere1",od,16) DLUtils.MoveObject("Sphere1",mathutils.Vector([0,0,L/4])) DLUtils.DrawSphere("Sphere2",od,32) DLUtils.MoveObject("Sphere2",mathutils.Vector([0,0,-L/4])) DLUtils.ConvexHull(["Sphere1","Sphere2","Base"]) DLUtils.BooleanMesh("Convex Hull","LEDHole","DIFFERENCE",True) DLUtils.BooleanMesh("Convex Hull","LEDHole2","DIFFERENCE",True) DLUtils.DeleteMesh("Sphere1") DLUtils.DeleteMesh("Sphere2") DLUtils.DeleteMesh("Base")
def Rotor(rotorName,hubDia,rotorDia,hubHeight,hubThickness,axleDia,\ camber_root,camber_tip,camber_position,thickness,\ bladeHeight,twistAngle,rootChord,\ tipChord,clearance,centerOfTwist,nspan,\ npts,rootAngle,nRotorBlades): res = 64 #Delete any existing hubs # remove mesh Hub DLUtils.DeleteMesh(rotorName) #Generate Hub bpy.ops.mesh.primitive_cylinder_add(vertices=res,radius=hubDia/2,depth=hubHeight,location=(0,0,0)) cyl = bpy.data.objects["Cylinder"] cyl.name = rotorName cyl.data.name = rotorName bpy.ops.transform.rotate(value=math.radians(90),axis=(0.0,1.0,0.0)) #Generate all Blades for i in range(0,nRotorBlades): #Generate blade TurboMachLib.NACA4Blade("RotorBlade"+str(i),camber_root,camber_tip,camber_position,thickness, bladeHeight, twistAngle,rootChord,tipChord, centerOfTwist, nspan,npts) #Grab the mesh me = bpy.data.meshes["RotorBlade"+str(i)] #We want to rotate the blades (twist angle of the root), so generate the rotation matrix R = mathutils.Matrix.Rotation(math.radians(rootAngle),3,(0,0,1)) #Shift and rotate the verts for v in me.vertices: v.co += mathutils.Vector((0,0,hubDia/2.5)) v.co = R*v.co #Deselect all bpy.ops.object.select_all(action='DESELECT') #Grab the blade object ob = bpy.data.objects["RotorBlade"+str(i)] ob.delta_location = [hubThickness/2,0,0] DLUtils.SelectOnly("RotorBlade"+str(i)) #Remove doubles print("RemoveDoubles: RotorBlade"+str(i)) bpy.ops.object.editmode_toggle() bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() #Rotate the blade to it's proper position bpy.ops.transform.rotate(value=i*math.pi*2/nRotorBlades,axis=(1.0,0.0,0.0)) #Boolean union the blades to the hub print("Boolean: RotorBlade"+str(i)) DLUtils.BooleanMesh(rotorName,"RotorBlade"+str(i),"UNION",False) #clean up! for n in range(0,nRotorBlades): DLUtils.DeleteMesh("RotorBlade"+str(n)) axelName = "AxleHole" DLUtils.DeleteMesh(axelName) rimThickness = 1.25 rimDepth = 2 #Hollow out hub DLUtils.DrawCylinder("cutout",hubDia-hubThickness*2,0,hubHeight,res) bpy.data.objects["cutout"].delta_rotation_euler = [0,math.pi/2,0] bpy.data.objects["cutout"].delta_location = [hubThickness+(rimDepth+hubThickness),0,0] DLUtils.BooleanMesh(rotorName,"cutout","DIFFERENCE",True) DLUtils.DrawCylinder("cutout",hubDia-hubThickness*4,0,hubHeight,res) bpy.data.objects["cutout"].delta_rotation_euler = [0,math.pi/2,0] bpy.data.objects["cutout"].delta_location = [hubThickness,0,0] DLUtils.BooleanMesh(rotorName,"cutout","DIFFERENCE",True) #Generate axle hole extrusion DLUtils.DrawCylinder(axelName,axleDia+hubThickness*2,0,hubHeight-hubThickness*2,res) bpy.data.objects[axelName].delta_location = [-hubThickness*0.9,0,0] bpy.data.objects[axelName].delta_rotation_euler = [0,math.pi/2,0] DLUtils.BooleanMesh(rotorName,axelName,"UNION",True) #Generate hole for axle DLUtils.DrawCylinder(axelName,axleDia,0,hubHeight*2,res) bpy.data.objects[axelName].delta_rotation_euler = [0,math.pi/2,0] DLUtils.BooleanMesh(rotorName,axelName,"DIFFERENCE",True) #Trim Blades DLUtils.DrawCylinder("cutBlades",rotorDia-clearance*2,0,hubHeight*2,res) bpy.data.objects["cutBlades"].delta_rotation_euler = [0,math.pi/2,0] DLUtils.BooleanMesh(rotorName,"cutBlades","INTERSECT",True) #Draw inside spokes ri= (axleDia+hubThickness*2)/2 ro= hubDia/2 nSpokes=7 for i in range(0,nSpokes): DLUtils.DrawBox("spoke"+str(i),hubHeight-hubThickness*2.5,hubThickness,ro-ri) DLUtils.ShiftVerts("spoke"+str(i),mathutils.Vector((-hubThickness*0.9,0,(ri+(ro-ri)/2)*0.9))) #Rotate the spoke to it's proper position bpy.ops.transform.rotate(value=i*math.pi*2/nSpokes,axis=(1.0,0.0,0.0)) DLUtils.BooleanMesh(rotorName,"spoke"+str(i),"UNION",True) #Ream out the rim for the hub cone DLUtils.DrawCylinder("rimCut",hubDia+1,hubDia-2*rimThickness,rimDepth+1,res) bpy.data.objects["rimCut"].delta_rotation_euler = [0,math.pi/2,0] DLUtils.MoveObject("rimCut",mathutils.Vector([-(hubHeight/2-rimDepth/2),0,0])) #remove doubles to prevent errors DLUtils.SelectOnly("rimCut") bpy.ops.object.editmode_toggle() bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() DLUtils.SelectOnly(rotorName) bpy.ops.object.editmode_toggle() bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() #ream it DLUtils.BooleanMesh(rotorName,"rimCut","DIFFERENCE",True)
def Stator(ductID=64,ductThickness=2,ductLength=60,res=64,\ mountFaceXLoc=20,mountCanID=28.8,mountCanLength=20,\ nBlades=1,rootAngle=0,camberRoot=6,camberTip=6,camber_position=50,\ bladeThickness=6,bladeHeight=50,twistAngle=5,rootChord=10,\ tipChord=10,centerOfTwist=[50,0],nspan=5,npts=25,screwHoleDia=2.6,screwHoleSpreadDia=16,shaftHoleDia=9): #Names we are going to use, we are going to clean up first ductName = "duct" mountName= "can" bladeName= "blade" DLUtils.DeleteMesh(ductName) DLUtils.DeleteMesh(mountName) DLUtils.DeleteMesh(mountName+"Inside") for i in range(0,nBlades): DLUtils.DeleteMesh(bladeName+str(i)) #Draw duct DLUtils.DrawCylinder(ductName,ductID+ductThickness*2,ductID,ductLength,res) DLUtils.SelectOnly(ductName) bpy.ops.transform.rotate(value=math.radians(90),axis=(0.0,1.0,0.0)) #Draw duct tabs tabLength = 36.8 tabWidth = 11 tabHeight = 1.5 DLUtils.DrawBox("tab1", tabLength,tabWidth,tabHeight) DLUtils.DrawBox("tab2", tabLength,tabWidth,tabHeight) DLUtils.MoveObject("tab1",mathutils.Vector([0,ductID/2+tabWidth/2 + ductThickness/2,0])) DLUtils.MoveObject("tab2",mathutils.Vector([0,-(ductID/2+tabWidth/2 + ductThickness/2),0])) DLUtils.BooleanMesh(ductName,"tab1","UNION",True) DLUtils.BooleanMesh(ductName,"tab2","UNION",True) #Draw mount can DLUtils.DrawCylinder(mountName,mountCanID+ductThickness*2,0,mountCanLength,res) DLUtils.DrawCylinder(mountName+"Inside",mountCanID,0,mountCanLength,res) bpy.data.objects[mountName+"Inside"].delta_location = [0,0,ductThickness] #Cut out the can interior DLUtils.BooleanMesh(mountName,mountName+"Inside","DIFFERENCE",True) #Cut out mount and shaft holes DLUtils.DrawCylinder("shaftHole",shaftHoleDia,0,mountCanLength*2,res) bpy.data.objects["shaftHole"].delta_location = [0,0,0] DLUtils.BooleanMesh(mountName,"shaftHole","DIFFERENCE",True) #ewHoleDia=2.5,screwHoleSpreadDia=16,shaftHoleDia=8): for i in range(0,4): DLUtils.DrawCylinder("screwHole",screwHoleDia,0,mountCanLength*2,res) bpy.data.objects["screwHole"].delta_location = [screwHoleSpreadDia/2*math.cos(i*math.pi*2/4),screwHoleSpreadDia/2*math.sin(i*math.pi*2/4),0] DLUtils.BooleanMesh(mountName,"screwHole","DIFFERENCE",True) #Rotate the mount horizontally DLUtils.SelectOnly(mountName) bpy.ops.transform.rotate(value=math.radians(90),axis=(0.0,1.0,0.0)) #Add box to cut out wire hole DLUtils.DrawBox("wireBox", 15,10,15) bpy.data.objects["wireBox"].delta_location = [mountCanLength/2-2,-mountCanID/2,0] #DLUtils.MoveObject("wireBox",mathutils.Vector([mountCanLength-7,-mountCanID/2,0])) DLUtils.BooleanMesh(mountName,"wireBox","DIFFERENCE",True) for i in range(0,nBlades): #Generate blade TurboMachLib.NACA4Blade(bladeName+str(i),camberRoot, camberTip,camber_position,bladeThickness, bladeHeight, twistAngle,rootChord,tipChord, centerOfTwist, nspan,npts) #Grab the mesh me = bpy.data.meshes[bladeName+str(i)] #We want to rotate the blades (twist angle of the root), so generate the rotation matrix R = mathutils.Matrix.Rotation(math.radians(rootAngle),3,(0,0,1)) #Shift and rotate the verts for v in me.vertices: v.co += mathutils.Vector((0,0,mountCanID/2)) v.co = R*v.co #Deselect all bpy.ops.object.select_all(action='DESELECT') #Grab the blade object ob = bpy.data.objects[bladeName+str(i)] ob.delta_location = [ductThickness/2,0,0] #ensure it is selected ob.select = True #Remove doubles print("RemoveDoubles: "+bladeName+str(i)) bpy.ops.object.editmode_toggle() bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() #Rotate the blade to it's proper position bpy.ops.transform.rotate(value=i*math.pi*2/nBlades,axis=(1.0,0.0,0.0)) #Boolean union the blades to the hub print("Boolean: blade"+str(i)) #DLUtils.BooleanMesh(ductName,bladeName+str(i),"UNION",False) #Add inside blade cut DLUtils.DrawCylinder("bladeCut",mountCanID+ductThickness,0,mountCanLength,res) DLUtils.SelectOnly("bladeCut") bpy.ops.transform.rotate(value=math.radians(90),axis=(0.0,1.0,0.0)) for i in range(0,nBlades): DLUtils.BooleanMesh(bladeName+str(i),"bladeCut","DIFFERENCE",False) DLUtils.BooleanMesh(mountName,bladeName+str(i),"UNION",True) #Delete "BladeCut" DLUtils.DeleteMesh("bladeCut") #Add outside blade Cut DLUtils.DrawCylinder("bladeCut",ductID+ductThickness,0,ductLength,res) DLUtils.SelectOnly("bladeCut") bpy.ops.transform.rotate(value=math.radians(90),axis=(0.0,1.0,0.0)) #cut the outside of the blades DLUtils.BooleanMesh(mountName,"bladeCut","INTERSECT",True) #Move the can to the mountFaceXLoc bpy.data.objects[mountName].delta_location = [mountCanLength/2-ductLength/2+mountFaceXLoc,0,0] #Union the can and the duct DLUtils.BooleanMesh(ductName,mountName,"UNION",True) LEDHolder()
def Propeller(propName,propDia,pitch,\ hubHeight,hubDia,axleDia,\ PropellerProps,\ bladeTransition,nspan,npts,nBlades): p = PropellerProps res = 64 #used to define cylinder resolution. #initialising arrays we'll need. verts = [] tmpVerts = [] tmpVert = [0, 0, 0] faces = [] origin = (0, 0, 0) centerOfTwist = [0, 0] p.rootSlope *= math.pi / 180 p.transitionSlope *= math.pi / 180 p.tipSlope *= math.pi / 180 p.rootSkewSlope *= math.pi / 180 p.transitionSkewSlope *= math.pi / 180 p.tipSkewSlope *= math.pi / 180 #An array of the chord lengths at each span point chordArray = [] #An array of the NACA4 digits at each span point. NACAArray = [] #An array that holds the position along the blade span of the airfoil cross-sections sPos = [] #An array that holds the amount of skew of each airfoil cross-section skew = [] #Blade root will be at center of rotation. bladeHeight = propDia / 2 bladeLen = bladeHeight - bladeTransition dSpan = bladeHeight / nspan lastI = 0 for i in range(0, nspan + 1): span = i * dSpan if (span < bladeTransition): #Using cubic spline interpolation. t = span / bladeTransition tm1 = 1 - t #root to transition point interpolation y1 = p.rootChord y2 = p.rootChord + math.sin(p.rootSlope) * p.rootStrength y3 = p.transitionChord - math.sin( p.transitionSlope) * p.transitionStrengthRoot y4 = p.transitionChord chord = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 chordArray.append(chord) x1 = 0 x2 = math.cos(p.rootSlope) * p.rootStrength x3 = (bladeTransition - math.cos(p.transitionSlope) * p.transitionStrengthRoot) x4 = bladeTransition x = pow(tm1, 3) * x1 + 3 * pow(tm1, 2) * t * x2 + 3 * tm1 * pow( t, 2) * x3 + pow(t, 3) * x4 sPos.append(x) y1 = p.rootThick y2 = p.rootThick + math.sin(p.rootThickSlope) * p.rootThickStrength y3 = p.transitionThick - math.sin( p.transitionThickSlope) * p.transitionThickStrengthRoot y4 = p.transitionThick thickPt = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 print(thickPt) NACAArray.append([ 5, 3, int(thickPt * 10), int(thickPt * 100 - int(thickPt * 10) * 10) ]) y1 = p.rootSkew y2 = p.rootSkew + math.sin(p.rootSkewSlope) * p.rootSkewStrength y3 = p.transitionSkew - math.sin( p.transitionSkewSlope) * p.transitionSkewStrengthRoot y4 = p.transitionSkew skewPt = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 skew.append(skewPt) else: #Using cubic spline interpolation. t = (span - bladeTransition) / bladeLen tm1 = 1 - t y1 = p.transitionChord y2 = p.transitionChord + math.sin( p.transitionSlope) * p.transitionStrengthTip y3 = p.tipChord - math.sin(p.tipSlope) * p.tipStrength y4 = p.tipChord chord = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 chordArray.append(chord) x1 = 0 x2 = math.cos(p.transitionSlope) * p.transitionStrengthTip x3 = (bladeLen - math.cos(p.tipSlope) * p.tipStrength) x4 = bladeLen x = pow(tm1, 3) * x1 + 3 * pow(tm1, 2) * t * x2 + 3 * tm1 * pow( t, 2) * x3 + pow(t, 3) * x4 sPos.append(bladeTransition + x) y1 = p.transitionThick y2 = p.transitionThick + math.sin( p.rootThickSlope) * p.rootThickStrength y3 = p.tipThick - math.sin( p.transitionThickSlope) * p.transitionThickStrengthTip y4 = p.tipThick thickPt = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 NACAArray.append([ 5, 3, int(thickPt * 10), int(thickPt * 100 - int(thickPt * 10) * 10) ]) y1 = p.transitionSkew y2 = p.transitionSkew + math.sin( p.transitionSkewSlope) * p.transitionSkewStrengthTip y3 = p.tipSkew - math.sin(p.tipSkewSlope) * p.tipSkewStrength y4 = p.tipSkew skewPt = pow(tm1, 3) * y1 + 3 * pow( tm1, 2) * t * y2 + 3 * tm1 * pow(t, 2) * y3 + pow(t, 3) * y4 skew.append(skewPt) #error check of inputs if (len(chordArray) != nspan or len(NACAArray) != nspan): print( "The size of the array of chord lengths or the array of airfoil NACA digits does not match the number of span points used to define the blade geometry." ) #Delete any existing prop geoms DLUtils.DeleteMesh(propName) #Generate Hub DLUtils.DrawCylinder("Hub", hubDia, 0, hubHeight, res) #use a 0.001m tolerance which we'll trim off. cyl = bpy.data.objects["Hub"] cyl.name = propName cyl.data.name = propName DLUtils.SelectOnly(propName) bpy.ops.transform.rotate(value=math.radians(90), axis=(0.0, 1.0, 0.0)) DLUtils.MoveObject(propName, [2.0, 0, 0]) areaArray = [] #Generate vertex coordinates with twist and scale along the span for i in range(0, nspan + 1): span = sPos[i] #i*dSpan if (span == 0): twistAngle = 0 elif (span < bladeTransition): twistAngle = math.atan( pitch / (2 * math.pi * span)) * span / bladeTransition else: twistAngle = math.atan(pitch / (2 * math.pi * span)) #get the airfoil profile vertices tmpVerts = TurboMachLib.NACA4Profile(camber=NACAArray[i][0], thickness=NACAArray[i][2] * 10 + NACAArray[i][3], camberPos=NACAArray[i][1] * 10, chord=chordArray[i], npts=npts) areaArray.append(0) centerOfTwist[0] = chordArray[i] * skew[i] #centerOfTwist[1] = raiseFoil for v in range(0, len(tmpVerts)): #shift all verts for twisting tmpVerts[v][0] -= centerOfTwist[0] tmpVerts[v][1] -= centerOfTwist[1] #Twist the airfoil vertices. First we shift them to get the desired center of rotation. tmpVert[0] = tmpVerts[v][0] * math.cos( twistAngle) - tmpVerts[v][1] * math.sin(twistAngle) tmpVert[1] = tmpVerts[v][0] * math.sin( twistAngle) + tmpVerts[v][1] * math.cos(twistAngle) #shift all verts to their proper span location in Z tmpVert[ 2] = span + 0.01 * bladeHeight #Shift blade by 1% of blade height to prevent poor boolean ops #append the vert to the master vertex list verts.append((tmpVert[0], tmpVert[1], tmpVert[2])) if (v != 0): dx = abs(verts[len(verts) - 1][0] - verts[len(verts) - 2][0]) dy = abs(verts[len(verts) - 1][1] + verts[len(verts) - 2][1]) / 2 areaArray[i] += dy * dx #Generate Polies from vertex IDs #Bottom Cap faces.append((0, 1, npts)) for i in range(1, npts - 1): faces.append((i, i + 1, npts + i)) faces.append((i, npts + i, npts + i - 1)) #Middle nPerStage = npts * 2 - 1 for j in range(0, nspan): #Top Side for i in range(0, npts - 1): faces.append((nPerStage * j + i, nPerStage * (j + 1) + i, nPerStage * (j + 1) + i + 1)) faces.append((nPerStage * j + i, nPerStage * (j + 1) + i + 1, nPerStage * j + i + 1)) #First strip for bottom side (hooks to verts from top side) faces.append( (nPerStage * j, nPerStage * (j + 1) + npts, nPerStage * (j + 1))) faces.append( (nPerStage * j, nPerStage * j + npts, nPerStage * (j + 1) + npts)) #Rest of bottom side for i in range(0, npts - 2): faces.append( (nPerStage * j + i + npts, nPerStage * (j + 1) + i + npts + 1, nPerStage * (j + 1) + i + npts)) faces.append( (nPerStage * j + i + npts, nPerStage * j + i + npts + 1, nPerStage * (j + 1) + i + npts + 1)) #Back face faces.append((nPerStage * j + npts - 1, nPerStage * (j + 1) + npts - 1, nPerStage * (j + 1) + npts * 2 - 2)) faces.append( (nPerStage * j + npts - 1, nPerStage * (j + 1) + npts * 2 - 2, nPerStage * (j) + npts * 2 - 2)) #Top Cap faces.append((nPerStage * (nspan), nPerStage * (nspan) + 1, nPerStage * (nspan) + npts)) for i in range(1, npts - 1): faces.append((nPerStage * (nspan) + i, nPerStage * (nspan) + npts + i, nPerStage * (nspan) + i + 1)) faces.append( (nPerStage * (nspan) + i, nPerStage * (nspan) + npts + i - 1, nPerStage * (nspan) + npts + i)) #Create Blender object for the blade dAngle = 360.0 / nBlades for i in range(0, nBlades): print("Draw Blade_" + str(i)) blade = DLUtils.createMesh("Blade_" + str(i), origin, verts, [], faces) DLUtils.SelectOnly("Blade_" + str(i)) bpy.ops.transform.rotate(value=math.radians(90), axis=(0.0, 0.0, 1.0)) bpy.ops.transform.rotate(value=math.radians(dAngle) * i, axis=(1.0, 0.0, 0.0)) #Union the blades to the hub for i in range(0, nBlades): print("Union: Blade_" + str(i)) DLUtils.BooleanMesh(propName, "Blade_" + str(i), "UNION", True) #trim the blades to hub height DLUtils.DrawBox("box", hubDia * 1.1, hubDia * 1.1, hubDia * 1.1) DLUtils.MoveObject("box", [propDia / 2 + hubHeight / 2 + 0.001, 0, 0]) DLUtils.BooleanMesh(propName, "box", "DIFFERENCE", True) #cut the axle hole DLUtils.DrawCylinder("hole", axleDia, 0, hubHeight * 2, res) DLUtils.SelectOnly("hole") bpy.ops.transform.rotate(value=math.radians(90), axis=(0.0, 1.0, 0.0)) DLUtils.BooleanMesh(propName, "hole", 'DIFFERENCE', True) #Cut room for the axle shive DLUtils.DrawCylinder("ShiveHole", (hubDia - axleDia) / 4 + axleDia, 0, hubHeight / 1.5, res) DLUtils.SelectOnly("ShiveHole") bpy.ops.transform.rotate(value=math.radians(90), axis=(0.0, 1.0, 0.0)) DLUtils.BooleanMesh(propName, "ShiveHole", 'DIFFERENCE', True) #DLUtils.MoveObject(propName,[2.0,0,0]) #trim the blades to the proper dia DLUtils.DrawCylinder("BladeTrim", propDia, 0, propDia, 256) DLUtils.SelectOnly("BladeTrim") bpy.ops.transform.rotate(value=math.radians(90), axis=(0.0, 1.0, 0.0)) DLUtils.BooleanMesh(propName, "BladeTrim", 'INTERSECT', True) #done! print((BladeAxialStress(sPos, areaArray, 40e6, 1300, 15000))) return