/Electronics/BatteryCase.foocad

Uses BatteryTube
, but inside there is space for wire(s) running the
length of the tube, with an option for holes in the base for those wires.
You should probably include strain relief (to prevent wires disconnecting, or worse; short-circuiting). This could be as simple as hot glue.
import uk.co.nickthecoder.foocad.extras.v1.* import static uk.co.nickthecoder.foocad.extras.v1.Extras.* include BatteryTube.foocad class BatteryCase : Model { @Custom( about="The data for the battery size. The final tube will be wider than this." ) var tube = BatteryTube() @Custom( about="Additional width added to `tube` to accommodate wires(s)" ) var slotSize = 2.0 @Custom( about="Number of slots in the base (0,1 or 2)" ) var baseSlotCount = 2 @Custom( about="Add threads at the bottom of the tube too?" ) var additionalThread = true meth largerTube() : BatteryTube { return BatteryTube().apply { size = Vector2( tube.size.x + slotSize, tube.size.y ) thickness = tube.thickness baseThickness = tube.baseThickness clearance = tube.clearance capHeight = tube.capHeight extra = tube.extra } } meth slotShape() : Shape2d { val diameter = tube.size.x val tube = largerTube() val outer = Circle( tube.size.x/2 + tube.clearance + 0.1 ) val slot = Square( slotSize*2 ).centerY() .centerXTo( outer.right ) return slot intersection outer } meth fillShape() : Shape2d { val diameter = tube.size.x val tube = largerTube() val outer = Circle( tube.size.x/2 + tube.clearance + 0.1 ) val inner = Circle( diameter/2 + tube.clearance ) .leftTo( outer.left + 0.1 ) val slot = Square( slotSize*2 ).centerY() .centerXTo( inner.right ) return outer - inner - slot } @Piece meth body() : Shape3d { val largerTube = largerTube() val largeBody = largerTube.body() val fill = fillShape() .extrude( tube.size.y ) .bottomTo( tube.baseThickness ) val baseHole = slotShape().extrude( tube.baseThickness + 0.2 ) .bottomTo(-0.1) val baseHoles = if ( baseSlotCount == 1 ) { baseHole } else if (baseSlotCount > 1) { baseHole.mirrorX().also() } else { null } val baseThreads = largerTube.threads() return largeBody + baseThreads + fill - baseHoles } @Piece meth cap() : Shape3d { return largerTube().cap() } // An example "cap" that can be screwed to the bottom of the // body to make a torch. // You will need a switch, and LED and a current limiting resistor. // The resistor can be placed in-line with the body's slot. @Piece meth torch() : Shape3d { val largerTube = largerTube() val threads = largerTube.cap() .bottomTo( -largerTube.baseThickness ) - Cube( 100 ).centerXY().topTo(0) val diameter = threads.size.x val base = Square( diameter ).center() .roundAllCorners(6) val outside = Circle( diameter / 2 ) val thickBase = 4 val extra = ExtrusionBuilder().apply { crossSection( base.offset(-2) ) forward(2) crossSection( base ) forward( 8 ) crossSection() forward( 4 ) crossSection( outside ) crossSection( -largerTube.thickness ) forward( - 2 - 8 - 4 + thickBase ) crossSection( base.offset( - largerTube.thickness ) ) }.build() // Prevent the cap being twisted on too far. val stops = Cube( 4, 2, 2 + 8 + 4 - thickBase ) .centerX() .backTo( extra.back - 0.5 ) .bottomTo( thickBase ) .mirrorY().also() val ledHole = Cylinder( 10, 5/2 + 0.2 ).center() val switchHole = Cube( 8, 8, 4 ) .centerY() .centerXTo( extra.right ) .bottomTo( thickBase ) return extra + stops + threads.translateZ( extra.size.z ) - ledHole - switchHole } @Piece meth all() : Shape3d { return body().rightTo(-1) + cap().leftTo(1) } @Piece( print="all" ) override fun build() : Shape3d { val body = body() val cap = cap().rotateX(180).bottomTo( body.top + 10 ) val torch = torch() return body + cap + torch().leftTo( body.right + 2 ) } }