Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env -S mg run
- import "mg/face"
- import "mg/math"
- import "mg/prim"
- import "mg/topology"
- import "mg/trans"
- import "mg/types"
- import "mg/util"
- threshold := 0.00001
- func deskFan(smoothness=1.0) {
- # Base
- baseCols := types.Int(16.0*smoothness)
- baseMaxRows := types.Int(32.0*smoothness)
- baseRadius := 0.5
- baseRadiusThreshold := baseRadius / (smoothness*15.0)
- baseTopRadius := 0.075
- baseHeight := 0.7
- base := trans.Scale([baseRadius, baseRadius], prim.Ngon(baseCols))
- prevRadius := baseRadius
- prevRing := base
- baseRad := func() {
- return func(i=0) {
- i++
- curve := (types.Float(baseMaxRows+1)/(types.Float(i)/smoothness+1.0)-1.0)/types.Float(baseMaxRows+1)
- return curve*(baseRadius-baseTopRadius)+baseTopRadius
- }
- }()
- for i := range baseMaxRows {
- nextRadius := baseRad(i)
- if i < baseMaxRows-1 && nextRadius ~baseRadiusThreshold:>= prevRadius {
- continue
- }
- z := baseHeight*types.Float(i+1)/types.Float(baseMaxRows)
- nextRing := trans.Translate([0, 0, z],
- trans.Scale([nextRadius, nextRadius],
- prim.Ngon(baseCols)))
- topology.Quads(prevRing, nextRing, true)
- prevRing = nextRing
- prevRadius = nextRadius
- }
- face.Face(util.Reverse(base).(base)...)
- out := face.Connected(base...)
- # Back
- backRadius := 0.25
- backFacets := types.Int(6.0*smoothness)
- backDomeScale := 0.5
- backSideLength := 0.40
- backBaseOverlap := 0.03
- back := trans.Scale([backRadius, backRadius, backRadius],
- trans.Scale([1.0, 1.0, backDomeScale],
- prim.Sphere(backFacets*2, backFacets*4)))
- backBottom := [for _, v := range back; if v.z ~threshold:<= 0.0 {v}]
- backEquator := [for _, v := range backBottom; if v.z ~threshold:>= 0.0 {v}]
- backExtend := trans.Translate([0.0, 0.0, backSideLength],
- util.DeepCopy(backEquator).(backEquator))
- topology.Quads(backEquator, backExtend, true)
- face.Face(backExtend...)
- back &= backExtend
- out &= backBottom & backExtend
- trans.Translate([0.0, 0.0, baseHeight-backBaseOverlap],
- trans.Rotate([0.0, 90.0, 0.0],
- trans.Translate([-backRadius, 0.0, -backSideLength/2.0],
- back)))
- backRef := [backSideLength/2.0, 0.0, baseHeight-backBaseOverlap+backRadius]
- backTop := baseHeight+backRadius*2.0-backBaseOverlap
- # Cage
- cageScale := 0.4
- cageRadius := 0.75
- cageOverlap := 0.035
- cageRibCount := 18
- cageFacets := types.Int(20.0*smoothness)
- cageRibFacets := types.Int(2.0*smoothness)
- cageRibWidth := 0.03
- cageCenter := [backRef[0]+cageRadius*cageScale-cageOverlap, 0.0, backRef[2]]
- cage := [{0, 0, 0}][:0]
- cageRibCrossSection := trans.Scale([types.Float(cageRibWidth)/2.0, types.Float(cageRibWidth)/2.0], prim.Ngon(cageRibFacets*2))
- for ribi := range cageRibCount {
- baseRib := trans.Scale([cageRadius*cageScale, cageRadius, 0.0],
- [for _, v := range prim.Ngon(cageFacets); if v.y ~threshold:>= 0.0 {v}])
- rib := topology.ExtrudeAlong(baseRib, cageRibCrossSection)
- trans.Translate(cageCenter, trans.Rotate([90.0+types.Float(ribi)*360.0/types.Float(cageRibCount), 0.0, 0.0], rib))
- cage &= rib
- }
- out &= cage
- # Blades hub
- bladesHubRadius := 0.1
- bladesHubFacets := types.Int(4.0*smoothness)
- bladesHubDomeScale := 0.75
- bladesHubSideLength := 0.15
- bladesHubOffset := 0.04
- bladesHub := trans.Scale([bladesHubRadius, bladesHubRadius, bladesHubRadius*bladesHubDomeScale],
- [for _, v := range prim.Sphere(bladesHubFacets*2, bladesHubFacets*4); if v.z ~threshold:<= 0.0 {v}])
- bladesHubEquator := [for _, v := range bladesHub; if v.z ~threshold:>= 0.0 {v}]
- bladesHubExtend := trans.Translate([0.0, 0.0, bladesHubSideLength],
- util.DeepCopy(bladesHubEquator).(bladesHubEquator))
- face.Face(bladesHubExtend...)
- topology.Quads(bladesHubEquator, bladesHubExtend, true)
- bladesHub &= bladesHubExtend
- trans.Translate(cageCenter + [bladesHubOffset+bladesHubSideLength-(bladesHubDomeScale*bladesHubRadius+bladesHubSideLength)/2.0, 0.0, 0.0],
- trans.Rotate([0.0, -90.0, 0.0],
- bladesHub))
- out &= bladesHub
- # Blades
- bladesCount := 3
- bladesAngleGap := 20.0
- bladesLength := cageRadius*0.70
- bladesRoundRadius := bladesLength/4.0
- bladesRoundFacets := types.Int(6.0*smoothness)
- bladesTwistAngle := 15.0
- blades := [{0, 0, 0}][:0]
- bladesHalfAngle := (360.0/types.Float(bladesCount)-bladesAngleGap)/2.0
- bladesRoundVert := func(k=0) {
- a := types.Float(k)*(90.0+bladesHalfAngle)/types.Float(bladesRoundFacets)-bladesHalfAngle
- return {bladesRoundRadius*math.Cos(a), bladesRoundRadius*math.Sin(a), 0.0}
- }
- for i := range bladesCount {
- vs := [for j := range bladesRoundFacets+1 {bladesRoundVert(j)}]
- vs += {(bladesLength-(1.0+math.Sin(bladesHalfAngle))*bladesRoundRadius)*math.Tan(bladesHalfAngle)-bladesRoundRadius*math.Cos(bladesHalfAngle), bladesLength-bladesRoundRadius, 0.0}
- vs &= util.Reverse(trans.Scale([-1.0, 1.0, 1.0], util.DeepCopy(vs).(vs))).(vs)
- vs &= [{0, 0, 0}]
- vs = trans.Rotate([0.0, bladesTwistAngle, 360.0*types.Float(i)/types.Float(bladesCount)], vs)
- blades &= vs
- face.Face(vs...)
- face.Face(util.Reverse(vs).(vs)...)
- }
- trans.Translate(cageCenter + [bladesHubSideLength-(bladesHubDomeScale*bladesHubRadius+bladesHubSideLength)/2.0, 0.0, 0.0],
- trans.Rotate([0.0, -90.0, 0.0],
- blades))
- out &= blades
- # Oscillate peg
- pegOffset := -0.13
- pegOverlap := 0.015
- pegLoc := [pegOffset, 0.0, backTop-pegOverlap]
- pegBaseRadius := 0.035
- pegBaseHeight := 0.03
- pegBaseFacets := types.Int(14.0*smoothness)
- pegRadius := 0.017
- pegHeight := 0.05
- pegFacets := types.Int(10.0*smoothness)
- pegTopRadius := 0.035
- pegTopHeight := 0.02
- pegTopFacets := types.Int(14.0*smoothness)
- peg := trans.Scale([pegTopRadius, pegTopRadius, pegTopHeight],
- trans.Translate([0.0, 0.0, 0.5],
- prim.Cylinder(pegTopFacets, true)))
- peg = trans.Translate([0.0, 0.0, pegHeight], peg)
- peg &= trans.Scale([pegRadius, pegRadius, pegHeight],
- trans.Translate([0.0, 0.0, 0.5],
- prim.Cylinder(pegFacets)))
- peg = trans.Translate([0.0, 0.0, pegBaseHeight], peg)
- peg &= trans.Scale([pegBaseRadius, pegBaseRadius, pegBaseHeight],
- trans.Translate([0.0, 0.0, 0.5],
- prim.Cylinder(pegBaseFacets, true)))
- peg = trans.Translate(pegLoc, peg)
- out &= peg
- # Switch
- switchBaseRadius := 0.03
- switchBaseFacets := types.Int(2.0*smoothness)
- switchDistFromBase := 0.09
- switchFulcrumRadius := 0.013
- switchFulcrumFacets := types.Int(2.0*smoothness)
- switchFulcrumOverlap := 0.008
- switchHandleRadius := 0.008
- switchHandleFacets := types.Int(2.0*smoothness)
- switchHandleLength := 0.05
- switchHandleAngle := 15.0
- switchBase := trans.Scale([switchBaseRadius, switchBaseRadius, switchBaseRadius],
- prim.Sphere(switchBaseFacets*2, switchBaseFacets*4))
- switchBase = [for _, v := range switchBase; if v.z ~threshold:>= 0.0 {v}]
- switchFulcrum := trans.Scale([switchFulcrumRadius, switchFulcrumRadius, switchFulcrumRadius],
- prim.Sphere(switchFulcrumFacets*2, switchFulcrumFacets*4))
- switchFulcrum = [for _, v := range switchFulcrum; if v.z ~threshold:>= 0.0 {v}]
- switchFulcrum = trans.Translate([0.0, 0.0, switchBaseRadius-switchFulcrumOverlap], switchFulcrum)
- switchHandle := trans.Scale([switchHandleRadius, switchHandleRadius, switchHandleRadius],
- prim.Sphere(switchHandleFacets*2, switchHandleFacets*4))
- switchHandle = [for _, v := range switchHandle; if v.z ~threshold:>= 0.0 {v}]
- switchHandleEquator := [for _, v := range switchHandle; if v.z ~threshold:<= 0.0 {v}]
- switchHandle = trans.Translate([0.0, 0.0, switchHandleLength-switchHandleRadius], switchHandle)
- switchHandlePoint := {0, 0, -(switchBaseRadius-switchFulcrumOverlap)}
- topology.BTris(switchHandlePoint, switchHandleEquator, true)
- switchHandle &= [switchHandlePoint]
- switchHandle = trans.Rotate([switchHandleAngle, 0.0, 0.0], switchHandle)
- switchHandle = trans.Translate([0.0, 0.0, switchBaseRadius-switchFulcrumOverlap], switchHandle)
- switch := switchBase & switchFulcrum & switchHandle
- switch = trans.Translate([baseRadius-switchDistFromBase, 0.0, 0.0], switch)
- out &= switch
- # Motor axle
- axleRadius := 0.017
- axleFacets := types.Int(8.0*smoothness)
- axleHeight := cageCenter[0] - backRef[0]
- axle := trans.Translate(backRef,
- trans.Rotate([0.0, 90.0, 0.0],
- trans.Scale([axleRadius, axleRadius, axleHeight],
- trans.Translate([0.0, 0.0, 0.5],
- prim.Cylinder(axleFacets)))))
- out &= axle
- return out
- }
- # Display it
- util.Display(deskFan(1.0))
- #all := [{0, 0, 0}][:0]
- #for i, s := range [1.0, 2.0, 4.0, 8.0] {
- # all &= trans.Translate([0.0, types.Float(i)*1.5, 0.0],
- # deskFan(s))
- #}
- #util.Display(all)
Advertisement
Add Comment
Please, Sign In to add comment