import static uk.co.nickthecoder.foocad.extras.v1.Extras.* class LayeringPod : Model { @Custom( about="Width x Height of the pod" ) var size = Vector2( 50, 60 ) @Custom var thickness = 2.0 @Custom( about="Diameter of the hexagonal gromets" ) var grometSize = Vector2( 30, 4 ) @Custom( about="Branch diameter for piece 'gromet'" ) var branchD = 10 @Custom( about="Size of 'clip' is bigger than the dovetails") var slack = 0.5 fun shape(closed : boolean) = PolygonBuilder().apply { val neck = 5 moveTo(0,0) lineBy( size.x / 2, 0 ) lineBy( 0, size.y ) lineBy( -size.x / 4, 0 ) lineBy( 0, neck ) lineBy( size.x / 4, size.x / 4 ) if( closed ) { lineTo( 0, size.y + size.x / 4 + neck ) } } fun washerSlot() : Shape3d { val in = grometSize.x + 1 val box = Circle( grometSize.x/2 + thickness + 1 ) .sides(6) .extrude( grometSize.y + 1 + thickness * 2 ) .center() - Circle( grometSize.x/2 + 1 ) .sides(6) .extrude( grometSize.y + 1 ) .center() return box.rotateX(90).backTo(thickness) intersection Cube( 1000 ).centerXY() } val dove = 4 val margin = dove + thickness * 2 fun dovetailProfile( round : boolean ) : Shape2d { val radius = if (round) 1 else 0 return Square( dove/2 ,dove ) .roundCorner(3,radius) .rightTo(0) + Triangle( dove/2, dove ) .roundCorner(1, radius) .mirrorY() .frontTo(0) } @Piece fun half() : Shape3d { val shape : Shape2d = shape(true).build().mirrorX().also() val base = (Square(shape.size.x + margin * 2, shape.size.y ).centerX() - shape) .extrude(thickness) val case = shape(false).buildPath().thickness(thickness).revolve().sides(6) .rotateX(-90).translateY(thickness/2) / Cube( 1000 ).centerXY() val hole = Circle( grometSize.x * 0.4 ) .sides(6) .extrude(30) .center() .rotateX(90) val dovetail = dovetailProfile( true ).extrude( base.size.y ) .rotateX(90) .frontTo( 0 ) .leftTo( -base.right ) return washerSlot() + base + case - hole + dovetail.mirrorX().also() } // Two halves joined by a thin (bendable?) hinge. @Piece fun pair() : Shape3d { val one = half().leftTo(slack).mirrorX().also() return one.mirrorX() + Cube( slack *3, one.back, 0.2 ).centerX().color("Green") } @Piece fun clip() : Shape3d { val in = dovetailProfile( false ).offset(slack).mirrorY().also().rotate(90) val out = Square( in.size.x + thickness*4, in.size.y + thickness*2 ).center() val slot = Square( thickness * 2 + slack*2, 10 ).centerX() val tube = (out - in - slot).extrude( thickness + size.y + size.x / 4 + 5 ) val end = out.extrude(thickness) return ( end + tube.bottomTo(thickness)) .rotateX(-90) .bottomTo(0) .color( "lightBlue" ) } fun gromet( branchD : double ) : Shape3d { val outside = Circle( grometSize.x/2 ).sides(6) .roundAllCorners(4) val torus = (outside - Circle( branchD/2 )) .extrude( grometSize.y ) val slot = Cube( grometSize.x*2, 1, 100).center().leftTo( 4-grometSize.x / 2 ) val flap = outside.extrude(0.4) - slot.rotateZ(90) return torus + flap - slot } @Piece fun gromet() : Shape3d { return gromet( branchD ) } @Piece fun grometSelection() : Shape3d { val mid = gromet( 12 ) val small = gromet( 8 ).rightTo( mid.left - 1 ) val large = gromet( 16 ).leftTo( mid.right + 1 ) return small + mid + large } @Piece fun all() : Shape3d { val main = pair() val clips = clip().leftTo(1).mirrorX().also() return main + clips.leftTo(main.right + 1 ) } override fun build() : Shape3d { val half : Shape3d = half() val grom = gromet() .color("white") .rotateX(90).frontTo(half.front + thickness + 0.5 ) val clip : Shape3d = clip() .rotateY(90) .mirrorY() .rightTo( half.right + thickness + slack) .frontTo(0) return half + //(half.rotateY(180).translateZ(-0.1).color("green")) + grom + clip } }