class ToothbrushHolder : Model { @Custom var insertHeight = 125 var insertWidth = 17 var insertThickness = 1 var pasteHeight = 60 var pasteR = 20 var pasteX = 20 var lipHeight = 2 var lipWidth = 5 var bracketThickness = 8 var bracketTaper = 3 val offset = 5 val slack = 0.5 var piece = "" fun bushing( size : double ) : Shape3d { val solid = Cylinder( bracketThickness, insertWidth/2 + insertThickness) + Cylinder( lipHeight, insertWidth/2 + insertThickness + lipWidth) .color("Green") val hole = Cylinder( 30, size / 2 ).center() return solid - hole } fun displayBrushInsert() : Shape3d { val solid = Sphere( insertWidth/2 + insertThickness ) + Cylinder( insertHeight, insertWidth/2 + insertThickness) + Cylinder( lipHeight, insertWidth/2 + insertThickness + lipWidth) .translateZ( insertHeight ) .color("Green") val inside = Sphere( insertWidth/2) + Cylinder( insertHeight+10, insertWidth/2 ) // The hole makes the print worse, so I prefer to drill it out manually // val drainage = Cylinder( 200, 2 ).center() // translate the inside up a little, so that the bottom is thicker // and therefore it is more likely to be well printed return solid - inside.translateZ(1) } fun pasteInsert() : Shape3d { val solid = Sphere( pasteR+insertThickness ).hull( Sphere(pasteR+insertThickness).translateX(pasteX) ).center() + Circle( pasteR+insertThickness ).hull( Circle( pasteR+insertThickness ).translateX(pasteX) ).center() .extrude( pasteHeight ) + Circle( pasteR+insertThickness + lipWidth ).hull( Circle( pasteR + insertThickness + lipWidth ).translateX(pasteX) ).center() .extrude( lipHeight ) .translateZ( pasteHeight ).color("Green") val inside = (Sphere( pasteR ).hull( Sphere(pasteR).translateX(pasteX) ).centerX()) + (Cylinder( pasteHeight+10, pasteR ).hull( Cylinder( pasteHeight+10, pasteR ).translateX(pasteX) ).centerX()) // The hole makes the print worse, so I prefer to drill it out manually // val drainage = Cylinder( 200, 2 ).translateX(pasteX/2).mirrorX().also().center() // translate the inside up a little, so that the bottom is thicker // and therefore it is more likely to be well printed return solid - inside.translateZ(1) //- drainage } fun displayBracket() : Shape3d { val brushP = Circle(insertWidth/2 + insertThickness + offset) val pasteHole = Circle( pasteR + insertThickness + slack ).hull( Circle( pasteR + insertThickness + slack ).translateX(pasteX) ).center() val profile = pasteHole.offset( offset ) + layoutBrushes( brushP.hull( brushP.translateX(40) ) ) val hole = Circle( insertWidth/2 + insertThickness + slack ) .translateX(40) val holes = layoutBrushes(hole) + pasteHole val solid = ExtrusionBuilder.drum( profile.offset(-bracketTaper), profile, bracketThickness ) val mount = Square( 38, 30 ) .roundAllCorners( 4 ) .centerX() .extrude( 10 ) .rotateX(90) .translateY( pasteR + offset + insertThickness ) .translateZ( -30 + bracketThickness ) val screwHole = ( Cylinder( 50, 2 ) + (Cylinder( 10, 2, 10 ).mirrorZ().translateZ(4)) ).rotateX(-90).translateY( pasteR + offset + insertThickness -8) .translateZ(-6) return mount + solid - holes.extrude( 100 ).centerZ() - screwHole.translateX(10).mirrorX().also() } fun layoutBrushes( shape : Shape3d ) : Shape3d { return shape .translateX(11).rotateZ(-20) .mirrorX().also() + shape .translateX(5).rotateZ(-65) .mirrorX().also() } fun layoutBrushes( shape : Shape2d ) : Shape2d { return shape .translateX(11).rotate(-20) .mirrorX().also() + shape .translateX(5).rotate(-65) .mirrorX().also() } override fun pieceNames() = listOf( "paste", "brush", "bushing", "all" ) @Piece fun bracket() = displayBracket().mirrorZ().toOriginZ() @Piece fun brushInsert() = displayBrushInsert().mirrorZ().toOriginZ() @Piece fun bushing() = bushing( 13 ) @Piece fun bushings() = bushing( 13 ) + bushing( 14 ).translateX( 30 ) + bushing( 15 ).translateY( 30 ) + bushing( 12 ).translate( 30, 30, 0 ) @Piece fun paste() = pasteInsert().mirrorZ().toOriginZ() override fun build() : Shape3d { return displayBracket().color("Blue") + pasteInsert() .translateZ(-pasteHeight + bracketThickness + lipHeight ) + layoutBrushes( displayBrushInsert().translateX(40) ) .translateZ(-insertHeight + bracketThickness + lipHeight ) } }