boxes package

Subpackage boxes.generators

class boxes.generators.UIGroup(name: str, title: str | None = None, description: str = '', image: str = '')[source]

Bases: object

add(box) None[source]
property image: str
property thumbnail: str
boxes.generators.getAllBoxGenerators() dict[str, type[Boxes]][source]
boxes.generators.getAllGeneratorModules() dict[str, ModuleType][source]

All Box Generators

Submodules

boxes.Color module

class boxes.Color.Color[source]

Bases: object

ANNOTATIONS = [1.0, 0.0, 0.0]
BLACK = [0.0, 0.0, 0.0]
BLUE = [0.0, 0.0, 1.0]
CYAN = [0.0, 1.0, 1.0]
ETCHING = [0.0, 1.0, 0.0]
ETCHING_DEEP = [0.0, 1.0, 1.0]
GREEN = [0.0, 1.0, 0.0]
INNER_CUT = [0.0, 0.0, 1.0]
MAGENTA = [1.0, 0.0, 1.0]
OUTER_CUT = [0.0, 0.0, 0.0]
RED = [1.0, 0.0, 0.0]
WHITE = [1.0, 1.0, 1.0]
YELLOW = [1.0, 1.0, 0.0]

boxes.edges module

class boxes.edges.BaseEdge(boxes, settings)[source]

Bases: ABC

Abstract base class for all Edges

char: str | None = None
description: str = 'Abstract Edge Class'
endAngle() float[source]

Not yet supported

endwidth() float[source]
margin() float[source]

Space needed right of the starting point

spacing() float[source]

Space the edge needs outside of the inner space of the part

startAngle() float[source]

Not yet supported

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.BoltPolicy[source]

Bases: ABC

Abstract class

Distributes (bed) bolts on a number of segments (fingers of a finger joint)

drawbolt(pos) bool[source]

Add a bolt to this segment?

Parameters:

pos – number of the finger

numFingers(numFingers: int) int[source]

Return next smaller, possible number of fingers

Parameters:

numFingers – number of fingers to aim for

class boxes.edges.Bolts(bolts: int = 1)[source]

Bases: BoltPolicy

Distribute a fixed number of bolts evenly

drawBolt(pos)[source]

Return if this finger needs a bolt

Parameters:

pos – number of this finger

numFingers(numFingers: int) int[source]

Return next smaller, possible number of fingers

Parameters:

numFingers – number of fingers to aim for

class boxes.edges.CabinetHingeEdge(boxes, settings=None, top: bool = False, angled: bool = False)[source]

Bases: BaseEdge

Edge with cabinet hinges

char: str | None = 'u'
description: str = 'Edge with cabinet hinges'
parts(move=None) None[source]
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.CabinetHingeSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Cabinet Hinges Values:

  • absolute_params

  • bore : 3.2 : diameter of the pin hole in mm

  • eyes_per_hinge : 5 : pieces per hinge

  • hinges : 2 : number of hinges per edge

  • style : inside : style of hinge used

  • relative (in multiples of thickness)

  • eye : 1.5 : radius of the eye (multiples of thickness)

  • play : 0.05 : space between eyes (multiples of thickness)

  • spacing : 2.0 : minimum space around the hinge (multiples of thickness)

absolute_params: dict[str, Any] = {'bore': 3.2, 'eyes_per_hinge': 5, 'hinges': 2, 'style': ('inside', 'outside')}
edgeObjects(boxes, chars: str = 'uUvV', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'eye': 1.5, 'play': 0.05, 'spacing': 2.0}
class boxes.edges.ChestHinge(boxes, settings=None, reversed: bool = False)[source]

Bases: BaseEdge

char: str | None = 'o'
description: str = 'Edge with chest hinge'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.ChestHingeFront(boxes, settings)[source]

Bases: Edge

