import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* class Layering : Model { // The length of the cylinder @Custom var length = 50 // The diameter of the cylinder @Custom var diameter = 30 // The thickness of the walls @Custom var thickness = 1.2 // The width of the gap (must be bigger than the diameter of the branch) @Custom var gap = 12 // The diameter of the hole in the gromet. Should be about the size of the branch. // If you use the piece name "gromets", it will produce a range of sizes, and ignore this value. @Custom var gromet = 5 @Custom var slack = 0.3 fun profile() = Circle( diameter/2 )//.sides(8).rotate(45/2) fun cylinder() : Shape3d { val profile : Shape2d = profile() val thin = profile - profile.offset(-thickness) val cylinder = thin.extrude(length) // The small holes ensure that water doesn't pool in the bottom. val hole = Circle( gap/2 ) val holes = Circle( thickness ).translateY(diameter/2-thickness*3).repeatAround( 9 ) val bottom = (profile - hole - holes).extrude(thickness) val slot = Cube( diameter, gap, length + 2 ).centerY().translateZ(-1) return (cylinder + bottom).color("Orange") - slot } @Piece fun join() : Shape3d { val profile : Shape2d = profile() val fat = (profile.offset(thickness+slack) - profile.offset(-thickness*2-slack)) / Square(diameter, gap).centerY().translateX(gap/2) val overlap = thickness*4 val thin1 = (profile.offset(thickness+slack) - profile.offset(+slack)) / Square(diameter, gap+overlap).centerY().translateX(gap/2) val thin2 = (profile.offset(-thickness-slack) - profile.offset(-thickness*2-slack*2)) / Square(diameter, gap+overlap).centerY().translateX(gap/2) val hole = Circle( gap/2 ) val slot = Square( diameter, gap ).centerY().mirrorX() val bottom = (profile.offset(-thickness-slack) - hole - slot).extrude(thickness) val foo = (fat + thin1 + thin2).extrude(length-thickness*4-slack*2) return (foo+bottom).color("yellow") } @Piece fun top() : Shape3d { val profile : Shape2d = profile() val hole = Circle( gap/2) + Square( diameter, gap ).centerY() val outerRing = (profile.offset(thickness+slack) - profile.offset(slack) - hole) .extrude(thickness*4) val innerRing = (profile.offset(-thickness-slack) - profile.offset(-thickness*2-slack) - hole) .extrude(thickness*4) val base1 = (profile.offset(thickness+slack) - profile.offset(-thickness-slack) - hole) .extrude(thickness).translateZ(thickness*3) val base2 = (profile.offset(-thickness-slack) - hole) .extrude(thickness) return (innerRing + outerRing+ base1 + base2).color("Green") } @Piece fun gromet( size : double ) : Shape3d { val envelope = Circle( diameter/2 - thickness*3 - slack ) val profile = ( Square(diameter,gap-slack*2).centerY() / envelope ) + Circle( gap/2 - slack ) - Square( diameter,2).centerY() - Circle( size/2 ) val bigger = ( Square(diameter,gap+thickness*2).centerY() / envelope ) + Circle( gap/2 +thickness ) - Square( diameter,2).centerY() - Circle( size/2 ) return profile.extrude( 6 ) + bigger.extrude( 3 ) } @Piece fun gromets() : Shape3d { val dy = gap + thickness*3 return gromet(4) + gromet(5).translateY(dy) + gromet(6).translateY(dy*2) + gromet(7).translateY(dy*3) + gromet(8).translateY(dy*4) } @Piece fun all() : Shape3d { return cylinder() + join().translateX(-diameter-thickness*2) + top().translateX(diameter+thickness*2) } override fun build() : Shape3d { return cylinder()+ join().mirrorZ().bottomTo(thickness+slack) + top().topTo( length + thickness ) + gromet(gromet).topTo( thickness -slack ) } }