import uk.co.nickthecoder.foocad.smartextrusion.v1.* import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.* class HiFi : Model { @Custom( about="Size of the phone/table, which determines the overall size of the model" ) var tabletSize = Vector2( 190, 110 ) @Custom( about="Thickness of the base, shelf and back" ) var thickness = 10 @Custom( about="The sides are thinner than other parts" ) var sideThickness = 5 @Custom( about="Y distance of the shelf" ) var shelfDepth = 65 @Custom( about="Distance bwetween the base and the shelf" ) var shelfHeight = 23 @Custom( about="Height above the shelf" ) var extraZ = 10 @Custom( about="Helps align felt on the shelves and the feet on the base" ) var inlayDepth = 1.0 @Custom( about="Optional feet printed in TPU" ) var footSize = Vector2( 20, 4 ) @Custom( about="Radius of fillets" ) var round = 10 @Custom( about="Size of chamfers" ) var chamfer = 1 meth size() = tabletSize + Vector2( sideThickness * 2 + 5, thickness + sideThickness + 3 ) meth tablet() = Square( tabletSize ) .center().roundAllCorners(10) .extrude( 10 ) meth speaker() = Square( 170, 70 ) .center().roundAllCorners( 34 ) .extrude( 57 ) .rotateX(90).bottomTo(0).centerXY() meth indent( x : double, y : double ) = ( Square( x, y ).centerX() + Square( x*2, y * 2 ).centerX().backTo(0) ).toPolygon().roundAllCorners(y / 2 - 0.01) meth baseShape() : Shape2d { val size = size() // A gap near the front to aid lifting up the tablet. val baseIndent = indent( size.x/2, round*2 ) return (Square( size() ).centerX().roundCorners(listOf(0,1), round) - baseIndent).center() .toPolygon() } meth inlayShape() = baseShape().offset( -sideThickness ) @Piece meth inlayPattern() = (inlayShape() - Square(1000).centerX()).extrude(0.2) @Piece( print="print" ) meth stand() : Shape3d { val size = size() val base = baseShape() .smartExtrude( thickness ) .edges( Chamfer( chamfer ) ) val back = Square( size.x, thickness ).centerX().roundAllCorners(chamfer, 1) .smartExtrude( shelfHeight + thickness *2 + extraZ ) .edges(Chamfer(chamfer)) .backTo( base.back + chamfer ) // Big enough to fit 4 fingers when moving the hifi to other parts of the house. val backGap = Square( size.x*0.5, 18 ).centerX().roundAllCorners(8.5) .smartExtrude( back.size.y + 0.02 ) .edges( Chamfer(chamfer).reverse() ) .rotateX(90) .topTo( thickness + shelfHeight ) .backTo( back.back + 0.01 ) val shelfShape = Square( size.x, shelfDepth + thickness ).centerX().backTo( back.back - chamfer ) .roundCorners( listOf(0,1), round ) val shelf = shelfShape .smartExtrude( thickness ) .edges( Chamfer( chamfer ) ) .topTo( back.top - thickness ) val sideDepth = Math.min( shelfDepth, size.y / 2 - 6 ) val sides = Square( back.size.z ) .roundCorner(0,back.size.z - thickness) .scaleY( sideDepth / back.size.z ) .smartExtrude( sideThickness ) .edges( Chamfer( chamfer ) ) .rotateY(90) .bottomTo(0).backTo( back.back - chamfer ).leftTo( back.left ) .mirrorX().also() // For a USB cable plugged into the back of the speaker. val backIndent = indent( size.x/4, extraZ ) .extrude( thickness + 0.02 ) .rotateX(-90) .bottomTo( shelf.top + 0.01 ) .backTo( back.back + 0.01 ) val baseInlay = if (inlayDepth > 0 ) { inlayShape() .smartExtrude(inlayDepth) .bottom( Chamfer(inlayDepth/2,inlayDepth) ) .topTo( base.top + 0.01 ) } else { null } val shelfInlay = if ( inlayDepth > 0 ) { shelfShape.offset( -sideThickness ) .smartExtrude( inlayDepth ) .bottom( Chamfer(inlayDepth/2,inlayDepth) ) .topTo( shelf.top + 0.01 ) } else { null } val feetIndents = if ( inlayDepth > 0 ) { positionFeet( Circle( footSize.x / 2 + 1 ) .smartExtrude( inlayDepth ) .top( Chamfer(inlayDepth/2,inlayDepth) ) .bottomTo( -0.01 ) .color("Red") ) } else { null } return base + shelf + sides - baseInlay - shelfInlay + back - backGap - backIndent - feetIndents } meth positionFeet( foot : Shape3d ) : Shape3d { return foot .translateX( size().x/2 - footSize.x /2 - 5 ) .translateY( size().y/2 - footSize.x /2 - 5 ) .mirrorX().also() .mirrorY().also() } @Piece meth print() = stand().rotateX(-90).bottomTo(0) @Piece meth foot() = Circle( footSize.x / 2 ) .smartExtrude( footSize.y ) .top( Chamfer( footSize.y * 0.7 ) ) @Piece( print="print") override fun build() : Shape3d { val stand = stand() val tablet = tablet().previewOnly() .bottomTo( thickness ) .backTo( stand.back - thickness - 2 ) val speaker = speaker().previewOnly() .bottomTo( tablet.top + thickness * 2 ) .backTo( stand.back - thickness - 2 ) val feet = positionFeet( foot().mirrorZ().topTo( 0 ) ) .color( "Black" ) return tablet + speaker + stand + feet } }