char: str | None = 'Q'
description: str = 'Edge opposing a chest hinge'
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.ChestHingePin(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'q'
description: str = 'Edge with pins for an chest hinge'
margin() float[source]

Space needed right of the starting point

class boxes.edges.ChestHingeSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Chest Hinges Values:

  • relative (in multiples of thickness)

  • pin_height : 2.0 : radius of the disc rotating in the hinge (multiples of thickness)

  • hinge_strength : 1.0 : thickness of the arc holding the pin in place (multiples of thickness)

  • absolute

  • finger_joints_on_box : False : whether to include finger joints on the edge with the box

  • finger_joints_on_lid : False : whether to include finger joints on the edge with the lid

absolute_params: dict[str, Any] = {'finger_joints_on_box': False, 'finger_joints_on_lid': False}
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

edgeObjects(boxes, chars: str = 'oOpPqQ', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

pinheight()[source]
relative_params: dict[str, Any] = {'hinge_strength': 1.0, 'pin_height': 2.0, 'play': 0.1}
class boxes.edges.ChestHingeTop(boxes, settings=None, reversed: bool = False)[source]

Bases: ChestHinge

Edge above a chest hinge

char: str | None = 'p'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.ClickConnector(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'c'
description: str = 'Click on (bottom side)'
finger(length) None[source]
hook(reverse: bool = False) None[source]
hookOffset()[source]
hookWidth()[source]
margin() float[source]

Space needed right of the starting point

class boxes.edges.ClickEdge(boxes, settings)[source]

Bases: ClickConnector

char: str | None = 'C'
description: str = 'Click on (top)'
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.ClickSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Click-on Lids Values:

  • absolute_params

    • angle : 5.0 : angle of the hooks bending outward

  • relative (in multiples of thickness)

    • depth : 3.0 : length of the hooks (multiples of thickness)

    • bottom_radius : 0.1 : radius at the bottom (multiples of thickness)

absolute_params: dict[str, Any] = {'angle': 5.0}
edgeObjects(boxes, chars: str = 'cC', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'bottom_radius': 0.1, 'depth': 3.0}
class boxes.edges.CompoundEdge(boxes, types, lengths)[source]

Bases: BaseEdge

Edge composed of multiple different Edges

description: str = 'Compound Edge'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.CrossingFingerHoleEdge(boxes, height, fingerHoles=None, outset: float = 0.0, **kw)[source]

Bases: Edge

Edge with holes for finger joints 90° above

char: str | None = '|'
description: str = 'Edge (orthogonal Finger Joint Holes)'
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.DoveTailJoint(boxes, settings)[source]

Bases: BaseEdge

Edge with dove tail joints

char: str | None = 'd'
description: str = 'Dove Tail Joint'
margin() float[source]
positive = True
class boxes.edges.DoveTailJointCounterPart(boxes, settings)[source]

Bases: DoveTailJoint

Edge for other side of dove joints

char: str | None = 'D'
description: str = 'Dove Tail Joint (opposing side)'
margin() float[source]
positive = False
class boxes.edges.DoveTailSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Dove Tail Joints

Values:

  • absolute

    • angle : 50 : how much should fingers widen (-80 to 80)

  • relative (in multiples of thickness)

    • size : 3 : from one middle of a dove tail to another (multiples of thickness)

    • depth : 1.5 : how far the dove tails stick out of/into the edge (multiples of thickness)

    • radius : 0.2 : radius used on all four corners (multiples of thickness)

absolute_params: dict[str, Any] = {'angle': 50}
edgeObjects(boxes, chars: str = 'dD', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'depth': 1.5, 'radius': 0.2, 'size': 3}
class boxes.edges.Edge(boxes, settings)[source]

Bases: BaseEdge

Straight edge

char: str | None = 'e'
description: str = 'Straight Edge'
positive = False
class boxes.edges.FingerHoleEdge(boxes, fingerHoles=None, **kw)[source]

Bases: BaseEdge

Edge with holes for a parallel finger joint

char: str | None = 'h'
description: str = 'Edge (parallel Finger Joint Holes)'
margin() float[source]

Space needed right of the starting point

startwidth() float[source]
class boxes.edges.FingerHoles(boxes, settings)[source]

Bases: FingerJointBase

Hole matching a finger joint edge

class boxes.edges.FingerJointBase[source]

Bases: ABC

Abstract base class for finger joint.

calcFingers(length: float, bedBolts) tuple[int, float][source]
fingerLength(angle: float) tuple[float, float][source]
class boxes.edges.FingerJointEdge(boxes, settings)[source]

Bases: BaseEdge, FingerJointBase

Finger joint edge

char: str | None = 'f'
description: str = 'Finger Joint'
draw_finger(f, h, style, positive: bool = True, firsthalf: bool = True) None[source]
margin() float[source]
positive = True
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.FingerJointEdgeCounterPart(boxes, settings)[source]

Bases: FingerJointEdge

Finger joint edge - other side

char: str | None = 'F'
description: str = 'Finger Joint (opposing side)'
positive = False
class boxes.edges.FingerJointSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Finger Joints

Values:

  • absolute * style : “rectangular” : style of the fingers * surroundingspaces : 2.0 : space at the start and end in multiple of normal spaces

  • relative (in multiples of thickness)

    • space : 2.0 : space between fingers (multiples of thickness)

    • finger : 2.0 : width of the fingers (multiples of thickness)

    • width : 1.0 : width of finger holes (multiples of thickness)

    • edge_width : 1.0 : space below holes of FingerHoleEdge (multiples of thickness)

    • play : 0.0 : extra space to allow finger move in and out (multiples of thickness)

    • extra_length : 0.0 : extra material to grind away burn marks (multiples of thickness)

    • bottom_lip : 0.0 : height of the bottom lips sticking out (multiples of thickness) FingerHoleEdge only!

absolute_params: dict[str, Any] = {'style': ('rectangular', 'springs', 'barbs', 'snap'), 'surroundingspaces': 2.0}
angle = 90
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

edgeObjects(boxes, chars: str = 'fFh', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'bottom_lip': 0.0, 'edge_width': 1.0, 'extra_length': 0.0, 'finger': 2.0, 'play': 0.0, 'space': 2.0, 'width': 1.0}
class boxes.edges.FlexEdge(boxes, settings)[source]

Bases: BaseEdge

Edge with flex cuts - use straight edge for the opposing side

char: str | None = 'X'
description: str = 'Flex cut'
class boxes.edges.FlexSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Flex

Values:

  • absolute

  • stretch : 1.05 : Hint of how much the flex part should be shortened

  • relative (in multiples of thickness)

  • distance : 0.5 : width of the pattern perpendicular to the cuts (multiples of thickness)

  • connection : 1.0 : width of the gaps in the cuts (multiples of thickness)

  • width : 5.0 : width of the pattern in direction of the cuts (multiples of thickness)

absolute_params: dict[str, Any] = {'stretch': 1.05}
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

relative_params: dict[str, Any] = {'connection': 1.0, 'distance': 0.5, 'width': 5.0}
class boxes.edges.GearSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for rack (and pinion) edge Values: * absolute_params

  • dimension : 3.0 : modulus of the gear (in mm)

  • angle : 20.0 : pressure angle

  • profile_shift : 20.0 : Profile shift

  • clearance : 0.0 : clearance

absolute_params: dict[str, Any] = {'angle': 20.0, 'clearance': 0.0, 'dimension': 3.0, 'profile_shift': 20.0}
relative_params: dict[str, Any] = {}
class boxes.edges.GripSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for GrippingEdge Values:

  • absolute_params

  • style : “wave” : “wave” or “bumps”

  • outset : True : extend outward the straight edge

  • relative (in multiples of thickness)

  • depth : 0.3 : depth of the grooves

absolute_params: dict[str, Any] = {'outset': True, 'style': ('wave', 'bumps')}
edgeObjects(boxes, chars: str = 'g', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'depth': 0.3}
class boxes.edges.GrippingEdge(boxes, settings)[source]

Bases: BaseEdge

bumps(length) None[source]
char: str | None = 'g'
description: str = 'Corrugated edge useful as an gipping area'
margin() float[source]

Space needed right of the starting point

wave(length) None[source]
class boxes.edges.GroovedEdge(boxes, settings)[source]

Bases: GroovedEdgeBase

char: str | None = 'z'
description: str = 'Edge with grooves'
inverse = False
class boxes.edges.GroovedEdgeBase(boxes, settings)[source]

Bases: BaseEdge

groove_arc(width, angle: float = 90.0, inv: float = -1.0) None[source]
groove_soft_arc(width, angle: float = 60.0, inv: float = -1.0) None[source]
groove_triangle(width, angle: float = 45.0, inv: float = -1.0) None[source]
is_inverse() bool[source]
class boxes.edges.GroovedEdgeCounterPart(boxes, settings)[source]

Bases: GroovedEdgeBase

char: str | None = 'Z'
description: str = 'Edge with grooves (opposing side)'
inverse = True
class boxes.edges.GroovedSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Grooved Edge Values:

  • absolute_params

  • style : “arc” : the style of grooves

  • tri_angle : 30 : the angle of triangular cuts

  • arc_angle : 120 : the angle of arc cuts

  • width : 0.2 : the width of each groove (fraction of the edge length)

  • gap : 0.1 : the gap between grooves (fraction of the edge length)

  • margin : 0.3 : minimum space left and right without grooves (fraction of the edge length)

  • inverse : False : invert the groove directions

  • interleave : False : alternate the direction of grooves

PARAM_ARC = 'arc'
PARAM_FLAT = 'flat'
PARAM_SOFTARC = 'softarc'
PARAM_TRIANGLE = 'triangle'
absolute_params: dict[str, Any] = {'arc_angle': 120, 'gap': 0.1, 'interleave': False, 'inverse': False, 'margin': 0.3, 'style': ('arc', 'flat', 'triangle', 'softarc'), 'tri_angle': 30, 'width': 0.2}
edgeObjects(boxes, chars: str = 'zZ', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

class boxes.edges.HandleEdge(boxes, settings)[source]

Bases: Edge

Extends an ‘edge’ by adding a rounded bumpout with optional holes

char: str | None = 'y'
description: str = 'Handle for e.g. a drawer'
extra_height = 0.0
margin() float[source]

Space needed right of the starting point

class boxes.edges.HandleEdgeSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for HandleEdge Values:

  • absolute_params

  • height : 20. : height above the wall in mm

  • radius : 10. : radius of corners in mm

  • hole_width : “40:40” : width of hole(s) in percentage of maximum hole width (width of edge - (n+1) * material thickness)

  • hole_height : 75. : height of hole(s) in percentage of maximum hole height (handle height - 2 * material thickness)

  • on_sides : True, : added to side panels if checked, to front and back otherwise (only used with top_edge parameter)

  • relative

  • outset : 1. : extend the handle along the length of the edge (multiples of thickness)

absolute_params: dict[str, Any] = {'height': 20.0, 'hole_height': 75.0, 'hole_width': '40:40', 'on_sides': True, 'radius': 10.0}
edgeObjects(boxes, chars: str = 'yY', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'outset': 1.0}
class boxes.edges.HandleHoleEdge(boxes, settings)[source]

Bases: HandleEdge

Extends an ‘edge’ by adding a rounded bumpout with optional holes and holes for parallel finger joint

char: str | None = 'Y'
description: str = 'Handle with holes for parallel finger joint'
extra_height = 1.0
margin() float[source]

Space needed right of the starting point

class boxes.edges.Hinge(boxes, settings=None, layout: int = 1)[source]

Bases: BaseEdge

char: str | None = 'i'
description: str = 'Straight edge with hinge eye'
flush(_reversed: bool = False) None[source]
flushlen() float[source]
margin() float[source]

Space needed right of the starting point

outset(_reversed: bool = False) None[source]
outsetlen() float[source]
class boxes.edges.HingePin(boxes, settings=None, layout: int = 1)[source]

Bases: BaseEdge

char: str | None = 'I'
description: str = 'Edge with hinge pin'
endwidth() float[source]
flush(_reversed: bool = False) None[source]
flushlen()[source]
margin() float[source]

Space needed right of the starting point

outset(_reversed: bool = False) None[source]
outsetlen()[source]
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.HingeSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Hinges and HingePins Values:

  • absolute_params

  • style : “outset” : “outset” or “flush”

  • outset : False : have lid overlap at the sides (similar to OutSetEdge)

  • pinwidth : 1.0 : set to lower value to get disks surrounding the pins

  • grip_percentage” : 0 : percentage of the lid that should get grips

  • relative (in multiples of thickness)

  • hingestrength : 1 : thickness of the arc holding the pin in place (multiples of thickness)

  • axle : 2 : diameter of the pin hole (multiples of thickness)

  • grip_length : 0 : fixed length of the grips on he lids (multiples of thickness)

absolute_params: dict[str, Any] = {'grip_percentage': 0, 'outset': False, 'pinwidth': 0.5, 'style': ('outset', 'flush')}
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

edgeObjects(boxes, chars: str = 'iIjJkK', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'axle': 2.0, 'grip_length': 0, 'hingestrength': 1}
class boxes.edges.LidEdge(boxes, settings)[source]

Bases: FingerJointEdge

char: str | None = 'l'
description: str = 'Edge for slide on lid (back)'
class boxes.edges.LidHoleEdge(boxes, fingerHoles=None, **kw)[source]

Bases: FingerHoleEdge

char: str | None = 'L'
description: str = 'Edge for slide on lid (box back)'
class boxes.edges.LidLeft(boxes, settings)[source]

Bases: LidRight

char: str | None = 'm'
description: str = 'Edge for slide on lid (left)'
rightside = False
class boxes.edges.LidRight(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'n'
description: str = 'Edge for slide on lid (right)'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

rightside = True
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.LidSideLeft(boxes, settings)[source]

Bases: LidSideRight

char: str | None = 'M'
description: str = 'Edge for slide on lid (box left)'
rightside = False
class boxes.edges.LidSideRight(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'N'
description: str = 'Edge for slide on lid (box right)'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

rightside = True
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.MountingEdge(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'G'
description: str = 'Edge with pear shaped mounting holes'
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.MountingSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Mounting Edge Values: * absolute_params

  • style : “straight edge, within” : edge style

  • side : “back” : side of box (not all valid configurations make sense…)

  • num : 2 : number of mounting holes (integer)

  • margin : 0.125 : minimum space left and right without holes (fraction of the edge length)

  • d_shaft : 3.0 : shaft diameter of mounting screw (in mm)

  • d_head : 6.5 : head diameter of mounting screw (in mm)

PARAM_BACK = 'back'
PARAM_EXT = 'straight edge, extended'
PARAM_FRONT = 'front'
PARAM_IN = 'straight edge, within'
PARAM_LEFT = 'left'
PARAM_RIGHT = 'right'
PARAM_TAB = 'mounting tab'
absolute_params: dict[str, Any] = {'d_head': 6.5, 'd_shaft': 3.0, 'margin': 0.125, 'num': 2, 'side': ('back', 'left', 'right', 'front'), 'style': ('straight edge, within', 'straight edge, extended', 'mounting tab')}
edgeObjects(boxes, chars: str = 'G', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

class boxes.edges.NoopEdge(boxes, margin=0)[source]

Bases: BaseEdge

Edge which does nothing, not even turn or move.

margin() float[source]

Space needed right of the starting point

class boxes.edges.OutSetEdge(boxes, settings)[source]

Bases: Edge

Straight edge out set by one thickness

char: str | None = 'E'
description: str = 'Straight Edge (outset by thickness)'
positive = True
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.RackEdge(boxes, settings)[source]

Bases: BaseEdge

char: str | None = 'R'
description: str = 'Rack (and pinion) Edge'
margin() float[source]

Space needed right of the starting point

class boxes.edges.RoundedTriangleEdge(boxes, settings)[source]

Bases: Edge

Makes an ‘edge’ with a rounded triangular bumpout and optional hole

char: str | None = 't'
description: str = 'Triangle for handle'
margin() float[source]

Space needed right of the starting point

class boxes.edges.RoundedTriangleEdgeSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for RoundedTriangleEdge Values:

  • absolute_params

  • height : 150. : height above the wall

  • radius : 30. : radius of top corner

  • r_hole : 0. : radius of hole

  • relative (in multiples of thickness)

  • outset : 0 : extend the triangle along the length of the edge (multiples of thickness)

absolute_params: dict[str, Any] = {'height': 50.0, 'r_hole': 2.0, 'radius': 30.0}
edgeObjects(boxes, chars: str = 't', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'outset': 0.0}
class boxes.edges.RoundedTriangleFingerHolesEdge(boxes, settings)[source]

Bases: RoundedTriangleEdge

char: str | None = 'T'
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.Settings(thickness, relative: bool = True, **kw)[source]

Bases: object

Generic Settings class

Used by different other classes to store measurements and details. Supports absolute values and settings that grow with the thickness of the material used.

Overload the absolute_params and relative_params class attributes with the supported keys and default values. The values are available via attribute access.

Store values that are not supposed to be changed by the users in class or instance properties. This way API users can set them as needed while still be shared between all (Edge) instances using this settings object.

absolute_params: dict[str, Any] = {}
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

edgeObjects(boxes, chars: str = '', add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

classmethod parserArguments(parser, prefix=None, **defaults)[source]
relative_params: dict[str, Any] = {}
setValues(thickness, relative: bool = True, **kw)[source]

Set values

Parameters:
  • thickness – thickness of the material used

  • relative – Do scale by thickness (Default value = True)

  • kw – parameters to set

class boxes.edges.SlideOnLidSettings(thickness, relative: bool = True, **kw)[source]

Bases: FingerJointSettings

Settings for Slide-on Lids

Note that edge_width below also determines how much the sides extend above the lid.

Values:

  • absolute_params

  • second_pin : True : additional pin for better positioning

  • spring : “both” : position(s) of the extra locking springs in the lid

  • hole_width0width of the “finger hole” in mm

    Settings for Finger Joints

Values:

  • absolute * style : “rectangular” : style of the fingers * surroundingspaces : 2.0 : space at the start and end in multiple of normal spaces

  • relative (in multiples of thickness)

    • space : 2.0 : space between fingers (multiples of thickness)

    • finger : 2.0 : width of the fingers (multiples of thickness)

    • width : 1.0 : width of finger holes (multiples of thickness)

    • edge_width : 1.0 : space below holes of FingerHoleEdge (multiples of thickness)

    • play : 0.0 : extra space to allow finger move in and out (multiples of thickness)

    • extra_length : 0.0 : extra material to grind away burn marks (multiples of thickness)

    • bottom_lip : 0.0 : height of the bottom lips sticking out (multiples of thickness) FingerHoleEdge only!

absolute_params: dict[str, Any] = {'hole_width': 0, 'second_pin': True, 'spring': ('both', 'none', 'left', 'right'), 'style': ('rectangular', 'springs', 'barbs', 'snap'), 'surroundingspaces': 2.0}
edgeObjects(boxes, chars=None, add: bool = True)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'bottom_lip': 0.0, 'edge_width': 1.0, 'extra_length': 0.0, 'finger': 3.0, 'play': 0.05, 'space': 2.0, 'width': 1.0}
class boxes.edges.Slot(boxes, depth)[source]

Bases: BaseEdge

Edge with a slot to slide another piece through

description: str = 'Slot'
class boxes.edges.SlottedEdge(boxes, sections, edge: str = 'e', slots: int = 0)[source]

Bases: BaseEdge

Edge with multiple slots

description: str = 'Straight Edge with slots'
endwidth() float[source]
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.StackableBaseEdge(boxes, settings, fingerjointsettings)[source]

Bases: BaseEdge

Edge for having stackable Boxes. The Edge creates feet on the bottom and has matching recesses on the top corners.

bottom = True
char: str | None = 's'
description: str = 'Abstract Stackable class'
margin() float[source]

Space needed right of the starting point

startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.StackableEdge(boxes, settings, fingerjointsettings)[source]

Bases: StackableBaseEdge

Edge for having stackable Boxes. The Edge creates feet on the bottom and has matching recesses on the top corners.

char: str | None = 's'
description: str = 'Stackable (bottom, finger joint holes)'
class boxes.edges.StackableEdgeTop(boxes, settings, fingerjointsettings)[source]

Bases: StackableBaseEdge

bottom = False
char: str | None = 'S'
description: str = 'Stackable (top)'
class boxes.edges.StackableFeet(boxes, settings, fingerjointsettings)[source]

Bases: StackableBaseEdge

char: str | None = 'š'
description: str = 'Stackable feet (bottom)'
class boxes.edges.StackableHoleEdgeTop(boxes, settings, fingerjointsettings)[source]

Bases: StackableBaseEdge

bottom = False
char: str | None = 'Š'
description: str = 'Stackable edge with finger holes (top)'
startwidth() float[source]

Amount of space the beginning of the edge is set below the inner space of the part

class boxes.edges.StackableSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Stackable Edges

Values:

  • absolute_params

    • angle : 60 : inside angle of the feet

  • relative (in multiples of thickness)

    • height : 2.0 : height of the feet (multiples of thickness)

    • width : 4.0 : width of the feet (multiples of thickness)

    • holedistance : 1.0 : distance from finger holes to bottom edge (multiples of thickness)

    • bottom_stabilizers : 0.0 : height of strips to be glued to the inside of bottom edges (multiples of thickness)

absolute_params: dict[str, Any] = {'angle': 60}
checkValues() None[source]

Check if all values are in the right range. Raise ValueError if needed.

edgeObjects(boxes, chars: str = 'sSšŠ', add: bool = True, fingersettings=None)[source]

Generate Edge objects using this kind of settings

Parameters:
  • boxes – Boxes object

  • chars – sequence of chars to be used by Edge objects

  • add – add the resulting Edge objects to the Boxes object’s edges

relative_params: dict[str, Any] = {'bottom_stabilizers': 0.0, 'height': 2.0, 'holedistance': 1.0, 'width': 4.0}
boxes.edges.argparseSections(s: str) list[float][source]

Parse sections parameter

Parameters:

s – string to parse

boxes.edges.getDescriptions() dict[source]

boxes.formats module

class boxes.formats.Formats[source]

Bases: object

convert(data, fmt)[source]
formats = {'dxf': '{pstoedit} -flat 0.1 -f dxf:-mm {input} {output}', 'gcode': '{pstoedit} -f gcode {input} {output}', 'lbrn2': None, 'pdf': '{ps2pdf} -dEPSCrop {input} {output}', 'plt': '{pstoedit} -f hpgl {input} {output}', 'ps': None, 'svg': None, 'svg_Ponoko': None}
getFormats()[source]
getSurface(fmt)[source]
http_headers = {'dxf': [('Content-type', 'image/vnd.dxf')], 'gcode': [('Content-type', 'text/plain; charset=utf-8')], 'lbrn2': [('Content-type', 'application/lbrn2')], 'plt': [('Content-type', ' application/vnd.hp-hpgl')], 'ps': [('Content-type', 'application/postscript')], 'svg': [('Content-type', 'image/svg+xml; charset=utf-8')], 'svg_Ponoko': [('Content-type', 'image/svg+xml; charset=utf-8')]}
ps2pdf_candidates = ['/usr/bin/ps2pdf', 'ps2pdf', 'ps2pdf.exe']
pstoedit_candidates = ['/usr/bin/pstoedit', 'pstoedit', 'pstoedit.exe']

boxes.gears module

class boxes.gears.Gears(boxes, **kw)[source]

Bases: object

calc_circular_pitch()[source]

We use math based on circular pitch.

gearCarrier(r, spoke_width, positions, mount_radius, mount_hole, circle=True, callback=None, move=None)[source]
generate_spokes(root_radius, spoke_width, spokes, mount_radius, mount_hole, unit_factor, unit_label)[source]

given a set of constraints - generate the svg path for the gear spokes - lies between mount_radius (inner hole) and root_radius (bottom of the teeth) - spoke width also defines the spacing at the root_radius - mount_radius is adjusted so that spokes fit if there is room - if no room (collision) then spokes not drawn

sizes(**kw)[source]
class boxes.gears.OptionParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=<class 'argparse.HelpFormatter'>, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True)[source]

Bases: ArgumentParser

add_option(short, long_, **kw)[source]
types = {'float': <class 'float'>, 'inkbool': <function inkbool>, 'int': <class 'int'>, 'string': <class 'str'>}
boxes.gears.gear_calculations(num_teeth, circular_pitch, pressure_angle, clearance=0, ring_gear=False, profile_shift=0.0)[source]

Put base calcs for spur/ring gears in one place. - negative profile shifting helps against undercut.

boxes.gears.generate_rack_points(tooth_count, pitch, addendum, pressure_angle, base_height, tab_length, clearance=0, draw_guides=False)[source]

Return path (suitable for svg) of the Rack gear. - rack gear uses straight sides

  • involute on a circle of infinite radius is a simple linear ramp

  • the meshing circle touches at y = 0,

  • the highest elevation of the teeth is at y = +addendum

  • the lowest elevation of the teeth is at y = -addendum-clearance

  • the base_height extends downwards from the lowest elevation.

  • we generate this middle tooth exactly centered on the y=0 line. (one extra tooth on the right hand side, if number of teeth is even)

boxes.gears.generate_spur_points(teeth, base_radius, pitch_radius, outer_radius, root_radius, accuracy_involute, accuracy_circular)[source]

given a set of core gear params - generate the svg path for the gear

boxes.gears.have_undercut(teeth, pitch_angle=20.0, k=1.0)[source]

returns true if the specified number of teeth would cause an undercut.

boxes.gears.inkbool(val)[source]
boxes.gears.involute_intersect_angle(Rb, R)[source]
boxes.gears.linspace(a, b, n)[source]

return list of linear interp of a to b in n steps - if a and b are ints - you’ll get an int result. - n must be an integer

boxes.gears.point_on_circle(radius, angle)[source]

return xy coord of the point at distance radius from origin at angle

boxes.gears.undercut_max_k(teeth, pitch_angle=20.0)[source]

computes the maximum k value for a given teeth count and pitch_angle so that no undercut occurs.

boxes.gears.undercut_min_angle(teeth, k=1.0)[source]

computes the minimum pitch angle, to that the given teeth count (and profile shift) cause no undercut.

boxes.gears.undercut_min_teeth(pitch_angle, k=1.0)[source]

computes the minimum tooth count for a spur gear so that no undercut with the given pitch_angle (in deg) and an addendum = k * metric_module, where 0 < k < 1

Note: The return value should be rounded upwards for perfect safety. E.g. min_teeth = int(math.ceil(undercut_min_teeth(20.0))) # 18, not 17

boxes.lids module

class boxes.lids.Lid(boxes, settings: LidSettings)[source]

Bases: object

chestSide(x: float, angle: float = 0, move='', label: str = '') None[source]
chestTop(x: float, y: float, angle: float = 0, callback=None, move=None, label: str = '') None[source]
getChestR(x: float, angle: float = 0) float[source]
handleCB(x: float, y: float) Callable[source]
handleParts(x: float, y: float) None[source]
knobHandle(x: float, y: float, style, move=None) None[source]
longHandle(x: float, y: float, style='long_rounded', move=None) None[source]
class boxes.lids.LidSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for the Lid Values: * absolute

  • style : “none” : type of lid to create

  • handle : “none” : type of handle

  • relative (in multiples of thickness)

    • height : 4.0 : height of the brim (if any)

    • play : 0.1 : play when sliding the lid on (if applicable)

    • handle_height : 8.0 : height of the handle (if applicable)

absolute_params: dict[str, Any] = {'handle': ('none', 'long_rounded', 'long_trapezoid', 'long_doublerounded', 'knob'), 'style': ('none', 'flat', 'chest', 'overthetop', 'ontop')}
relative_params: dict[str, Any] = {'handle_height': 8.0, 'height': 4.0, 'play': 0.1}

boxes.mounts module

boxes.parts module

class boxes.parts.Parts(boxes)[source]

Bases: object

concaveKnob(diameter: float, n: int = 3, rounded: float = 0.2, angle: float = 70, hole: float = 0, callback: Callable | None = None, move: str = '') None[source]

Knob with dents to be easier to be gripped

Parameters:
  • diameter – diameter of the knob

  • n – (Default value = 3) number of dents

  • rounded – (Default value = 0.2) proportion of circumference remaining

  • angle – (Default value = 70) angle the dents meet the circumference

  • hole – (Default value = 0)

  • callback – (Default value = None) called in the center

  • move – (Default value = “”)

disc(diameter: float, hole: float = 0, dwidth: float = 1.0, callback: Callable | None = None, move: str = '', label: str = '') None[source]

Simple disc

Parameters:
  • diameter – diameter of the disc

  • hole – (Default value = 0)

  • callback – (Default value = None) called in the center

  • dwidth – (Default value = 1) flatten on right side to given ratio

  • move – (Default value = “”)

  • label – (Default value = “”)

ringSegment(r_outside: float, r_inside: float, angle: float, n: int = 1, move: str = '') None[source]

Ring Segment

Parameters:
  • r_outside – outer radius

  • r_inside – inner radius

  • angle – angle the segment is spanning

  • n – (Default value = 1) number of segments

  • move – (Default value = “”)

wavyKnob(diameter: float, n: int = 20, angle: float = 45, hole: float = 0, callback: Callable | None = None, move: str = '') None[source]

Disc with a wavy edge to be easier to be gripped

Parameters:
  • diameter – diameter of the knob

  • n – (Default value = 20) number of waves

  • angle – (Default value = 45) maximum angle of the wave

  • hole – (Default value = 0)

  • callback – (Default value = None) called in the center

  • move – (Default value = “”)

boxes.parts.arcOnCircle(spanning_angle: float, outgoing_angle: float, r: float = 1.0) tuple[float, float][source]

boxes.pulley module

// Parametric Pulley with multiple belt profiles // by droftarts January 2012

// Based on pulleys by: // https://www.thingiverse.com/thing:11256 by me! // https://github.com/prusajr/PrusaMendel by Josef Prusa // https://www.thingiverse.com/thing:3104 by GilesBathgate // https://www.thingiverse.com/thing:2079 by nophead

// dxf tooth data from http://oem.cadregister.com/asp/PPOW_Entry.asp?company=915217&elementID=07807803/METRIC/URETH/WV0025/F // pulley diameter checked and modelled from data at https://www.sdp-si.com/D265/HTML/D265T016.html

class boxes.pulley.Pulley(boxes)[source]

Bases: object

diameter(teeth, profile)[source]
classmethod getProfiles()[source]
profile_data = {'40DP': (0.457, 1.226), 'AT5': (1.19, 4.268), 'GT2_2mm': (0.764, 1.494), 'GT2_3mm': (1.169, 2.31), 'GT2_5mm': (1.969, 3.952), 'H': (1.905, 5.359), 'HTD_3mm': (1.289, 2.27), 'HTD_5mm': (2.199, 3.781), 'HTD_8mm': (3.607, 6.603), 'MXL': (0.508, 1.321), 'T10': (2.5, 6.13), 'T2_5': (0.7, 1.678), 'T5': (1.19, 3.264), 'XL': (1.27, 3.051)}
spacing = {'40DP': (False, 2.07264, 0.1778), 'AT5': (True, 0.6523, 1.591, 1.064), 'GT2_2mm': (False, 2, 0.254), 'GT2_3mm': (False, 3, 0.381), 'GT2_5mm': (False, 5, 0.5715), 'H': (False, 9.525, 0.381), 'HTD_3mm': (False, 3, 0.381), 'HTD_5mm': (False, 5, 0.5715), 'HTD_8mm': (False, 8, 0.6858), 'MXL': (False, 2.032, 0.254), 'T10': (False, 10, 0.93), 'T2_5': (True, 0.7467, 0.796, 1.026), 'T5': (True, 0.6523, 1.591, 1.064), 'XL': (False, 5.08, 0.254)}
teeth = {'40DP': [[-0.612775, -0.5], [-0.612775, 0], [-0.574719, 0.010187], [-0.546453, 0.0381], [-0.355953, 0.3683], [-0.327604, 0.405408], [-0.291086, 0.433388], [-0.248548, 0.451049], [-0.202142, 0.4572], [0.202494, 0.4572], [0.248653, 0.451049], [0.291042, 0.433388], [0.327609, 0.405408], [0.356306, 0.3683], [0.546806, 0.0381], [0.574499, 0.010187], [0.612775, 0], [0.612775, -0.5]], 'AT5': [[-2.134129, -0.75], [-2.134129, 0], [-2.058023, 0.005488], [-1.984595, 0.021547], [-1.914806, 0.047569], [-1.849614, 0.082947], [-1.789978, 0.127073], [-1.736857, 0.179338], [-1.691211, 0.239136], [-1.653999, 0.305859], [-1.349199, 0.959203], [-1.286933, 1.054635], [-1.201914, 1.127346], [-1.099961, 1.173664], [-0.986896, 1.18992], [0.986543, 1.18992], [1.099614, 1.173664], [1.201605, 1.127346], [1.286729, 1.054635], [1.349199, 0.959203], [1.653646, 0.305859], [1.690859, 0.239136], [1.73651, 0.179338], [1.789644, 0.127073], [1.849305, 0.082947], [1.914539, 0.047569], [1.984392, 0.021547], [2.057906, 0.005488], [2.134129, 0], [2.134129, -0.75]], 'GT2_2mm': [[-0.747183, -0.5], [-0.747183, 0], [-0.647876, 0.037218], [-0.598311, 0.130528], [-0.578556, 0.238423], [-0.547158, 0.343077], [-0.504649, 0.443762], [-0.451556, 0.53975], [-0.358229, 0.636924], [-0.2484, 0.707276], [-0.127259, 0.750044], [0, 0.76447], [0.127259, 0.750044], [0.2484, 0.707276], [0.358229, 0.636924], [0.451556, 0.53975], [0.504797, 0.443762], [0.547291, 0.343077], [0.578605, 0.238423], [0.598311, 0.130528], [0.648009, 0.037218], [0.747183, 0], [0.747183, -0.5]], 'GT2_3mm': [[-1.155171, -0.5], [-1.155171, 0], [-1.065317, 0.016448], [-0.989057, 0.062001], [-0.93297, 0.130969], [-0.90364, 0.217664], [-0.863705, 0.408181], [-0.800056, 0.591388], [-0.713587, 0.765004], [-0.60519, 0.926747], [-0.469751, 1.032548], [-0.320719, 1.108119], [-0.162625, 1.153462], [0, 1.168577], [0.162625, 1.153462], [0.320719, 1.108119], [0.469751, 1.032548], [0.60519, 0.926747], [0.713587, 0.765004], [0.800056, 0.591388], [0.863705, 0.408181], [0.90364, 0.217664], [0.932921, 0.130969], [0.988924, 0.062001], [1.065168, 0.016448], [1.155171, 0], [1.155171, -0.5]], 'GT2_5mm': [[-1.975908, -0.75], [-1.975908, 0], [-1.797959, 0.03212], [-1.646634, 0.121224], [-1.534534, 0.256431], [-1.474258, 0.426861], [-1.446911, 0.570808], [-1.411774, 0.712722], [-1.368964, 0.852287], [-1.318597, 0.989189], [-1.260788, 1.123115], [-1.195654, 1.25375], [-1.12331, 1.380781], [-1.043869, 1.503892], [-0.935264, 1.612278], [-0.817959, 1.706414], [-0.693181, 1.786237], [-0.562151, 1.851687], [-0.426095, 1.9027], [-0.286235, 1.939214], [-0.143795, 1.961168], [0, 1.9685], [0.143796, 1.961168], [0.286235, 1.939214], [0.426095, 1.9027], [0.562151, 1.851687], [0.693181, 1.786237], [0.817959, 1.706414], [0.935263, 1.612278], [1.043869, 1.503892], [1.123207, 1.380781], [1.195509, 1.25375], [1.26065, 1.123115], [1.318507, 0.989189], [1.368956, 0.852287], [1.411872, 0.712722], [1.447132, 0.570808], [1.474611, 0.426861], [1.534583, 0.256431], [1.646678, 0.121223], [1.798064, 0.03212], [1.975908, 0], [1.975908, -0.75]], 'H': [[-2.6797, -1], [-2.6797, 0], [-2.600907, 0.006138], [-2.525342, 0.024024], [-2.45412, 0.052881], [-2.388351, 0.091909], [-2.329145, 0.140328], [-2.277614, 0.197358], [-2.234875, 0.262205], [-2.202032, 0.334091], [-1.75224, 1.57093], [-1.719538, 1.642815], [-1.676883, 1.707663], [-1.62542, 1.764693], [-1.566256, 1.813112], [-1.500512, 1.85214], [-1.4293, 1.880997], [-1.353742, 1.898883], [-1.274949, 1.905021], [1.275281, 1.905021], [1.354056, 1.898883], [1.429576, 1.880997], [1.500731, 1.85214], [1.566411, 1.813112], [1.625508, 1.764693], [1.676919, 1.707663], [1.719531, 1.642815], [1.752233, 1.57093], [2.20273, 0.334091], [2.235433, 0.262205], [2.278045, 0.197358], [2.329455, 0.140328], [2.388553, 0.091909], [2.454233, 0.052881], [2.525384, 0.024024], [2.600904, 0.006138], [2.6797, 0], [2.6797, -1]], 'HTD_3mm': [[-1.135062, -0.5], [-1.135062, 0], [-1.048323, 0.015484], [-0.974284, 0.058517], [-0.919162, 0.123974], [-0.889176, 0.206728], [-0.81721, 0.579614], [-0.800806, 0.653232], [-0.778384, 0.72416], [-0.750244, 0.792137], [-0.716685, 0.856903], [-0.678005, 0.918199], [-0.634505, 0.975764], [-0.586483, 1.029338], [-0.534238, 1.078662], [-0.47807, 1.123476], [-0.418278, 1.16352], [-0.355162, 1.198533], [-0.289019, 1.228257], [-0.22015, 1.25243], [-0.148854, 1.270793], [-0.07543, 1.283087], [-0.000176, 1.28905], [0.075081, 1.283145], [0.148515, 1.270895], [0.219827, 1.252561], [0.288716, 1.228406], [0.354879, 1.19869], [0.418018, 1.163675], [0.477831, 1.123623], [0.534017, 1.078795], [0.586276, 1.029452], [0.634307, 0.975857], [0.677809, 0.91827], [0.716481, 0.856953], [0.750022, 0.792167], [0.778133, 0.724174], [0.800511, 0.653236], [0.816857, 0.579614], [0.888471, 0.206728], [0.919014, 0.123974], [0.974328, 0.058517], [1.048362, 0.015484], [1.135062, 0], [1.135062, -0.5]], 'HTD_5mm': [[-1.89036, -0.75], [-1.89036, 0], [-1.741168, 0.02669], [-1.61387, 0.100806], [-1.518984, 0.21342], [-1.467026, 0.3556], [-1.427162, 0.960967], [-1.398568, 1.089602], [-1.359437, 1.213531], [-1.310296, 1.332296], [-1.251672, 1.445441], [-1.184092, 1.552509], [-1.108081, 1.653042], [-1.024167, 1.746585], [-0.932877, 1.832681], [-0.834736, 1.910872], [-0.730271, 1.980701], [-0.62001, 2.041713], [-0.504478, 2.09345], [-0.384202, 2.135455], [-0.259708, 2.167271], [-0.131524, 2.188443], [-0.000176, 2.198511], [0.131296, 2.188504], [0.259588, 2.167387], [0.384174, 2.135616], [0.504527, 2.093648], [0.620123, 2.04194], [0.730433, 1.980949], [0.834934, 1.911132], [0.933097, 1.832945], [1.024398, 1.746846], [1.108311, 1.653291], [1.184308, 1.552736], [1.251865, 1.445639], [1.310455, 1.332457], [1.359552, 1.213647], [1.39863, 1.089664], [1.427162, 0.960967], [1.467026, 0.3556], [1.518984, 0.21342], [1.61387, 0.100806], [1.741168, 0.02669], [1.89036, 0], [1.89036, -0.75]], 'HTD_8mm': [[-3.301471, -1], [-3.301471, 0], [-3.16611, 0.012093], [-3.038062, 0.047068], [-2.919646, 0.10297], [-2.813182, 0.177844], [-2.720989, 0.269734], [-2.645387, 0.376684], [-2.588694, 0.496739], [-2.553229, 0.627944], [-2.460801, 1.470025], [-2.411413, 1.691917], [-2.343887, 1.905691], [-2.259126, 2.110563], [-2.158035, 2.30575], [-2.041518, 2.490467], [-1.910478, 2.66393], [-1.76582, 2.825356], [-1.608446, 2.973961], [-1.439261, 3.10896], [-1.259169, 3.22957], [-1.069074, 3.335006], [-0.869878, 3.424485], [-0.662487, 3.497224], [-0.447804, 3.552437], [-0.226732, 3.589341], [-0.000176, 3.607153], [0.226511, 3.589461], [0.447712, 3.552654], [0.66252, 3.497516], [0.870027, 3.424833], [1.069329, 3.33539], [1.259517, 3.229973], [1.439687, 3.109367], [1.608931, 2.974358], [1.766344, 2.825731], [1.911018, 2.664271], [2.042047, 2.490765], [2.158526, 2.305998], [2.259547, 2.110755], [2.344204, 1.905821], [2.411591, 1.691983], [2.460801, 1.470025], [2.553229, 0.627944], [2.588592, 0.496739], [2.645238, 0.376684], [2.720834, 0.269734], [2.81305, 0.177844], [2.919553, 0.10297], [3.038012, 0.047068], [3.166095, 0.012093], [3.301471, 0], [3.301471, -1]], 'MXL': [[-0.660421, -0.5], [-0.660421, 0], [-0.621898, 0.006033], [-0.587714, 0.023037], [-0.560056, 0.049424], [-0.541182, 0.083609], [-0.417357, 0.424392], [-0.398413, 0.458752], [-0.370649, 0.48514], [-0.336324, 0.502074], [-0.297744, 0.508035], [0.297744, 0.508035], [0.336268, 0.502074], [0.370452, 0.48514], [0.39811, 0.458752], [0.416983, 0.424392], [0.540808, 0.083609], [0.559752, 0.049424], [0.587516, 0.023037], [0.621841, 0.006033], [0.660421, 0], [0.660421, -0.5]], 'T10': [[-3.06511, -1], [-3.06511, 0], [-2.971998, 0.007239], [-2.882718, 0.028344], [-2.79859, 0.062396], [-2.720931, 0.108479], [-2.651061, 0.165675], [-2.590298, 0.233065], [-2.539962, 0.309732], [-2.501371, 0.394759], [-1.879071, 2.105025], [-1.840363, 2.190052], [-1.789939, 2.266719], [-1.729114, 2.334109], [-1.659202, 2.391304], [-1.581518, 2.437387], [-1.497376, 2.47144], [-1.408092, 2.492545], [-1.314979, 2.499784], [1.314979, 2.499784], [1.408091, 2.492545], [1.497371, 2.47144], [1.581499, 2.437387], [1.659158, 2.391304], [1.729028, 2.334109], [1.789791, 2.266719], [1.840127, 2.190052], [1.878718, 2.105025], [2.501018, 0.394759], [2.539726, 0.309732], [2.59015, 0.233065], [2.650975, 0.165675], [2.720887, 0.108479], [2.798571, 0.062396], [2.882713, 0.028344], [2.971997, 0.007239], [3.06511, 0], [3.06511, -1]], 'T2_5': [[-0.839258, -0.5], [-0.839258, 0], [-0.770246, 0.021652], [-0.726369, 0.079022], [-0.529167, 0.620889], [-0.485025, 0.67826], [-0.416278, 0.699911], [0.416278, 0.699911], [0.484849, 0.67826], [0.528814, 0.620889], [0.726369, 0.079022], [0.770114, 0.021652], [0.839258, 0], [0.839258, -0.5]], 'T5': [[-1.632126, -0.5], [-1.632126, 0], [-1.568549, 0.004939], [-1.507539, 0.019367], [-1.450023, 0.042686], [-1.396912, 0.074224], [-1.349125, 0.113379], [-1.307581, 0.159508], [-1.273186, 0.211991], [-1.246868, 0.270192], [-1.009802, 0.920362], [-0.983414, 0.978433], [-0.949018, 1.030788], [-0.907524, 1.076798], [-0.859829, 1.115847], [-0.80682, 1.147314], [-0.749402, 1.170562], [-0.688471, 1.184956], [-0.624921, 1.189895], [0.624971, 1.189895], [0.688622, 1.184956], [0.749607, 1.170562], [0.807043, 1.147314], [0.860055, 1.115847], [0.907754, 1.076798], [0.949269, 1.030788], [0.9837, 0.978433], [1.010193, 0.920362], [1.246907, 0.270192], [1.273295, 0.211991], [1.307726, 0.159508], [1.349276, 0.113379], [1.397039, 0.074224], [1.450111, 0.042686], [1.507589, 0.019367], [1.568563, 0.004939], [1.632126, 0], [1.632126, -0.5]], 'XL': [[-1.525411, -1], [-1.525411, 0], [-1.41777, 0.015495], [-1.320712, 0.059664], [-1.239661, 0.129034], [-1.180042, 0.220133], [-0.793044, 1.050219], [-0.733574, 1.141021], [-0.652507, 1.210425], [-0.555366, 1.254759], [-0.447675, 1.270353], [0.447675, 1.270353], [0.555366, 1.254759], [0.652507, 1.210425], [0.733574, 1.141021], [0.793044, 1.050219], [1.180042, 0.220133], [1.239711, 0.129034], [1.320844, 0.059664], [1.417919, 0.015495], [1.525411, 0], [1.525411, -1]]}
boxes.pulley.mirrorx(points)[source]
boxes.pulley.tooth_spaceing_curvefit(teeth, b, c, d)[source]
boxes.pulley.tooth_spacing(teeth, tooth_pitch, pitch_line_offset)[source]

boxes.robot module

class boxes.robot.RobotArg(includenone=False)[source]

Bases: object

choices()[source]
html(name, default, translate)[source]
class boxes.robot.RobotArmMM(boxes, servo, servo2=None)[source]

Bases: _RobotArm

Robot arm segment with two parallel servos

class boxes.robot.RobotArmMm(boxes, servo, servo2=None)[source]

Bases: _RobotArm

Robot arm segment with two orthogonal servos

class boxes.robot.RobotArmMu(boxes, servo, servo2=None)[source]

Bases: _RobotArm

Robot arm segment with a servo and an orthogonal sets of hinge knuckles

class boxes.robot.RobotArmUU(boxes, servo, servo2=None)[source]

Bases: _RobotArm

Robot arm segment with two parallel sets of hinge knuckles

class boxes.robot.RobotArmUu(boxes, servo, servo2=None)[source]

Bases: _RobotArm

Robot arm segment with two orthogonal sets of hinge knuckles

boxes.servos module

class boxes.servos.EyeEdge(boxes, servo, fingerHoles=None, driven: bool = False, outset: bool = False, **kw)[source]

Bases: FingerHoleEdge

char: str | None = 'm'
margin() float[source]

Space needed right of the starting point

startwidth() float[source]
class boxes.servos.Servo(boxes, axle: float = 3)[source]

Bases: object

edges(edges)[source]
class boxes.servos.Servo9g(boxes, axle: float = 3)[source]

Bases: Servo

axle_pos: float = 6.0
bottom(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
front(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
height: float = 22.5
hinge_depth() float[source]
hinge_width() float[source]
length: float = 28.0
servo_axle: float = 4.6
top(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
width: float = 12.0
class boxes.servos.Servo9gt(boxes, axle: float = 3)[source]

Bases: Servo9g

bottom(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
front(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
height: float = 35
top(x: float = 0.0, y: float = 0.0, angle: float = 90.0) None[source]
class boxes.servos.ServoArg(includeNone: bool = False)[source]

Bases: object

choices() list[str][source]
html(name: str, default: str, translate) str[source]
boxes.servos.buildEdges(boxes, servo, chars: str = 'mMnN')[source]

boxes.svgutil module

boxes.vectors module

boxes.vectors.circlepoint(r, a)[source]
boxes.vectors.dotproduct(v1, v2)[source]

Dot product

boxes.vectors.kerf(points, k, closed=True)[source]

Outset points by k Assumes a closed loop of points

boxes.vectors.mmul(m0, m1)[source]
boxes.vectors.normalize(v)[source]

set length of vector to one

boxes.vectors.rotm(angle)[source]

Rotation matrix

boxes.vectors.tangent(x, y, r)[source]

angle and length of a tangent to a circle at x,y with radius r

boxes.vectors.vadd(v1, v2)[source]

Sum of two vectors

boxes.vectors.vclip(v, length)[source]
boxes.vectors.vdiff(p1, p2)[source]

vector from point1 to point2

boxes.vectors.vlength(v)[source]
boxes.vectors.vorthogonal(v)[source]

Orthogonal vector

boxes.vectors.vscalmul(v, a)[source]

scale vector by a

boxes.vectors.vtransl(v, m)[source]

Module contents

class boxes.ArgparseEdgeType(edges: str | None = None)[source]

Bases: object

argparse type to select from a set of edge types

edges: list[str] = []
html(name, default, translate)[source]
inx(name, viewname, arg)[source]
names = {'C': 'Click on (top)', 'D': 'Dove Tail Joint (opposing side)', 'E': 'Straight Edge (outset by thickness)', 'F': 'Finger Joint (opposing side)', 'G': 'Edge with pear shaped mounting holes', 'I': 'Edge with hinge pin', 'J': 'Edge with hinge pin (other end)', 'K': 'Edge with hinge pin (both ends)', 'L': 'Edge for slide on lid (box back)', 'M': 'Edge for slide on lid (box left)', 'N': 'Edge for slide on lid (box right)', 'O': 'Edge with chest hinge (other end)', 'P': 'Edge with chest hinge (other end)', 'Q': 'Edge opposing a chest hinge', 'R': 'Rack (and pinion) Edge', 'S': 'Stackable (top)', 'T': 'Triangle for handle', 'U': 'Edge with cabinet hinges top side', 'V': 'Edge with cabinet hinges 90° lid', 'X': 'Flex cut', 'Y': 'Handle with holes for parallel finger joint', 'Z': 'Edge with grooves (opposing side)', 'c': 'Click on (bottom side)', 'd': 'Dove Tail Joint', 'e': 'Straight Edge', 'f': 'Finger Joint', 'g': 'Corrugated edge useful as an gipping area', 'h': 'Edge (parallel Finger Joint Holes)', 'i': 'Straight edge with hinge eye', 'j': 'Straight edge with hinge eye (other end)', 'k': 'Straight edge with hinge eye (both ends)', 'l': 'Edge for slide on lid (back)', 'm': 'Edge for slide on lid (left)', 'n': 'Edge for slide on lid (right)', 'o': 'Edge with chest hinge', 'p': 'Edge with chest hinge', 'q': 'Edge with pins for an chest hinge', 's': 'Stackable (bottom, finger joint holes)', 't': 'Triangle for handle', 'u': 'Edge with cabinet hinges', 'v': 'Edge with cabinet hinges for 90° lid', 'y': 'Handle for e.g. a drawer', 'z': 'Edge with grooves', '|': 'Edge (orthogonal Finger Joint Holes)', 'Š': 'Stackable edge with finger holes (top)', 'š': 'Stackable feet (bottom)'}
class boxes.BoolArg[source]

Bases: object

html(name, default, _)[source]
class boxes.Boxes[source]

Bases: object

Main class – Generator should subclass this

NEMA(size, x=0, y=0, angle=0, screwholes=None)[source]

Draw holes for mounting a NEMA stepper motor

Parameters:
  • size – Nominal size in tenths of inches

  • x – (Default value = 0)

  • y – (Default value = 0)

  • angle – (Default value = 0)

  • screwholes

TX(size, x=0, y=0, angle=0)[source]

Draw a star pattern

Parameters:
  • size – 1 to 100

  • x – (Default value = 0)

  • y – (Default value = 0)

  • angle – (Default value = 0)

UI = ''
addPart(part, name=None)[source]

Add Edge or other part instance to this one and add it as attribute

Parameters:
  • part – Callable

  • name – (Default value = None) attribute name (__name__ as default)

addParts(parts)[source]
addSettingsArgs(settings, prefix=None, **defaults)[source]
adjustSize(l, e1=True, e2=True)[source]
bedBoltHole(length, bedBoltSettings=None, tabs=0)[source]

Draw an edge with slot for a bed bolt

Parameters:
  • length – length of the edge in mm

  • bedBoltSettings – (Default value = None) Dimensions of the slot

buildArgParser(*l, **kw)[source]

Add commonly used arguments

Parameters:
  • l – parameter names

  • kw – parameters with new default values

Supported parameters are

  • floats: x, y, h, hi

  • argparseSections: sx, sy, sh

  • ArgparseEdgeType: bottom_edge, top_edge

  • boolarg: outside

  • str (selection): nema_mount

cc(callback, number, x=0.0, y=None, a=0.0)[source]

Call callback from edge of a part

Parameters:
  • callback – callback (callable or list of callables)

  • number – number of the callback

  • x – (Default value = 0.0) x position to be call on

  • y – (Default value = None) y position to be called on (default does burn correction)

circle(x, y, r)[source]

Draw a round disc

Parameters:
  • x – x position

  • y – y position

  • r – radius

close()[source]

Finish rendering

Flush canvas to disk and convert output to requested format if needed. Call after .render()

corner(degrees, radius=0, tabs=0)[source]

Draw a corner

This is what does the burn corrections

Parameters:
  • degrees – angle

  • radius – (Default value = 0)

curveTo(x1, y1, x2, y2, x3, y3)[source]

control point 1, control point 2, end point

Parameters:
  • x1

  • y1

  • x2

  • y2

  • x3

  • y3

dHole(x, y, r=None, d=None, w=None, rel_w=0.75, angle=0)[source]

Draw a hole for a shaft with flat edge - D shaped hole

Parameters:
  • x – center x position

  • y – center y position

  • r – radius (overrides d)

  • d – diameter

  • w – width measured against flat side in mm

  • rel_w – width in percent

  • angle – orientation (rotation) of the flat side

description: str = ''
drawPoints(lines, kerfdir=1, close=True)[source]
edge(length, tabs=0)[source]

Simple line :param length: length in mm

edgeCorner(edge1, edge2, angle=90)[source]

Make a corner between two Edges. Take width of edges into account

fillHoles(pattern, border, max_radius, hspace=3, bspace=0, min_radius=0.5, style='round', bar_length=50, max_random=1000)[source]

fill a polygon defined by its outline with holes

Parameters:
  • pattern – defines the hole pattern - currently “random”, “hex”, “square” “hbar” or “vbar” are supported

  • border – array with coordinate [(x0,y0), (x1,y1),…] of the border polygon

  • max_radius – maximum hole radius

  • hspace – space between holes

  • bspace – space to border

  • min_radius – minimum hole radius

  • style – defines hole style - currently one of “round”, “triangle”, “square”, “hexagon” or “octagon”

  • bar_length – maximum bar length

  • max_random – maximum number of random holes

fingerHoleRectangle(dx, dy, x=0.0, y=0.0, angle=0.0, outside=False)[source]

Place finger holes for four walls - attaching a box on this plane

Parameters:
  • dx – size in x direction

  • dy – size in y direction

  • x – x position of the center

  • y – y position of the center

  • angle – angle in which the rectangle is placed

  • outside – measure size from the outside of the walls - not the inside

fingerHolesAt: Any
flangedWall(x, y, edges='FFFF', flanges=None, r=0.0, callback=None, move=None, label='')[source]

Rectangular wall with flanges extending the regular size

This is similar to the rectangularWall but it may extend to either side. Sides with flanges may only have e, E, or F edges - the later being replaced with fingerHoles.

Parameters:
  • x – width

  • y – height

  • edges – (Default value = “FFFF”) bottom, right, top, left

  • flanges – (Default value = None) list of width of the flanges

  • r – radius of the corners of the flange

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

flatHole(x, y, r=None, d=None, w=None, rel_w=0.75, angle=0)[source]

Draw a hole for a shaft with two opposed flat edges - ( ) shaped hole

Parameters:
  • x – center x position

  • y – center y position

  • r – radius (overrides d)

  • d – diameter

  • w – width measured against flat side in mm

  • rel_w – width in percent

  • angle – orientation (rotation) of the flat sides

flex2D(x, y, width=1)[source]

Fill a rectangle with a pattern allowing bending in both axis

Parameters:
  • x – width

  • y – height

  • width – width between the lines of the pattern in multiples of thickness

getEntry(param, idx)[source]

Get entry from list or items itself

Parameters:
  • param – list or item

  • idx – index in list

grip(length, depth)[source]

Corrugated edge useful as a gipping area

Parameters:
  • length – length

  • depth – depth of the grooves

handle(x, h, hl, r=30)[source]

Creates an Edge with a handle

Parameters:
  • x – width in mm

  • h – height in mm

  • hl – height if the grip hole

  • r – (Default value = 30) radius of the corners

hexHolesCircle(d, settings=None)[source]

Fill circle with holes in a hex pattern

Parameters:
  • d – diameter of the circle

  • settings – (Default value = None)

hexHolesHex(h, settings=None, grow=None)[source]

Fill a hexagon with holes in a hex pattern

Parameters:
  • h – height

  • settings – (Default value = None)

  • grow – (Default value = None)

hexHolesPlate(x, y, rc, settings=None)[source]

Fill a plate with holes in a hex pattern

Parameters:
  • x – width

  • y – height

  • rc – radius of the corners

  • settings – (Default value = None)

hexHolesRectangle(x, y, settings=None, skip=None)[source]

Fills a rectangle with holes in a hex pattern.

Settings have: r : radius of holes b : space between holes style : what types of holes (not yet implemented)

Parameters:
  • x – width

  • y – height

  • settings – (Default value = None)

  • skip – (Default value = None) function to check if hole should be present gets x, y, r, b, posx, posy

hole(x, y, r=0.0, d=0.0, tabs=0)[source]

Draw a round hole

Parameters:
  • x – x position

  • y – y position

  • r – radius

latch(length, positive=True, reverse=False, extra_length=0.0)[source]

Latch to fix a flex box door to the box

Parameters:
  • length – length in mm

  • positive – (Default value = True) False: Door side; True: Box side

  • reverse – (Default value = False) True when running away from the latch

mirrorX(f, offset=0.0)[source]

Wrap a function to draw mirrored at the y axis

Parameters:
  • f – function to wrap

  • offset – (default value = 0.0) axis to mirror at

mirrorY(f, offset=0.0)[source]

Wrap a function to draw mirrored at the x axis

Parameters:
  • f – function to wrap

  • offset – (default value = 0.0) axis to mirror at

mountingHole(x, y, d_shaft, d_head=0.0, angle=0, tabs=0)[source]

Draw a pear shaped mounting hole for sliding over a screw head. Total height = 1.5* d_shaft + d_head

Parameters:
  • x – x position

  • y – y position

  • d_shaft – diameter of the screw shaft

  • d_head – diameter of the screw head

  • angle – rotation angle of the hole

move(x, y, where, before=False, label='')[source]

Intended to be used by parts where can be combinations of “up” or “down”, “left” or “right”, “only”, “mirror” and “rotated” when “only” is included the move is only done when before is True “mirror” will flip the part along the y-axis “rotated” draws the parts rotated 90 counter clockwise The function returns whether actual drawing of the part should be omitted.

Parameters:
  • x – width of part

  • y – height of part

  • where – which direction to move

  • before – (Default value = False) called before or after part being drawn

moveArc(angle, r=0.0)[source]
Parameters:
  • angle

  • r – (Default value = 0.0)

moveTo(x, y=0.0, degrees=0)[source]

Move coordinate system to given point

Parameters:
  • x

  • y – (Default value = 0.0)

  • degrees – (Default value = 0)

nema_sizes = {8: (20.3, 16, 15.4, 3), 11: (28.2, 22, 23, 4), 14: (35.2, 22, 26, 4), 16: (39.2, 22, 31, 4), 17: (42.2, 22, 31, 4), 23: (56.4, 38.1, 47.1, 5.2), 24: (60, 36, 49.8, 5.1), 34: (86.3, 73, 69.8, 6.6), 42: (110, 55.5, 89, 8.5)}
open()[source]

Prepare for rendering

Create canvas and edge and other objects Call this before .render()

parseArgs(args=None)[source]

Parse command line parameters

Parameters:

args – (Default value = None) parameters, None for using sys.argv

partsMatrix(n, width, move, part, *l, **kw)[source]

place many of the same part

Parameters:
  • n – number of parts

  • width – number of parts in a row (0 for same as n)

  • move – (Default value = “”)

  • part – callable that draws a part and knows move param

  • l – params for part

  • kw – keyword params for part

polygonWall(borders, edge='f', turtle=False, correct_corners=True, callback=None, move=None, label='')[source]

Polygon wall for all kind of multi-edged objects

Parameters:
  • borders – array of distance and angles to draw

  • edge – (Default value = “f”) Edges to apply. If the array of borders contains more segments that edges, the edge will wrap. Only edge types without start and end width supported for now.

  • turtle – (Default value = False)

  • correct_corners – (Default value = True)

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

borders is alternating between length of the edge and angle of the corner. For now neither tabs nor radii are supported. None at the end closes the polygon.

polygonWalls(borders, h, bottom='F', top='F', symmetrical=True)[source]
polyline(*args)[source]

Draw multiple connected lines

Parameters:

args – Alternating length in mm and angle in degrees.

lengths may be a tuple (length, #tabs) angles may be tuple (angle, radius)

qrcode(content, box_size=1.0, color=[0.0, 1.0, 0.0], move=None)[source]
rectangularHole(x, y, dx, dy, r=0, center_x=True, center_y=True)[source]

Draw a rectangular hole

Parameters:
  • x – x position

  • y – y position

  • dx – width

  • dy – height

  • r – (Default value = 0) radius of the corners

  • center_x – (Default value = True) if True, x position is the center, else the start

  • center_y – (Default value = True) if True, y position is the center, else the start

rectangularTriangle(x, y, edges='eee', r=0.0, num=1, bedBolts=None, bedBoltSettings=None, callback=None, move=None, label='')[source]

Rectangular triangular wall

Parameters:
  • x – width

  • y – height

  • edges – (Default value = “eee”) bottom, right[, diagonal]

  • r – radius towards the hypotenuse

  • num – (Default value = 1) number of triangles

  • bedBolts – (Default value = None)

  • bedBoltSettings – (Default value = None)

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

rectangularWall(x, y, edges='eeee', ignore_widths=[], holesMargin=None, holesSettings=None, bedBolts=None, bedBoltSettings=None, callback=None, move=None, label='')[source]

Rectangular wall for all kind of box like objects

Parameters:
  • x – width

  • y – height

  • edges – (Default value = “eeee”) bottom, right, top, left

  • ignore_widths – list of edge_widths added to adjacent edge

  • holesMargin – (Default value = None)

  • holesSettings – (Default value = None)

  • bedBolts – (Default value = None)

  • bedBoltSettings – (Default value = None)

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

regularPolygon(corners=3, radius=None, h=None, side=None)[source]

Give measures of a regular polygon

Parameters:
  • corners – number of corners of the polygon

  • radius – distance center to one of the corners

  • h – distance center to one of the sides (height of sector)

  • side – length of one side

Returns:

(radius, h, side)

regularPolygonAt(x, y, corners, angle=0, r=None, h=None, side=None)[source]

Draw regular polygon

regularPolygonHole(x, y, r=0.0, d=0.0, n=6, a=0.0, tabs=0, corner_radius=0.0)[source]

Draw a hole in shape of an n-edged regular polygon

Parameters:
  • x – x position

  • y – y position

  • r – radius

  • n – number of edges

  • a – rotation angle

regularPolygonWall(corners=3, r=None, h=None, side=None, edges='e', hole=None, callback=None, move=None)[source]

Create regular polygon as a wall

Parameters:
  • corners – number of corners of the polygon

  • r – radius distance center to one of the corners

  • h – distance center to one of the sides (height of sector)

  • side – length of one side

  • edges – (Default value = “e”, may be string/list of length corners)

  • hole – diameter of central hole (Default value = 0)

  • callback – (Default value = None, middle=0, then sides=1..)

  • move – (Default value = None)

render()[source]

Implement this method in your subclass.

You will typically need to call .parseArgs() before calling this one

renderQrCode()[source]
roundedPlate(x, y, r, edge='f', callback=None, holesMargin=None, holesSettings=None, bedBolts=None, bedBoltSettings=None, wallpieces=1, extend_corners=True, move=None, label=None)[source]

Plate with rounded corner fitting to .surroundingWall()

For the callbacks the sides are counted depending on wallpieces

Parameters:
  • x – width

  • y – height

  • r – radius of the corners

  • edge

  • callback – (Default value = None)

  • holesMargin – (Default value = None) set to get hex holes

  • holesSettings – (Default value = None)

  • bedBolts – (Default value = None)

  • bedBoltSettings – (Default value = None)

  • wallpieces – (Default value = 1) # of separate surrounding walls

  • extend_corners – (Default value = True) have corners outset with the edges

  • move – (Default value = None)

  • label – (Default value = None)

saved_context()[source]

Generator: for saving and restoring contexts.

set_font(style, bold=False, italic=False)[source]

Set font style used :param style: “serif”, “sans-serif” or “monospaced” :param bold: Use bold font :param italic: Use italic font

set_source_color(color)[source]

Sets the color of the pen.

showBorderPoly(border, color=[1.0, 0.0, 0.0])[source]

draw border polygon (for debugging only)

Parameters:
  • border – array with coordinate [(x0,y0), (x1,y1),…] of the border polygon

  • color

step(out)[source]

Create a parallel step perpendicular to the current direction Positive values move to the outside of the part

surroundingWall(x, y, r, h, bottom='e', top='e', left='D', right='d', pieces=1, extend_corners=True, callback=None, move=None)[source]

Wall(s) with flex filing around a roundedPlate()

For the callbacks the sides are counted depending on pieces

Parameters:
  • x – width of matching roundedPlate

  • y – height of matching roundedPlate

  • r – corner radius of matching roundedPlate

  • h – inner height of the wall (without edges)

  • bottom – (Default value = ‘e’) Edge type

  • top – (Default value = ‘e’) Edge type

  • left – (Default value = ‘D’) left edge(s)

  • right – (Default value = ‘d’) right edge(s)

  • pieces – (Default value = 1) number of separate pieces

  • callback – (Default value = None)

  • move – (Default value = None)

surroundingWallPiece(cbnr, x, y, r, pieces=1)[source]

Return the geometry of a pices of surroundingWall with the given callback number. :param cbnr: number of the callback corresponding to this part of the wall :param x: width of matching roundedPlate :param y: height of matching roundedPlate :param r: corner radius of matching roundedPlate :param pieces: (Default value = 1) number of separate pieces :return: (left, length, right) left and right are Booleans that are True if the start or end of the wall is on that side.

text(text, x=0, y=0, angle=0, align='', fontsize=10, color=[0.0, 0.0, 0.0], font='Arial')[source]

Draw text

Parameters:
  • text – text to render

  • x – (Default value = 0)

  • y – (Default value = 0)

  • angle – (Default value = 0)

  • align – (Default value = “”) string with combinations of (top|middle|bottom) and (left|center|right) separated by a space

trapezoidSideWall(w, h0, h1, edges='eeee', radius=0.0, callback=None, move=None, label='')[source]

Rectangular trapezoidal wall

Parameters:
  • w – width

  • h0 – left height

  • h1 – right height

  • edges – (Default value = “eeee”) bottom, right, left

  • radius – (Default value = 0.0) radius of upper corners

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

trapezoidWall(w, h0, h1, edges='eeee', callback=None, move=None, label='')[source]

Rectangular trapezoidal wall

Parameters:
  • w – width

  • h0 – left height

  • h1 – right height

  • edges – (Default value = “eee”) bottom, right, left

  • callback – (Default value = None)

  • move – (Default value = None)

  • label – rendered to identify parts, it is not meant to be cut or etched (Default value = “”)

tx_sizes = {1: 0.61, 2: 0.7, 3: 0.82, 4: 0.96, 5: 1.06, 6: 1.27, 7: 1.49, 8: 1.75, 9: 1.87, 10: 2.05, 15: 2.4, 20: 2.85, 25: 3.25, 30: 4.05, 40: 4.85, 45: 5.64, 50: 6.45, 55: 8.05, 60: 9.6, 70: 11.2, 80: 12.8, 90: 14.4, 100: 16.0}
ui_group = 'Misc'
webinterface = True
class boxes.HexHolesSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for hexagonal hole patterns

Values:

  • absolute * diameter : 5.0 : diameter of the holes * distance : 3.0 : distance between the holes * style : “circle” : currently only supported style

absolute_params: dict[str, Any] = {'diameter': 10.0, 'distance': 3.0, 'style': ('circle',)}
relative_params: dict[str, Any] = {}
class boxes.NutHole(boxes, settings)[source]

Bases: object

Draw a hex nut

boxes.argparseSections(s)[source]

Parse sections parameter

Parameters:

s – string to parse

boxes.dist(dx, dy)[source]

Return distance

Parameters:
  • dx – delta x

  • dy – delay y

class boxes.fillHolesSettings(thickness, relative: bool = True, **kw)[source]

Bases: Settings

Settings for Hole filling

Values:

  • absolute * fill_pattern : “no fill” : style of hole pattern * hole_style : “round” : style of holes (does not apply to fill patterns ‘vbar’ and ‘hbar’) * max_random : 1000 : maximum number of random holes * bar_length : 50 : maximum length of bars * hole_max_radius : 12.0 : maximum radius of generated holes (in mm) * hole_min_radius : 4.0 : minimum radius of generated holes (in mm) * space_between_holes : 4.0 : hole to hole spacing (in mm) * space_to_border : 4.0 : hole to border spacing (in mm)

absolute_params: dict[str, Any] = {'bar_length': 50, 'fill_pattern': ('no fill', 'hex', 'square', 'random', 'hbar', 'vbar'), 'hole_max_radius': 3.0, 'hole_min_radius': 0.5, 'hole_style': ('round', 'triangle', 'square', 'hexagon', 'octagon'), 'max_random': 1000, 'space_between_holes': 4.0, 'space_to_border': 4.0}
boxes.holeCol(func)[source]

Wrapper: color holes differently

Parameters:

func – function to wrap

boxes.restore(func)[source]

Wrapper: Restore coordinates after function

Parameters:

func – function to wrap