class BootsBottleTop : Model { @Custom var capHeight = 3 @Custom var capRadius = 30/2 @Custom var extraHeight = 37 @Custom var bottleRadius = 56/2 @Custom var thickness = 2 @Custom var chamfer = 1.5 @Custom( lines=3 ) var text = "SLOE GIN" @Custom var fontSize = 24 fun exterior() : Shape2d { return Circle(capRadius + thickness) } fun around( str : String ) :Shape3d { val text = Text( str, BOLD, fontSize).center() val drum = ExtrusionBuilder.drum( text.offset(fontSize/30), text.offset(-fontSize/50), 2 ) val result = drum.aroundCylinder( bottleRadius, true ).color("Red") return result.rotateX(90) } override fun build() : Shape3d { val smallest = Circle(capRadius) val mid = Circle( bottleRadius - thickness ) val cham = Circle( bottleRadius - chamfer ) val outside = Circle( bottleRadius ) val cap = ExtrusionBuilder().apply { forward(capHeight + extraHeight) crossSection( smallest ) // Top of cap forward( -capHeight ) crossSection() // Bottom of cap crossSection( mid ) // Interior forward( -extraHeight ) crossSection() crossSection(cham) forward(chamfer) crossSection(outside) forward(capHeight+extraHeight-chamfer+thickness) crossSection() // Top pre-chamfer forward(chamfer) crossSection(cham) // Top post chamfer }.build() val text = around(text).translateZ((capHeight+thickness+extraHeight)/2) // Flip it upside down, so that the top of the cap is on the print bed. return (cap + text).rotateX(180).toOriginZ() } }