class CallButtonHolder : Model { val hookSize = Vector2( 46, 20 ) val hookThickness = 3 val indent = 2 val shelfThickness = 2 val shelfSize = Vector2( 15,70 ) val shelfWidth1 = 29 val shelfWidth2 = 24 fun hook() : Shape3d { val radius = hookSize.x/2 - hookThickness/2 val foo = radius*0.4 val profile = PolygonBuilder().apply { circularArcBy( foo, foo, foo, false, true ) bezierBy( Vector2( 0, foo ), Vector2( 0, foo ), Vector2(-indent, radius ) ) lineBy( 0, radius*0.1 ) circularArcBy( radius *2, 0, radius, true, false ) bezierBy( Vector2( 0,-foo ), Vector2( 0,-foo ), Vector2(-indent, -radius ) ) circularArcBy( foo,-foo, foo, false, true ) }.buildPath().thickness( hookThickness ).backTo(shelfThickness).centerX() return profile.extrude( hookSize.y ) } fun shelf() : Shape3d { val main = ExtrusionBuilder().apply { crossSection( shelfCrossSection( shelfWidth1, shelfThickness ) ) forward( shelfSize.y ) crossSection( shelfCrossSection( shelfWidth2, shelfThickness ) ) }.build() val end = shelfCrossSection(shelfWidth1 - 4*2, 4) .extrude( shelfThickness ) return main + end } fun shelfCrossSection( width : double, thickness : double ) : Shape2d { return Square( width + thickness * 2, shelfSize.x ).centerX() - Square( width, shelfSize.x + 0.1 ).centerX().translateY(thickness ) } @Slice(brimWidth=5, perimeters=6 ) override fun build() = hook() + shelf() + Cube( 28, 23, 77 ).centerX().previewOnly() }