/Hardware/PaverCover.foocad

I have spare paving blocks that I like to use to weigh things down in the garden, and when woodworking. However, I don't want to damage paintwork etc.
Previously, I tried wrapping them in plastic sheets (like wrapping a present), but the plastic soon deteriorated. Hopefully, using ASA will give a long life???
This provides 3 different "covers".
- Fully cover the block (in 2 pieces
top
andbottom
) - Partially cover the ends (a pair of piece
sideBumper
) - Partially cover the top and bottom (pieces
topBumper
andbottomBumper
).
While the model has custom values for the size, the location of the blocks' spacers is somewhat hard-coded, and probably will only be suitable for the 200x100x50 blocks that I used. Also note that some blocks of the same size have the spacers mirrored! Therefore, you may need to edit the code, rather than just change @Custom values for this model to work with other blocks.
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.smartextrusion.v1.* import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.* import uk.co.nickthecoder.foocad.cup.v1.* import static uk.co.nickthecoder.foocad.cup.v1.Cup.* class PaverCover : Model { @Custom var size = Vector3( 200, 100, 50 ) @Custom var clearance = 0 @Custom var round = 4 @Custom var chamfer = 2 @Custom var topThickness = 0.8 @Custom var wallThickness = 1.1 @Custom var ribSize = Vector2( 4, 2 ) @Custom( about="height and thickness" ) var bumperSize = Vector2( 16, 2 ) // The 2D shape for the outside shape used by `top` and `bottom` pieces. meth shape() : Shape2d = Square( size.x, size.y ) .roundAllCorners( round ) .offset( wallThickness + clearance ) .center() // Use to remove parts for the block's spacers (small protruberances on the sides of the block). meth brickSpacers() : Shape3d { val rib = Square( 10, 4 ) val x = rib .backTo( size.y / 2 ) .centerXTo( size.x/2 - 20 ) .translateX( -100 ).also() .rotate(180).also() val y = rib.rotate(-90) .rightTo( size.x / 2 ) .centerYTo( -size.y / 2 + 20 ) .rotate(180).also() return (x + y).extrude( size.z ) } // Ribs inside pieces `top` and `bottom` so that the brick fits snuggly inside // The ribs are the same size as the block's spacers. meth ribs( height : double ) : Shape3d { val rib = Square( ribSize ) .roundCorner(1, 1, 1) .roundCorner(0, 1 ,1) .extrude( height - topThickness ) .bottomTo( topThickness ) val x = rib .repeatX( 5, size.x * 0.2 ).rightTo( size.x/2 - 12 ) .backTo( size.y/2 + clearance ) .rotateZ(180).also() val y = rib.rotateZ(-90) .repeatY( 3, size.y * 0.4 ) .centerY() .rightTo( size.x/2 + clearance ) .rotateZ(180).also() return x + y } // When combined with `bottom`, fully encloses the block. @Piece meth top() = top( size.z / 2 + topThickness ) meth top( height : double ) : Shape3d { return Cup( shape(), height, wallThickness ) .baseThickness( topThickness ) .insideTop( Chamfer(-ribSize.y,ribSize.y) ) .bottom( Chamfer( chamfer ) ) + ribs( height ).mirrorX() - brickSpacers().mirrorX().bottomTo( topThickness + chamfer ) } // When combined with `top`, fully encloses the block. @Piece meth bottom() = bottom( size.z / 2 + topThickness ) @Piece meth bottom( height : double ) : Shape3d { return Cup( shape(), height, wallThickness ) .baseThickness( topThickness ) .insideTop( Chamfer(-ribSize.y,ribSize.y) ) .outsideBottom( Chamfer( 0.5 ) ) + ribs( height ) - brickSpacers().bottomTo( topThickness ) } // Used to test the fit without printing a complete cover. @Piece meth test() : Shape3d { size = Vector3( size.x, size.y, 10 ) return top() - Cube( size.x * 0.9, size.y * 0.8, 10 ).center() } @Piece meth topBumper() = top( 12 ) - Square( size.x * 0.9, size.y*0.8 ).roundAllCorners(5).extrude( size.z ).center() @Piece meth bottomBumper() = bottom( 12 ) - Square( size.x * 0.9, size.y*0.8 ).roundAllCorners(5).extrude( size.z ).center() @Piece meth sideBumper() : Shape3d { val shape = Square( size.z, size.y - ribSize.y ) .roundCorner( 3, chamfer, 1 ) .roundCorner( 2, 0.5 ) .roundCorner( 1, 0.5 ) .roundCorner( 0, chamfer, 1 ) .offset( clearance + bumperSize.y ) .center() val main = Cup( shape, bumperSize.x, bumperSize.y ) .outsideBottom( Chamfer( bumperSize.y *0.7 ) ) val rib = Square( size.z, ribSize.x ) .center() .extrude( ribSize.y ) .backTo( -size.y/2 + 10 ) .bottomTo( bumperSize.y ) val hole = Square( size.z, size.y ).offset( -10 ) .roundAllCorners(5) .extrude( size.z ) .center() return main + rib - hole } @Piece( printable=false ) override fun build() : Shape3d { val bottom = bottom() val top = top().rotateX(180).translateZ( size.z*2 ) //.previewOnly() val block = Square( size.x, size.y ).offset( -ribSize.y ) .center() .roundAllCorners( round ) .extrude( size.z ) .bottomTo( topThickness ).previewOnly() val sideBlock = block .rightTo( block.left - 20 ) .bottomTo( bumperSize.y ) val sideBumpers = sideBumper() .rotateY(90) .bottomTo(0) .leftTo( block.left - bumperSize.y ) .centerYTo( sideBlock.middle.y ) .mirrorX().also() .centerXTo( sideBlock.middle.x ) val block3 = block .leftTo( block.right + 20 ) val topBumper = topBumper() .rotateY(180) .centerXTo( block3.middle.x ) .topTo( block3.top + topThickness*2 ) val bottomBumper = bottomBumper() .centerXTo( block3.middle.x ) return bottom + top + block + sideBlock + sideBumpers + block3 + topBumper + bottomBumper } }