#!/usr/bin/env python3 import hazwaz import svgwrite try: import argcomplete # type: ignore except ImportError: argcomplete = False mm = 3.7795276 LINE_STYLE = { 'stroke': svgwrite.utils.rgb(127, 127, 127), 'stroke_width': 0.5, 'fill': 'none' } class Structure(object): def __init__(self, x, y, z, flap=15): """ """ self.x = x * mm self.y = y * mm self.z = z * mm self.f = flap * mm self.t = self.y / 3 # tab lenght self.full_width = self.f * 2 + self.z * 2 + self.x self.full_height = self.f * 2 + self.z * 2 + self.y def add_to(self, drw, canvas_x=210 * mm, canvas_y=297 * mm): grp = drw.g() grp.add(drw.rect( (self.z + self.f, self.z + self.f), (self.x, self.y), id='base', ** LINE_STYLE, )) grp.add(drw.rect( (self.f, (self.z + self.f)), (self.z, self.y), id='left', ** LINE_STYLE, )) grp.add(drw.rect( ((self.z + self.f + self.x), (self.z + self.f)), (self.z, self.y), id='right', ** LINE_STYLE, )) grp.add(drw.rect( ((self.z + self.f), self.f), (self.x, self.z), id='top', ** LINE_STYLE, )) grp.add(drw.rect( ((self.z + self.f), (self.f + self.z + self.y)), (self.x, self.z), id='bottom', ** LINE_STYLE, )) grp.add(drw.rect( (0, (self.f + self.z)), (self.f, self.y), id='left_flap', ** LINE_STYLE, )) grp.add(drw.rect( ((self.f + self.z * 2 + self.x), (self.f + self.z)), (self.f, self.y), id='right_flap', ** LINE_STYLE, )) grp.add(drw.rect( ((self.f + self.z), 0), (self.x, self.f), id='top_flap', ** LINE_STYLE, )) grp.add(drw.rect( ((self.f + self.z), (self.f + self.z * 2 + self.y)), (self.x, self.f), id='bottom_flap', ** LINE_STYLE, )) grp.add(drw.polygon( ( (self.f + self.z, self.f), (self.f + self.z, self.f + self.z), (self.f + self.z - self.t, self.f + self.z - 2 * mm), (self.f + self.z - self.t, self.f + 4 * mm) ), id='top_left_tab', ** LINE_STYLE, )) grp.add(drw.polygon( ( (self.f + self.z + self.x, self.f), (self.f + self.z + self.x + self.t, self.f + 4 * mm), (self.f + self.z + self.x + self.t, self.f + self.z - 2 * mm), (self.f + self.z + self.x, self.f + self.z), ), id='top_right_tab', ** LINE_STYLE, )) grp.add(drw.polygon( ( (self.f + self.z, self.f + self.y + self.z), (self.f + self.z, self.f + self.z + self.y + self.z), (self.f + self.z - self.t, self.f + self.z - 4 * mm + self.y + self.z), (self.f + self.z - self.t, self.f + 2 * mm + self.y + self.z) ), id='bottom_left_tab', ** LINE_STYLE, )) grp.add(drw.polygon( ( (self.f + self.z + self.x, self.f + self.y + self.z), (self.f + self.z + self.x + self.t, self.f + 4 * mm + self.y + self.z), (self.f + self.z + self.x + self.t, self.f + self.z - 2 * mm + self.y + self.z), (self.f + self.z + self.x, self.f + self.z + self.y + self.z), ), id='bottom_left_tab', ** LINE_STYLE, )) grp.translate( (canvas_x - self.full_width) / 2, (canvas_y - self.full_height) / 2 ) drw.add(grp) class Cardboard(object): def __init__(self, x, y, z, thickness=1): """ """ self.x = x * mm self.y = y * mm self.z = z * mm self.th = thickness * mm @property def full_width(self): return max(self.x + self.z * 2, self.x * 2 + self.th * 4) @property def full_height(self): return self.y + self.z def _get_grp(self, drw): grp = drw.g() grp.add(drw.rect( (self.z, 0), (self.x, self.y), id='base_base', ** LINE_STYLE, )) grp.add(drw.rect( (0, 0), (self.z, self.y), id='base_left_side', ** LINE_STYLE, )) grp.add(drw.rect( (self.z + self.x, 0), (self.z, self.y), id='base_right_side', ** LINE_STYLE, )) grp.add(drw.rect( (0, self.y), (self.x + self.th * 2, self.z), id='base_top_side', ** LINE_STYLE, )) grp.add(drw.rect( (self.x + self.th * 2, self.y), (self.x + self.th * 2, self.z), id='base_bottom_side', ** LINE_STYLE, )) return grp def add_to(self, drw, canvas_x=210 * mm, canvas_y=297 * mm): grp = self._get_grp(drw) grp.translate( (canvas_x - self.full_width) / 2, (canvas_y / 2 - self.full_height) ) drw.add(grp) self.x = self.x + self.th * 4 self.y = self.y + self.th * 4 self.z = self.z + self.th grp = self._get_grp(drw) grp.translate( (canvas_x - self.full_width) / 2, canvas_y / 2 ) drw.add(grp) class Base(Structure): def __init__(self, x, y, z, thickness=1, flap=15): """ """ super().__init__( x + thickness * 2, y + thickness * 2, z + thickness, flap=flap, ) class Lid(Structure): def __init__(self, x, y, z, thickness=1, flap=15): """ """ super().__init__( x + thickness * 6, y + thickness * 6, z + thickness * 2, flap=flap, ) class Command(hazwaz.MainCommand): """ Generate SVGs templates to build a telescoping box. """ def add_arguments(self, parser): parser.add_argument( "size_x", help="inner width of the box", type=int, ) parser.add_argument( "size_y", help="inner height of the box", type=int, ) parser.add_argument( "size_z", help="inner depth of the box", type=int, ) parser.add_argument( "-o", "--base_output", help="base destination filename", default="telescoping_box", ) parser.add_argument( "--paper_width", help="paper width in millimiters", type=int, default=210, ) parser.add_argument( "--paper_height", help="paper height in millimiters", type=int, default=297, ) def main(self): size_spec = "{}×{}×{}".format( str(self.args.size_x), str(self.args.size_y), str(self.args.size_z), ) paper_size = ( "{}mm".format(self.args.paper_width), "{}mm".format(self.args.paper_height), ) # lid dest = svgwrite.Drawing( filename="{}-{}-lid.svg".format( self.args.base_output, size_spec, ), size=paper_size, profile='full', ) struc = Lid(self.args.size_x, self.args.size_y, self.args.size_z) struc.add_to( dest, canvas_x=self.args.paper_width * mm, canvas_y=self.args.paper_height * mm, ) dest.save() # base dest = svgwrite.Drawing( filename="{}-{}-base.svg".format( self.args.base_output, size_spec, ), size=paper_size, profile='full', ) struc = Base(self.args.size_x, self.args.size_y, self.args.size_z) struc.add_to( dest, canvas_x=self.args.paper_width * mm, canvas_y=self.args.paper_height * mm, ) dest.save() # cardboard dest = svgwrite.Drawing( filename="{}-{}-cardboard.svg".format( self.args.base_output, size_spec, ), size=paper_size, profile='full', ) struc = Cardboard(self.args.size_x, self.args.size_y, self.args.size_z) struc.add_to( dest, canvas_x=self.args.paper_width * mm, canvas_y=self.args.paper_height * mm, ) dest.save() if __name__ == '__main__': Command().run()