/** Holds a phone or remote control, clipped over a bar. In my case, the is for a hospital-style bed's remote control. */ class BedReomteClip : Model { val hookSize = Vector2( 30, 20 ) val hookThickness = 3 val indent = 1 val shelfThickness = 2 val shelfWidth = 10 val angle = 10 val hook1Length = 30 val hook2Length = 60 val moreSurface = 20 val remoteSize = Vector3( 180, 63, 18 ) fun hook(extraLength : double) : 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 ) ) lineBy( 0, -extraLength ) }.buildPath().thickness( hookThickness ).rightTo(0).frontTo(0) val hook = profile.extrude( hookSize.y ) return hook } fun moreSurface(angle : double ) : Shape3d { val moreSurface = Square( moreSurface + hookSize.y, shelfWidth ) .roundCorner(3,4) .roundCorner(0,4) .extrude( hookThickness ) .rotateY(90) .bottomTo(0) .frontTo(0) .rightTo(0) .rotateX(-angle) return moreSurface } fun chamferredSquare( x : double, y : double, round : double ) = Square( x, y ).centerX() .roundCorner(1,round) .roundCorner(0,round) @Piece @Slice(brimWidth=5, perimeters=6 ) fun shelf() : Shape3d { val y = remoteSize.y / 2 - 3 val rect = chamferredSquare( remoteSize.x + shelfThickness*2, y, 6 ) val hole = chamferredSquare( remoteSize.x - shelfWidth*2, remoteSize.y, 4) .translateY(shelfWidth ) val shelfP = rect - hole val solid = shelfP.extrude( remoteSize.z + shelfThickness * 2 ) val remove = chamferredSquare( remoteSize.x, remoteSize.y, 6 ) .translateY(shelfThickness) .extrude( remoteSize.z ) .translateZ( shelfThickness ) .color("Blue") return (solid - remove).rotateX(90) } @Piece @Slice(brimWidth=5, perimeters=6 ) fun hook1() : Shape3d { val hook = (hook( hook1Length ) + moreSurface(-angle)) return hook.mirrorX() } @Piece @Slice(brimWidth=5, perimeters=6 ) fun hook2() : Shape3d { val hook = hook( hook2Length ) + moreSurface(angle) val angled = hook - Cube( 200 ).center().backTo(0).rotateX(-angle) - Cube( 200 ).center().topTo(0) - Cube( 200, 6, 6 ).center().rotateX(45-angle) return angled } override fun build() : Shape3d { val shelf = shelf().frontTo(0).leftTo(0) val hook1 = hook1() .rotateX(90).rotateZ(-90).rotateY(angle) .translateX(remoteSize.x-10) .backTo(0) .color("Orange") val hook2 = hook2() .rotateX(90).rotateZ(90).rotateY(angle) .backTo(0) .color("Orange").darker() val remote = Square( remoteSize.x, remoteSize.y ).roundAllCorners(5).extrude( remoteSize.z ) .rotateX(90) .frontTo( shelfThickness ).leftTo(shelfThickness).bottomTo(shelfThickness) val bed = Cylinder( 200, hookSize.x/2 ) .rotateY(90+angle) .backTo(-hookThickness) .translateZ( (hook1.top + hook2.top)/2 - 10 ) .previewOnly() val all = hook1 + hook2 + shelf + remote.previewOnly() + bed return all.rotateY(-angle) } }