Add minimal doc strings

This commit is contained in:
Florian Festi 2016-03-28 16:55:41 +02:00
parent 31a6af5116
commit 09871be797
2 changed files with 375 additions and 21 deletions

View File

@ -23,9 +23,21 @@ from functools import wraps
from boxes import edges from boxes import edges
def dist(dx, dy): def dist(dx, dy):
"""
Return distance
:param dx: delta x
:param dy: delat y
"""
return (dx*dx+dy*dy)**0.5 return (dx*dx+dy*dy)**0.5
def restore(func): def restore(func):
"""
Wrapper: Restore coordiantes after function
:param func: function to wrap
"""
@wraps(func) @wraps(func)
def f(self, *args, **kw): def f(self, *args, **kw):
self.ctx.save() self.ctx.save()
@ -41,6 +53,7 @@ def restore(func):
############################################################################# #############################################################################
class NutHole: class NutHole:
"""Draw a hex nut"""
sizes = { sizes = {
"M1.6" : (3.2, 1.3), "M1.6" : (3.2, 1.3),
"M2" : (4, 1.6), "M2" : (4, 1.6),
@ -80,6 +93,12 @@ class NutHole:
self.boxes.corner(-60) self.boxes.corner(-60)
def argparseSections(s): def argparseSections(s):
"""
Parse sections parameter
:param s: string to parse
"""
m = re.match(r"(\d+(\.\d+)?)/(\d+)", s) m = re.match(r"(\d+(\.\d+)?)/(\d+)", s)
if m: if m:
n = int(m.group(3)) n = int(m.group(3))
@ -95,6 +114,7 @@ def argparseSections(s):
raise argparse.ArgumentTypeError("Don't understand sections string") raise argparse.ArgumentTypeError("Don't understand sections string")
class Boxes: class Boxes:
"""Main class -- Generator should sub class this """
def __init__(self): def __init__(self):
self.argparser = ArgumentParser(description=self.__doc__) self.argparser = ArgumentParser(description=self.__doc__)
@ -112,6 +132,15 @@ class Boxes:
help="burn correction in mm") help="burn correction in mm")
def open(self, width, height): def open(self, width, height):
"""
Prepare for rendering
Call this function from your .render() method
:param width: width of canvas in mm
:param height: height of canvas in mm
"""
self.spacing = 2*self.burn + 0.5 * self.thickness self.spacing = 2*self.burn + 0.5 * self.thickness
self.fingerHoleEdgeWidth = 1.0 # multitudes of self.thickness self.fingerHoleEdgeWidth = 1.0 # multitudes of self.thickness
@ -121,6 +150,12 @@ class Boxes:
self._buildObjects() self._buildObjects()
def buildArgParser(self, *l): def buildArgParser(self, *l):
"""
Add commonly used commandf line parameters
:param \*l: parameter names
"""
for arg in l: for arg in l:
if arg == "x": if arg == "x":
self.argparser.add_argument( self.argparser.add_argument(
@ -153,9 +188,22 @@ class Boxes:
raise ValueError("No default for argument", arg) raise ValueError("No default for argument", arg)
def parseArgs(self, args=None): def parseArgs(self, args=None):
"""
Parse command line parameters
:param args: (Default value = None) parameters, None for using sys.argv
"""
self.argparser.parse_args(args=args, namespace=self) self.argparser.parse_args(args=args, namespace=self)
def addPart(self, part, name=None): def addPart(self, part, name=None):
"""
Add Edge or other part instance to this one and add it as attribute
:param part: Callable
:param name: (Default value = None) attribute name (__name__ as default)
"""
if name is None: if name is None:
name = part.__class__.__name__ name = part.__class__.__name__
name = name[0].lower() + name[1:] name = name[0].lower() + name[1:]
@ -165,6 +213,7 @@ class Boxes:
self.edges[part.char] = part self.edges[part.char] = part
def _buildObjects(self): def _buildObjects(self):
"""Add default edges and parts """
self.edges = {} self.edges = {}
self.addPart(edges.Edge(self, None)) self.addPart(edges.Edge(self, None))
self.addPart(edges.OutSetEdge(self, None)) self.addPart(edges.OutSetEdge(self, None))
@ -185,6 +234,13 @@ class Boxes:
self.addPart(NutHole(self, None)) self.addPart(NutHole(self, None))
def _init_surface(self, width, height): def _init_surface(self, width, height):
"""
Initialize cairo canvas
:param width: canvas size
:param height: canvas height
"""
#mm2pt = 90 / 25.4 / 1.25 #mm2pt = 90 / 25.4 / 1.25
mm2pt = 1 mm2pt = 1
#width *= mm2pt #width *= mm2pt
@ -203,7 +259,14 @@ class Boxes:
def cc(self, callback, number, x=0.0, y=None): def cc(self, callback, number, x=0.0, y=None):
"""call callback""" """Call callback from edge of a part
:param callback: callback (callable or list of callables)
:param number: number of the callback
:param x: (Default value = 0.0) x position to be call on
:param y: (Default value = None) y position to be called on (default does burn correction)
"""
if y is None: if y is None:
y = self.burn y = self.burn
self.ctx.save() self.ctx.save()
@ -223,6 +286,13 @@ class Boxes:
self.ctx.restore() self.ctx.restore()
def getEntry(self, param, idx): def getEntry(self, param, idx):
"""
Get entry from list or items itself
:param param: list or item
:param idx: index in list
"""
if isinstance(param, list): if isinstance(param, list):
if len(param)>idx: if len(param)>idx:
return param[idx] return param[idx]
@ -232,6 +302,9 @@ class Boxes:
return param return param
def close(self): def close(self):
"""Finish rendering
Call at the end of your .render() method"""
self.ctx.stroke() self.ctx.stroke()
self.surface.flush() self.surface.flush()
self.surface.finish() self.surface.finish()
@ -256,6 +329,15 @@ class Boxes:
############################################################ ############################################################
def corner(self, degrees, radius=0): def corner(self, degrees, radius=0):
"""
Draw a corner
This is what does the burn corrections
:param degrees: angle
:param radius: (Default value = 0)
"""
rad = degrees*math.pi/180 rad = degrees*math.pi/180
if degrees > 0: if degrees > 0:
self.ctx.arc(0, radius+self.burn, radius+self.burn, self.ctx.arc(0, radius+self.burn, radius+self.burn,
@ -270,12 +352,26 @@ class Boxes:
self.continueDirection(rad) self.continueDirection(rad)
def edge(self, length): def edge(self, length):
"""
Simple line
:param length: length in mm
"""
self.ctx.move_to(0,0) self.ctx.move_to(0,0)
self.ctx.line_to(length, 0) self.ctx.line_to(length, 0)
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
def curveTo(self, x1, y1, x2, y2, x3, y3): def curveTo(self, x1, y1, x2, y2, x3, y3):
"""control point 1, control point 2, end point""" """control point 1, control point 2, end point
:param x1:
:param y1:
:param x2:
:param y2:
:param x3:
:param y3:
"""
self.ctx.curve_to(x1, y1, x2, y2, x3, y3) self.ctx.curve_to(x1, y1, x2, y2, x3, y3)
dx = x3-x2 dx = x3-x2
dy = y3-y2 dy = y3-y2
@ -283,6 +379,12 @@ class Boxes:
self.continueDirection(rad) self.continueDirection(rad)
def polyline(self, *args): def polyline(self, *args):
"""
Draw multiple connected lines
:param \*args: Alternating length in mm and angle
"""
for i, arg in enumerate(args): for i, arg in enumerate(args):
if i % 2: if i % 2:
self.corner(arg) self.corner(arg)
@ -290,6 +392,13 @@ class Boxes:
self.edge(arg) self.edge(arg)
def bedBoltHole(self, length, bedBoltSettings=None): def bedBoltHole(self, length, bedBoltSettings=None):
"""
Draw an edge with slot for a bed bolt
:param length: length of the edge in mm
:param bedBoltSettings: (Default value = None) Dimmensions of the slot
"""
d, d_nut, h_nut, l, l1 = bedBoltSettings or self.bedBoltSettings d, d_nut, h_nut, l, l1 = bedBoltSettings or self.bedBoltSettings
self.edge((length-d)/2.0) self.edge((length-d)/2.0)
self.corner(90) self.corner(90)
@ -319,7 +428,12 @@ class Boxes:
def grip(self, length, depth): def grip(self, length, depth):
"""corrugated edge useful as an gipping area""" """Corrugated edge useful as an gipping area
:param length: length
:param depth: depth of the grooves
"""
grooves = int(length // (depth*2.0)) + 1 grooves = int(length // (depth*2.0)) + 1
depth = length / grooves / 4.0 depth = length / grooves / 4.0
for groove in range(grooves): for groove in range(grooves):
@ -328,6 +442,11 @@ class Boxes:
self.corner(90, depth) self.corner(90, depth)
def _latchHole(self, length): def _latchHole(self, length):
"""
:param length:
"""
self.edge(1.1*self.thickness) self.edge(1.1*self.thickness)
self.corner(-90) self.corner(-90)
self.edge(length/2.0+0.2*self.thickness) self.edge(length/2.0+0.2*self.thickness)
@ -335,14 +454,22 @@ class Boxes:
self.edge(1.1*self.thickness) self.edge(1.1*self.thickness)
def _latchGrip(self, length): def _latchGrip(self, length):
"""
:param length:
"""
self.corner(90, self.thickness/4.0) self.corner(90, self.thickness/4.0)
self.grip(length/2.0-self.thickness/2.0-0.2*self.thickness, self.thickness/2.0) self.grip(length/2.0-self.thickness/2.0-0.2*self.thickness, self.thickness/2.0)
self.corner(90, self.thickness/4.0) self.corner(90, self.thickness/4.0)
def latch(self, length, positive=True, reverse=False): def latch(self, length, positive=True, reverse=False):
"""Fix a flex box door at the box """Latch to fix a flex box door to the box
positive: False: Door side; True: Box side
reverse: True when running away from the latch :param length: length in mm
:param positive: (Default value = True) False: Door side; True: Box side
:param reverse: (Default value = False) True when running away from the latch
""" """
if positive: if positive:
if reverse: if reverse:
@ -368,7 +495,14 @@ class Boxes:
self.corner(90) self.corner(90)
def handle(self, x, h, hl, r=30): def handle(self, x, h, hl, r=30):
"""Creates and Edge with a handle""" """Creates an Edge with a handle
:param x: width in mm
:param h: height in mm
:param hl: height if th grip hole
:param r: (Default value = 30) radius of the corners
"""
d = (x-hl-2*r)/2.0 d = (x-hl-2*r)/2.0
if d < 0: if d < 0:
print("Handle too wide") print("Handle too wide")
@ -398,12 +532,26 @@ class Boxes:
### Navigation ### Navigation
def moveTo(self, x, y=0.0, degrees=0): def moveTo(self, x, y=0.0, degrees=0):
"""
Move coordinate system to given point
:param x:
:param y: (Default value = 0.0)
:param degrees: (Default value = 0)
"""
self.ctx.move_to(0, 0) self.ctx.move_to(0, 0)
self.ctx.translate(x, y) self.ctx.translate(x, y)
self.ctx.rotate(degrees*math.pi/180.0) self.ctx.rotate(degrees*math.pi/180.0)
self.ctx.move_to(0, 0) self.ctx.move_to(0, 0)
def continueDirection(self, angle=0): def continueDirection(self, angle=0):
"""
Set coordinate system to current position (end point)
:param angle: (Default value = 0) heading
"""
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
self.ctx.rotate(angle) self.ctx.rotate(angle)
@ -413,6 +561,12 @@ class Boxes:
when "only" is included the move is only done when before is True when "only" is included the move is only done when before is True
The function returns whether actual drawing of the part The function returns whether actual drawing of the part
should be omited. should be omited.
:param x: width of part
:param y: height of part
:param where: which direction to move
:param before: (Default value = False) called before or after part being drawn
""" """
if not where: if not where:
return False return False
@ -443,6 +597,17 @@ class Boxes:
def fingerHolesAt(self, x, y, length, angle=90, def fingerHolesAt(self, x, y, length, angle=90,
bedBolts=None, bedBoltSettings=None): bedBolts=None, bedBoltSettings=None):
"""
Draw holes for a matching finger joint edge
:param x: position
:param y: position
:param length: length of matching edge
:param angle: (Default value = 90)
:param bedBolts: (Default value = None)
:param bedBoltSettings: (Default value = None)
"""
self.ctx.save() self.ctx.save()
self.moveTo(x, y, angle) self.moveTo(x, y, angle)
self.fingerHoles(length, bedBolts, bedBoltSettings) self.fingerHoles(length, bedBolts, bedBoltSettings)
@ -450,11 +615,32 @@ class Boxes:
@restore @restore
def hole(self, x, y, r): def hole(self, x, y, r):
"""
Draw a round hole
:param x: position
:param y: postion
:param r: radius
"""
radius -= self.burn
if radius < 0:
radius = 1E-9
self.moveTo(x+r, y) self.moveTo(x+r, y)
self.ctx.arc(-r, 0, r, 0, 2*math.pi) self.ctx.arc(-r, 0, r, 0, 2*math.pi)
@restore @restore
def rectangularHole(self, x, y, dx, dy, r=0): def rectangularHole(self, x, y, dx, dy, r=0):
"""
Draw an rectangulat hole
:param x: position
:param y: position
:param dx: width
:param dy: height
:param r: (Default value = 0) radius of the corners
"""
self.moveTo(x+r-dx/2.0, y-dy/2.0, 180) self.moveTo(x+r-dx/2.0, y-dy/2.0, 180)
for d in (dy, dx, dy, dx): for d in (dy, dx, dy, dx):
self.corner(-90, r) self.corner(-90, r)
@ -462,6 +648,16 @@ class Boxes:
@restore @restore
def text(self, text, x=0, y=0, angle=0, align=""): def text(self, text, x=0, y=0, angle=0, align=""):
"""
Draw text
:param text: text to render
:param x: (Default value = 0)
:param y: (Default value = 0)
:param angle: (Default value = 0)
:param align: (Default value = "") string with combinations of (top|middle|bottom) and (left|center|right) separated by a space
"""
self.moveTo(x, y, angle) self.moveTo(x, y, angle)
(tx, ty, width, height, dx, dy) = self.ctx.text_extents(text) (tx, ty, width, height, dx, dy) = self.ctx.text_extents(text)
align = align.split() align = align.split()
@ -484,6 +680,14 @@ class Boxes:
@restore @restore
def NEMA(self, size, x=0, y=0, angle=0): def NEMA(self, size, x=0, y=0, angle=0):
"""Draw holes for mounting a NEMA stepper motor
:param size: Nominal size in tenths of inches
:param x: (Default value = 0)
:param y: (Default value = 0)
:param angle: (Default value = 0)
"""
nema = { nema = {
# motor,flange, holes, screws # motor,flange, holes, screws
8 : (20.3, 16, 15.4, 3), 8 : (20.3, 16, 15.4, 3),
@ -511,13 +715,20 @@ class Boxes:
# hexHoles # hexHoles
def hexHolesRectangle(self, x, y, settings=None, skip=None): def hexHolesRectangle(self, x, y, settings=None, skip=None):
""" """Fills a rectangle with holes in a hex pattern.
Fills a rectangle with holes.
Settings have:
r : radius of holes r : radius of holes
b : space between holes b : space between holes
style : what types of holes (not yet implemented) style : what types of holes (not yet implemented)
skip : function to check if hole should be present
:param x: width
:param y: heigth
:param settings: (Default value = None)
:param skip: (Default value = None) function to check if hole should be present
gets x, y, r, b, posx, posy gets x, y, r, b, posx, posy
""" """
if settings is None: if settings is None:
settings = self.hexHolesSettings settings = self.hexHolesSettings
@ -549,11 +760,37 @@ class Boxes:
return (dist(posx-cx, posy-cy) > (cx-r)) return (dist(posx-cx, posy-cy) > (cx-r))
def hexHolesCircle(self, d, settings=None): def hexHolesCircle(self, d, settings=None):
"""
Fill circle with holes in a hex pattern
:param d: diameter of the circle
:param settings: (Default value = None)
"""
d2 = d/2.0 d2 = d/2.0
self.hexHolesRectangle(d, d, settings=settings, skip=self.__skipcircle) self.hexHolesRectangle(d, d, settings=settings, skip=self.__skipcircle)
def hexHolesPlate(self, x, y, rc, settings=None): def hexHolesPlate(self, x, y, rc, settings=None):
"""
Fill a plate with holes in a hex pattern
:param x: width
:param y: height
:param rc: radius of the corners
:param settings: (Default value = None)
"""
def skip(x, y, r, b, posx, posy): def skip(x, y, r, b, posx, posy):
"""
:param x:
:param y:
:param r:
:param b:
:param posx:
:param posy:
"""
posx = abs(posx-(x/2.0)) posx = abs(posx-(x/2.0))
posy = abs(posy-(y/2.0)) posy = abs(posy-(y/2.0))
@ -567,6 +804,14 @@ class Boxes:
self.hexHolesRectangle(x, y, settings, skip=skip) self.hexHolesRectangle(x, y, settings, skip=skip)
def hexHolesHex(self, h, settings=None, grow=None): def hexHolesHex(self, h, settings=None, grow=None):
"""
Fill a hexagon with holes in a hex pattern
:param h: height
:param settings: (Default value = None)
:param grow: (Default value = None)
"""
if settings is None: if settings is None:
settings = self.hexHolesSettings settings = self.hexHolesSettings
r, b, style = settings r, b, style = settings
@ -600,12 +845,22 @@ class Boxes:
holesMargin=None, holesSettings=None, holesMargin=None, holesSettings=None,
bedBolts=None, bedBoltSettings=None, bedBolts=None, bedBoltSettings=None,
move=None): move=None):
"""fits surroundingWall """Plate with rounded corner fitting to .surroundingWall()
first edge is split to have a joint in the middle of the side
First edge is split to have a joint in the middle of the side
callback is called at the beginning of the straight edges callback is called at the beginning of the straight edges
0, 1 for the two part of the first edge, 2, 3, 4 for the others 0, 1 for the two part of the first edge, 2, 3, 4 for the others
set holesMargin to get hex holes. :param x: width
:param y: hight
:param r: radius of the corners
:param callback: (Default value = None)
:param holesMargin: (Default value = None) set to get hex holes
:param holesSettings: (Default value = None)
:param bedBolts: (Default value = None)
:param bedBoltSettings: (Default value = None)
:param move: (Default value = None)
""" """
overallwidth = x+2*self.fingerJointEdge.spacing() overallwidth = x+2*self.fingerJointEdge.spacing()
@ -654,13 +909,23 @@ class Boxes:
bottom='e', top='e', bottom='e', top='e',
callback=None, callback=None,
move=None): move=None):
""" """h : inner height, not counting the joints
h : inner height, not counting the joints
callback is called a beginn of the flat sides with callback is called a beginn of the flat sides with
0 for right half of first x side;
1 and 3 for y sides; * 0 for right half of first x side;
2 for second x side * 1 and 3 for y sides;
4 for second half of the first x side * 2 for second x side
* 4 for second half of the first x side
:param x: width of matching roundedPlate
:param y: height of matching roundedPlate
:param r: corner radius of matching roundedPlate
:param h: height of the wall
:param bottom: (Default value = 'e') Edge type
:param top: (Default value = 'e') Edge type
:param callback: (Default value = None)
:param move: (Default value = None)
""" """
c4 = (r+self.burn)*math.pi*0.5 # circumference of quarter circle c4 = (r+self.burn)*math.pi*0.5 # circumference of quarter circle
c4 = 0.9 * c4 # stretch flex 10% c4 = 0.9 * c4 # stretch flex 10%
@ -721,6 +986,20 @@ class Boxes:
bedBolts=None, bedBoltSettings=None, bedBolts=None, bedBoltSettings=None,
callback=None, callback=None,
move=None): move=None):
"""
Rectangular wall for all kind of box like objects
:param x: width
:param y: height
:param edges: (Default value = "eeee") bottom, right, top, left
:param holesMargin: (Default value = None)
:param holesSettings: (Default value = None)
:param bedBolts: (Default value = None)
:param bedBoltSettings: (Default value = None)
:param callback: (Default value = None)
:param move: (Default value = None)
"""
if len(edges) != 4: if len(edges) != 4:
raise ValueError("four edges required") raise ValueError("four edges required")
edges = [self.edges.get(e, e) for e in edges] edges = [self.edges.get(e, e) for e in edges]
@ -764,6 +1043,7 @@ class DemoBox(Boxes):
self.buildArgParser("x", "y", "h") self.buildArgParser("x", "y", "h")
def render(self): def render(self):
""" """
x, y, h, t = self.x, self.y, self.h, self.thickness x, y, h, t = self.x, self.y, self.h, self.thickness
self.open(2*x+10*self.thickness, y+2*h+20*self.thickness) self.open(2*x+10*self.thickness, y+2*h+20*self.thickness)
self.ctx.save() self.ctx.save()

View File

@ -20,18 +20,39 @@ class BoltPolicy:
"""Abstract class """Abstract class
Distributes (bed) bolts on a number of segments Distributes (bed) bolts on a number of segments
(fingers of a finger joint) (fingers of a finger joint)
""" """
def drawbolt(self, pos): def drawbolt(self, pos):
"""Add a bolt to this segment?""" """Add a bolt to this segment?
:param pos: number of the finger
"""
return False return False
def numFingers(self, numfingers): def numFingers(self, numfingers):
"""returns next smaller, possible number of fingers""" """Return next smaller, possible number of fingers
:param numfingers: number of fingers to aim for
"""
return numFingers return numFingers
def _even(self, numFingers): def _even(self, numFingers):
"""
Return same or next smaller even number
:param numFingers:
"""
return (numFingers//2) * 2 return (numFingers//2) * 2
def _odd(self, numFingers): def _odd(self, numFingers):
"""
Return same or next smaller odd number
:param numFingers:
"""
if numFingers % 2: if numFingers % 2:
return numFingers return numFingers
else: else:
@ -41,6 +62,7 @@ class Bolts(BoltPolicy):
"""Distribute a fixed number of bolts evenly""" """Distribute a fixed number of bolts evenly"""
def __init__(self, bolts=1): def __init__(self, bolts=1):
self.bolts = bolts self.bolts = bolts
def numFingers(self, numFingers): def numFingers(self, numFingers):
if self.bolts % 2: if self.bolts % 2:
self.fingers = self._even(numFingers) self.fingers = self._even(numFingers)
@ -49,6 +71,12 @@ class Bolts(BoltPolicy):
return self.fingers return self.fingers
def drawBolt(self, pos): def drawBolt(self, pos):
"""
Return if this finger needs a bolt
:param pos: number of this finger
"""
if pos > self.fingers//2: if pos > self.fingers//2:
pos = self.fingers - pos pos = self.fingers - pos
if pos==0: if pos==0:
@ -65,6 +93,12 @@ class Bolts(BoltPolicy):
############################################################################# #############################################################################
class Settings: class Settings:
"""Generic Settings class
Used by different other classes to store messurements and details.
Supports absolutevalues and settings that grow with the thinckness
of the material used.
"""
absolute_params = { } absolute_params = { }
relative_params = { } relative_params = { }
@ -79,6 +113,14 @@ class Settings:
self.setValues(thickness, relative, **kw) self.setValues(thickness, relative, **kw)
def setValues(self, thickness, relative=True, **kw): def setValues(self, thickness, relative=True, **kw):
"""
Set values
:param thickness: thickness of the material used
:param relative: (Default value = True) Do scale by thinckness
:param **kw: parameters to set
"""
factor = 1.0 factor = 1.0
if relative: if relative:
factor = thickness factor = thickness
@ -100,6 +142,7 @@ class Settings:
class Edge: class Edge:
"""Straight edge"""
char = 'e' char = 'e'
def __init__(self, boxes, settings): def __init__(self, boxes, settings):
@ -117,27 +160,35 @@ class Edge:
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
def width(self): def width(self):
"""Amount of space the beginning of the edge is set below the inner space of the part """
return 0.0 return 0.0
def margin(self): def margin(self):
"""Space needed right of the starting point"""
return self.boxes.spacing return self.boxes.spacing
def spacing(self): def spacing(self):
"""Space the edge needs outside of the inner space of the part"""
return self.width() + self.margin() return self.width() + self.margin()
def startAngle(self): def startAngle(self):
"""Not yet supported"""
return 0.0 return 0.0
def endAngle(self): def endAngle(self):
"""Not yet supported"""
return 0.0 return 0.0
class OutSetEdge(Edge): class OutSetEdge(Edge):
"""Straight edge out set by one thickness"""
char = 'E' char = 'E'
def width(self): def width(self):
return self.boxes.thickness return self.boxes.thickness
class CompoundEdge(Edge): class CompoundEdge(Edge):
"""Edge composed of multiple different Edges"""
def __init__(self, boxes, types, lengths): def __init__(self, boxes, types, lengths):
Edge.__init__(self, boxes, None) Edge.__init__(self, boxes, None)
self.types = [self.edges.get(edge, edge) for edge in types] self.types = [self.edges.get(edge, edge) for edge in types]
@ -158,6 +209,7 @@ class CompoundEdge(Edge):
e(l) e(l)
class Slot(Edge): class Slot(Edge):
"""Edge with an slot to slid another pice through """
def __init__(self, boxes, depth): def __init__(self, boxes, depth):
Edge.__init__(self, boxes, None) Edge.__init__(self, boxes, None)
self.depth = depth self.depth = depth
@ -175,6 +227,7 @@ class Slot(Edge):
self.boxes.edge(self.length) self.boxes.edge(self.length)
class SlottedEdge(Edge): class SlottedEdge(Edge):
"""Edge with multiple slots"""
def __init__(self, boxes, sections, edge="e", slots=0): def __init__(self, boxes, sections, edge="e", slots=0):
Edge.__init__(self, boxes, None) Edge.__init__(self, boxes, None)
@ -198,6 +251,10 @@ class SlottedEdge(Edge):
self.edge(self.sections[-1]) self.edge(self.sections[-1])
class FingerJointSettings(Settings): class FingerJointSettings(Settings):
"""Setting for all different finger joint components
Both sides should use the same instance to ensure they match"""
absolute_params = { absolute_params = {
"surroundingspaces" : 2, "surroundingspaces" : 2,
} }
@ -210,6 +267,7 @@ class FingerJointSettings(Settings):
} }
class FingerJointEdge(Edge): class FingerJointEdge(Edge):
"""Finger joint edge """
char = 'f' char = 'f'
positive = True positive = True
@ -253,19 +311,24 @@ class FingerJointEdge(Edge):
self.edge(leftover/2.0) self.edge(leftover/2.0)
def margin(self): def margin(self):
""" """
return self.boxes.spacing + self.boxes.thickness return self.boxes.spacing + self.boxes.thickness
class FingerJointEdgeCounterPart(FingerJointEdge): class FingerJointEdgeCounterPart(FingerJointEdge):
"""Finger joint edge - other side"""
char = 'F' char = 'F'
positive = False positive = False
def width(self): def width(self):
""" """
return self.boxes.thickness return self.boxes.thickness
def margin(self): def margin(self):
""" """
return self.boxes.spacing return self.boxes.spacing
class FingerHoleEdge(Edge): class FingerHoleEdge(Edge):
"""Edge with holes for a parallel finger joint"""
char = 'h' char = 'h'
def __call__(self, length, dist=None, def __call__(self, length, dist=None,
@ -282,9 +345,11 @@ class FingerHoleEdge(Edge):
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
def width(self): def width(self):
""" """
return (self.fingerHoleEdgeWidth+1) * self.thickness return (self.fingerHoleEdgeWidth+1) * self.thickness
class FingerHoles: class FingerHoles:
"""Hole mathcing a finger joint edge"""
def __init__(self, boxes, settings): def __init__(self, boxes, settings):
self.boxes = boxes self.boxes = boxes
self.ctx = boxes.ctx self.ctx = boxes.ctx
@ -313,6 +378,7 @@ class FingerHoles:
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
class CrossingFingerHoleEdge(Edge): class CrossingFingerHoleEdge(Edge):
"""Edge with holes for finger joints 90° above"""
def __init__(self, boxes, height, **kw): def __init__(self, boxes, height, **kw):
Edge.__init__(self, boxes, None, **kw) Edge.__init__(self, boxes, None, **kw)
self.height = height self.height = height
@ -323,6 +389,9 @@ class CrossingFingerHoleEdge(Edge):
class DoveTailSettings(Settings): class DoveTailSettings(Settings):
"""Settings used for dove tail joints
Both sides should use the same instance to ensure they match"""
absolute_params = { absolute_params = {
"angle" : 50, "angle" : 50,
} }
@ -333,6 +402,7 @@ class DoveTailSettings(Settings):
} }
class DoveTailJoint(Edge): class DoveTailJoint(Edge):
"""Edge with dove tail joints """
char = 'd' char = 'd'
positive = True positive = True
@ -367,9 +437,11 @@ class DoveTailJoint(Edge):
self.ctx.translate(*self.ctx.get_current_point()) self.ctx.translate(*self.ctx.get_current_point())
def margin(self): def margin(self):
""" """
return self.settings.depth + self.boxes.spacing return self.settings.depth + self.boxes.spacing
class DoveTailJointCounterPart(DoveTailJoint): class DoveTailJointCounterPart(DoveTailJoint):
"""Edge for other side of dove joints """
char = 'D' char = 'D'
positive = False positive = False
@ -381,6 +453,7 @@ class DoveTailJointCounterPart(DoveTailJoint):
return self.boxes.spacing return self.boxes.spacing
class FlexSettings(Settings): class FlexSettings(Settings):
"""Settings for one directional flex cuts"""
relative_params = { relative_params = {
"distance" : 0.5, "distance" : 0.5,
"connection" : 1.0, "connection" : 1.0,
@ -391,6 +464,7 @@ class FlexSettings(Settings):
} }
class FlexEdge(Edge): class FlexEdge(Edge):
"""Edge with flex cuts - use straight edge for the opposing side"""
char = 'X' char = 'X'
def __call__(self, x, h, **kw): def __call__(self, x, h, **kw):