From 39e31f9231fb7b5493a31c6fa5c7745f4b7fab81 Mon Sep 17 00:00:00 2001 From: Elena ``of Valhalla'' Grandi Date: Sat, 12 Aug 2023 10:21:35 +0200 Subject: Moved box template generators to a subdirectory --- boxes/telescoping_box.py | 351 +++++++++++++++++++++++++++++++++++++++++++++++ boxes/tuckbox.py | 230 +++++++++++++++++++++++++++++++ telescoping_box.py | 351 ----------------------------------------------- tuckbox.py | 230 ------------------------------- 4 files changed, 581 insertions(+), 581 deletions(-) create mode 100755 boxes/telescoping_box.py create mode 100755 boxes/tuckbox.py delete mode 100755 telescoping_box.py delete mode 100755 tuckbox.py diff --git a/boxes/telescoping_box.py b/boxes/telescoping_box.py new file mode 100755 index 0000000..53a83bb --- /dev/null +++ b/boxes/telescoping_box.py @@ -0,0 +1,351 @@ +#!/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, + ) + parser.add_argument( + "--flap", + help="height of the flap, in millimiters", + type=int, + default=15 + ) + + 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, + flap=self.args.flap, + ) + 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, + flap=self.args.flap, + ) + 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() diff --git a/boxes/tuckbox.py b/boxes/tuckbox.py new file mode 100755 index 0000000..73d4eaf --- /dev/null +++ b/boxes/tuckbox.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 + +import argparse + +import svgwrite + +try: + from lesana.command import _get_first_docstring_line # type: ignore +except ImportError: + def _get_first_docstring_line(obj): + return "" + +try: + import argcomplete # type: ignore +except ImportError: + argcomplete = False + + +# 1 mm in px +mm = 3.7795276 + +LINE_STYLE = { + 'stroke': svgwrite.utils.rgb(127, 127, 127), + 'stroke_width': 0.5, + 'fill': 'none' + } + + +class Structure(): + def __init__(self, x, y, z, flap=20, tab=16): + """ + """ + self.x = x * mm + self.y = y * mm + self.z = z * mm + self.f = flap * mm + self.t = tab * mm # tab lenght + + self.full_width = self.t + self.x * 2 + self.z * 2 + self.full_height = self.f + self.z * 2 + self.y + + def add_to(self, drw, canvas_x=297 * mm, canvas_y=210 * mm): + grp = drw.g() + grp.add(drw.polygon( + ( + (3 * mm, self.z - self.t), + (self.z - 3 * mm, self.z - self.t), + (self.z, self.z), + (0, self.z), + ), + id='right_side_bottom_tab', + ** LINE_STYLE, + )) + grp.add(drw.rect( + (self.z, 0), + (self.x, self.z), + id='base', + ** LINE_STYLE, + )) + grp.add(drw.polygon( + ( + (self.z + self.x + 3 * mm, self.z - self.t), + (self.z * 2 + self.x - 3 * mm, self.z - self.t), + (self.z * 2 + self.x, self.z), + (self.z + self.x, self.z), + ), + id='left_side_bottom_tab', + ** LINE_STYLE, + )) + grp.add(drw.polygon( + ( + (self.z * 2 + self.x + 3 * mm, self.z - self.t), + (self.z * 2 + self.x * 2 - 3 * mm, self.z - self.t), + (self.z * 2 + self.x * 2, self.z), + (self.z * 2 + self.x, self.z), + ), + id='back_bottom_tab', + ** LINE_STYLE, + )) + + grp.add(drw.rect( + (0, self.z), + (self.z, self.y), + id='right_side', + ** LINE_STYLE, + )) + grp.add(drw.rect( + (self.z, self.z), + (self.x, self.y), + id='front', + ** LINE_STYLE, + )) + grp.add(drw.rect( + (self.x + self.z, self.z), + (self.z, self.y), + id='left_side', + ** LINE_STYLE, + )) + # TODO: remove the semicircle from the rect + grp.add(drw.rect( + (self.x + self.z * 2, self.z), + (self.x, self.y), + id='back', + ** LINE_STYLE, + )) + grp.add(drw.ellipse( + (self.x + self.z * 2 + self.x / 2, self.z + self.y), + (8 * mm, 8 * mm), + id='back_cut', + ** LINE_STYLE, + )) + grp.add(drw.polygon( + ( + (self.x * 2 + self.z * 2, self.z), + (self.x * 2 + self.z * 2 + self.t, self.z + 3 * mm), + (self.x * 2 + self.z * 2 + self.t, self.z + self.y - 3 * mm), + (self.x * 2 + self.z * 2, self.z + self.y), + ), + id='side_tab', + ** LINE_STYLE, + )) + + grp.add(drw.polygon( + ( + (0, self.z + self.y), + (self.z, self.z + self.y), + (self.z - 3 * mm, self.z + self.y + self.t), + (3 * mm, self.z + self.y + self.t), + ), + id='right_side_top_tab', + ** LINE_STYLE, + )) + grp.add(drw.rect( + (self.z, self.z + self.y), + (self.x, self.z), + id='top', + ** LINE_STYLE, + )) + grp.add(drw.polygon( + ( + (self.z + self.x, self.z + self.y), + (self.z * 2 + self.x, self.z + self.y), + (self.z * 2 + self.x - 3 * mm, self.z + self.y + self.t), + (self.z + self.x + 3 * mm, self.z + self.y + self.t), + ), + id='left_side_top_tab', + ** LINE_STYLE, + )) + + # TODO: make this an half-ellipse + grp.add(drw.ellipse( + (self.z + self.x / 2, self.z * 2 + self.y), + (self.x / 2, self.f), + id='top_tab', + ** LINE_STYLE, + )) + grp.add(drw.rect( + (self.z, self.z + self.y + self.z - self.f - 1), + (self.x, self.f + 1), + id='top_tab_excess', + ** LINE_STYLE, + )) + + grp.rotate( + 180, + center=(canvas_x / 2, canvas_y / 2), + ) + grp.translate( + (canvas_x - self.full_width) / 2, + (canvas_y - self.full_height) / 2 + ) + drw.add(grp) + + +class Command(): + """ + Generate an SVG with the basic shape of a tuckbox for gaming cards. + """ + + def get_parser(self): + desc = _get_first_docstring_line(self) + parser = argparse.ArgumentParser(description=desc) + parser.add_argument( + "-x", "--size-x", + default=60, + type=int, + help="Internal width of the box.", + ) + parser.add_argument( + "-y", "--size-y", + default=94, + type=int, + help="Internal height of the box.", + ) + parser.add_argument( + "-z", "--size-z", + default=42, + type=int, + help="Internal thickness of the box.", + ) + parser.add_argument( + "-o", "--output", + default="tuckbox", + help="Base output file name." + ) + return parser + + def main(self): + self.parser = self.get_parser() + if argcomplete: + argcomplete.autocomplete(self.parser) + self.args = self.parser.parse_args() + + size_spec = "{}×{}×{}".format( + self.args.size_x, + self.args.size_y, + self.args.size_z, + ) + dest = svgwrite.Drawing( + filename="{}-{}.svg".format(self.args.output, size_spec), + size=('297mm', '210mm'), + profile='full', + ) + struc = Structure(self.args.size_x, self.args.size_y, self.args.size_z) + struc.add_to(dest) + dest.save() + + +if __name__ == '__main__': + Command().main() diff --git a/telescoping_box.py b/telescoping_box.py deleted file mode 100755 index 53a83bb..0000000 --- a/telescoping_box.py +++ /dev/null @@ -1,351 +0,0 @@ -#!/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, - ) - parser.add_argument( - "--flap", - help="height of the flap, in millimiters", - type=int, - default=15 - ) - - 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, - flap=self.args.flap, - ) - 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, - flap=self.args.flap, - ) - 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() diff --git a/tuckbox.py b/tuckbox.py deleted file mode 100755 index 73d4eaf..0000000 --- a/tuckbox.py +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/env python3 - -import argparse - -import svgwrite - -try: - from lesana.command import _get_first_docstring_line # type: ignore -except ImportError: - def _get_first_docstring_line(obj): - return "" - -try: - import argcomplete # type: ignore -except ImportError: - argcomplete = False - - -# 1 mm in px -mm = 3.7795276 - -LINE_STYLE = { - 'stroke': svgwrite.utils.rgb(127, 127, 127), - 'stroke_width': 0.5, - 'fill': 'none' - } - - -class Structure(): - def __init__(self, x, y, z, flap=20, tab=16): - """ - """ - self.x = x * mm - self.y = y * mm - self.z = z * mm - self.f = flap * mm - self.t = tab * mm # tab lenght - - self.full_width = self.t + self.x * 2 + self.z * 2 - self.full_height = self.f + self.z * 2 + self.y - - def add_to(self, drw, canvas_x=297 * mm, canvas_y=210 * mm): - grp = drw.g() - grp.add(drw.polygon( - ( - (3 * mm, self.z - self.t), - (self.z - 3 * mm, self.z - self.t), - (self.z, self.z), - (0, self.z), - ), - id='right_side_bottom_tab', - ** LINE_STYLE, - )) - grp.add(drw.rect( - (self.z, 0), - (self.x, self.z), - id='base', - ** LINE_STYLE, - )) - grp.add(drw.polygon( - ( - (self.z + self.x + 3 * mm, self.z - self.t), - (self.z * 2 + self.x - 3 * mm, self.z - self.t), - (self.z * 2 + self.x, self.z), - (self.z + self.x, self.z), - ), - id='left_side_bottom_tab', - ** LINE_STYLE, - )) - grp.add(drw.polygon( - ( - (self.z * 2 + self.x + 3 * mm, self.z - self.t), - (self.z * 2 + self.x * 2 - 3 * mm, self.z - self.t), - (self.z * 2 + self.x * 2, self.z), - (self.z * 2 + self.x, self.z), - ), - id='back_bottom_tab', - ** LINE_STYLE, - )) - - grp.add(drw.rect( - (0, self.z), - (self.z, self.y), - id='right_side', - ** LINE_STYLE, - )) - grp.add(drw.rect( - (self.z, self.z), - (self.x, self.y), - id='front', - ** LINE_STYLE, - )) - grp.add(drw.rect( - (self.x + self.z, self.z), - (self.z, self.y), - id='left_side', - ** LINE_STYLE, - )) - # TODO: remove the semicircle from the rect - grp.add(drw.rect( - (self.x + self.z * 2, self.z), - (self.x, self.y), - id='back', - ** LINE_STYLE, - )) - grp.add(drw.ellipse( - (self.x + self.z * 2 + self.x / 2, self.z + self.y), - (8 * mm, 8 * mm), - id='back_cut', - ** LINE_STYLE, - )) - grp.add(drw.polygon( - ( - (self.x * 2 + self.z * 2, self.z), - (self.x * 2 + self.z * 2 + self.t, self.z + 3 * mm), - (self.x * 2 + self.z * 2 + self.t, self.z + self.y - 3 * mm), - (self.x * 2 + self.z * 2, self.z + self.y), - ), - id='side_tab', - ** LINE_STYLE, - )) - - grp.add(drw.polygon( - ( - (0, self.z + self.y), - (self.z, self.z + self.y), - (self.z - 3 * mm, self.z + self.y + self.t), - (3 * mm, self.z + self.y + self.t), - ), - id='right_side_top_tab', - ** LINE_STYLE, - )) - grp.add(drw.rect( - (self.z, self.z + self.y), - (self.x, self.z), - id='top', - ** LINE_STYLE, - )) - grp.add(drw.polygon( - ( - (self.z + self.x, self.z + self.y), - (self.z * 2 + self.x, self.z + self.y), - (self.z * 2 + self.x - 3 * mm, self.z + self.y + self.t), - (self.z + self.x + 3 * mm, self.z + self.y + self.t), - ), - id='left_side_top_tab', - ** LINE_STYLE, - )) - - # TODO: make this an half-ellipse - grp.add(drw.ellipse( - (self.z + self.x / 2, self.z * 2 + self.y), - (self.x / 2, self.f), - id='top_tab', - ** LINE_STYLE, - )) - grp.add(drw.rect( - (self.z, self.z + self.y + self.z - self.f - 1), - (self.x, self.f + 1), - id='top_tab_excess', - ** LINE_STYLE, - )) - - grp.rotate( - 180, - center=(canvas_x / 2, canvas_y / 2), - ) - grp.translate( - (canvas_x - self.full_width) / 2, - (canvas_y - self.full_height) / 2 - ) - drw.add(grp) - - -class Command(): - """ - Generate an SVG with the basic shape of a tuckbox for gaming cards. - """ - - def get_parser(self): - desc = _get_first_docstring_line(self) - parser = argparse.ArgumentParser(description=desc) - parser.add_argument( - "-x", "--size-x", - default=60, - type=int, - help="Internal width of the box.", - ) - parser.add_argument( - "-y", "--size-y", - default=94, - type=int, - help="Internal height of the box.", - ) - parser.add_argument( - "-z", "--size-z", - default=42, - type=int, - help="Internal thickness of the box.", - ) - parser.add_argument( - "-o", "--output", - default="tuckbox", - help="Base output file name." - ) - return parser - - def main(self): - self.parser = self.get_parser() - if argcomplete: - argcomplete.autocomplete(self.parser) - self.args = self.parser.parse_args() - - size_spec = "{}×{}×{}".format( - self.args.size_x, - self.args.size_y, - self.args.size_z, - ) - dest = svgwrite.Drawing( - filename="{}-{}.svg".format(self.args.output, size_spec), - size=('297mm', '210mm'), - profile='full', - ) - struc = Structure(self.args.size_x, self.args.size_y, self.args.size_z) - struc.add_to(dest) - dest.save() - - -if __name__ == '__main__': - Command().main() -- cgit v1.2.3