summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2022-07-16 16:03:32 +0200
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2022-07-16 16:03:32 +0200
commitd981e03ee07c4486ec161fa84e15da711109243e (patch)
tree61a89386912fa634070ffa68b6ab1d85138a1d68
parente0541a6200abfb16949b256c4032eba3129a6bcc (diff)
Telescoping box: generate templates for a box made of cardboard and labels
-rwxr-xr-xtelescoping_box.py339
1 files changed, 339 insertions, 0 deletions
diff --git a/telescoping_box.py b/telescoping_box.py
new file mode 100755
index 0000000..c7baf73
--- /dev/null
+++ b/telescoping_box.py
@@ -0,0 +1,339 @@
+#!/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()