Code Reformat #1
This commit is contained in:
parent
af167295b8
commit
93af56ff9c
|
@ -7,4 +7,5 @@
|
|||
*.ud
|
||||
build/
|
||||
dist/
|
||||
boxes.py.egg-info/
|
||||
boxes.py.egg-info/
|
||||
.idea
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
try:
|
||||
import cairocffi
|
||||
|
||||
cairocffi.install_as_pycairo()
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -31,6 +32,7 @@ from boxes import gears
|
|||
from boxes import pulley
|
||||
from boxes import parts
|
||||
|
||||
|
||||
### Helpers
|
||||
|
||||
def dist(dx, dy):
|
||||
|
@ -40,7 +42,8 @@ def dist(dx, dy):
|
|||
: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):
|
||||
"""
|
||||
|
@ -49,6 +52,7 @@ def restore(func):
|
|||
:param func: function to wrap
|
||||
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def f(self, *args, **kw):
|
||||
self.ctx.save()
|
||||
|
@ -56,8 +60,10 @@ def restore(func):
|
|||
func(self, *args, **kw)
|
||||
self.ctx.restore()
|
||||
self.ctx.move_to(*pt)
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def holeCol(func):
|
||||
"""
|
||||
Wrapper: color holes differently
|
||||
|
@ -65,6 +71,7 @@ def holeCol(func):
|
|||
:param func: function to wrap
|
||||
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def f(self, *args, **kw):
|
||||
self.ctx.stroke()
|
||||
|
@ -72,8 +79,8 @@ def holeCol(func):
|
|||
func(self, *args, **kw)
|
||||
self.ctx.stroke()
|
||||
self.ctx.set_source_rgb(0.0, 0.0, 0.0)
|
||||
return f
|
||||
|
||||
return f
|
||||
|
||||
|
||||
#############################################################################
|
||||
|
@ -83,27 +90,27 @@ def holeCol(func):
|
|||
class NutHole:
|
||||
"""Draw a hex nut"""
|
||||
sizes = {
|
||||
"M1.6" : (3.2, 1.3),
|
||||
"M2" : (4, 1.6),
|
||||
"M2.5" : (5, 2.0),
|
||||
"M3" : (5.5, 2.4),
|
||||
"M4" : (7, 3.2),
|
||||
"M5" : (8, 4.7),
|
||||
"M6" : (10, 5.2),
|
||||
"M8" : (13, 6.8),
|
||||
"M10" : (16, 8.4),
|
||||
"M12" : (18, 10.8),
|
||||
"M14" : (21, 12.8),
|
||||
"M16" : (24, 14.8),
|
||||
"M20" : (30, 18.0),
|
||||
"M24" : (36, 21.5),
|
||||
"M30" : (46, 25.6),
|
||||
"M36" : (55, 31),
|
||||
"M42" : (65, 34),
|
||||
"M48" : (75, 38),
|
||||
"M56" : (85, 45),
|
||||
"M64" : (95, 51),
|
||||
}
|
||||
"M1.6": (3.2, 1.3),
|
||||
"M2": (4, 1.6),
|
||||
"M2.5": (5, 2.0),
|
||||
"M3": (5.5, 2.4),
|
||||
"M4": (7, 3.2),
|
||||
"M5": (8, 4.7),
|
||||
"M6": (10, 5.2),
|
||||
"M8": (13, 6.8),
|
||||
"M10": (16, 8.4),
|
||||
"M12": (18, 10.8),
|
||||
"M14": (21, 12.8),
|
||||
"M16": (24, 14.8),
|
||||
"M20": (30, 18.0),
|
||||
"M24": (36, 21.5),
|
||||
"M30": (46, 25.6),
|
||||
"M36": (55, 31),
|
||||
"M42": (65, 34),
|
||||
"M48": (75, 38),
|
||||
"M56": (85, 45),
|
||||
"M64": (95, 51),
|
||||
}
|
||||
|
||||
def __init__(self, boxes, settings):
|
||||
self.boxes = boxes
|
||||
|
@ -114,13 +121,14 @@ class NutHole:
|
|||
@holeCol
|
||||
def __call__(self, size, x=0, y=0, angle=0):
|
||||
size = self.sizes.get(size, (size,))[0]
|
||||
side = size / 3**0.5
|
||||
side = size / 3 ** 0.5
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.moveTo(-0.5*side, 0.5*size, angle)
|
||||
self.boxes.moveTo(-0.5 * side, 0.5 * size, angle)
|
||||
for i in range(6):
|
||||
self.boxes.edge(side)
|
||||
self.boxes.corner(-60)
|
||||
|
||||
|
||||
##############################################################################
|
||||
### Argument types
|
||||
##############################################################################
|
||||
|
@ -135,17 +143,18 @@ def argparseSections(s):
|
|||
m = re.match(r"(\d+(\.\d+)?)/(\d+)", s)
|
||||
if m:
|
||||
n = int(m.group(3))
|
||||
print([ float(m.group(1)) ] * n)
|
||||
return [ float(m.group(1))/n ] * n
|
||||
print([float(m.group(1))] * n)
|
||||
return [float(m.group(1)) / n] * n
|
||||
m = re.match(r"(\d+(\.\d+)?)\*(\d+)", s)
|
||||
if m:
|
||||
n = int(m.group(3))
|
||||
return [ float(m.group(1)) ] * n
|
||||
return [float(m.group(1))] * n
|
||||
try:
|
||||
return [float(part) for part in s.split(":")]
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError("Don't understand sections string")
|
||||
|
||||
|
||||
class ArgparseEdgeType:
|
||||
names = edges.getDescriptions()
|
||||
edges = []
|
||||
|
@ -169,6 +178,7 @@ class ArgparseEdgeType:
|
|||
e, self.names.get(e, "")) for e in self.edges))
|
||||
return """<select name="%s" size="1">\n%s</select>\n""" % (name, options)
|
||||
|
||||
|
||||
##############################################################################
|
||||
### Main class
|
||||
##############################################################################
|
||||
|
@ -182,32 +192,32 @@ class Boxes:
|
|||
self.formats = formats.Formats()
|
||||
self.argparser = ArgumentParser(description=self.__doc__)
|
||||
self.argparser.add_argument(
|
||||
"--fingerjointfinger", action="store", type=float, default=1.0,
|
||||
"--fingerjointfinger", action="store", type=float, default=1.0,
|
||||
help="width of the fingers in multiples of thickness")
|
||||
self.argparser.add_argument(
|
||||
"--fingerjointspace", action="store", type=float, default=1.0,
|
||||
"--fingerjointspace", action="store", type=float, default=1.0,
|
||||
help="width of the space between fingers in multiples of thickness")
|
||||
self.argparser.add_argument(
|
||||
"--fingerjointsurrounding", action="store", type=float, default=1.0,
|
||||
"--fingerjointsurrounding", action="store", type=float, default=1.0,
|
||||
help="amount of space needed at the end in multiples of normal spaces")
|
||||
self.argparser.add_argument(
|
||||
"--thickness", action="store", type=float, default=4.0,
|
||||
"--thickness", action="store", type=float, default=4.0,
|
||||
help="thickness of the material")
|
||||
self.argparser.add_argument(
|
||||
"--output", action="store", type=str, default="box.svg",
|
||||
"--output", action="store", type=str, default="box.svg",
|
||||
help="name of resulting file")
|
||||
self.argparser.add_argument(
|
||||
"--format", action="store", type=str, default="svg",
|
||||
"--format", action="store", type=str, default="svg",
|
||||
choices=self.formats.getFormats(),
|
||||
help="format of resulting file")
|
||||
self.argparser.add_argument(
|
||||
"--debug", action="store", type=bool, default=False,
|
||||
"--debug", action="store", type=bool, default=False,
|
||||
help="print surrounding boxes for some structures")
|
||||
self.argparser.add_argument(
|
||||
"--reference", action="store", type=float, default=100,
|
||||
"--reference", action="store", type=float, default=100,
|
||||
help="print reference rectangle with given length")
|
||||
self.argparser.add_argument(
|
||||
"--burn", action="store", type=float, default=0.05,
|
||||
"--burn", action="store", type=float, default=0.05,
|
||||
help="burn correction in mm")
|
||||
|
||||
def open(self):
|
||||
|
@ -216,21 +226,21 @@ class Boxes:
|
|||
|
||||
Call this function from your .render() method
|
||||
"""
|
||||
self.spacing = 2*self.burn + 0.5 * self.thickness
|
||||
self.spacing = 2 * self.burn + 0.5 * self.thickness
|
||||
|
||||
self.bedBoltSettings = (3, 5.5, 2, 20, 15) #d, d_nut, h_nut, l, l1
|
||||
self.hexHolesSettings = (5, 3, 'circle') # r, dist, style
|
||||
self.bedBoltSettings = (3, 5.5, 2, 20, 15) # d, d_nut, h_nut, l, l1
|
||||
self.hexHolesSettings = (5, 3, 'circle') # r, dist, style
|
||||
self.surface, self.ctx = self.formats.getSurface(self.format, self.output)
|
||||
self.ctx.set_line_width(2*self.burn)
|
||||
self.ctx.set_line_width(2 * self.burn)
|
||||
self._buildObjects()
|
||||
if self.reference:
|
||||
self.move(10, 10, "up", before=True)
|
||||
self.ctx.rectangle(0, 0, self.reference, 10)
|
||||
if self.reference < 40:
|
||||
self.text("%.fmm" % self.reference, self.reference+5, 5,
|
||||
self.text("%.fmm" % self.reference, self.reference + 5, 5,
|
||||
align="middle left")
|
||||
else:
|
||||
self.text("%.fmm" % self.reference, self.reference/2.0, 5,
|
||||
self.text("%.fmm" % self.reference, self.reference / 2.0, 5,
|
||||
align="middle center")
|
||||
self.move(10, 10, "up")
|
||||
|
||||
|
@ -244,45 +254,45 @@ class Boxes:
|
|||
for arg in l:
|
||||
if arg == "x":
|
||||
self.argparser.add_argument(
|
||||
"--x", action="store", type=float, default=100.0,
|
||||
"--x", action="store", type=float, default=100.0,
|
||||
help="inner width in mm")
|
||||
elif arg == "y":
|
||||
self.argparser.add_argument(
|
||||
"--y", action="store", type=float, default=100.0,
|
||||
"--y", action="store", type=float, default=100.0,
|
||||
help="inner depth in mm")
|
||||
elif arg == "sx":
|
||||
self.argparser.add_argument(
|
||||
"--sx", action="store", type=argparseSections,
|
||||
"--sx", action="store", type=argparseSections,
|
||||
default="50*3",
|
||||
help="""sections left to right in mm. Possible formats: overallwidth/numberof sections e.g. "250/5"; sectionwidth*numberofsections e.g. "50*5"; section widths separated by ":" e.g. "30:25.5:70"
|
||||
""")
|
||||
elif arg == "sy":
|
||||
self.argparser.add_argument(
|
||||
"--sy", action="store", type=argparseSections,
|
||||
"--sy", action="store", type=argparseSections,
|
||||
default="50*3",
|
||||
help="""sections back to front in mm. See --sx for format""")
|
||||
elif arg == "h":
|
||||
self.argparser.add_argument(
|
||||
"--h", action="store", type=float, default=100.0,
|
||||
"--h", action="store", type=float, default=100.0,
|
||||
help="inner height in mm")
|
||||
elif arg == "hi":
|
||||
self.argparser.add_argument(
|
||||
"--hi", action="store", type=float, default=0.0,
|
||||
"--hi", action="store", type=float, default=0.0,
|
||||
help="inner height of inner walls in mm (leave to zero for same as outer walls)")
|
||||
elif arg == "bottom_edge":
|
||||
self.argparser.add_argument(
|
||||
"--bottom_edge", action="store",
|
||||
"--bottom_edge", action="store",
|
||||
type=ArgparseEdgeType("Fhs"), choices=list("Fhs"),
|
||||
default="h",
|
||||
help="edge type for bottom edge")
|
||||
elif arg == "top_edge":
|
||||
self.argparser.add_argument(
|
||||
"--top_edge", action="store",
|
||||
"--top_edge", action="store",
|
||||
type=ArgparseEdgeType("ecESik"), choices=list("ecESik"),
|
||||
default="e", help="edge type for top edge")
|
||||
elif arg=="outside":
|
||||
elif arg == "outside":
|
||||
self.argparser.add_argument(
|
||||
"--outside", action="store", type=bool, default=False,
|
||||
"--outside", action="store", type=bool, default=False,
|
||||
help="treat sizes as outside measurements that include the walls")
|
||||
else:
|
||||
raise ValueError("No default for argument", arg)
|
||||
|
@ -294,7 +304,7 @@ class Boxes:
|
|||
:param args: (Default value = None) parameters, None for using sys.argv
|
||||
|
||||
"""
|
||||
for key,value in vars(self.argparser.parse_args(args=args)).items():
|
||||
for key, value in vars(self.argparser.parse_args(args=args)).items():
|
||||
setattr(self, key, value)
|
||||
|
||||
# Change file ending to format if not given explicitly
|
||||
|
@ -312,7 +322,7 @@ class Boxes:
|
|||
if name is None:
|
||||
name = part.__class__.__name__
|
||||
name = name[0].lower() + name[1:]
|
||||
#if not hasattr(self, name):
|
||||
# if not hasattr(self, name):
|
||||
if isinstance(part, edges.BaseEdge):
|
||||
self.edges[part.char] = part
|
||||
else:
|
||||
|
@ -354,9 +364,11 @@ class Boxes:
|
|||
self.addPart(edges.ClickEdge(self, s))
|
||||
# Hinges
|
||||
s = edges.HingeSettings(self.thickness)
|
||||
|
||||
for i in range(1, 4):
|
||||
self.addPart(edges.Hinge(self, s, i))
|
||||
self.addPart(edges.HingePin(self, s, i))
|
||||
|
||||
# Nuts
|
||||
self.addPart(NutHole(self, None))
|
||||
# Gears
|
||||
|
@ -367,7 +379,7 @@ class Boxes:
|
|||
def adjustSize(self, l, e1=True, e2=True):
|
||||
try:
|
||||
total = sum(l)
|
||||
walls = (len(l)-1) * self.thickness
|
||||
walls = (len(l) - 1) * self.thickness
|
||||
except TypeError:
|
||||
total = l
|
||||
walls = 0
|
||||
|
@ -376,14 +388,15 @@ class Boxes:
|
|||
walls += e1.startwidth() + e1.margin()
|
||||
elif e1:
|
||||
walls += self.thickness
|
||||
|
||||
if isinstance(e2, edges.BaseEdge):
|
||||
walls += e2.startwidth + e2.margin()
|
||||
elif e2:
|
||||
walls += self.thickness
|
||||
|
||||
try:
|
||||
factor = (total-walls) / total
|
||||
return [s*factor for s in l]
|
||||
factor = (total - walls) / total
|
||||
return [s * factor for s in l]
|
||||
except TypeError:
|
||||
return l - walls
|
||||
|
||||
|
@ -414,6 +427,7 @@ class Boxes:
|
|||
callback()
|
||||
else:
|
||||
callback(number)
|
||||
|
||||
elif hasattr(callback, '__getitem__'):
|
||||
try:
|
||||
callback = callback[number]
|
||||
|
@ -424,6 +438,7 @@ class Boxes:
|
|||
except:
|
||||
self.ctx.restore()
|
||||
raise
|
||||
|
||||
self.ctx.restore()
|
||||
|
||||
def getEntry(self, param, idx):
|
||||
|
@ -435,7 +450,7 @@ class Boxes:
|
|||
|
||||
"""
|
||||
if isinstance(param, list):
|
||||
if len(param)>idx:
|
||||
if len(param) > idx:
|
||||
return param[idx]
|
||||
else:
|
||||
return None
|
||||
|
@ -466,16 +481,16 @@ class Boxes:
|
|||
:param radius: (Default value = 0)
|
||||
|
||||
"""
|
||||
rad = degrees*math.pi/180
|
||||
rad = degrees * math.pi / 180
|
||||
if degrees > 0:
|
||||
self.ctx.arc(0, radius+self.burn, radius+self.burn,
|
||||
-0.5*math.pi, rad - 0.5*math.pi)
|
||||
self.ctx.arc(0, radius + self.burn, radius + self.burn,
|
||||
-0.5 * math.pi, rad - 0.5 * math.pi)
|
||||
elif radius > self.burn:
|
||||
self.ctx.arc_negative(0, -(radius-self.burn), radius-self.burn,
|
||||
0.5*math.pi, rad + 0.5*math.pi)
|
||||
else: # not rounded inner corner
|
||||
self.ctx.arc_negative(0, self.burn-radius, self.burn-radius,
|
||||
-0.5*math.pi, -0.5*math.pi+rad)
|
||||
self.ctx.arc_negative(0, -(radius - self.burn), radius - self.burn,
|
||||
0.5 * math.pi, rad + 0.5 * math.pi)
|
||||
else: # not rounded inner corner
|
||||
self.ctx.arc_negative(0, self.burn - radius, self.burn - radius,
|
||||
-0.5 * math.pi, -0.5 * math.pi + rad)
|
||||
|
||||
self.continueDirection(rad)
|
||||
|
||||
|
@ -485,7 +500,7 @@ class Boxes:
|
|||
: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.translate(*self.ctx.get_current_point())
|
||||
|
||||
|
@ -501,8 +516,8 @@ class Boxes:
|
|||
|
||||
"""
|
||||
self.ctx.curve_to(x1, y1, x2, y2, x3, y3)
|
||||
dx = x3-x2
|
||||
dy = y3-y2
|
||||
dx = x3 - x2
|
||||
dy = y3 - y2
|
||||
rad = math.atan2(dy, dx)
|
||||
self.continueDirection(rad)
|
||||
|
||||
|
@ -532,37 +547,37 @@ class Boxes:
|
|||
|
||||
"""
|
||||
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.edge(l1)
|
||||
self.corner(90)
|
||||
self.edge((d_nut-d)/2.0)
|
||||
self.edge((d_nut - d) / 2.0)
|
||||
self.corner(-90)
|
||||
self.edge(h_nut)
|
||||
self.corner(-90)
|
||||
self.edge((d_nut-d)/2.0)
|
||||
self.edge((d_nut - d) / 2.0)
|
||||
self.corner(90)
|
||||
self.edge(l-l1-h_nut)
|
||||
self.edge(l - l1 - h_nut)
|
||||
self.corner(-90)
|
||||
self.edge(d)
|
||||
self.corner(-90)
|
||||
self.edge(l-l1-h_nut)
|
||||
self.edge(l - l1 - h_nut)
|
||||
self.corner(90)
|
||||
self.edge((d_nut-d)/2.0)
|
||||
self.edge((d_nut - d) / 2.0)
|
||||
self.corner(-90)
|
||||
self.edge(h_nut)
|
||||
self.corner(-90)
|
||||
self.edge((d_nut-d)/2.0)
|
||||
self.edge((d_nut - d) / 2.0)
|
||||
self.corner(90)
|
||||
self.edge(l1)
|
||||
self.corner(90)
|
||||
self.edge((length-d)/2.0)
|
||||
self.edge((length - d) / 2.0)
|
||||
|
||||
def edgeCorner(self, edge1, edge2, angle=90):
|
||||
"""Make a corner between two Edges. Take width of edges into account"""
|
||||
self.edge(edge2.startwidth()/math.sin(math.radians(180-angle)))
|
||||
self.edge(edge2.startwidth() / math.sin(math.radians(180 - angle)))
|
||||
self.corner(angle)
|
||||
self.edge(edge1.endwidth()/math.sin(math.radians(180-angle)))
|
||||
self.edge(edge1.endwidth() / math.sin(math.radians(180 - angle)))
|
||||
|
||||
def grip(self, length, depth):
|
||||
"""Corrugated edge useful as an gipping area
|
||||
|
@ -571,7 +586,7 @@ class Boxes:
|
|||
: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
|
||||
for groove in range(grooves):
|
||||
self.corner(90, depth)
|
||||
|
@ -584,11 +599,11 @@ class Boxes:
|
|||
:param length:
|
||||
|
||||
"""
|
||||
self.edge(1.1*self.thickness)
|
||||
self.edge(1.1 * self.thickness)
|
||||
self.corner(-90)
|
||||
self.edge(length/2.0+0.2*self.thickness)
|
||||
self.edge(length / 2.0 + 0.2 * self.thickness)
|
||||
self.corner(-90)
|
||||
self.edge(1.1*self.thickness)
|
||||
self.edge(1.1 * self.thickness)
|
||||
|
||||
def _latchGrip(self, length):
|
||||
"""
|
||||
|
@ -596,9 +611,9 @@ class Boxes:
|
|||
:param length:
|
||||
|
||||
"""
|
||||
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.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.corner(90, self.thickness / 4.0)
|
||||
|
||||
def latch(self, length, positive=True, reverse=False):
|
||||
"""Latch to fix a flex box door to the box
|
||||
|
@ -610,16 +625,16 @@ class Boxes:
|
|||
"""
|
||||
if positive:
|
||||
if reverse:
|
||||
self.edge(length/2.0-self.burn)
|
||||
self.edge(length / 2.0 - self.burn)
|
||||
self.corner(-90)
|
||||
self.edge(self.thickness)
|
||||
self.corner(90)
|
||||
self.edge(length/2.0)
|
||||
self.edge(length / 2.0)
|
||||
self.corner(90)
|
||||
self.edge(self.thickness)
|
||||
self.corner(-90)
|
||||
if not reverse:
|
||||
self.edge(length/2.0-self.burn)
|
||||
self.edge(length / 2.0 - self.burn)
|
||||
else:
|
||||
if reverse:
|
||||
self._latchGrip(length)
|
||||
|
@ -640,31 +655,31 @@ class Boxes:
|
|||
: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:
|
||||
print("Handle too wide")
|
||||
|
||||
self.ctx.save()
|
||||
|
||||
# Hole
|
||||
self.moveTo(d+2*r, 0)
|
||||
self.edge(hl-2*r)
|
||||
self.moveTo(d + 2 * r, 0)
|
||||
self.edge(hl - 2 * r)
|
||||
self.corner(-90, r)
|
||||
self.edge(h-3*r)
|
||||
self.edge(h - 3 * r)
|
||||
self.corner(-90, r)
|
||||
self.edge(hl-2*r)
|
||||
self.edge(hl - 2 * r)
|
||||
self.corner(-90, r)
|
||||
self.edge(h-3*r)
|
||||
self.edge(h - 3 * r)
|
||||
self.corner(-90, r)
|
||||
|
||||
self.ctx.restore()
|
||||
self.moveTo(0,0)
|
||||
self.moveTo(0, 0)
|
||||
|
||||
self.curveTo(d, 0, d, 0, d, -h+r)
|
||||
self.curveTo(d, 0, d, 0, d, -h + r)
|
||||
self.curveTo(r, 0, r, 0, r, r)
|
||||
self.edge(hl)
|
||||
self.curveTo(r, 0, r, 0, r, r)
|
||||
self.curveTo(h-r, 0, h-r, 0, h-r, -d)
|
||||
self.curveTo(h - r, 0, h - r, 0, h - r, -d)
|
||||
|
||||
### Navigation
|
||||
|
||||
|
@ -679,7 +694,7 @@ class Boxes:
|
|||
"""
|
||||
self.ctx.move_to(0, 0)
|
||||
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)
|
||||
|
||||
def continueDirection(self, angle=0):
|
||||
|
@ -715,11 +730,11 @@ class Boxes:
|
|||
y += self.spacing
|
||||
moves = {
|
||||
"up": (0, y, False),
|
||||
"down" : (0, -y, True),
|
||||
"left" : (-x, 0, True),
|
||||
"right" : (x, 0, False),
|
||||
"only" : (0, 0, None),
|
||||
}
|
||||
"down": (0, -y, True),
|
||||
"left": (-x, 0, True),
|
||||
"right": (x, 0, False),
|
||||
"only": (0, 0, None),
|
||||
}
|
||||
|
||||
if not before:
|
||||
# restore position
|
||||
|
@ -737,7 +752,7 @@ class Boxes:
|
|||
if before:
|
||||
# save position
|
||||
self.ctx.save()
|
||||
self.moveTo(self.spacing/2.0, self.spacing/2.0)
|
||||
self.moveTo(self.spacing / 2.0, self.spacing / 2.0)
|
||||
return dontdraw
|
||||
|
||||
@restore
|
||||
|
@ -754,8 +769,8 @@ class Boxes:
|
|||
r -= self.burn
|
||||
if r < 0:
|
||||
r = 1E-9
|
||||
self.moveTo(x+r, y)
|
||||
self.ctx.arc(-r, 0, r, 0, 2*math.pi)
|
||||
self.moveTo(x + r, y)
|
||||
self.ctx.arc(-r, 0, r, 0, 2 * math.pi)
|
||||
|
||||
@restore
|
||||
@holeCol
|
||||
|
@ -770,10 +785,10 @@ class Boxes:
|
|||
: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):
|
||||
self.corner(-90, r)
|
||||
self.edge(d-2*r)
|
||||
self.edge(d - 2 * r)
|
||||
|
||||
@restore
|
||||
def text(self, text, x=0, y=0, angle=0, align=""):
|
||||
|
@ -791,12 +806,12 @@ class Boxes:
|
|||
(tx, ty, width, height, dx, dy) = self.ctx.text_extents(text)
|
||||
align = align.split()
|
||||
moves = {
|
||||
"top" : (0, -height),
|
||||
"middle" : (0, -0.5*height),
|
||||
"bottom" : (0, 0),
|
||||
"left" : (0, 0),
|
||||
"center" : (-0.5*width, 0),
|
||||
"right" : (-width, 0),
|
||||
"top": (0, -height),
|
||||
"middle": (0, -0.5 * height),
|
||||
"bottom": (0, 0),
|
||||
"left": (0, 0),
|
||||
"center": (-0.5 * width, 0),
|
||||
"right": (-width, 0),
|
||||
}
|
||||
for a in align:
|
||||
if a in moves:
|
||||
|
@ -819,27 +834,26 @@ class Boxes:
|
|||
"""
|
||||
nema = {
|
||||
# motor,flange, holes, screws
|
||||
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),
|
||||
}
|
||||
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),
|
||||
}
|
||||
width, flange, holedistance, diameter = nema[size]
|
||||
self.moveTo(x, y, angle)
|
||||
if self.debug:
|
||||
self.rectangularHole(0, 0, width, width)
|
||||
self.hole(0,0, 0.5*flange)
|
||||
self.hole(0, 0, 0.5 * flange)
|
||||
for x in (-1, 1):
|
||||
for y in (-1, 1):
|
||||
self.hole(x*0.5*holedistance,
|
||||
y*0.5*holedistance,
|
||||
0.5*diameter)
|
||||
|
||||
self.hole(x * 0.5 * holedistance,
|
||||
y * 0.5 * holedistance,
|
||||
0.5 * diameter)
|
||||
|
||||
# hexHoles
|
||||
|
||||
|
@ -863,21 +877,21 @@ class Boxes:
|
|||
settings = self.hexHolesSettings
|
||||
r, b, style = settings
|
||||
|
||||
w = r+b/2.0
|
||||
dist = w * math.cos(math.pi/6.0)
|
||||
w = r + b / 2.0
|
||||
dist = w * math.cos(math.pi / 6.0)
|
||||
|
||||
# how many half circles do fit
|
||||
cx = int((x-2*r) // (w)) + 2
|
||||
cy = int((y-2*r) // (dist)) + 2
|
||||
cx = int((x - 2 * r) // (w)) + 2
|
||||
cy = int((y - 2 * r) // (dist)) + 2
|
||||
|
||||
# what's left on the sides
|
||||
lx = (x - (2*r+(cx-2)*w))/2.0
|
||||
ly = (y - (2*r+((cy//2)*2)*dist-2*dist))/2.0
|
||||
lx = (x - (2 * r + (cx - 2) * w)) / 2.0
|
||||
ly = (y - (2 * r + ((cy // 2) * 2) * dist - 2 * dist)) / 2.0
|
||||
|
||||
for i in range(cy//2):
|
||||
for j in range((cx-(i%2))//2):
|
||||
px = 2*j*w + r + lx
|
||||
py = i*2*dist + r + ly
|
||||
for i in range(cy // 2):
|
||||
for j in range((cx - (i % 2)) // 2):
|
||||
px = 2 * j * w + r + lx
|
||||
py = i * 2 * dist + r + ly
|
||||
if i % 2:
|
||||
px += w
|
||||
if skip and skip(x, y, r, b, px, py):
|
||||
|
@ -885,8 +899,8 @@ class Boxes:
|
|||
self.hole(px, py, r)
|
||||
|
||||
def __skipcircle(self, x, y, r, b, posx, posy):
|
||||
cx, cy = x/2.0, y/2.0
|
||||
return (dist(posx-cx, posy-cy) > (cx-r))
|
||||
cx, cy = x / 2.0, y / 2.0
|
||||
return (dist(posx - cx, posy - cy) > (cx - r))
|
||||
|
||||
def hexHolesCircle(self, d, settings=None):
|
||||
"""
|
||||
|
@ -896,7 +910,7 @@ class Boxes:
|
|||
:param settings: (Default value = None)
|
||||
|
||||
"""
|
||||
d2 = d/2.0
|
||||
d2 = d / 2.0
|
||||
self.hexHolesRectangle(d, d, settings=settings, skip=self.__skipcircle)
|
||||
|
||||
def hexHolesPlate(self, x, y, rc, settings=None):
|
||||
|
@ -909,6 +923,7 @@ class Boxes:
|
|||
:param settings: (Default value = None)
|
||||
|
||||
"""
|
||||
|
||||
def skip(x, y, r, b, posx, posy):
|
||||
"""
|
||||
|
||||
|
@ -920,15 +935,15 @@ class Boxes:
|
|||
:param posy:
|
||||
|
||||
"""
|
||||
posx = abs(posx-(x/2.0))
|
||||
posy = abs(posy-(y/2.0))
|
||||
posx = abs(posx - (x / 2.0))
|
||||
posy = abs(posy - (y / 2.0))
|
||||
|
||||
wx = 0.5*x-rc-r
|
||||
wy = 0.5*y-rc-r
|
||||
wx = 0.5 * x - rc - r
|
||||
wy = 0.5 * y - rc - r
|
||||
|
||||
if (posx <= wx) or (posy <= wx):
|
||||
return 0
|
||||
return dist(posx-wx, posy-wy) > rc
|
||||
return dist(posx - wx, posy - wy) > rc
|
||||
|
||||
self.hexHolesRectangle(x, y, settings, skip=skip)
|
||||
|
||||
|
@ -946,53 +961,53 @@ class Boxes:
|
|||
r, b, style = settings
|
||||
|
||||
self.ctx.rectangle(0, 0, h, h)
|
||||
w = r+b/2.0
|
||||
dist = w * math.cos(math.pi/6.0)
|
||||
cy = 2 * int((h-4*dist)// (4*w)) + 1
|
||||
w = r + b / 2.0
|
||||
dist = w * math.cos(math.pi / 6.0)
|
||||
cy = 2 * int((h - 4 * dist) // (4 * w)) + 1
|
||||
|
||||
leftover = h-2*r-(cy-1)*2*r
|
||||
if grow=='space ':
|
||||
b += leftover / (cy-1) / 2
|
||||
leftover = h - 2 * r - (cy - 1) * 2 * r
|
||||
if grow == 'space ':
|
||||
b += leftover / (cy - 1) / 2
|
||||
|
||||
# recalulate with adjusted values
|
||||
w = r+b/2.0
|
||||
dist = w * math.cos(math.pi/6.0)
|
||||
w = r + b / 2.0
|
||||
dist = w * math.cos(math.pi / 6.0)
|
||||
|
||||
self.moveTo(h/2.0-(cy//2)*2*w, h/2.0)
|
||||
self.moveTo(h / 2.0 - (cy // 2) * 2 * w, h / 2.0)
|
||||
for j in range(cy):
|
||||
self.hole(2*j*w, 0, r)
|
||||
for i in range(1, cy/2+1):
|
||||
for j in range(cy-i):
|
||||
self.hole(j*2*w+i*w, i*2*dist, r)
|
||||
self.hole(j*2*w+i*w, -i*2*dist, r)
|
||||
self.hole(2 * j * w, 0, r)
|
||||
for i in range(1, cy / 2 + 1):
|
||||
for j in range(cy - i):
|
||||
self.hole(j * 2 * w + i * w, i * 2 * dist, r)
|
||||
self.hole(j * 2 * w + i * w, -i * 2 * dist, r)
|
||||
|
||||
def flex2D(self, x, y, width=1):
|
||||
width *= self.thickness
|
||||
cx = int(x // (5*width))
|
||||
cx = int(x // (5 * width))
|
||||
wx = x / 5. / cx
|
||||
cy = int(y // (5*width))
|
||||
cy = int(y // (5 * width))
|
||||
wy = y / 5. / cy
|
||||
|
||||
armx = (4*wx, 90, 4*wy, 90, 2*wx, 90, 2*wy)
|
||||
army = (4*wy, 90, 4*wx, 90, 2*wy, 90, 2*wx)
|
||||
armx = (4 * wx, 90, 4 * wy, 90, 2 * wx, 90, 2 * wy)
|
||||
army = (4 * wy, 90, 4 * wx, 90, 2 * wy, 90, 2 * wx)
|
||||
for i in range(cx):
|
||||
for j in range(cy):
|
||||
if (i+j) % 2:
|
||||
if (i + j) % 2:
|
||||
self.ctx.save()
|
||||
self.moveTo((5*i)*wx, (5*j)*wy)
|
||||
self.moveTo((5 * i) * wx, (5 * j) * wy)
|
||||
self.polyline(*armx)
|
||||
self.ctx.restore()
|
||||
self.ctx.save()
|
||||
self.moveTo((5*i+5)*wx, (5*j+5)*wy, -180)
|
||||
self.moveTo((5 * i + 5) * wx, (5 * j + 5) * wy, -180)
|
||||
self.polyline(*armx)
|
||||
self.ctx.restore()
|
||||
else:
|
||||
self.ctx.save()
|
||||
self.moveTo((5*i+5)*wx, (5*j)*wy, 90)
|
||||
self.moveTo((5 * i + 5) * wx, (5 * j) * wy, 90)
|
||||
self.polyline(*army)
|
||||
self.ctx.restore()
|
||||
self.ctx.save()
|
||||
self.moveTo((5*i)*wx, (5*j+5)*wy, -90)
|
||||
self.moveTo((5 * i) * wx, (5 * j + 5) * wy, -90)
|
||||
self.polyline(*army)
|
||||
self.ctx.restore()
|
||||
self.ctx.stroke()
|
||||
|
@ -1023,8 +1038,8 @@ class Boxes:
|
|||
|
||||
"""
|
||||
|
||||
overallwidth = x+2*self.edges["f"].spacing()
|
||||
overallheight = y+2*self.edges["f"].spacing()
|
||||
overallwidth = x + 2 * self.edges["f"].spacing()
|
||||
overallheight = y + 2 * self.edges["f"].spacing()
|
||||
|
||||
if self.move(overallwidth, overallheight, move, before=True):
|
||||
return
|
||||
|
@ -1034,16 +1049,16 @@ class Boxes:
|
|||
self.moveTo(r, 0)
|
||||
|
||||
self.cc(callback, 0)
|
||||
self.edges["f"](x/2.0-r, bedBolts=self.getEntry(bedBolts, 0),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, 0))
|
||||
self.edges["f"](x / 2.0 - r, bedBolts=self.getEntry(bedBolts, 0),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, 0))
|
||||
self.cc(callback, 1)
|
||||
self.edges["f"](x/2.0-r, bedBolts=self.getEntry(bedBolts, 1),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, 1))
|
||||
self.edges["f"](x / 2.0 - r, bedBolts=self.getEntry(bedBolts, 1),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, 1))
|
||||
for i, l in zip(range(3), (y, x, y)):
|
||||
self.corner(90, r)
|
||||
self.cc(callback, i+2)
|
||||
self.edges["f"](l-2*r, bedBolts=self.getEntry(bedBolts, i+2),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i+2))
|
||||
self.cc(callback, i + 2)
|
||||
self.edges["f"](l - 2 * r, bedBolts=self.getEntry(bedBolts, i + 2),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i + 2))
|
||||
self.corner(90, r)
|
||||
|
||||
self.ctx.restore()
|
||||
|
@ -1058,7 +1073,7 @@ class Boxes:
|
|||
r -= holesMargin
|
||||
else:
|
||||
r = 0
|
||||
self.hexHolesPlate(x-2*holesMargin, y-2*holesMargin, r,
|
||||
self.hexHolesPlate(x - 2 * holesMargin, y - 2 * holesMargin, r,
|
||||
settings=holesSettings)
|
||||
self.ctx.stroke()
|
||||
self.move(overallwidth, overallheight, move)
|
||||
|
@ -1086,7 +1101,7 @@ class Boxes:
|
|||
: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 = c4 / self.edges["X"].settings.stretch
|
||||
|
||||
top = self.edges.get(top, top)
|
||||
|
@ -1098,42 +1113,41 @@ class Boxes:
|
|||
topwidth = top.startwidth()
|
||||
bottomwidth = bottom.startwidth()
|
||||
|
||||
overallwidth = 2*x + 2*y - 8*r + 4*c4 + \
|
||||
self.edges["d"].spacing() + self.edges["D"].spacing()
|
||||
overallwidth = 2 * x + 2 * y - 8 * r + 4 * c4 + \
|
||||
self.edges["d"].spacing() + self.edges["D"].spacing()
|
||||
overallheight = h + top.spacing() + bottom.spacing()
|
||||
|
||||
|
||||
if self.move(overallwidth, overallheight, move, before=True):
|
||||
return
|
||||
|
||||
self.moveTo(left.spacing(), bottom.margin())
|
||||
|
||||
self.cc(callback, 0, y=bottomwidth+self.burn)
|
||||
bottom(x/2.0-r)
|
||||
if (y-2*r) < 1E-3:
|
||||
self.edges["X"](2*c4, h+topwidth+bottomwidth)
|
||||
self.cc(callback, 2, y=bottomwidth+self.burn)
|
||||
bottom(x-2*r)
|
||||
self.edges["X"](2*c4, h+topwidth+bottomwidth)
|
||||
self.cc(callback, 4, y=bottomwidth+self.burn)
|
||||
self.cc(callback, 0, y=bottomwidth + self.burn)
|
||||
bottom(x / 2.0 - r)
|
||||
if (y - 2 * r) < 1E-3:
|
||||
self.edges["X"](2 * c4, h + topwidth + bottomwidth)
|
||||
self.cc(callback, 2, y=bottomwidth + self.burn)
|
||||
bottom(x - 2 * r)
|
||||
self.edges["X"](2 * c4, h + topwidth + bottomwidth)
|
||||
self.cc(callback, 4, y=bottomwidth + self.burn)
|
||||
else:
|
||||
for i, l in zip(range(4), (y, x, y, 0)):
|
||||
self.edges["X"](c4, h+topwidth+bottomwidth)
|
||||
self.cc(callback, i+1, y=bottomwidth+self.burn)
|
||||
self.edges["X"](c4, h + topwidth + bottomwidth)
|
||||
self.cc(callback, i + 1, y=bottomwidth + self.burn)
|
||||
if i < 3:
|
||||
bottom(l-2*r)
|
||||
bottom(x/2.0-r)
|
||||
bottom(l - 2 * r)
|
||||
bottom(x / 2.0 - r)
|
||||
|
||||
self.edgeCorner(bottom, right, 90)
|
||||
right(h)
|
||||
self.edgeCorner(right, top, 90)
|
||||
|
||||
top(x/2.0-r)
|
||||
top(x / 2.0 - r)
|
||||
for i, l in zip(range(4), (y, x, y, 0)):
|
||||
self.edge(c4)
|
||||
if i < 3:
|
||||
top(l - 2*r)
|
||||
top(x/2.0-r)
|
||||
top(l - 2 * r)
|
||||
top(x / 2.0 - r)
|
||||
|
||||
self.edgeCorner(top, left, 90)
|
||||
left(h)
|
||||
|
@ -1165,7 +1179,7 @@ class Boxes:
|
|||
if len(edges) != 4:
|
||||
raise ValueError("four edges required")
|
||||
edges = [self.edges.get(e, e) for e in edges]
|
||||
edges += edges # append for wrapping around
|
||||
edges += edges # append for wrapping around
|
||||
overallwidth = x + edges[-1].spacing() + edges[1].spacing()
|
||||
overallheight = y + edges[0].spacing() + edges[2].spacing()
|
||||
|
||||
|
@ -1174,16 +1188,16 @@ class Boxes:
|
|||
|
||||
self.moveTo(edges[-1].spacing(), edges[0].margin())
|
||||
for i, l in enumerate((x, y, x, y)):
|
||||
self.cc(callback, i, y=edges[i].startwidth()+self.burn)
|
||||
self.cc(callback, i, y=edges[i].startwidth() + self.burn)
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
self.edgeCorner(edges[i], edges[i+1], 90)
|
||||
self.edgeCorner(edges[i], edges[i + 1], 90)
|
||||
|
||||
if holesMargin is not None:
|
||||
self.moveTo(holesMargin+edges[-1].endwidth(),
|
||||
holesMargin+edges[0].startwidth())
|
||||
self.hexHolesRectangle(x-2*holesMargin, y-2*holesMargin)
|
||||
self.moveTo(holesMargin + edges[-1].endwidth(),
|
||||
holesMargin + edges[0].startwidth())
|
||||
self.hexHolesRectangle(x - 2 * holesMargin, y - 2 * holesMargin)
|
||||
|
||||
self.ctx.stroke()
|
||||
|
||||
|
|
471
boxes/edges.py
471
boxes/edges.py
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,3 @@
|
|||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
|
@ -6,8 +5,8 @@ import cairo
|
|||
import re
|
||||
from boxes import svgutil
|
||||
|
||||
class PSFile:
|
||||
|
||||
class PSFile:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
|
||||
|
@ -15,38 +14,40 @@ class PSFile:
|
|||
with open(self.filename, "r+") as f:
|
||||
s = f.read(1024)
|
||||
m = re.search(r"%%BoundingBox: (\d+) (\d+) (\d+) (\d+)", s)
|
||||
|
||||
if not m:
|
||||
raise ValueError("%%BoundingBox in Postscript file not found")
|
||||
|
||||
x1, y1, x2, y2 = m.groups()
|
||||
m = re.search(r"%%DocumentMedia: \d+x\d+mm ((\d+) (\d+)) 0 \(", s)
|
||||
f.seek(m.start(1))
|
||||
media = "%i %i" % (int(x1)+int(x2), int(y1)+int(y2))
|
||||
f.write(media + " " * (len(m.group(1))-len(media)))
|
||||
media = "%i %i" % (int(x1) + int(x2), int(y1) + int(y2))
|
||||
f.write(media + " " * (len(m.group(1)) - len(media)))
|
||||
|
||||
|
||||
class Formats:
|
||||
|
||||
pstoedit = "/usr/bin/pstoedit"
|
||||
|
||||
formats = {
|
||||
"svg" : None,
|
||||
"ps" : None,
|
||||
"dxf" : "-flat 0.1 -f dxf:-mm".split(),
|
||||
"gcode" : "-f gcode".split(),
|
||||
"plt" : "-f plot-hpgl".split(),
|
||||
"ai" : "-f ps2ai".split(),
|
||||
"pdf" : "-f pdf".split(),
|
||||
"svg": None,
|
||||
"ps": None,
|
||||
"dxf": "-flat 0.1 -f dxf:-mm".split(),
|
||||
"gcode": "-f gcode".split(),
|
||||
"plt": "-f plot-hpgl".split(),
|
||||
"ai": "-f ps2ai".split(),
|
||||
"pdf": "-f pdf".split(),
|
||||
}
|
||||
|
||||
http_headers = {
|
||||
"svg" : [('Content-type', 'image/svg+xml; charset=utf-8')],
|
||||
"ps" : [('Content-type', 'application/postscript')],
|
||||
"dxf" : [('Content-type', 'image/vnd.dxf')],
|
||||
"plt" : [('Content-type', ' application/vnd.hp-hpgl')],
|
||||
"gcode" : [('Content-type', 'text/plain; charset=utf-8')],
|
||||
"svg": [('Content-type', 'image/svg+xml; charset=utf-8')],
|
||||
"ps": [('Content-type', 'application/postscript')],
|
||||
"dxf": [('Content-type', 'image/vnd.dxf')],
|
||||
"plt": [('Content-type', ' application/vnd.hp-hpgl')],
|
||||
"gcode": [('Content-type', 'text/plain; charset=utf-8')],
|
||||
|
||||
# "" : [('Content-type', '')],
|
||||
}
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
@ -58,7 +59,7 @@ class Formats:
|
|||
|
||||
def getSurface(self, fmt, filename):
|
||||
|
||||
width = height = 10000 # mm
|
||||
width = height = 10000 # mm
|
||||
|
||||
if fmt == "svg":
|
||||
surface = cairo.SVGSurface(filename, width, height)
|
||||
|
@ -66,7 +67,7 @@ class Formats:
|
|||
else:
|
||||
mm2pt = 72 / 25.4
|
||||
width *= mm2pt
|
||||
height *= mm2pt #3.543307
|
||||
height *= mm2pt # 3.543307
|
||||
surface = cairo.PSSurface(filename, width, height)
|
||||
|
||||
ctx = cairo.Context(surface)
|
||||
|
@ -86,11 +87,14 @@ class Formats:
|
|||
else:
|
||||
ps = PSFile(filename)
|
||||
ps.adjustDocumentMedia()
|
||||
|
||||
if fmt not in ("svg", "ps"):
|
||||
fd, tmpfile = tempfile.mkstemp()
|
||||
cmd = [self.pstoedit] + self.formats[fmt] + [filename, tmpfile]
|
||||
err = subprocess.call(cmd)
|
||||
|
||||
if err:
|
||||
# XXX show stderr output
|
||||
raise ValueError("Conversion failed. pstoedit returned %i" % err)
|
||||
|
||||
os.rename(tmpfile, filename)
|
||||
|
|
|
@ -107,26 +107,22 @@ def gear_calculations(num_teeth, circular_pitch, pressure_angle, clearance=0, ri
|
|||
pitch_diameter = num_teeth / diametral_pitch
|
||||
pitch_radius = pitch_diameter / 2.0
|
||||
addendum = 1 / diametral_pitch
|
||||
#dedendum = 1.157 / diametral_pitch # auto calc clearance
|
||||
dedendum = addendum
|
||||
dedendum *= 1+profile_shift
|
||||
addendum *= 1-profile_shift
|
||||
|
||||
if ring_gear:
|
||||
addendum = addendum + clearance # our method
|
||||
else:
|
||||
dedendum = dedendum + clearance # our method
|
||||
#
|
||||
#
|
||||
|
||||
base_radius = pitch_diameter * cos(radians(pressure_angle)) / 2.0
|
||||
outer_radius = pitch_radius + addendum
|
||||
root_radius = pitch_radius - dedendum
|
||||
|
||||
# Tooth thickness: Tooth width along pitch circle.
|
||||
tooth_thickness = ( pi * pitch_diameter ) / ( 2.0 * num_teeth )
|
||||
# we don't use these
|
||||
working_depth = 2 / diametral_pitch
|
||||
whole_depth = 2.157 / diametral_pitch
|
||||
#outside_diameter = (num_teeth + 2) / diametral_pitch
|
||||
#
|
||||
|
||||
return (pitch_radius, base_radius,
|
||||
addendum, dedendum, outer_radius, root_radius,
|
||||
tooth_thickness
|
||||
|
@ -146,6 +142,7 @@ def generate_rack_points(tooth_count, pitch, addendum, pressure_angle,
|
|||
(one extra tooth on the right hand side, if number of teeth is even)
|
||||
"""
|
||||
spacing = 0.5 * pitch # rolling one pitch distance on the spur gear pitch_diameter.
|
||||
|
||||
# roughly center rack in drawing, exact position is so that it meshes
|
||||
# nicely with the spur gear.
|
||||
# -0.5*spacing has a gap in the center.
|
||||
|
@ -158,7 +155,7 @@ def generate_rack_points(tooth_count, pitch, addendum, pressure_angle,
|
|||
base_bot = addendum+clearance+base_height
|
||||
|
||||
x_lhs = -pitch * int(0.5*tooth_count-.5) - spacing - tab_length - tasc + fudge
|
||||
#inkex.debug("angle=%s spacing=%s"%(pressure_angle, spacing))
|
||||
|
||||
# Start with base tab on LHS
|
||||
points = [] # make list of points
|
||||
points.append((x_lhs, base_bot))
|
||||
|
@ -175,6 +172,7 @@ def generate_rack_points(tooth_count, pitch, addendum, pressure_angle,
|
|||
points.append((x+spacing-tas, -addendum))
|
||||
points.append((x+spacing+tasc, base_top))
|
||||
x += pitch
|
||||
|
||||
x -= spacing # remove last adjustment
|
||||
# add base on RHS
|
||||
x_rhs = x+tasc+tab_length
|
||||
|
@ -189,7 +187,7 @@ def generate_rack_points(tooth_count, pitch, addendum, pressure_angle,
|
|||
p = []
|
||||
p.append( (x_lhs + 0.5 * tab_length, 0) )
|
||||
p.append( (x_rhs - 0.5 * tab_length, 0) )
|
||||
# return points ready for use in an SVG 'path'
|
||||
|
||||
return (points, p)
|
||||
|
||||
|
||||
|
@ -233,6 +231,7 @@ def generate_spur_points(teeth, base_radius, pitch_radius, outer_radius, root_ra
|
|||
p_tmp = points1 + points_on_outer_radius[1:-1] + points2[::-1] + points_on_root # [::-1] reverses list
|
||||
|
||||
points.extend( p_tmp )
|
||||
|
||||
return (points)
|
||||
|
||||
def inkbool(val):
|
||||
|
@ -257,6 +256,7 @@ class OptionParser(argparse.ArgumentParser):
|
|||
self.add_argument(*names, **kw)
|
||||
|
||||
class Gears():
|
||||
|
||||
def __init__(self, boxes, **kw):
|
||||
# an alternate way to get debug info:
|
||||
# could use inkex.debug(string) instead...
|
||||
|
@ -385,12 +385,16 @@ class Gears():
|
|||
help="Let the user confirm a warning dialog if undercut occurs. This dialog also shows helpful hints against undercut")
|
||||
|
||||
def drawPoints(self, lines, kerfdir=1):
|
||||
|
||||
if kerfdir != 0:
|
||||
lines = kerf(lines, self.boxes.burn*kerfdir)
|
||||
|
||||
self.boxes.ctx.save()
|
||||
self.boxes.ctx.move_to(*lines[0])
|
||||
|
||||
for x, y in lines[1:]:
|
||||
self.boxes.ctx.line_to(x, y)
|
||||
|
||||
self.boxes.ctx.line_to(*lines[0])
|
||||
self.boxes.ctx.restore()
|
||||
|
||||
|
@ -406,6 +410,7 @@ class Gears():
|
|||
circular_pitch = dimension
|
||||
else:
|
||||
raise ValueError("unknown system '%s', try CP, DP, MM" % self.options.system)
|
||||
|
||||
# circular_pitch defines the size in mm
|
||||
return circular_pitch
|
||||
|
||||
|
@ -436,6 +441,7 @@ class Gears():
|
|||
# check for mount hole collision with inner spokes
|
||||
if mount_radius <= mount_hole/2:
|
||||
adj_factor = (r_outer - mount_hole/2) / 5
|
||||
|
||||
if adj_factor < 0.1:
|
||||
# not enough reasonable room
|
||||
collision = True
|
||||
|
@ -446,6 +452,7 @@ class Gears():
|
|||
# then check to see if cross-over on spoke width
|
||||
for i in range(spoke_count):
|
||||
angle = spokes[i]-spokes[i-1]
|
||||
|
||||
if spoke_width >= angle * mount_radius:
|
||||
adj_factor = 1.2 # wrong value. its probably one of the points distances calculated below
|
||||
mount_radius += adj_factor
|
||||
|
@ -458,6 +465,7 @@ class Gears():
|
|||
if collision: # don't draw spokes if no room.
|
||||
messages.append("Not enough room for Spokes. Decrease Spoke width.")
|
||||
else: # draw spokes
|
||||
|
||||
for i in range(spoke_count):
|
||||
self.boxes.ctx.save()
|
||||
start_a, end_a = spokes[i], spokes[i+1]
|
||||
|
@ -486,6 +494,7 @@ class Gears():
|
|||
)
|
||||
|
||||
self.boxes.ctx.restore()
|
||||
|
||||
return messages
|
||||
|
||||
def sizes(self, **kw):
|
||||
|
@ -517,8 +526,10 @@ class Gears():
|
|||
|
||||
def gearCarrier(self, r, spoke_width, positions, mount_radius, mount_hole, circle=True, move=None):
|
||||
width = (r+spoke_width)*2
|
||||
|
||||
if self.boxes.move(width, width, move, before=True):
|
||||
return
|
||||
|
||||
try:
|
||||
positions = [i*360/positions for i in range(positions)]
|
||||
except TypeError:
|
||||
|
@ -528,11 +539,13 @@ class Gears():
|
|||
self.boxes.moveTo(width/2.0, width/2.0)
|
||||
self.generate_spokes(r+0.5*spoke_width, spoke_width, positions, mount_radius, mount_hole, 1, "")
|
||||
self.boxes.hole(0, 0, mount_hole)
|
||||
|
||||
for angle in positions:
|
||||
self.boxes.ctx.save()
|
||||
self.boxes.moveTo(0, 0, angle)
|
||||
self.boxes.hole(r, 0, mount_hole)
|
||||
self.boxes.ctx.restore()
|
||||
|
||||
self.boxes.moveTo(r+0.5*spoke_width+self.boxes.burn, 0, 90)
|
||||
self.boxes.corner(360, r+0.5*spoke_width)
|
||||
|
||||
|
@ -578,6 +591,7 @@ class Gears():
|
|||
else: accuracy_involute = 6
|
||||
else:
|
||||
accuracy_involute = self.options.accuracy
|
||||
|
||||
accuracy_circular = max(3, int(accuracy_involute/2) - 1) # never less than three
|
||||
# print >>self.tty, "accuracy_circular=%s accuracy_involute=%s" % (accuracy_circular, accuracy_involute)
|
||||
# Pitch (circular pitch): Length of the arc from one tooth to the next)
|
||||
|
@ -599,17 +613,20 @@ class Gears():
|
|||
height = base_height+ 2* addendum
|
||||
if self.boxes.move(width, height, move, before=True):
|
||||
return
|
||||
|
||||
self.boxes.cc(callback, None, s+b, s+b)
|
||||
self.boxes.moveTo(width/2.0, base_height+addendum, -180)
|
||||
self.drawPoints(points)
|
||||
self.drawPoints(guide_points, kerfdir=0)
|
||||
self.boxes.move(width, height, move)
|
||||
|
||||
return
|
||||
|
||||
# Move only
|
||||
width = height = 2 * outer_radius
|
||||
if self.options.internal_ring:
|
||||
width = height = width + 2 * self.options.spoke_width
|
||||
|
||||
if self.boxes.move(width, height, move, before=True):
|
||||
return
|
||||
|
||||
|
@ -624,6 +641,7 @@ class Gears():
|
|||
# alas annotation cannot handle the degree symbol. Also it ignore newlines.
|
||||
# so split and make a list
|
||||
warnings.extend(msg.split("\n"))
|
||||
|
||||
if self.options.undercut_alert:
|
||||
inkex.debug(msg)
|
||||
else:
|
||||
|
@ -653,6 +671,7 @@ class Gears():
|
|||
self.boxes.moveTo(r, 0)
|
||||
self.boxes.ctx.arc(-r, 0, r, 0, 2*pi)
|
||||
self.boxes.ctx.restore()
|
||||
|
||||
# Add center
|
||||
if centercross:
|
||||
cs = pitch / 3.0 # centercross length
|
||||
|
@ -667,12 +686,13 @@ class Gears():
|
|||
if pitchcircle:
|
||||
self.boxes.hole(0, 0, pitch_radius)
|
||||
|
||||
|
||||
# Add Annotations (above)
|
||||
if self.options.annotation:
|
||||
outer_dia = outer_radius * 2
|
||||
|
||||
if self.options.internal_ring:
|
||||
outer_dia += 2 * spoke_width
|
||||
|
||||
notes = []
|
||||
notes.extend(warnings)
|
||||
#notes.append('Document (%s) scale conversion = %2.4f' % (self.document.getroot().find(inkex.addNS('namedview', 'sodipodi')).get(inkex.addNS('document-units', 'inkscape')), unit_factor))
|
||||
|
@ -690,6 +710,7 @@ class Gears():
|
|||
text_height = max(10, min(10+(outer_dia-60)/24, 22))
|
||||
# position above
|
||||
y = - outer_radius - (len(notes)+1) * text_height * 1.2
|
||||
|
||||
for note in notes:
|
||||
self.boxes.text(note, -outer_radius, y)
|
||||
y += text_height * 1.2
|
||||
|
|
|
@ -16,15 +16,17 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class Box(Boxes):
|
||||
"""Fully closed box"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "outside")
|
||||
self.argparser.set_defaults(
|
||||
fingerjointfinger=3.0,
|
||||
fingerjointspace=3.0
|
||||
)
|
||||
)
|
||||
|
||||
def render(self):
|
||||
self.open()
|
||||
|
@ -47,16 +49,18 @@ class Box(Boxes):
|
|||
self.rectangularWall(y, h, "FfFf", bedBolts=d3, move="up")
|
||||
self.rectangularWall(y, h, "FfFf", bedBolts=d3)
|
||||
self.rectangularWall(x, h, "FFFF", bedBolts=d2, move="left up")
|
||||
|
||||
|
||||
self.rectangularWall(x, y, "ffff", bedBolts=[d2, d3, d2, d3], move="right")
|
||||
self.rectangularWall(x, y, "ffff", bedBolts=[d2, d3, d2, d3])
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Box()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -120,6 +120,7 @@ class Box2(Boxes):
|
|||
bedBolts=[d2], move="up only")
|
||||
|
||||
self.rectangularWall(x, y, "ffff", bedBolts=[d2, d3, d2, d3], move="right")
|
||||
|
||||
if self.top_edge == "c":
|
||||
self.rectangularWall(x, y, "CCCC", bedBolts=[d2, d3, d2, d3], move="up")
|
||||
elif self.top_edge == "i":
|
||||
|
|
|
@ -18,6 +18,7 @@ from boxes import *
|
|||
|
||||
class Box3(Boxes):
|
||||
"""Box with just 3 walls"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "outside")
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
class Castle(Boxes):
|
||||
|
||||
class Castle(Boxes):
|
||||
webinterface = False
|
||||
|
||||
def __init__(self):
|
||||
|
@ -26,21 +26,21 @@ class Castle(Boxes):
|
|||
def render(self, t_x=70, t_h=250, w1_x=300, w1_h=120, w2_x=100, w2_h=120):
|
||||
self.open()
|
||||
s = edges.FingerJointSettings(self.thickness, relative=False,
|
||||
space = 10, finger=10, height=10,
|
||||
space=10, finger=10, height=10,
|
||||
width=self.thickness)
|
||||
|
||||
p = edges.FingerJointEdge(self, s)
|
||||
p.char = "p"
|
||||
self.addPart(p)
|
||||
|
||||
P = edges.FingerJointEdgeCounterPart(self, s)
|
||||
P.char = "P"
|
||||
self.addPart(P)
|
||||
|
||||
self.moveTo(0,0)
|
||||
self.rectangularWall(t_x, t_h, edges="efPf", move="right", callback=
|
||||
[lambda: self.fingerHolesAt(t_x*0.5, 0, w1_h, 90),])
|
||||
self.moveTo(0, 0)
|
||||
self.rectangularWall(t_x, t_h, edges="efPf", move="right", callback=[lambda: self.fingerHolesAt(t_x * 0.5, 0, w1_h, 90), ])
|
||||
self.rectangularWall(t_x, t_h, edges="efPf", move="right")
|
||||
self.rectangularWall(t_x, t_h, edges="eFPF", move="right", callback=
|
||||
[lambda: self.fingerHolesAt(t_x*0.5, 0, w2_h, 90),])
|
||||
self.rectangularWall(t_x, t_h, edges="eFPF", move="right", callback=[lambda: self.fingerHolesAt(t_x * 0.5, 0, w2_h, 90), ])
|
||||
self.rectangularWall(t_x, t_h, edges="eFPF", move="right")
|
||||
|
||||
self.rectangularWall(w1_x, w1_h, "efpe", move="right")
|
||||
|
@ -48,10 +48,12 @@ class Castle(Boxes):
|
|||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
c = Castle()
|
||||
c.parseArgs()
|
||||
c.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class DrillBox(Boxes):
|
||||
"""Not yet parametrized box for drills from 1 to 12.5mm
|
||||
in 0.5mm steps, 3 holes each size"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.x, self.y, self.h = 120, 240, 60
|
||||
|
@ -31,51 +33,46 @@ in 0.5mm steps, 3 holes each size"""
|
|||
self.fingerHolesAt(0, 5, self.y, angle=0)
|
||||
self.fingerHolesAt(0, 25, self.y, angle=0)
|
||||
|
||||
|
||||
def drillholes(self):
|
||||
for i in range(6):
|
||||
for j in range(4):
|
||||
for k in range(3):
|
||||
r = (12.5-2*i-0.5*j) * 0.5
|
||||
self.hole(i*20+10, j*60+k*20+10, r+0.05)
|
||||
r = (12.5 - 2 * i - 0.5 * j) * 0.5
|
||||
self.hole(i * 20 + 10, j * 60 + k * 20 + 10, r + 0.05)
|
||||
|
||||
def description(self):
|
||||
self.ctx.set_font_size(6)
|
||||
for i in range(4):
|
||||
for j in range(6):
|
||||
self.rectangularHole(i*60+30, 20*j+10, 58, 14+1*j)
|
||||
d = 2.5-0.5*i+2*j
|
||||
self.text("%.1f" % d, i*60+20, 19*j+6,
|
||||
self.rectangularHole(i * 60 + 30, 20 * j + 10, 58, 14 + 1 * j)
|
||||
d = 2.5 - 0.5 * i + 2 * j
|
||||
self.text("%.1f" % d, i * 60 + 20, 19 * j + 6,
|
||||
align="center")
|
||||
|
||||
|
||||
def render(self):
|
||||
x, y, h = self.x, self.y, self.h
|
||||
t = self.thickness
|
||||
|
||||
self.open()
|
||||
self.edges["f"].settings.setValues(self.thickness, space=3, finger=3,
|
||||
surroundingspaces=1)
|
||||
self.edges["f"].settings.setValues(self.thickness, space=3, finger=3, surroundingspaces=1)
|
||||
|
||||
self.rectangularWall(x, h, "FfeF", callback=[self.holesx],move="right")
|
||||
self.rectangularWall(x, h, "FfeF", callback=[self.holesx], move="right")
|
||||
self.rectangularWall(y, h, "FfeF", callback=[self.holesy], move="up")
|
||||
self.rectangularWall(y, h, "FfeF", callback=[self.holesy])
|
||||
self.rectangularWall(x, h, "FfeF", callback=[self.holesx],
|
||||
move="left up")
|
||||
|
||||
self.rectangularWall(x, h, "FfeF", callback=[self.holesx], move="left up")
|
||||
|
||||
self.rectangularWall(x, y, "ffff", move="up")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.drillholes],
|
||||
move="up")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.drillholes,
|
||||
self.description],
|
||||
move="up")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.drillholes], move="up")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.drillholes, self.description], move="up")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = DrillBox()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -17,29 +17,33 @@
|
|||
import boxes
|
||||
import math
|
||||
|
||||
|
||||
class FlexBox(boxes.Boxes):
|
||||
"""Box with living hinge and round corners"""
|
||||
|
||||
def __init__(self):
|
||||
boxes.Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=15,
|
||||
"--radius", action="store", type=float, default=15,
|
||||
help="Radius of the latch in mm")
|
||||
|
||||
|
||||
@boxes.restore
|
||||
def flexBoxSide(self, x, y, r, callback=None):
|
||||
self.moveTo(r, 0)
|
||||
|
||||
for i, l in zip(range(2), (x, y)):
|
||||
self.cc(callback, i)
|
||||
self.edges["f"](l-2*r)
|
||||
self.edges["f"](l - 2 * r)
|
||||
self.corner(90, r)
|
||||
|
||||
self.cc(callback, 2)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 3)
|
||||
self.latch(self.latchsize)
|
||||
self.cc(callback, 4)
|
||||
self.edges["f"](y-2*r-self.latchsize)
|
||||
self.edges["f"](y - 2 * r - self.latchsize)
|
||||
self.corner(90, r)
|
||||
|
||||
def surroundingWall(self):
|
||||
|
@ -47,33 +51,33 @@ class FlexBox(boxes.Boxes):
|
|||
|
||||
c4 = math.pi * r * 0.5
|
||||
|
||||
self.edges["F"](y-2*r-self.latchsize, False)
|
||||
if x-2*r < self.thickness:
|
||||
self.edges["X"](2*c4+x-2*r, h+2*self.thickness)
|
||||
self.edges["F"](y - 2 * r - self.latchsize, False)
|
||||
if x - 2 * r < self.thickness:
|
||||
self.edges["X"](2 * c4 + x - 2 * r, h + 2 * self.thickness)
|
||||
else:
|
||||
self.edges["X"](c4, h+2*self.thickness)
|
||||
self.edges["F"](x-2*r, False)
|
||||
self.edges["X"](c4, h+2*self.thickness)
|
||||
self.edges["F"](y-2*r, False)
|
||||
if x-2*r < self.thickness:
|
||||
self.edges["X"](2*c4+x-2*r, h+2*self.thickness)
|
||||
self.edges["X"](c4, h + 2 * self.thickness)
|
||||
self.edges["F"](x - 2 * r, False)
|
||||
self.edges["X"](c4, h + 2 * self.thickness)
|
||||
self.edges["F"](y - 2 * r, False)
|
||||
if x - 2 * r < self.thickness:
|
||||
self.edges["X"](2 * c4 + x - 2 * r, h + 2 * self.thickness)
|
||||
else:
|
||||
self.edges["X"](c4, h+2*self.thickness)
|
||||
self.edge(x-2*r)
|
||||
self.edges["X"](c4, h+2*self.thickness)
|
||||
self.edges["X"](c4, h + 2 * self.thickness)
|
||||
self.edge(x - 2 * r)
|
||||
self.edges["X"](c4, h + 2 * self.thickness)
|
||||
self.latch(self.latchsize, False)
|
||||
self.edge(h+2*self.thickness)
|
||||
self.edge(h + 2 * self.thickness)
|
||||
self.latch(self.latchsize, False, True)
|
||||
self.edge(c4)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.edge(c4)
|
||||
self.edges["F"](y-2*r, False)
|
||||
self.edges["F"](y - 2 * r, False)
|
||||
self.edge(c4)
|
||||
self.edges["F"](x-2*r, False)
|
||||
self.edges["F"](x - 2 * r, False)
|
||||
self.edge(c4)
|
||||
self.edges["F"](y-2*r-self.latchsize, False)
|
||||
self.edges["F"](y - 2 * r - self.latchsize, False)
|
||||
self.corner(90)
|
||||
self.edge(h+2*self.thickness)
|
||||
self.edge(h + 2 * self.thickness)
|
||||
self.corner(90)
|
||||
|
||||
def render(self):
|
||||
|
@ -85,27 +89,29 @@ class FlexBox(boxes.Boxes):
|
|||
|
||||
x, y, h = self.x, self.y, self.h
|
||||
self.latchsize = 8 * self.thickness
|
||||
r = self.radius or min(x, y-self.latchsize)/2.0
|
||||
r = min(r, x/2.0)
|
||||
self.radius = r = min(r, max(0, (y-self.latchsize)/2.0))
|
||||
r = self.radius or min(x, y - self.latchsize) / 2.0
|
||||
r = min(r, x / 2.0)
|
||||
self.radius = r = min(r, max(0, (y - self.latchsize) / 2.0))
|
||||
c4 = math.pi * r * 0.5
|
||||
|
||||
self.open()
|
||||
|
||||
self.moveTo(self.thickness, self.thickness)
|
||||
self.surroundingWall()
|
||||
self.moveTo(self.thickness, self.h+5*self.thickness)
|
||||
self.moveTo(self.thickness, self.h + 5 * self.thickness)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
self.moveTo(2*self.x+3*self.thickness, 0)
|
||||
self.moveTo(2 * self.x + 3 * self.thickness, 0)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = FlexBox()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -17,49 +17,53 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
class FlexBox2(Boxes):
|
||||
"""Box with living hinge and top corners rounded"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=15,
|
||||
"--radius", action="store", type=float, default=15,
|
||||
help="Radius of the corners in mm")
|
||||
|
||||
|
||||
@restore
|
||||
def flexBoxSide(self, x, y, r, callback=None):
|
||||
self.cc(callback, 0)
|
||||
self.edges["f"](x)
|
||||
self.corner(90, 0)
|
||||
self.cc(callback, 1)
|
||||
self.edges["f"](y-r)
|
||||
self.edges["f"](y - r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 2)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 3)
|
||||
self.latch(self.latchsize)
|
||||
self.cc(callback, 4)
|
||||
self.edges["f"](y-r-self.latchsize)
|
||||
self.edges["f"](y - r - self.latchsize)
|
||||
self.corner(90)
|
||||
|
||||
def surroundingWall(self):
|
||||
x, y, h, r = self.x, self.y, self.h, self.radius
|
||||
|
||||
self.edges["F"](y-r, False)
|
||||
if (x-2*r < self.thickness):
|
||||
self.edges["X"](2*self.c4+x-2*r, h+2*self.thickness)
|
||||
|
||||
self.edges["F"](y - r, False)
|
||||
|
||||
if (x - 2 * r < self.thickness):
|
||||
self.edges["X"](2 * self.c4 + x - 2 * r, h + 2 * self.thickness)
|
||||
else:
|
||||
self.edges["X"](self.c4, h+2*self.thickness)
|
||||
self.edge(x-2*r)
|
||||
self.edges["X"](self.c4, h+2*self.thickness)
|
||||
self.edges["X"](self.c4, h + 2 * self.thickness)
|
||||
self.edge(x - 2 * r)
|
||||
self.edges["X"](self.c4, h + 2 * self.thickness)
|
||||
|
||||
self.latch(self.latchsize, False)
|
||||
self.edge(h+2*self.thickness)
|
||||
self.edge(h + 2 * self.thickness)
|
||||
self.latch(self.latchsize, False, True)
|
||||
self.edge(self.c4)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.edge(self.c4)
|
||||
self.edges["F"](y-r)
|
||||
self.edges["F"](y - r)
|
||||
self.corner(90)
|
||||
self.edge(self.thickness)
|
||||
self.edges["f"](h)
|
||||
|
@ -67,41 +71,48 @@ class FlexBox2(Boxes):
|
|||
self.corner(90)
|
||||
|
||||
def render(self):
|
||||
|
||||
if self.outside:
|
||||
self.x = self.adjustSize(self.x)
|
||||
self.y = self.adjustSize(self.y)
|
||||
self.h = self.adjustSize(self.h)
|
||||
|
||||
self.latchsize = 8*self.thickness
|
||||
self.radius = self.radius or min(self.x/2.0, self.y-self.latchsize)
|
||||
self.radius = min(self.radius, self.x/2.0)
|
||||
self.radius = min(self.radius, max(0, self.y-self.latchsize))
|
||||
self.latchsize = 8 * self.thickness
|
||||
self.radius = self.radius or min(self.x / 2.0, self.y - self.latchsize)
|
||||
self.radius = min(self.radius, self.x / 2.0)
|
||||
self.radius = min(self.radius, max(0, self.y - self.latchsize))
|
||||
self.c4 = c4 = math.pi * self.radius * 0.5
|
||||
|
||||
self.open()
|
||||
|
||||
self.fingerJointSettings = (4, 4)
|
||||
|
||||
self.moveTo(2*self.thickness, self.thickness)
|
||||
self.moveTo(2 * self.thickness, self.thickness)
|
||||
self.ctx.save()
|
||||
self.surroundingWall()
|
||||
self.moveTo(self.x+self.y-3*self.radius+2*self.c4+self.latchsize+1*self.thickness, 0)
|
||||
|
||||
self.moveTo(self.x + self.y - 3 * self.radius + 2 * self.c4 + self.latchsize + 1 * self.thickness, 0)
|
||||
self.rectangularWall(self.x, self.h, edges="FFFF")
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, self.h+4*self.thickness)
|
||||
|
||||
self.moveTo(0, self.h + 4 * self.thickness)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
self.moveTo(2*self.x+3*self.thickness, 0)
|
||||
|
||||
self.moveTo(2 * self.x + 3 * self.thickness, 0)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.moveTo(2*self.thickness, 0)
|
||||
self.rectangularWall(self.h, self.y-self.radius-self.latchsize, edges="fFeF")
|
||||
|
||||
self.moveTo(2 * self.thickness, 0)
|
||||
self.rectangularWall(self.h, self.y - self.radius - self.latchsize, edges="fFeF")
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = FlexBox2()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -17,22 +17,24 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
class FlexBox3(Boxes):
|
||||
"""Box with living hinge"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--z", action="store", type=float, default=100.0,
|
||||
"--z", action="store", type=float, default=100.0,
|
||||
help="height of the box")
|
||||
self.argparser.add_argument(
|
||||
"--h", action="store", type=float, default=10.0,
|
||||
"--h", action="store", type=float, default=10.0,
|
||||
help="height of the lid")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=10.0,
|
||||
"--radius", action="store", type=float, default=10.0,
|
||||
help="radius of the lids living hinge")
|
||||
self.argparser.add_argument(
|
||||
"--c", action="store", type=float, default=1.0,
|
||||
"--c", action="store", type=float, default=1.0,
|
||||
dest="d", help="clearance of the lid")
|
||||
|
||||
def rectangleCorner(self, edge1=None, edge2=None):
|
||||
|
@ -50,10 +52,10 @@ class FlexBox3(Boxes):
|
|||
self.edges["f"](x)
|
||||
self.corner(90, 0)
|
||||
self.cc(callback, 1)
|
||||
self.edges["f"](y-r)
|
||||
self.edges["f"](y - r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 2)
|
||||
self.edge(x-r)
|
||||
self.edge(x - r)
|
||||
self.corner(90, 0)
|
||||
self.cc(callback, 3)
|
||||
self.edges["f"](y)
|
||||
|
@ -61,22 +63,22 @@ class FlexBox3(Boxes):
|
|||
|
||||
def surroundingWall(self):
|
||||
x, y, z, r, d = self.x, self.y, self.z, self.radius, self.d
|
||||
|
||||
self.edges["F"](y-r, False)
|
||||
self.edges["X"](self.c4, z+2*self.thickness)
|
||||
|
||||
self.edges["F"](y - r, False)
|
||||
self.edges["X"](self.c4, z + 2 * self.thickness)
|
||||
self.corner(-90)
|
||||
self.edge(d)
|
||||
self.corner(90)
|
||||
self.edges["f"](x-r+d)
|
||||
self.edges["f"](x - r + d)
|
||||
self.corner(90)
|
||||
self.edges["f"](z+2*self.thickness+2*d)
|
||||
self.edges["f"](z + 2 * self.thickness + 2 * d)
|
||||
self.corner(90)
|
||||
self.edges["f"](x-r+d)
|
||||
self.edges["f"](x - r + d)
|
||||
self.corner(90)
|
||||
self.edge(d)
|
||||
self.corner(-90)
|
||||
self.edge(self.c4)
|
||||
self.edges["F"](y-r)
|
||||
self.edges["F"](y - r)
|
||||
self.corner(90)
|
||||
self.edge(self.thickness)
|
||||
self.edges["f"](z)
|
||||
|
@ -87,16 +89,16 @@ class FlexBox3(Boxes):
|
|||
def lidSide(self):
|
||||
x, y, z, r, d, h = self.x, self.y, self.z, self.radius, self.d, self.h
|
||||
t = self.thickness
|
||||
r2 = r+t if r+t <=h+t else h+t
|
||||
r2 = r + t if r + t <= h + t else h + t
|
||||
self.moveTo(self.thickness, self.thickness)
|
||||
self.edge(h+self.thickness-r2)
|
||||
self.edge(h + self.thickness - r2)
|
||||
self.corner(90, r2)
|
||||
self.edge(r-r2+2*t)
|
||||
self.edges["F"](x-r)
|
||||
self.edge(r - r2 + 2 * t)
|
||||
self.edges["F"](x - r)
|
||||
self.rectangleCorner("F", "f")
|
||||
self.edges["g"](h)
|
||||
self.rectangleCorner("f", "e")
|
||||
self.edge(x+2*t)
|
||||
self.edge(x + 2 * t)
|
||||
|
||||
def render(self):
|
||||
if self.outside:
|
||||
|
@ -105,56 +107,57 @@ class FlexBox3(Boxes):
|
|||
self.z = self.adjustSize(self.z)
|
||||
|
||||
x, y, z, d, h = self.x, self.y, self.z, self.d, self.h
|
||||
r = self.radius = self.radius or min(x, y)/2.0
|
||||
r = self.radius = self.radius or min(x, y) / 2.0
|
||||
thickness = self.thickness
|
||||
|
||||
self.c4 = c4 = math.pi * r * 0.5 * 0.95
|
||||
self.latchsize = 8*thickness
|
||||
self.latchsize = 8 * thickness
|
||||
|
||||
width = 2*x + y - 2*r + c4 + 14*thickness + 3*h # lock
|
||||
height = y + z + 8*thickness
|
||||
width = 2 * x + y - 2 * r + c4 + 14 * thickness + 3 * h # lock
|
||||
height = y + z + 8 * thickness
|
||||
|
||||
self.open()
|
||||
|
||||
self.edges["f"].settings.setValues(
|
||||
self.thickness, finger=2, space=2, surroundingspaces=1)
|
||||
self.edges["f"].settings.setValues(self.thickness, finger=2, space=2, surroundingspaces=1)
|
||||
|
||||
s = edges.FingerJointSettings(self.thickness, surroundingspaces=1)
|
||||
g = edges.FingerJointEdge(self, s)
|
||||
g.char = "g"
|
||||
self.addPart(g)
|
||||
|
||||
G = edges.FingerJointEdgeCounterPart(self, s)
|
||||
G.char = "G"
|
||||
self.addPart(G)
|
||||
|
||||
self.moveTo(2*self.thickness, self.thickness+2*d)
|
||||
self.moveTo(2 * self.thickness, self.thickness + 2 * d)
|
||||
self.ctx.save()
|
||||
self.surroundingWall()
|
||||
self.moveTo(x+y-2*r+self.c4+2*self.thickness, -2*d-self.thickness)
|
||||
self.moveTo(x + y - 2 * r + self.c4 + 2 * self.thickness, -2 * d - self.thickness)
|
||||
self.rectangularWall(x, z, edges="FFFF", move="right")
|
||||
self.rectangularWall(h, z+2*(d+self.thickness),
|
||||
edges="GeGF", move="right")
|
||||
self.rectangularWall(h, z + 2 * (d + self.thickness), edges="GeGF", move="right")
|
||||
self.lidSide()
|
||||
self.moveTo(2*h+5*self.thickness, 0)
|
||||
self.moveTo(2 * h + 5 * self.thickness, 0)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.lidSide()
|
||||
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, z+4*self.thickness+2*d)
|
||||
self.moveTo(0, z + 4 * self.thickness + 2 * d)
|
||||
self.flexBoxSide(x, y, r)
|
||||
self.moveTo(2*x+3*self.thickness, 2*d)
|
||||
self.moveTo(2 * x + 3 * self.thickness, 2 * d)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.flexBoxSide(x, y, r)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.moveTo(2*self.thickness, -self.thickness)
|
||||
self.moveTo(2 * self.thickness, -self.thickness)
|
||||
self.rectangularWall(z, y, edges="fFeF")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = FlexBox3() #100, 40, 100, r=20, h=10, thickness=4.0)
|
||||
b = FlexBox3() # 100, 40, 100, r=20, h=10, thickness=4.0)
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -17,51 +17,54 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
class FlexBox4(Boxes):
|
||||
"""Box with living hinge and left corners rounded"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=15,
|
||||
"--radius", action="store", type=float, default=15,
|
||||
help="Radius of the corners in mm")
|
||||
|
||||
|
||||
@restore
|
||||
def flexBoxSide(self, x, y, r, callback=None):
|
||||
self.cc(callback, 0)
|
||||
self.edges["f"](x)
|
||||
self.corner(90, 0)
|
||||
self.cc(callback, 1)
|
||||
self.edges["f"](y-r)
|
||||
self.edges["f"](y - r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 2)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.corner(90, r)
|
||||
self.cc(callback, 3)
|
||||
self.edges["e"](y-r-self.latchsize)
|
||||
self.edges["e"](y - r - self.latchsize)
|
||||
self.cc(callback, 4)
|
||||
self.latch(self.latchsize)
|
||||
self.corner(90)
|
||||
|
||||
def surroundingWall(self):
|
||||
x, y, h, r = self.x, self.y, self.h, self.radius
|
||||
|
||||
self.edges["F"](y-r, False)
|
||||
if (x-2*r < self.thickness):
|
||||
self.edges["X"](2*self.c4+x-2*r, h+2*self.thickness)
|
||||
|
||||
self.edges["F"](y - r, False)
|
||||
if (x - 2 * r < self.thickness):
|
||||
self.edges["X"](2 * self.c4 + x - 2 * r, h + 2 * self.thickness)
|
||||
else:
|
||||
self.edges["X"](self.c4, h+2*self.thickness)
|
||||
self.edge(x-2*r)
|
||||
self.edges["X"](self.c4, h+2*self.thickness)
|
||||
self.edge(y-r-self.latchsize)
|
||||
self.edges["X"](self.c4, h + 2 * self.thickness)
|
||||
self.edge(x - 2 * r)
|
||||
self.edges["X"](self.c4, h + 2 * self.thickness)
|
||||
|
||||
self.edge(y - r - self.latchsize)
|
||||
self.latch(self.latchsize, False)
|
||||
self.edge(h+2*self.thickness)
|
||||
self.edge(h + 2 * self.thickness)
|
||||
self.latch(self.latchsize, False, True)
|
||||
self.edge(y-r-self.latchsize)
|
||||
self.edge(y - r - self.latchsize)
|
||||
self.edge(self.c4)
|
||||
self.edge(x-2*r)
|
||||
self.edge(x - 2 * r)
|
||||
self.edge(self.c4)
|
||||
self.edges["F"](y-r)
|
||||
self.edges["F"](y - r)
|
||||
self.corner(90)
|
||||
self.edge(self.thickness)
|
||||
self.edges["f"](h)
|
||||
|
@ -75,33 +78,35 @@ class FlexBox4(Boxes):
|
|||
self.h = self.adjustSize(self.h)
|
||||
|
||||
self.c4 = c4 = math.pi * self.radius * 0.5
|
||||
self.latchsize = 8*self.thickness
|
||||
self.radius = self.radius or min(self.x/2.0, self.y-self.latchsize)
|
||||
self.radius = min(self.radius, self.x/2.0)
|
||||
self.radius = min(self.radius, max(0, self.y-self.latchsize))
|
||||
self.latchsize = 8 * self.thickness
|
||||
self.radius = self.radius or min(self.x / 2.0, self.y - self.latchsize)
|
||||
self.radius = min(self.radius, self.x / 2.0)
|
||||
self.radius = min(self.radius, max(0, self.y - self.latchsize))
|
||||
|
||||
self.open()
|
||||
|
||||
self.fingerJointSettings = (4, 4)
|
||||
|
||||
self.moveTo(2*self.thickness, self.thickness)
|
||||
self.moveTo(2 * self.thickness, self.thickness)
|
||||
self.ctx.save()
|
||||
self.surroundingWall()
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, self.h+4*self.thickness)
|
||||
self.moveTo(0, self.h + 4 * self.thickness)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
self.moveTo(2*self.x+3*self.thickness, 0)
|
||||
self.moveTo(2 * self.x + 3 * self.thickness, 0)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.flexBoxSide(self.x, self.y, self.radius)
|
||||
self.ctx.scale(-1, 1)
|
||||
self.moveTo(2*self.thickness,-self.thickness)
|
||||
self.moveTo(2 * self.thickness, -self.thickness)
|
||||
self.rectangularWall(self.x, self.h, edges="FeFF")
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = FlexBox4()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -16,19 +16,21 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class FlexTest(Boxes):
|
||||
"Piece for testing different flex settings"
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y")
|
||||
self.argparser.add_argument(
|
||||
"--fd", action="store", type=float, default=0.5,
|
||||
"--fd", action="store", type=float, default=0.5,
|
||||
help="distance of flex cuts in multiples of thickness")
|
||||
self.argparser.add_argument(
|
||||
"--fc", action="store", type=float, default=1.0,
|
||||
"--fc", action="store", type=float, default=1.0,
|
||||
help="connections of flex cuts in multiples of thickness")
|
||||
self.argparser.add_argument(
|
||||
"--fw", action="store", type=float, default=5.0,
|
||||
"--fw", action="store", type=float, default=5.0,
|
||||
help="width of flex cuts in multiples of thickness")
|
||||
|
||||
def render(self):
|
||||
|
@ -46,17 +48,19 @@ class FlexTest(Boxes):
|
|||
self.corner(90)
|
||||
self.edge(y)
|
||||
self.corner(90)
|
||||
self.edge(x+20)
|
||||
self.edge(x + 20)
|
||||
self.corner(90)
|
||||
self.edge(y)
|
||||
self.corner(90)
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
f = FlexTest()
|
||||
f.parseArgs()
|
||||
f.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,26 +16,30 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class FlexTest2(Boxes):
|
||||
"Piece for testing 2D flex settings"
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y")
|
||||
self.argparser.add_argument(
|
||||
"--fw", action="store", type=float, default=1,
|
||||
"--fw", action="store", type=float, default=1,
|
||||
help="distance of flex cuts in multiples of thickness")
|
||||
|
||||
def render(self):
|
||||
x, y = self.x, self.y
|
||||
t = self.thickness
|
||||
|
||||
self.open()
|
||||
self.rectangularWall(x, y, callback=[lambda:self.flex2D(x, y, self.fw)])
|
||||
self.rectangularWall(x, y, callback=[lambda: self.flex2D(x, y, self.fw)])
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
f = FlexTest()
|
||||
f.parseArgs()
|
||||
f.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
class Folder(Boxes):
|
||||
"""Book cover with flex for the spine"""
|
||||
|
||||
|
@ -32,18 +33,18 @@ class Folder(Boxes):
|
|||
x, y, r, h = self.x, self.y, self.r, self.h
|
||||
c2 = math.pi * h
|
||||
self.open()
|
||||
self.moveTo(r+self.thickness, self.thickness)
|
||||
self.edge(x-r)
|
||||
self.moveTo(r + self.thickness, self.thickness)
|
||||
self.edge(x - r)
|
||||
self.edges["X"](c2, y)
|
||||
self.edge(x-r)
|
||||
self.edge(x - r)
|
||||
self.corner(90, r)
|
||||
self.edge(y-2*r)
|
||||
self.edge(y - 2 * r)
|
||||
self.corner(90, r)
|
||||
self.edge(2*x-2*r+c2)
|
||||
self.edge(2 * x - 2 * r + c2)
|
||||
self.corner(90, r)
|
||||
self.edge(y-2*r)
|
||||
self.edge(y - 2 * r)
|
||||
self.corner(90, r)
|
||||
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
|
@ -52,5 +53,6 @@ def main():
|
|||
f.parseArgs()
|
||||
f.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,89 +16,91 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class GearBox(Boxes):
|
||||
"""Gearbox with multiple identical stages"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.argparser.add_argument(
|
||||
"--teeth1", action="store", type=int, default=8,
|
||||
"--teeth1", action="store", type=int, default=8,
|
||||
help="number of teeth on ingoing shaft")
|
||||
self.argparser.add_argument(
|
||||
"--teeth2", action="store", type=int, default=20,
|
||||
"--teeth2", action="store", type=int, default=20,
|
||||
help="number of teeth on outgoing shaft")
|
||||
self.argparser.add_argument(
|
||||
"--modulus", action="store", type=float, default=3,
|
||||
"--modulus", action="store", type=float, default=3,
|
||||
help="modulus of the theeth in mm")
|
||||
self.argparser.add_argument(
|
||||
"--shaft", action="store", type=float, default=6.,
|
||||
"--shaft", action="store", type=float, default=6.,
|
||||
help="diameter of the shaft")
|
||||
self.argparser.add_argument(
|
||||
"--stages", action="store", type=int, default=4,
|
||||
"--stages", action="store", type=int, default=4,
|
||||
help="number of stages in the gear reduction")
|
||||
|
||||
def render(self):
|
||||
# Initialize canvas
|
||||
self.open()
|
||||
|
||||
|
||||
if self.teeth2 < self.teeth1:
|
||||
self.teeth2, self.teeth1 = self.teeth1, self.teeth2
|
||||
|
||||
pitch1, size1, xxx = self.gears.sizes(teeth=self.teeth1,
|
||||
dimension=self.modulus)
|
||||
pitch2, size2, xxx = self.gears.sizes(teeth=self.teeth2,
|
||||
dimension=self.modulus)
|
||||
pitch1, size1, xxx = self.gears.sizes(teeth=self.teeth1, dimension=self.modulus)
|
||||
pitch2, size2, xxx = self.gears.sizes(teeth=self.teeth2, dimension=self.modulus)
|
||||
|
||||
t = self.thickness
|
||||
x = 1.1*t*self.stages
|
||||
x = 1.1 * t * self.stages
|
||||
|
||||
if self.stages == 1:
|
||||
y = size1 + size2
|
||||
y1 = y/2-(pitch1+pitch2)+pitch1
|
||||
y2 = y/2+(pitch1+pitch2)-pitch2
|
||||
y1 = y / 2 - (pitch1 + pitch2) + pitch1
|
||||
y2 = y / 2 + (pitch1 + pitch2) - pitch2
|
||||
else:
|
||||
y = 2 * size2
|
||||
y1 = y/2 - (pitch1+pitch2)/2
|
||||
y2 = y/2 + (pitch1+pitch2)/2
|
||||
y1 = y / 2 - (pitch1 + pitch2) / 2
|
||||
y2 = y / 2 + (pitch1 + pitch2) / 2
|
||||
|
||||
h = max(size1, size2) + t
|
||||
|
||||
b = "F"
|
||||
t = "e" # prepare for close box
|
||||
t = "e" # prepare for close box
|
||||
mh = self.shaft
|
||||
|
||||
|
||||
def sideCB():
|
||||
self.hole(y1, h/2, mh/2)
|
||||
self.hole(y2, h/2, mh/2)
|
||||
|
||||
self.hole(y1, h / 2, mh / 2)
|
||||
self.hole(y2, h / 2, mh / 2)
|
||||
|
||||
self.moveTo(self.thickness, self.thickness)
|
||||
self.rectangularWall(y, h, [b, "f", t, "f"], callback=[sideCB], move="right")
|
||||
self.rectangularWall(x, h, [b, "F", t, "F"], move="up")
|
||||
self.rectangularWall(x, h, [b, "F", t, "F"])
|
||||
self.rectangularWall(y, h, [b, "f", t, "f"], callback=[sideCB], move="left")
|
||||
self.rectangularWall(x, h, [b, "F", t, "F"], move="up only")
|
||||
|
||||
|
||||
self.rectangularWall(x, y, "ffff", move="up")
|
||||
|
||||
profile_shift = 20
|
||||
pressure_angle = 20
|
||||
for i in range(self.stages-1):
|
||||
self.gears(teeth=self.teeth2, dimension=self.modulus,
|
||||
angle=pressure_angle,
|
||||
|
||||
for i in range(self.stages - 1):
|
||||
self.gears(teeth=self.teeth2, dimension=self.modulus, angle=pressure_angle,
|
||||
mount_hole=mh, profile_shift=profile_shift, move="up")
|
||||
self.gears(teeth=self.teeth2, dimension=self.modulus,
|
||||
angle=pressure_angle,
|
||||
|
||||
self.gears(teeth=self.teeth2, dimension=self.modulus, angle=pressure_angle,
|
||||
mount_hole=mh, profile_shift=profile_shift, move="right")
|
||||
|
||||
for i in range(self.stages):
|
||||
self.gears(teeth=self.teeth1, dimension=self.modulus,
|
||||
angle=pressure_angle,
|
||||
self.gears(teeth=self.teeth1, dimension=self.modulus, angle=pressure_angle,
|
||||
mount_hole=mh, profile_shift=profile_shift, move="down")
|
||||
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Box()
|
||||
b = GearBox()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -17,34 +17,34 @@
|
|||
from boxes import *
|
||||
import random
|
||||
|
||||
class JigsawPuzzle(Boxes): # change class name here and below
|
||||
|
||||
class JigsawPuzzle(Boxes): # change class name here and below
|
||||
"""Fractal jigsaw puzzle. Still aplha"""
|
||||
|
||||
webinterface = False # Change to make visible in web interface
|
||||
|
||||
webinterface = False # Change to make visible in web interface
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.count = 0
|
||||
self.argparser.add_argument(
|
||||
"--size", action="store", type=float, default=100,
|
||||
"--size", action="store", type=float, default=100,
|
||||
help="size of the puzzle in mm")
|
||||
self.argparser.add_argument(
|
||||
"--depth", action="store", type=int, default=5,
|
||||
"--depth", action="store", type=int, default=5,
|
||||
help="depth of the recursion/level of detail")
|
||||
|
||||
|
||||
def peano(self, level):
|
||||
if level == 0:
|
||||
self.edge(self.size/self.depth)
|
||||
self.edge(self.size / self.depth)
|
||||
return
|
||||
self.peano(self, level-1)
|
||||
self.corner()
|
||||
|
||||
self.peano(self, level - 1)
|
||||
self.corner()
|
||||
|
||||
def edge(self, l):
|
||||
self.count += 1
|
||||
Boxes.edge(self, l)
|
||||
#if (self.count % 2**5) == 0: #level == 3 and parity>0:
|
||||
# if (self.count % 2**5) == 0: #level == 3 and parity>0:
|
||||
# self.corner(-360, 0.25*self.size/2**self.depth)
|
||||
|
||||
def hilbert(self, level, parity=1):
|
||||
|
@ -53,28 +53,31 @@ class JigsawPuzzle(Boxes): # change class name here and below
|
|||
# rotate and draw first subcurve with opposite parity to big curve
|
||||
self.corner(parity * 90)
|
||||
self.hilbert(level - 1, -parity)
|
||||
|
||||
# interface to and draw second subcurve with same parity as big curve
|
||||
self.edge(self.size/2**self.depth)
|
||||
self.edge(self.size / 2 ** self.depth)
|
||||
self.corner(parity * -90)
|
||||
self.hilbert(level - 1, parity)
|
||||
|
||||
# third subcurve
|
||||
self.edge(self.size/2**self.depth)
|
||||
self.edge(self.size / 2 ** self.depth)
|
||||
self.hilbert(level - 1, parity)
|
||||
#if level == 3: self.corner(-360, 0.4*self.size/2**self.depth)
|
||||
|
||||
# if level == 3: self.corner(-360, 0.4*self.size/2**self.depth)
|
||||
# fourth subcurve
|
||||
self.corner(parity * -90)
|
||||
self.edge(self.size/2**self.depth)
|
||||
self.edge(self.size / 2 ** self.depth)
|
||||
self.hilbert(level - 1, -parity)
|
||||
# a final turn is needed to make the turtle
|
||||
# end up facing outward from the large square
|
||||
self.corner(parity * 90)
|
||||
#if level == 3 and parity>0: # and random.random() < 100*0.5**(self.depth-2):
|
||||
# if level == 3 and parity>0: # and random.random() < 100*0.5**(self.depth-2):
|
||||
# self.corner(-360, 0.4*self.size/2**self.depth)
|
||||
#self.ctx.save()
|
||||
#self.corner(parity*-90)
|
||||
#self.edge(self.size/2**self.depth)
|
||||
#self.ctx.restore()
|
||||
|
||||
# self.ctx.save()
|
||||
# self.corner(parity*-90)
|
||||
# self.edge(self.size/2**self.depth)
|
||||
# self.ctx.restore()
|
||||
|
||||
def render(self):
|
||||
size = self.size
|
||||
t = self.thickness
|
||||
|
@ -85,10 +88,12 @@ class JigsawPuzzle(Boxes): # change class name here and below
|
|||
self.hilbert(self.depth)
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = JigsawPuzzle()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -17,37 +17,39 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
"""
|
||||
22x7.5x7cm
|
||||
D=23cm, d=21cm
|
||||
d = 8" D = 9"
|
||||
"""
|
||||
|
||||
|
||||
class RoundedTriangleSettings(edges.Settings):
|
||||
absolute_params = {
|
||||
"angle" : 60,
|
||||
"radius" : 30,
|
||||
"r_hole" : None,
|
||||
}
|
||||
"angle": 60,
|
||||
"radius": 30,
|
||||
"r_hole": None,
|
||||
}
|
||||
|
||||
|
||||
class RoundedTriangle(edges.Edge):
|
||||
char = "t"
|
||||
|
||||
def __call__(self, length, **kw):
|
||||
angle = self.settings.angle
|
||||
r = self.settings.radius
|
||||
|
||||
if self.settings.r_hole:
|
||||
x = 0.5*(length-2*r)*math.tan(math.radians(angle))
|
||||
y = 0.5*(length)
|
||||
x = 0.5 * (length - 2 * r) * math.tan(math.radians(angle))
|
||||
y = 0.5 * (length)
|
||||
self.hole(x, y, self.settings.r_hole)
|
||||
|
||||
l = 0.5 * (length-2*r) / math.cos(math.radians(angle))
|
||||
self.corner(90-angle, r)
|
||||
l = 0.5 * (length - 2 * r) / math.cos(math.radians(angle))
|
||||
self.corner(90 - angle, r)
|
||||
self.edge(l)
|
||||
self.corner(2*angle, r)
|
||||
self.corner(2 * angle, r)
|
||||
self.edge(l)
|
||||
self.corner(90-angle, r)
|
||||
self.corner(90 - angle, r)
|
||||
|
||||
def startAngle(self):
|
||||
return 90
|
||||
|
@ -55,8 +57,8 @@ class RoundedTriangle(edges.Edge):
|
|||
def endAngle(self):
|
||||
return 90
|
||||
|
||||
class Lamp(Boxes):
|
||||
|
||||
class Lamp(Boxes):
|
||||
webinterface = False
|
||||
|
||||
def __init__(self):
|
||||
|
@ -82,7 +84,7 @@ class Lamp(Boxes):
|
|||
|
||||
self.open()
|
||||
|
||||
#self.edges["f"].settings = (5, 5) # XXX
|
||||
# self.edges["f"].settings = (5, 5) # XXX
|
||||
|
||||
s = RoundedTriangleSettings(self.thickness, angle=72, r_hole=2)
|
||||
self.addPart(RoundedTriangle(self, s))
|
||||
|
@ -90,19 +92,20 @@ class Lamp(Boxes):
|
|||
self.flexSettings = (3, 5.0, 20.0)
|
||||
|
||||
self.edges["f"].settings.setValues(self.thickness, finger=5, space=5, relative=False)
|
||||
d = 2*(r+w)
|
||||
d = 2 * (r + w)
|
||||
|
||||
self.roundedPlate(d, d, r, move="right", callback=[
|
||||
lambda: self.hole(w, r+w, r),])
|
||||
#dist = ((2**0.5)*r-r) / (2**0.5) + 4
|
||||
#pos = (w-dist, dist)
|
||||
self.roundedPlate(d, d, r, holesMargin=w/2.0) #, callback=[
|
||||
lambda: self.hole(w, r + w, r), ])
|
||||
|
||||
# dist = ((2**0.5)*r-r) / (2**0.5) + 4
|
||||
# pos = (w-dist, dist)
|
||||
self.roundedPlate(d, d, r, holesMargin=w / 2.0) # , callback=[
|
||||
# lambda: self.hole(pos[0], pos[1], 7),])
|
||||
self.roundedPlate(d, d, r, move="only left up")
|
||||
|
||||
hole = lambda: self.hole(w, 70, 2)
|
||||
self.surroundingWall(d, d, r, 120, top='h', bottom='h', callback=[
|
||||
None, hole, None, hole], move="up")
|
||||
None, hole, None, hole], move="up")
|
||||
|
||||
self.ctx.save()
|
||||
self.rectangularWall(x, y, edges="fFfF", holesMargin=5, move="right")
|
||||
|
@ -119,10 +122,12 @@ class Lamp(Boxes):
|
|||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
l = Lamp()
|
||||
l.parseArgs()
|
||||
l.render(r=4*25.4, w=20, x=270, y=150, h=100)
|
||||
l.render(r=4 * 25.4, w=20, x=270, y=150, h=100)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,25 +16,28 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class MagazinFile(Boxes):
|
||||
"""Open magazine file"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("x", "y", "h", "hi", "outside")
|
||||
self.argparser.set_defaults(
|
||||
fingerjointfinger=2.0,
|
||||
fingerjointspace=2.0
|
||||
)
|
||||
)
|
||||
|
||||
def side(self, w, h, hi):
|
||||
r = min(h-hi, w) / 2.0
|
||||
if (h-hi) > w:
|
||||
r = min(h - hi, w) / 2.0
|
||||
|
||||
if (h - hi) > w:
|
||||
r = w / 2.0
|
||||
lx = 0
|
||||
ly = (h-hi) - w
|
||||
ly = (h - hi) - w
|
||||
else:
|
||||
r = (h - hi) / 2.0
|
||||
lx = (w - 2*r) / 2.0
|
||||
lx = (w - 2 * r) / 2.0
|
||||
ly = 0
|
||||
|
||||
e_w = self.edges["F"].startwidth()
|
||||
|
@ -51,15 +54,15 @@ class MagazinFile(Boxes):
|
|||
self.corner(-90, r)
|
||||
self.edge(ly)
|
||||
self.corner(90, r)
|
||||
self.edge(lx)
|
||||
self.edge(lx)
|
||||
self.edge(e_w)
|
||||
self.corner(90)
|
||||
self.edges["F"](h)
|
||||
self.edge(e_w)
|
||||
self.corner(90)
|
||||
|
||||
|
||||
def render(self):
|
||||
|
||||
if self.outside:
|
||||
self.x = self.adjustSize(self.x)
|
||||
self.y = self.adjustSize(self.y)
|
||||
|
@ -80,15 +83,17 @@ class MagazinFile(Boxes):
|
|||
|
||||
self.rectangularWall(x, h, "Ffef", move="right only")
|
||||
self.side(y, h, hi)
|
||||
self.moveTo(y+15, h+hi+15, 180)
|
||||
self.moveTo(y + 15, h + hi + 15, 180)
|
||||
self.side(y, h, hi)
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = MagazinFile()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -17,29 +17,31 @@
|
|||
from boxes import *
|
||||
import math
|
||||
|
||||
|
||||
class Planetary(Boxes):
|
||||
"""Gearbox with multiple identical stages"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.argparser.add_argument(
|
||||
"--sunteeth", action="store", type=int, default=8,
|
||||
"--sunteeth", action="store", type=int, default=8,
|
||||
help="number of teeth on sun gear")
|
||||
self.argparser.add_argument(
|
||||
"--planetteeth", action="store", type=int, default=20,
|
||||
"--planetteeth", action="store", type=int, default=20,
|
||||
help="number of teeth on planets")
|
||||
self.argparser.add_argument(
|
||||
"--maxplanets", action="store", type=int, default=0,
|
||||
"--maxplanets", action="store", type=int, default=0,
|
||||
help="limit the number of planets (0 for as much as fit)")
|
||||
self.argparser.add_argument(
|
||||
"--deltateeth", action="store", type=int, default=0,
|
||||
"--deltateeth", action="store", type=int, default=0,
|
||||
help="enable secondary ring with given delta to the ring gear")
|
||||
self.argparser.add_argument(
|
||||
"--modulus", action="store", type=float, default=3,
|
||||
"--modulus", action="store", type=float, default=3,
|
||||
help="modulus of the theeth in mm")
|
||||
self.argparser.add_argument(
|
||||
"--shaft", action="store", type=float, default=6.,
|
||||
"--shaft", action="store", type=float, default=6.,
|
||||
help="diameter of the shaft")
|
||||
#self.argparser.add_argument(
|
||||
# self.argparser.add_argument(
|
||||
# "--stages", action="store", type=int, default=4,
|
||||
# help="number of stages in the gear reduction")
|
||||
|
||||
|
@ -47,48 +49,50 @@ class Planetary(Boxes):
|
|||
# Initialize canvas
|
||||
self.open()
|
||||
|
||||
ringteeth = self.sunteeth+2*self.planetteeth
|
||||
spoke_width = 3*self.shaft
|
||||
|
||||
ringteeth = self.sunteeth + 2 * self.planetteeth
|
||||
spoke_width = 3 * self.shaft
|
||||
|
||||
pitch1, size1, xxx = self.gears.sizes(teeth=self.sunteeth,
|
||||
dimension=self.modulus)
|
||||
dimension=self.modulus)
|
||||
pitch2, size2, xxx = self.gears.sizes(teeth=self.planetteeth,
|
||||
dimension=self.modulus)
|
||||
dimension=self.modulus)
|
||||
pitch3, size3, xxx = self.gears.sizes(
|
||||
teeth=ringteeth, internal_ring=True, spoke_width=spoke_width,
|
||||
dimension=self.modulus)
|
||||
|
||||
t = self.thickness
|
||||
planets = int(math.pi//math.asin((self.planetteeth+2)/(self.planetteeth+self.sunteeth)))
|
||||
planets = int(math.pi // math.asin((self.planetteeth + 2) / (self.planetteeth + self.sunteeth)))
|
||||
|
||||
if self.maxplanets:
|
||||
planets = min(self.maxplanets, planets)
|
||||
|
||||
# Make sure the teeth mash
|
||||
ta = self.sunteeth+ringteeth
|
||||
ta = self.sunteeth + ringteeth
|
||||
# There are sunteeth+ringteeth mashing positions for the planets
|
||||
if ta % planets:
|
||||
planetpositions = [round(i*ta/planets)*360/ta for i in range(planets)]
|
||||
planetpositions = [round(i * ta / planets) * 360 / ta for i in range(planets)]
|
||||
else:
|
||||
planetpositions = planets
|
||||
|
||||
# XXX make configurable?
|
||||
profile_shift = 20
|
||||
pressure_angle = 20
|
||||
self.parts.disc(size3, callback=lambda:self.hole(0,0,self.shaft/2), move="up")
|
||||
self.parts.disc(size3, callback=lambda: self.hole(0, 0, self.shaft / 2), move="up")
|
||||
self.gears(teeth=ringteeth, dimension=self.modulus,
|
||||
angle=pressure_angle, internal_ring=True,
|
||||
spoke_width=spoke_width, mount_hole=self.shaft,
|
||||
profile_shift=profile_shift, move="up")
|
||||
self.gears.gearCarrier(pitch1+pitch2, spoke_width, planetpositions,
|
||||
2*spoke_width, self.shaft/2, move="up")
|
||||
self.gears.gearCarrier(pitch1 + pitch2, spoke_width, planetpositions,
|
||||
2 * spoke_width, self.shaft / 2, move="up")
|
||||
self.gears(teeth=self.sunteeth, dimension=self.modulus,
|
||||
angle=pressure_angle,
|
||||
mount_hole=self.shaft, profile_shift=profile_shift, move="up")
|
||||
numplanets = planets
|
||||
|
||||
if self.deltateeth:
|
||||
numplanets += planets
|
||||
deltamodulus = self.modulus*ringteeth/(ringteeth-self.deltateeth)
|
||||
self.gears(teeth=ringteeth-self.deltateeth, dimension=deltamodulus,
|
||||
deltamodulus = self.modulus * ringteeth / (ringteeth - self.deltateeth)
|
||||
self.gears(teeth=ringteeth - self.deltateeth, dimension=deltamodulus,
|
||||
angle=pressure_angle, internal_ring=True,
|
||||
spoke_width=spoke_width, mount_hole=self.shaft,
|
||||
profile_shift=profile_shift, move="up")
|
||||
|
@ -97,13 +101,15 @@ class Planetary(Boxes):
|
|||
self.gears(teeth=self.planetteeth, dimension=self.modulus,
|
||||
angle=pressure_angle,
|
||||
mount_hole=self.shaft, profile_shift=profile_shift, move="up")
|
||||
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Box()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
class Printer(Boxes):
|
||||
|
||||
class Printer(Boxes):
|
||||
"""Work in progress"""
|
||||
|
||||
webinterface = False
|
||||
|
@ -30,46 +30,48 @@ class Printer(Boxes):
|
|||
# idlers
|
||||
self.D_i = 17.0
|
||||
self.d_i = 5.0
|
||||
self.w_i = 7.0 # includes washers
|
||||
|
||||
self.w_i = 7.0 # includes washers
|
||||
|
||||
def mainPlate(self, nr):
|
||||
r = self.r
|
||||
t2 = 0.5 * self.thickness
|
||||
if nr:
|
||||
return
|
||||
self.moveTo(r-5, r, -90)
|
||||
self.hole(0, 0, r-80)
|
||||
self.moveTo(r - 5, r, -90)
|
||||
self.hole(0, 0, r - 80)
|
||||
|
||||
D_i2 = self.D_i / 2
|
||||
w_i2 = self.w_i / 2
|
||||
|
||||
d_c2 = self.d_c/2
|
||||
d_c2 = self.d_c / 2
|
||||
|
||||
for i in range(6):
|
||||
self.ctx.save()
|
||||
self.moveTo(0, 0, i*60)
|
||||
self.moveTo(0, 0, i * 60)
|
||||
|
||||
# winches
|
||||
if i % 2:
|
||||
self.fingerHolesAt(r-80, (d_c2+20), 70, angle=0)
|
||||
self.fingerHolesAt(r-80, -(d_c2+20), 70, angle=0)
|
||||
if i==5:
|
||||
self.fingerHolesAt(r-70+t2, -(d_c2+20+t2), 40, angle=-90)
|
||||
self.fingerHolesAt(r - 80, (d_c2 + 20), 70, angle=0)
|
||||
self.fingerHolesAt(r - 80, -(d_c2 + 20), 70, angle=0)
|
||||
if i == 5:
|
||||
self.fingerHolesAt(r - 70 + t2, -(d_c2 + 20 + t2), 40, angle=-90)
|
||||
else:
|
||||
self.fingerHolesAt(r-70+t2, (d_c2+20+t2), 40, angle=90)
|
||||
self.fingerHolesAt(r - 70 + t2, (d_c2 + 20 + t2), 40, angle=90)
|
||||
# idler buck
|
||||
else:
|
||||
d = 0.5*(self.thickness)+w_i2
|
||||
for y in (-d-d_c2, d-d_c2, -d+d_c2, d+d_c2):
|
||||
self.fingerHolesAt(r-30, y, 30, angle=0)
|
||||
self.hole(r-15+D_i2, -self.d_c/2, 0.4)
|
||||
self.hole(r-15+D_i2, self.d_c/2, 0.4)
|
||||
self.ctx.restore()
|
||||
d = 0.5 * (self.thickness) + w_i2
|
||||
|
||||
for y in (-d - d_c2, d - d_c2, -d + d_c2, d + d_c2):
|
||||
self.fingerHolesAt(r - 30, y, 30, angle=0)
|
||||
|
||||
self.hole(r - 15 + D_i2, -self.d_c / 2, 0.4)
|
||||
self.hole(r - 15 + D_i2, self.d_c / 2, 0.4)
|
||||
self.ctx.restore()
|
||||
|
||||
def head(self):
|
||||
d_c = self.d_c
|
||||
|
||||
self.moveTo(self.spacing+10, self.spacing)
|
||||
self.moveTo(self.spacing + 10, self.spacing)
|
||||
for i in range(3):
|
||||
self.hole(0, 5, 0.3)
|
||||
self.fingerHolesAt(25, 0, 20)
|
||||
|
@ -78,20 +80,20 @@ class Printer(Boxes):
|
|||
self.hole(0, 5, 0.3)
|
||||
self.corner(120, 10)
|
||||
|
||||
|
||||
def support(self, x, y, edges="ff", pair=False, callback=None, move=None):
|
||||
if len(edges) != 2:
|
||||
raise ValueError("Two edges required")
|
||||
edges = [self.edges.get(e, e,) for e in edges]
|
||||
|
||||
edges = [self.edges.get(e, e, ) for e in edges]
|
||||
|
||||
overallwidth = x + edges[0].spacing() + self.edges["e"].spacing()
|
||||
overallheight = y + edges[1].spacing() + self.edges["e"].spacing()
|
||||
|
||||
r = 2*self.thickness
|
||||
r = 2 * self.thickness
|
||||
|
||||
if pair:
|
||||
overallwidth+= edges[0].spacing() + r - self.edges["e"].spacing()
|
||||
overallheight+= edges[1].spacing() + r - self.edges["e"].spacing()
|
||||
overallwidth += edges[0].spacing() + r - self.edges["e"].spacing()
|
||||
overallheight += edges[1].spacing() + r - self.edges["e"].spacing()
|
||||
|
||||
if self.move(overallwidth, overallheight, move, before=True):
|
||||
return
|
||||
|
@ -99,16 +101,16 @@ class Printer(Boxes):
|
|||
self.ctx.save()
|
||||
self.moveTo(edges[0].margin(), edges[1].margin())
|
||||
|
||||
angle = math.degrees(math.atan((y-r)/float(x-r)))
|
||||
angle = math.degrees(math.atan((y - r) / float(x - r)))
|
||||
|
||||
self.cc(callback, 0)
|
||||
edges[1](x)
|
||||
self.corner(90)
|
||||
#self.edge(self.thickness)
|
||||
self.corner(90-angle, r)
|
||||
self.edge(((x-r)**2+(y-r)**2)**0.5)
|
||||
# self.edge(self.thickness)
|
||||
self.corner(90 - angle, r)
|
||||
self.edge(((x - r) ** 2 + (y - r) ** 2) ** 0.5)
|
||||
self.corner(angle, r)
|
||||
#self.edge(self.thickness)
|
||||
# self.edge(self.thickness)
|
||||
self.corner(90)
|
||||
self.cc(callback, 0)
|
||||
edges[0](y)
|
||||
|
@ -127,61 +129,69 @@ class Printer(Boxes):
|
|||
self.open()
|
||||
self.edges["f"].settings.setValues(self.thickness, surroundingspaces=0)
|
||||
self.ctx.save()
|
||||
|
||||
for i in range(3):
|
||||
# motor mounts
|
||||
self.rectangularWall(70, 70, edges="feee", callback=[
|
||||
lambda: self.NEMA(23, 35, 35),],
|
||||
lambda: self.NEMA(23, 35, 35), ],
|
||||
move="right")
|
||||
# winch bucks
|
||||
self.rectangularWall(50, 70, edges="efee", callback=[
|
||||
None,
|
||||
lambda: self.hole(35, 35, 8.5),
|
||||
None,
|
||||
lambda: self.fingerHolesAt(10, 0, 50)], move="right")
|
||||
None,
|
||||
lambda: self.hole(35, 35, 8.5),
|
||||
None,
|
||||
lambda: self.fingerHolesAt(10, 0, 50)], move="right")
|
||||
|
||||
self.support(40, 50, move="right", pair=True)
|
||||
self.support(40, 50, move="right")
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, 80)
|
||||
self.ctx.save()
|
||||
|
||||
# idler bucks
|
||||
for i in range(12):
|
||||
self.rectangularWall(30, 30, edges="feee", callback=[
|
||||
lambda: self.hole(15, 15, 3),], move="right")
|
||||
lambda: self.hole(15, 15, 3), ], move="right")
|
||||
# Cable adjustment blocks
|
||||
self.ctx.save()
|
||||
|
||||
for i in range(6):
|
||||
def holes():
|
||||
self.hole(5, 4, 1.5)
|
||||
self.hole(15, 4, 1.5)
|
||||
self.rectangularWall(20, 8, edges="feee", callback=[holes,],
|
||||
|
||||
self.rectangularWall(20, 8, edges="feee", callback=[holes, ],
|
||||
move="right")
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, 20)
|
||||
|
||||
# Cable adjustment glyders
|
||||
for i in range(6):
|
||||
self.rectangularWall(8, 10, move="right", callback=[
|
||||
lambda: self.hole(4, 4, 1.5),
|
||||
None,
|
||||
lambda: self.hole(4, 1.5, 0.4)])
|
||||
lambda: self.hole(4, 4, 1.5),
|
||||
None,
|
||||
lambda: self.hole(4, 1.5, 0.4)])
|
||||
self.rectangularWall(8, 10, move="right", callback=[
|
||||
lambda: self.nutHole("M3", 4, 4),
|
||||
None,
|
||||
lambda: self.hole(4, 1.5, 0.4)])
|
||||
lambda: self.nutHole("M3", 4, 4),
|
||||
None,
|
||||
lambda: self.hole(4, 1.5, 0.4)])
|
||||
|
||||
self.ctx.restore()
|
||||
self.moveTo(0, 40)
|
||||
|
||||
# mainPlate
|
||||
self.rectangularWall(2*self.r-10, 2*self.r-10, edges="ffff",
|
||||
self.rectangularWall(2 * self.r - 10, 2 * self.r - 10, edges="ffff",
|
||||
callback=self.mainPlate, move="right")
|
||||
|
||||
|
||||
self.head()
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
p = Printer()
|
||||
p.parseArgs()
|
||||
p.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -18,64 +18,73 @@ from boxes import *
|
|||
from boxes import pulley
|
||||
import math
|
||||
|
||||
|
||||
class Pulley(Boxes):
|
||||
"""Timing belt pulleys for different profiles"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
# remove cli params you do not need
|
||||
self.buildArgParser("h")
|
||||
self.argparser.add_argument(
|
||||
"--profile", action="store", type=str, default="GT2_2mm",
|
||||
"--profile", action="store", type=str, default="GT2_2mm",
|
||||
choices=pulley.Pulley.getProfiles(),
|
||||
help="profile of the teeth/belt")
|
||||
self.argparser.add_argument(
|
||||
"--teeth", action="store", type=int, default=20,
|
||||
"--teeth", action="store", type=int, default=20,
|
||||
help="number of teeth")
|
||||
self.argparser.add_argument(
|
||||
"--axle", action="store", type=float, default=5,
|
||||
"--axle", action="store", type=float, default=5,
|
||||
help="diameter of the axle")
|
||||
self.argparser.add_argument(
|
||||
"--top", action="store", type=float, default=0,
|
||||
"--top", action="store", type=float, default=0,
|
||||
help="overlap of top rim (zero for none)")
|
||||
|
||||
|
||||
# Add non default cli params if needed (see argparse std lib)
|
||||
#self.argparser.add_argument(
|
||||
# self.argparser.add_argument(
|
||||
# "--XX", action="store", type=float, default=0.5,
|
||||
# help="DESCRIPTION")
|
||||
|
||||
|
||||
def disk(self, diameter, hole, callback=None, move=""):
|
||||
w = diameter + 2*self.spacing
|
||||
w = diameter + 2 * self.spacing
|
||||
|
||||
if self.move(w, w, move, before=True):
|
||||
return
|
||||
|
||||
self.ctx.save()
|
||||
self.moveTo(w/2, w/2)
|
||||
self.moveTo(w / 2, w / 2)
|
||||
self.cc(callback, None, 0.0, 0.0)
|
||||
|
||||
if hole:
|
||||
self.hole(0, 0, hole/2.0)
|
||||
self.moveTo(diameter/2+self.burn, 0, 90)
|
||||
self.corner(360, diameter/2)
|
||||
self.hole(0, 0, hole / 2.0)
|
||||
|
||||
self.moveTo(diameter / 2 + self.burn, 0, 90)
|
||||
self.corner(360, diameter / 2)
|
||||
self.ctx.restore()
|
||||
self.move(w, w, move)
|
||||
|
||||
|
||||
def render(self):
|
||||
# adjust to the variables you want in the local scope
|
||||
t = self.thickness
|
||||
# Initialize canvas
|
||||
self.open()
|
||||
|
||||
if self.top:
|
||||
self.disk(
|
||||
self.pulley.diameter(self.teeth, self.profile)+2*self.top,
|
||||
self.pulley.diameter(self.teeth, self.profile) + 2 * self.top,
|
||||
self.axle, move="right")
|
||||
for i in range(int(math.ceil(self.h/self.thickness))):
|
||||
self.pulley(self.teeth, self.profile, r_axle=self.axle/2.0, move="right")
|
||||
|
||||
for i in range(int(math.ceil(self.h / self.thickness))):
|
||||
self.pulley(self.teeth, self.profile, r_axle=self.axle / 2.0, move="right")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Box()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,49 +16,56 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class MotorEdge(edges.BaseEdge):
|
||||
#def margin(self):
|
||||
# def margin(self):
|
||||
# return 30
|
||||
def __call__(self, l, **kw):
|
||||
self.polyline(
|
||||
l-165, 45,
|
||||
25*2**0.5, -45,
|
||||
l - 165, 45,
|
||||
25 * 2 ** 0.5, -45,
|
||||
60, -45,
|
||||
25*2**0.5, 45,
|
||||
25 * 2 ** 0.5, 45,
|
||||
55)
|
||||
|
||||
|
||||
class OutsetEdge(edges.OutSetEdge):
|
||||
def startwidth(self):
|
||||
return 20
|
||||
|
||||
|
||||
class HangerEdge(edges.BaseEdge):
|
||||
char = "H"
|
||||
|
||||
def margin(self):
|
||||
return 40
|
||||
|
||||
def __call__(self, l, **kw):
|
||||
self.fingerHolesAt(0, -0.5*self.thickness, l, angle=0)
|
||||
self.fingerHolesAt(0, -0.5 * self.thickness, l, angle=0)
|
||||
w = self.settings
|
||||
self.polyline(0, -90,
|
||||
22+w, 90,
|
||||
22 + w, 90,
|
||||
70, 135,
|
||||
2**0.5*12, 45,
|
||||
2 ** 0.5 * 12, 45,
|
||||
35, -45,
|
||||
2**0.5*0.5*w, -90,
|
||||
2**0.5*0.5*w, -45,
|
||||
l -28, 45,
|
||||
2**0.5*5, 45, 5, -90)
|
||||
2 ** 0.5 * 0.5 * w, -90,
|
||||
2 ** 0.5 * 0.5 * w, -45,
|
||||
l - 28, 45,
|
||||
2 ** 0.5 * 5, 45, 5, -90)
|
||||
|
||||
|
||||
class RollerEdge(edges.BaseEdge):
|
||||
def margin(self):
|
||||
return 20
|
||||
|
||||
def __call__(self, l, **kw):
|
||||
m = 40+100
|
||||
self.polyline((l-m)/2.0, -45,
|
||||
2**0.5*20, 45,
|
||||
m = 40 + 100
|
||||
self.polyline((l - m) / 2.0, -45,
|
||||
2 ** 0.5 * 20, 45,
|
||||
100, 45,
|
||||
2**0.5*20, -45,
|
||||
(l-m)/2.0)
|
||||
2 ** 0.5 * 20, -45,
|
||||
(l - m) / 2.0)
|
||||
|
||||
|
||||
class RollerEdge2(edges.BaseEdge):
|
||||
def margin(self):
|
||||
|
@ -66,98 +73,102 @@ class RollerEdge2(edges.BaseEdge):
|
|||
|
||||
def __call__(self, l, **kw):
|
||||
a = 30
|
||||
f = 1/math.cos(math.radians(a))
|
||||
f = 1 / math.cos(math.radians(a))
|
||||
self.edges["f"](70)
|
||||
self.polyline(0, a, f*25, -a, l-190, -a, f*25, a, 0)
|
||||
self.polyline(0, a, f * 25, -a, l - 190, -a, f * 25, a, 0)
|
||||
self.edges["f"](70)
|
||||
|
||||
|
||||
class Rotary(Boxes):
|
||||
"""Rotary Attachment for engraving cylindrical objects in a laser cutter"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
# remove cli params you do not need
|
||||
#self.buildArgParser("x", "sx", "y", "sy", "h", "hi")
|
||||
# self.buildArgParser("x", "sx", "y", "sy", "h", "hi")
|
||||
# Add non default cli params if needed (see argparse std lib)
|
||||
self.argparser.add_argument(
|
||||
"--diameter", action="store", type=float, default=72.,
|
||||
"--diameter", action="store", type=float, default=72.,
|
||||
help="outer diameter of the wheels")
|
||||
self.argparser.add_argument(
|
||||
"--rubberthickness", action="store", type=float, default=5.,
|
||||
"--rubberthickness", action="store", type=float, default=5.,
|
||||
help="diameter of the strings of the O rings")
|
||||
self.argparser.add_argument(
|
||||
"--axle", action="store", type=float, default=6.,
|
||||
"--axle", action="store", type=float, default=6.,
|
||||
help="diameter of the axles")
|
||||
self.argparser.add_argument(
|
||||
"--knifethickness", action="store", type=float, default=8.,
|
||||
"--knifethickness", action="store", type=float, default=8.,
|
||||
help="thickness of the knifes in mm. Use 0 for use with honey comb table.")
|
||||
|
||||
|
||||
|
||||
def mainPlate(self):
|
||||
# Motor block outer side
|
||||
t = self.thickness
|
||||
d = self.diameter
|
||||
a = self.axle
|
||||
self.hole(1.0*d, 0.6*d, a/2.)
|
||||
#self.hole(1.0*d, 0.6*d, d/2.)
|
||||
self.hole(2.0*d+5, 0.6*d, a/2.)
|
||||
#self.hole(2.0*d+5, 0.6*d, d/2.)
|
||||
self.hole(1.0 * d, 0.6 * d, a / 2.)
|
||||
# self.hole(1.0*d, 0.6*d, d/2.)
|
||||
self.hole(2.0 * d + 5, 0.6 * d, a / 2.)
|
||||
# self.hole(2.0*d+5, 0.6*d, d/2.)
|
||||
# Main beam
|
||||
self.rectangularHole(1.5*d+2.5, 3.6, 32, 7.1)
|
||||
self.rectangularHole(1.5 * d + 2.5, 3.6, 32, 7.1)
|
||||
|
||||
def frontPlate(self):
|
||||
# Motor block inner side with motor mount
|
||||
t = self.thickness
|
||||
d = self.diameter
|
||||
a = self.axle
|
||||
self.hole(1.0*d, 0.6*d, a/2.)
|
||||
#self.hole(1.0*d, 0.6*d, d/2.)
|
||||
self.hole(2.0*d+5, 0.6*d, a/2.)
|
||||
#self.hole(2.0*d+5, 0.6*d, d/2.)
|
||||
self.hole(1.0 * d, 0.6 * d, a / 2.)
|
||||
# self.hole(1.0*d, 0.6*d, d/2.)
|
||||
self.hole(2.0 * d + 5, 0.6 * d, a / 2.)
|
||||
# self.hole(2.0*d+5, 0.6*d, d/2.)
|
||||
# Main beam
|
||||
self.rectangularHole(1.5*d+2.5, 3.6, 32, 7.1)
|
||||
self.rectangularHole(1.5 * d + 2.5, 3.6, 32, 7.1)
|
||||
# Motor
|
||||
mx = 2.7*d+20
|
||||
self.rectangularHole(mx, 0.6*d, 36+20, 36, r=36/2.0)
|
||||
mx = 2.7 * d + 20
|
||||
self.rectangularHole(mx, 0.6 * d, 36 + 20, 36, r=36 / 2.0)
|
||||
|
||||
for x in (-1, 1):
|
||||
for y in (-1,1):
|
||||
self.rectangularHole(mx+x*25, 0.6*d+y*25, 20, 4, r=2)
|
||||
for y in (-1, 1):
|
||||
self.rectangularHole(mx + x * 25, 0.6 * d + y * 25, 20, 4, r=2)
|
||||
|
||||
def link(self, x, y, a, middleHole=False, move=None):
|
||||
t = self. thickness
|
||||
t = self.thickness
|
||||
overallwidth = x + y
|
||||
overallheight = y
|
||||
ra = a/2.0
|
||||
ra = a / 2.0
|
||||
|
||||
if self.move(overallwidth, overallheight, move, before=True):
|
||||
return
|
||||
|
||||
self.moveTo(y/2.0, 0)
|
||||
self.hole(0, y/2., ra)
|
||||
self.hole(x, y/2., ra)
|
||||
self.moveTo(y / 2.0, 0)
|
||||
self.hole(0, y / 2., ra)
|
||||
self.hole(x, y / 2., ra)
|
||||
|
||||
if middleHole:
|
||||
self.hole(x/2., y/2., ra)
|
||||
self.hole(x / 2., y / 2., ra)
|
||||
|
||||
self.edge(10)
|
||||
self.edges["F"](60)
|
||||
self.polyline(x-70, (180, y/2.), x, (180, y/2.))
|
||||
self.polyline(x - 70, (180, y / 2.), x, (180, y / 2.))
|
||||
self.ctx.stroke()
|
||||
|
||||
self.move(overallwidth, overallheight, move)
|
||||
|
||||
def holderBaseCB(self):
|
||||
self.hole(20, 30, self.a/2)
|
||||
self.rectangularHole(self.hl-70, self.hh-10, 110, self.a, r=self.a/2)
|
||||
self.rectangularHole(self.hl/2, 3.6, 32, 7.1)
|
||||
self.hole(20, 30, self.a / 2)
|
||||
self.rectangularHole(self.hl - 70, self.hh - 10, 110, self.a, r=self.a / 2)
|
||||
self.rectangularHole(self.hl / 2, 3.6, 32, 7.1)
|
||||
|
||||
def holderTopCB(self):
|
||||
self.fingerHolesAt(0, 30-0.5*self.thickness, self.hl, 0)
|
||||
d = self.diameter/2.0 + 1
|
||||
y = -0.6*self.diameter + 2*self.hh
|
||||
self.fingerHolesAt(0, 30 - 0.5 * self.thickness, self.hl, 0)
|
||||
d = self.diameter / 2.0 + 1
|
||||
y = -0.6 * self.diameter + 2 * self.hh
|
||||
print(y)
|
||||
self.hole(self.hl/2+d, y, self.axle/2.0)
|
||||
self.hole(self.hl/2-d, y, self.axle/2.0)
|
||||
self.hole(self.hl/2+d, y, self.diameter/2.0)
|
||||
self.hole(self.hl/2-d, y, self.diameter/2.0)
|
||||
|
||||
self.hole(self.hl / 2 + d, y, self.axle / 2.0)
|
||||
self.hole(self.hl / 2 - d, y, self.axle / 2.0)
|
||||
self.hole(self.hl / 2 + d, y, self.diameter / 2.0)
|
||||
self.hole(self.hl / 2 - d, y, self.diameter / 2.0)
|
||||
|
||||
def render(self):
|
||||
# adjust to the variables you want in the local scope
|
||||
|
@ -166,11 +177,11 @@ class Rotary(Boxes):
|
|||
a = self.a = self.axle
|
||||
# Initialize canvas
|
||||
self.open()
|
||||
#self.spacing = 0.1 * t
|
||||
# self.spacing = 0.1 * t
|
||||
|
||||
# Change settings of default edges if needed. E.g.:
|
||||
self.edges["f"].settings.setValues(self.thickness, space=2, finger=2,
|
||||
surroundingspaces=1)
|
||||
surroundingspaces=1)
|
||||
if self.knifethickness:
|
||||
self.addPart(HangerEdge(self, self.knifethickness))
|
||||
else:
|
||||
|
@ -181,124 +192,137 @@ class Rotary(Boxes):
|
|||
hh = self.hh = 40.
|
||||
hl = self.hl = 240
|
||||
# Base
|
||||
self.rectangularWall(hl, hh, edges="hfef", callback=[self.holderBaseCB, None, lambda:self.rectangularHole(hl/2+50, hh-t/2-1, 60, t+2)], move="up")
|
||||
self.rectangularWall(hl, hh, edges="hfef", callback=[self.holderBaseCB, None,
|
||||
lambda: self.rectangularHole(hl / 2 + 50, hh - t / 2 - 1,
|
||||
60, t + 2)], move="up")
|
||||
self.rectangularWall(hl, hh, edges="hfef", callback=[self.holderBaseCB], move="up")
|
||||
self.rectangularWall(hl, hw, edges="ffff", callback=[
|
||||
lambda: self.hole(hl/2-16-20, 25, 5)], move="up")
|
||||
self.rectangularWall(hl, hw, edges="ffff", callback=[lambda: self.hole(hl / 2 - 16 - 20, 25, 5)], move="up")
|
||||
self.ctx.save()
|
||||
self.rectangularWall(hw, hh, edges="hFeF", callback=[
|
||||
lambda: self.hole(hw/2, 15, 4)],move="right")
|
||||
|
||||
self.rectangularWall(hw, hh, edges="hFeF", callback=[lambda: self.hole(hw / 2, 15, 4)], move="right")
|
||||
self.rectangularWall(hw, hh, edges="hFeF", move="right")
|
||||
# Top
|
||||
th = 30
|
||||
# sides
|
||||
self.rectangularWall(hw+20, th, edges="fFeF", move="right",
|
||||
callback=[lambda:self.fingerHolesAt(20-0.5*t,0,th)])
|
||||
self.rectangularWall(hw+20, th, edges="fFeF", move="right",
|
||||
callback=[lambda:self.fingerHolesAt(20-0.5*t,0,th)])
|
||||
|
||||
self.rectangularWall(hw + 20, th, edges="fFeF", move="right",
|
||||
callback=[lambda: self.fingerHolesAt(20 - 0.5 * t, 0, th)])
|
||||
self.rectangularWall(hw + 20, th, edges="fFeF", move="right",
|
||||
callback=[lambda: self.fingerHolesAt(20 - 0.5 * t, 0, th)])
|
||||
self.ctx.restore()
|
||||
|
||||
self.rectangularWall(hw, hh, edges="hFeF", move="up only")
|
||||
outset = OutsetEdge(self, None)
|
||||
roller2 = RollerEdge2(self, None)
|
||||
self.rectangularWall(hl, th, edges=[roller2, "f", "e", "f"], callback=[
|
||||
lambda:self.hole(20, 15, a/2), None, lambda:self.rectangularHole(50, th-15, 70, a, r=a/2)], move="up")
|
||||
lambda: self.hole(20, 15, a / 2), None, lambda: self.rectangularHole(50, th - 15, 70, a, r=a / 2)],
|
||||
move="up")
|
||||
self.rectangularWall(hl, th, edges=[roller2, "f", "e", "f"], callback=[
|
||||
lambda:self.hole(20, 15, a/2), None, lambda:self.rectangularHole(50, th-15-t, 70, a, r=a/2)], move="up")
|
||||
lambda: self.hole(20, 15, a / 2), None, lambda: self.rectangularHole(50, th - 15 - t, 70, a, r=a / 2)],
|
||||
move="up")
|
||||
self.rectangularWall(hl, th, edges=[roller2, "f", RollerEdge(self, None), "f"], callback=[
|
||||
self.holderTopCB], move="up")
|
||||
self.rectangularWall(hl, 20-t, edges="feee", move="up")
|
||||
self.rectangularWall(hl, 20 - t, edges="feee", move="up")
|
||||
tl = 70
|
||||
self.rectangularWall(tl, hw+20, edges="FeFF", move="right",
|
||||
callback=[None, lambda:self.fingerHolesAt(20-0.5*t,0, tl)])
|
||||
self.rectangularWall(tl, hw+20, edges="FeFF", move="",
|
||||
callback=[None, lambda:self.fingerHolesAt(20-0.5*t,0, tl)])
|
||||
self.rectangularWall(tl, hw+20, edges="FeFF", move="left up only",
|
||||
callback=[None, lambda:self.fingerHolesAt(20-0.5*t,0, tl)])
|
||||
self.rectangularWall(tl, hw + 20, edges="FeFF", move="right",
|
||||
callback=[None, lambda: self.fingerHolesAt(20 - 0.5 * t, 0, tl)])
|
||||
self.rectangularWall(tl, hw + 20, edges="FeFF", move="",
|
||||
callback=[None, lambda: self.fingerHolesAt(20 - 0.5 * t, 0, tl)])
|
||||
self.rectangularWall(tl, hw + 20, edges="FeFF", move="left up only",
|
||||
callback=[None, lambda: self.fingerHolesAt(20 - 0.5 * t, 0, tl)])
|
||||
|
||||
# Links
|
||||
self.link(hl-40, 25, a, True, move="up")
|
||||
self.link(hl-40, 25, a, True, move="up")
|
||||
self.link(hl-40, 25, a, True, move="up")
|
||||
self.link(hl-40, 25, a, True, move="up")
|
||||
self.link(hl - 40, 25, a, True, move="up")
|
||||
self.link(hl - 40, 25, a, True, move="up")
|
||||
self.link(hl - 40, 25, a, True, move="up")
|
||||
self.link(hl - 40, 25, a, True, move="up")
|
||||
|
||||
self.ctx.save()
|
||||
self.rectangularWall(hw-2*t-2, 60, edges="efef",move="right")
|
||||
self.rectangularWall(hw-4*t-4, 60, edges="efef",move="right")
|
||||
self.rectangularWall(hw - 2 * t - 2, 60, edges="efef", move="right")
|
||||
self.rectangularWall(hw - 4 * t - 4, 60, edges="efef", move="right")
|
||||
# Spindel auxiliaries
|
||||
self.parts.waivyKnob(50, callback=lambda:self.nutHole("M8"), move="right")
|
||||
self.parts.waivyKnob(50, callback=lambda:self.nutHole("M8"), move="right")
|
||||
self.parts.waivyKnob(50, callback=lambda: self.nutHole("M8"), move="right")
|
||||
self.parts.waivyKnob(50, callback=lambda: self.nutHole("M8"), move="right")
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(hw-2*t-4, 60, edges="efef",move="up only")
|
||||
self.rectangularWall(hw - 2 * t - 4, 60, edges="efef", move="up only")
|
||||
|
||||
self.ctx.save()
|
||||
slot = edges.SlottedEdge(self, [(30-t)/2, (30-t)/2], slots=15)
|
||||
slot = edges.SlottedEdge(self, [(30 - t) / 2, (30 - t) / 2], slots=15)
|
||||
self.rectangularWall(30, 30, edges=["e", "e", slot, "e"],
|
||||
callback=[lambda:self.hole(7, 23, self.axle/2)], move="right")
|
||||
callback=[lambda: self.hole(7, 23, self.axle / 2)], move="right")
|
||||
self.rectangularWall(30, 30, edges=["e", "e", slot, "e"],
|
||||
callback=[lambda:self.hole(7, 23, self.axle/2)], move="right")
|
||||
leftover = (hw-6*t-6-20) / 2.0
|
||||
callback=[lambda: self.hole(7, 23, self.axle / 2)], move="right")
|
||||
leftover = (hw - 6 * t - 6 - 20) / 2.0
|
||||
slot = edges.SlottedEdge(self, [leftover, 20, leftover], slots=15)
|
||||
self.rectangularWall(hw-4*t-6, 30, edges=[slot, "e", "e", "e"],
|
||||
callback=[lambda:self.hole((hw-4*t-6)/2., 15, 4)], move="right")
|
||||
self.rectangularWall(hw - 4 * t - 6, 30, edges=[slot, "e", "e", "e"],
|
||||
callback=[lambda: self.hole((hw - 4 * t - 6) / 2., 15, 4)], move="right")
|
||||
for i in range(3):
|
||||
self.rectangularWall(20, 30,
|
||||
callback=[lambda:self.nutHole("M8", 10, 15)], move="right")
|
||||
callback=[lambda: self.nutHole("M8", 10, 15)], move="right")
|
||||
self.rectangularWall(20, 30,
|
||||
callback=[lambda:self.hole(10, 15, 4)], move="right")
|
||||
|
||||
callback=[lambda: self.hole(10, 15, 4)], move="right")
|
||||
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(30, 30, move="up only")
|
||||
|
||||
# Other side
|
||||
if self.knifethickness:
|
||||
ow = 10
|
||||
self.rectangularWall(3.6*d, 1.1*d, edges="hfFf", callback=[
|
||||
lambda:self.rectangularHole(1.8*d, 3.6, 32, 7.1)], move="up")
|
||||
self.rectangularWall(3.6*d, 1.1*d, edges="hfFf", callback=[
|
||||
lambda:self.rectangularHole(1.8*d, 3.6, 32, 7.1)], move="up")
|
||||
self.rectangularWall(3.6*d, ow, edges="ffff", move="up")
|
||||
self.rectangularWall(3.6*d, ow, edges="ffff", move="up")
|
||||
self.rectangularWall(3.6 * d, 1.1 * d, edges="hfFf", callback=[
|
||||
lambda: self.rectangularHole(1.8 * d, 3.6, 32, 7.1)], move="up")
|
||||
self.rectangularWall(3.6 * d, 1.1 * d, edges="hfFf", callback=[
|
||||
lambda: self.rectangularHole(1.8 * d, 3.6, 32, 7.1)], move="up")
|
||||
self.rectangularWall(3.6 * d, ow, edges="ffff", move="up")
|
||||
self.rectangularWall(3.6 * d, ow, edges="ffff", move="up")
|
||||
self.ctx.save()
|
||||
self.rectangularWall(ow, 1.1*d, edges="hFFH", move="right")
|
||||
self.rectangularWall(ow, 1.1*d, edges="hFFH", move="right")
|
||||
self.rectangularWall(ow, 1.1 * d, edges="hFFH", move="right")
|
||||
self.rectangularWall(ow, 1.1 * d, edges="hFFH", move="right")
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(ow, 1.1*d, edges="hFFH", move="up only")
|
||||
|
||||
self.rectangularWall(ow, 1.1 * d, edges="hFFH", move="up only")
|
||||
|
||||
# Motor block
|
||||
mw = 40
|
||||
self.rectangularWall(3.6*d, 1.1*d, edges=["h", "f", MotorEdge(self, None),"f"], callback=[self.mainPlate], move="up")
|
||||
self.rectangularWall(3.6*d, 1.1*d, edges=["h", "f", MotorEdge(self, None),"f"], callback=[self.frontPlate], move="up")
|
||||
self.rectangularWall(3.6*d, mw, edges="ffff", move="up")
|
||||
self.rectangularWall(3.6 * d, 1.1 * d, edges=["h", "f", MotorEdge(self, None), "f"], callback=[self.mainPlate],
|
||||
move="up")
|
||||
self.rectangularWall(3.6 * d, 1.1 * d, edges=["h", "f", MotorEdge(self, None), "f"], callback=[self.frontPlate],
|
||||
move="up")
|
||||
self.rectangularWall(3.6 * d, mw, edges="ffff", move="up")
|
||||
self.ctx.save()
|
||||
self.rectangularWall(mw, 1.1*d, edges="hFeH", move="right")
|
||||
self.rectangularWall(mw, 1.1*d, edges="hFeH", move="right")
|
||||
self.rectangularWall(mw, 1.1 * d, edges="hFeH", move="right")
|
||||
self.rectangularWall(mw, 1.1 * d, edges="hFeH", move="right")
|
||||
|
||||
self.pulley(88, "GT2_2mm", r_axle=a/2.0,move="right")
|
||||
self.pulley(88, "GT2_2mm", r_axle=a/2.0,move="right")
|
||||
self.pulley(88, "GT2_2mm", r_axle=a / 2.0, move="right")
|
||||
self.pulley(88, "GT2_2mm", r_axle=a / 2.0, move="right")
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(mw, 1.1*d, edges="hFeH", move="up only")
|
||||
self.rectangularWall(mw, 1.1 * d, edges="hFeH", move="up only")
|
||||
self.axle = 19
|
||||
|
||||
for i in range(3):
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness,
|
||||
hole=self.axle, move="right")
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness,
|
||||
hole=self.axle, move="up right")
|
||||
|
||||
for i in range(3):
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness,
|
||||
hole=self.axle, move="left")
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness,
|
||||
hole=self.axle, move="left up")
|
||||
|
||||
for i in range(3):
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness+4,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness + 4,
|
||||
hole=self.axle, move="right")
|
||||
self.parts.disc(self.diameter-2*self.rubberthickness+4,
|
||||
self.parts.disc(self.diameter - 2 * self.rubberthickness + 4,
|
||||
hole=self.axle, move="right up")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Box()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
from boxes import Boxes
|
||||
|
||||
|
||||
class Silverware(Boxes):
|
||||
"""Not yet parametrized cuttlery stand with carrying grip
|
||||
using flex for rounded corners"""
|
||||
|
@ -26,20 +27,20 @@ using flex for rounded corners"""
|
|||
|
||||
def basePlate(self, x, y, r):
|
||||
self.roundedPlate(x, y, r, callback=[
|
||||
lambda: self.fingerHolesAt(x/3.0-r, 0, 0.5*(y-self.thickness)),
|
||||
lambda: self.fingerHolesAt(x/6.0, 0, 0.5*(y-self.thickness)),
|
||||
lambda: self.fingerHolesAt(y/2.0-r, 0, x),
|
||||
lambda: self.fingerHolesAt(x/2.0-r, 0, 0.5*(y-self.thickness))
|
||||
])
|
||||
lambda: self.fingerHolesAt(x / 3.0 - r, 0, 0.5 * (y - self.thickness)),
|
||||
lambda: self.fingerHolesAt(x / 6.0, 0, 0.5 * (y - self.thickness)),
|
||||
lambda: self.fingerHolesAt(y / 2.0 - r, 0, x),
|
||||
lambda: self.fingerHolesAt(x / 2.0 - r, 0, 0.5 * (y - self.thickness))
|
||||
])
|
||||
|
||||
def wall(self, x=100, y=100, h=100, r=0):
|
||||
self.surroundingWall(x,y,r,h, bottom='h', callback={
|
||||
0 : lambda: self.fingerHolesAt(x/6.0, 0, h-10),
|
||||
4 : lambda: self.fingerHolesAt(x/3.0-r, 0, h-10),
|
||||
1 : lambda: self.fingerHolesAt(y/2.0-r, 0, h-10),
|
||||
3 : lambda: self.fingerHolesAt(y/2.0-r, 0, h-10),
|
||||
2 : lambda: self.fingerHolesAt(x/2.0-r, 0, h-10),
|
||||
},
|
||||
self.surroundingWall(x, y, r, h, bottom='h', callback={
|
||||
0: lambda: self.fingerHolesAt(x / 6.0, 0, h - 10),
|
||||
4: lambda: self.fingerHolesAt(x / 3.0 - r, 0, h - 10),
|
||||
1: lambda: self.fingerHolesAt(y / 2.0 - r, 0, h - 10),
|
||||
3: lambda: self.fingerHolesAt(y / 2.0 - r, 0, h - 10),
|
||||
2: lambda: self.fingerHolesAt(x / 2.0 - r, 0, h - 10),
|
||||
},
|
||||
move="up")
|
||||
|
||||
def centerWall(self, x, h):
|
||||
|
@ -47,49 +48,52 @@ using flex for rounded corners"""
|
|||
|
||||
self.moveTo(self.edges["f"].spacing(), self.edges["f"].spacing())
|
||||
for i in range(2, 5):
|
||||
self.fingerHolesAt(i*x/6.0, 0, h-10)
|
||||
self.fingerHolesAt(i * x / 6.0, 0, h - 10)
|
||||
|
||||
self.edges["f"](x)
|
||||
self.corner(90)
|
||||
self.edges["f"](h-10)
|
||||
self.edges["f"](h - 10)
|
||||
self.corner(90)
|
||||
|
||||
self.handle(x, 150, 120)
|
||||
#self.handle(x, 40, 30, r=2)
|
||||
# self.handle(x, 40, 30, r=2)
|
||||
|
||||
self.corner(90)
|
||||
self.edges["f"](h-10)
|
||||
self.edges["f"](h - 10)
|
||||
self.corner(90)
|
||||
self.ctx.restore()
|
||||
|
||||
self.moveTo(x+2*self.edges["f"].spacing())
|
||||
self.moveTo(x + 2 * self.edges["f"].spacing())
|
||||
|
||||
##################################################
|
||||
### main
|
||||
##################################################
|
||||
|
||||
def render(self):
|
||||
x, y, h, r = 250, 250/1.618, 120, 30
|
||||
x, y, h, r = 250, 250 / 1.618, 120, 30
|
||||
self.open()
|
||||
t = self.thickness
|
||||
b = self.burn
|
||||
|
||||
self.wall(x, y, h, r)
|
||||
self.centerWall(x,h)
|
||||
self.centerWall(x, h)
|
||||
|
||||
l = (y - t) / 2.0
|
||||
|
||||
l = (y-t)/2.0
|
||||
for i in range(3):
|
||||
self.rectangularWall(l, h-10, edges="ffef", move="right")
|
||||
self.rectangularWall(l, h - 10, edges="ffef", move="right")
|
||||
|
||||
self.moveTo(-3.0*(l+2*t+8*b), h-10+2*t+8*b)
|
||||
self.moveTo(-3.0 * (l + 2 * t + 8 * b), h - 10 + 2 * t + 8 * b)
|
||||
self.basePlate(x, y, r)
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = Silverware()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,40 +16,44 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class TrayInsert(Boxes):
|
||||
"""Tray insert without floor and outer walls - allows only continuous walls"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("sx", "sy", "h", "outside")
|
||||
|
||||
def render(self):
|
||||
|
||||
if self.outside:
|
||||
self.sx = self.adjustSize(self.sx, False, False)
|
||||
self.sy = self.adjustSize(self.sy, False, False)
|
||||
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx)-1)
|
||||
y = sum(self.sy) + self.thickness * (len(self.sy)-1)
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
|
||||
y = sum(self.sy) + self.thickness * (len(self.sy) - 1)
|
||||
h = self.h
|
||||
t = self.thickness
|
||||
|
||||
self.open()
|
||||
|
||||
# Inner walls
|
||||
for i in range(len(self.sx)-1):
|
||||
e = [edges.SlottedEdge(self, self.sy, slots=0.5*h), "e", "e", "e"]
|
||||
self.rectangularWall(y, h, e,
|
||||
move="up")
|
||||
for i in range(len(self.sy)-1):
|
||||
e = ["e", "e",
|
||||
edges.SlottedEdge(self, self.sx[::-1], "e", slots=0.5*h), "e"]
|
||||
self.rectangularWall(x, h, e,
|
||||
move="up")
|
||||
for i in range(len(self.sx) - 1):
|
||||
e = [edges.SlottedEdge(self, self.sy, slots=0.5 * h), "e", "e", "e"]
|
||||
self.rectangularWall(y, h, e, move="up")
|
||||
|
||||
for i in range(len(self.sy) - 1):
|
||||
e = ["e", "e", edges.SlottedEdge(self, self.sx[::-1], "e", slots=0.5 * h), "e"]
|
||||
self.rectangularWall(x, h, e, move="up")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = TrayInsert()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -18,8 +18,8 @@ import sys, re
|
|||
from boxes import *
|
||||
import boxes
|
||||
|
||||
class Layout(Boxes):
|
||||
|
||||
class Layout(Boxes):
|
||||
"""Generate a typetray from a layout file"""
|
||||
|
||||
webinterface = False
|
||||
|
@ -29,64 +29,69 @@ class Layout(Boxes):
|
|||
self.buildArgParser("h", "hi", "outside")
|
||||
if not webargs:
|
||||
self.argparser.add_argument(
|
||||
"--input", action="store", type=argparse.FileType('r'),
|
||||
"--input", action="store", type=argparse.FileType('r'),
|
||||
help="layout file")
|
||||
self.argparser.add_argument(
|
||||
"--x", action="store", type=int, default=None,
|
||||
"--x", action="store", type=int, default=None,
|
||||
help="number of compartments side by side")
|
||||
self.argparser.add_argument(
|
||||
"--y", action="store", type=int, default=None,
|
||||
"--y", action="store", type=int, default=None,
|
||||
help="number of compartments back to front")
|
||||
else:
|
||||
self.argparser.add_argument(
|
||||
"--layout", action="store", type=str)
|
||||
"--layout", action="store", type=str)
|
||||
|
||||
def fillDefault(self, x, y):
|
||||
self.x = [0.0] * x
|
||||
self.y = [0.0] * y
|
||||
self.hwalls = [[True for i in range(x)] for j in range(y+1)]
|
||||
self.vwalls = [[True for i in range(x+1)] for j in range(y)]
|
||||
self.hwalls = [[True for i in range(x)] for j in range(y + 1)]
|
||||
self.vwalls = [[True for i in range(x + 1)] for j in range(y)]
|
||||
self.floors = [[True for i in range(x)] for j in range(y)]
|
||||
|
||||
|
||||
def __str__(self):
|
||||
r = []
|
||||
|
||||
for i, x in enumerate(self.x):
|
||||
r.append(" |" * (i) + " ,> %.1fmm\n" % x)
|
||||
|
||||
for hwalls, vwalls, floors, y in zip(
|
||||
self.hwalls, self.vwalls, self.floors, self.y):
|
||||
r.append("".join(("+" + " -"[h] for h in hwalls)) + "+\n")
|
||||
r.append("".join(("+" + " -"[h] for h in hwalls)) + "+\n")
|
||||
r.append("".join((" |"[v] + "X "[f] for v, f in zip(vwalls, floors)))
|
||||
+ " |"[vwalls[-1]] + " %.1fmm\n" % y)
|
||||
+ " |"[vwalls[-1]] + " %.1fmm\n" % y)
|
||||
r.append("".join(("+" + " -"[h] for h in self.hwalls[-1])) + "+\n")
|
||||
|
||||
return "".join(r)
|
||||
|
||||
def vWalls(self, x, y):
|
||||
"Number of vertical walls at a crossing"
|
||||
result = 0
|
||||
if y>0 and self.vwalls[y-1][x]:
|
||||
if y > 0 and self.vwalls[y - 1][x]:
|
||||
result += 1
|
||||
|
||||
if y < len(self.y) and self.vwalls[y][x]:
|
||||
result += 1
|
||||
|
||||
return result
|
||||
|
||||
def hWalls(self, x, y):
|
||||
"Number of horizontal walls at a crossing"
|
||||
result = 0
|
||||
if x>0 and self.hwalls[y][x-1]:
|
||||
if x > 0 and self.hwalls[y][x - 1]:
|
||||
result += 1
|
||||
if x<len(self.x) and self.hwalls[y][x]:
|
||||
if x < len(self.x) and self.hwalls[y][x]:
|
||||
result += 1
|
||||
return result
|
||||
|
||||
def vFloor(self, x, y):
|
||||
"Is there floor under vertical wall"
|
||||
return ((x>0 and self.floors[y][x-1]) or
|
||||
(x<len(self.x) and self.floors[y][x]))
|
||||
return ((x > 0 and self.floors[y][x - 1]) or
|
||||
(x < len(self.x) and self.floors[y][x]))
|
||||
|
||||
def hFloor(self, x, y):
|
||||
"Is there foor under horizontal wall"
|
||||
return ((y>0 and self.floors[y-1][x]) or
|
||||
(y<len(self.y) and self.floors[y][x]))
|
||||
return ((y > 0 and self.floors[y - 1][x]) or
|
||||
(y < len(self.y) and self.floors[y][x]))
|
||||
|
||||
@restore
|
||||
def edgeAt(self, edge, x, y, length, angle=0):
|
||||
|
@ -99,6 +104,7 @@ class Layout(Boxes):
|
|||
self.x = self.adjustSize(self.x)
|
||||
self.y = self.adjustSize(self.y)
|
||||
self.h = self.adjustSize(self.h, e2=False)
|
||||
|
||||
if self.hi:
|
||||
self.hi = self.adjustSize(self.hi, e2=False)
|
||||
|
||||
|
@ -117,7 +123,7 @@ class Layout(Boxes):
|
|||
|
||||
self.open()
|
||||
|
||||
self.edges["s"] = boxes.edges.Slot(self, self.hi/2.0)
|
||||
self.edges["s"] = boxes.edges.Slot(self, self.hi / 2.0)
|
||||
self.edges["C"] = boxes.edges.CrossingFingerHoleEdge(self, self.hi)
|
||||
|
||||
self.ctx.save()
|
||||
|
@ -128,22 +134,30 @@ class Layout(Boxes):
|
|||
h = self.h
|
||||
else:
|
||||
h = self.hi
|
||||
|
||||
start = 0
|
||||
end = 0
|
||||
|
||||
while end < lx:
|
||||
lengths = []
|
||||
edges = []
|
||||
while start < lx and not self.hwalls[y][start]: start += 1
|
||||
|
||||
while start < lx and not self.hwalls[y][start]:
|
||||
start += 1
|
||||
|
||||
if start == lx:
|
||||
break
|
||||
|
||||
end = start
|
||||
|
||||
while end < lx and self.hwalls[y][end]:
|
||||
if self.hFloor(end, y):
|
||||
edges.append("f")
|
||||
else:
|
||||
edges.append("e") # XXX E?
|
||||
edges.append("e") # XXX E?
|
||||
|
||||
lengths.append(self.x[end])
|
||||
edges.append("eCs"[self.vWalls(end+1, y)])
|
||||
edges.append("eCs"[self.vWalls(end + 1, y)])
|
||||
lengths.append(self.thickness)
|
||||
end += 1
|
||||
|
||||
|
@ -161,7 +175,7 @@ class Layout(Boxes):
|
|||
self.ctx.restore()
|
||||
self.rectangularWall(10, h, "ffef", move="up only")
|
||||
self.ctx.save()
|
||||
|
||||
|
||||
# Vertical Walls
|
||||
for x in range(lx + 1):
|
||||
if x == 0 or x == lx:
|
||||
|
@ -170,20 +184,26 @@ class Layout(Boxes):
|
|||
h = self.hi
|
||||
start = 0
|
||||
end = 0
|
||||
|
||||
while end < ly:
|
||||
lengths = []
|
||||
edges = []
|
||||
while start < ly and not self.vwalls[start][x]: start += 1
|
||||
while start < ly and not self.vwalls[start][x]:
|
||||
start += 1
|
||||
|
||||
if start == ly:
|
||||
break
|
||||
|
||||
end = start
|
||||
while end < ly and self.vwalls[end][x]:
|
||||
|
||||
while end < ly and self.vwalls[end][x]:
|
||||
if self.vFloor(x, end):
|
||||
edges.append("f")
|
||||
else:
|
||||
edges.append("e") # XXX E?
|
||||
edges.append("e") # XXX E?
|
||||
|
||||
lengths.append(self.y[end])
|
||||
edges.append("eCs"[self.hWalls(x, end+1)])
|
||||
edges.append("eCs"[self.hWalls(x, end + 1)])
|
||||
lengths.append(self.thickness)
|
||||
end += 1
|
||||
# remove last "slot"
|
||||
|
@ -191,23 +211,23 @@ class Layout(Boxes):
|
|||
edges.pop()
|
||||
|
||||
upper = [{
|
||||
"f" : "e",
|
||||
"s" : "s",
|
||||
"e" : "e",
|
||||
"E" : "e",
|
||||
"C" : "e"}[e] for e in reversed(edges)]
|
||||
"f": "e",
|
||||
"s": "s",
|
||||
"e": "e",
|
||||
"E": "e",
|
||||
"C": "e"}[e] for e in reversed(edges)]
|
||||
edges = ["e" if e == "s" else e for e in edges]
|
||||
self.rectangularWall(sum(lengths), h, [
|
||||
boxes.edges.CompoundEdge(self, edges, lengths),
|
||||
"eFf"[self.hWalls(x, end)],
|
||||
boxes.edges.CompoundEdge(self, upper, list(reversed(lengths))),
|
||||
"eFf"[self.hWalls(x, start)] ],
|
||||
move="right")
|
||||
"eFf"[self.hWalls(x, start)]],
|
||||
move="right")
|
||||
start = end
|
||||
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(10, h, "ffef", move="up only")
|
||||
self.moveTo(2*self.thickness, 2*self.thickness)
|
||||
self.moveTo(2 * self.thickness, 2 * self.thickness)
|
||||
self.ctx.save()
|
||||
|
||||
##########################################################
|
||||
|
@ -224,61 +244,61 @@ class Layout(Boxes):
|
|||
else:
|
||||
e = "e"
|
||||
if y < ly and self.floors[y][x]:
|
||||
if y>0 and self.floors[y-1][x]:
|
||||
if y > 0 and self.floors[y - 1][x]:
|
||||
# Inside Wall
|
||||
if self.hwalls[y][x]:
|
||||
self.fingerHolesAt(posx, posy+t2, self.x[x], angle=0)
|
||||
self.fingerHolesAt(posx, posy + t2, self.x[x], angle=0)
|
||||
else:
|
||||
# Top edge
|
||||
self.edgeAt(e, posx+self.x[x], posy+t, self.x[x],
|
||||
self.edgeAt(e, posx + self.x[x], posy + t, self.x[x],
|
||||
-180)
|
||||
if x==0 or y==0 or not self.floors[y-1][x-1]:
|
||||
self.edgeAt("e", posx, posy+t, t, -180)
|
||||
if x==lx-1 or y==0 or not self.floors[y-1][x+1]:
|
||||
self.edgeAt("e", posx+self.x[x]+t, posy+t, t, -180)
|
||||
elif y>0 and self.floors[y-1][x]:
|
||||
if x == 0 or y == 0 or not self.floors[y - 1][x - 1]:
|
||||
self.edgeAt("e", posx, posy + t, t, -180)
|
||||
if x == lx - 1 or y == 0 or not self.floors[y - 1][x + 1]:
|
||||
self.edgeAt("e", posx + self.x[x] + t, posy + t, t, -180)
|
||||
elif y > 0 and self.floors[y - 1][x]:
|
||||
# Bottom Edge
|
||||
self.edgeAt(e, posx, posy, self.x[x])
|
||||
if x==0 or y==ly or not self.floors[y][x-1]:
|
||||
self.edgeAt("e", posx-t, posy, t)
|
||||
if x==lx-1 or y==ly or not self.floors[y][x+1]:
|
||||
self.edgeAt("e", posx+self.x[x], posy, t)
|
||||
posx += self.x[x] + self. thickness
|
||||
posy += self.y[y-1] + self.thickness
|
||||
if x == 0 or y == ly or not self.floors[y][x - 1]:
|
||||
self.edgeAt("e", posx - t, posy, t)
|
||||
if x == lx - 1 or y == ly or not self.floors[y][x + 1]:
|
||||
self.edgeAt("e", posx + self.x[x], posy, t)
|
||||
posx += self.x[x] + self.thickness
|
||||
posy += self.y[y - 1] + self.thickness
|
||||
|
||||
posx = 0
|
||||
for x in range(lx+1):
|
||||
for x in range(lx + 1):
|
||||
posy = self.thickness
|
||||
for y in range(ly-1, -1, -1):
|
||||
for y in range(ly - 1, -1, -1):
|
||||
if self.vwalls[y][x]:
|
||||
e = "F"
|
||||
else:
|
||||
e = "e"
|
||||
if x>0 and self.floors[y][x-1]:
|
||||
if x > 0 and self.floors[y][x - 1]:
|
||||
if x < lx and self.floors[y][x]:
|
||||
# Inside wall
|
||||
if self.vwalls[y][x]:
|
||||
self.fingerHolesAt(posx+t2, posy, self.y[y])
|
||||
self.fingerHolesAt(posx + t2, posy, self.y[y])
|
||||
else:
|
||||
# Right edge
|
||||
self.edgeAt(e, posx+t, posy, self.y[y], 90)
|
||||
if x==lx or y==0 or not self.floors[y-1][x]:
|
||||
self.edgeAt("e", posx+t, posy+self.y[y], t, 90)
|
||||
if x==lx or y==ly-1 or not self.floors[y+1][x]:
|
||||
self.edgeAt("e", posx+t, posy-t, t, 90)
|
||||
self.edgeAt(e, posx + t, posy, self.y[y], 90)
|
||||
if x == lx or y == 0 or not self.floors[y - 1][x]:
|
||||
self.edgeAt("e", posx + t, posy + self.y[y], t, 90)
|
||||
if x == lx or y == ly - 1 or not self.floors[y + 1][x]:
|
||||
self.edgeAt("e", posx + t, posy - t, t, 90)
|
||||
elif x < lx and self.floors[y][x]:
|
||||
# Left edge
|
||||
self.edgeAt(e, posx, posy+self.y[y], self.y[y], -90)
|
||||
if x==0 or y==0 or not self.floors[y-1][x-1]:
|
||||
self.edgeAt("e", posx, posy+self.y[y]+t, t, -90)
|
||||
if x==0 or y==ly-1 or not self.floors[y+1][x-1]:
|
||||
self.edgeAt(e, posx, posy + self.y[y], self.y[y], -90)
|
||||
if x == 0 or y == 0 or not self.floors[y - 1][x - 1]:
|
||||
self.edgeAt("e", posx, posy + self.y[y] + t, t, -90)
|
||||
if x == 0 or y == ly - 1 or not self.floors[y + 1][x - 1]:
|
||||
self.edgeAt("e", posx, posy, t, -90)
|
||||
posy += self.y[y] + self.thickness
|
||||
if x < lx:
|
||||
posx += self.x[x] + self.thickness
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def parse(self, input):
|
||||
x = []
|
||||
y = []
|
||||
|
@ -302,18 +322,17 @@ class Layout(Boxes):
|
|||
w.append(True)
|
||||
else:
|
||||
pass
|
||||
#raise ValueError(line)
|
||||
# raise ValueError(line)
|
||||
else:
|
||||
if c != '+':
|
||||
pass
|
||||
#raise ValueError(line)
|
||||
# raise ValueError(line)
|
||||
|
||||
|
||||
hwalls.append(w)
|
||||
if line[0] in " |":
|
||||
w = []
|
||||
f = []
|
||||
for n, c in enumerate(line[:len(x)*2+1]):
|
||||
for n, c in enumerate(line[:len(x) * 2 + 1]):
|
||||
if n % 2:
|
||||
if c == 'X':
|
||||
f.append(False)
|
||||
|
@ -340,25 +359,26 @@ class Layout(Boxes):
|
|||
# check sizes
|
||||
lx = len(x)
|
||||
ly = len(y)
|
||||
if len(hwalls) != ly+1:
|
||||
raise ValueError("Wrong number of horizontal wall lines: %i (%i expected)" % (len(hwalls), ly+1))
|
||||
if len(hwalls) != ly + 1:
|
||||
raise ValueError("Wrong number of horizontal wall lines: %i (%i expected)" % (len(hwalls), ly + 1))
|
||||
for nr, walls in enumerate(hwalls):
|
||||
if len(walls)!= lx:
|
||||
if len(walls) != lx:
|
||||
raise ValueError("Wrong number of horizontal walls in line %i: %i (%i expected)" % (nr, len(walls), lx))
|
||||
if len(vwalls) != ly:
|
||||
raise ValueError("Wrong number of vertical wall lines: %i (%i expected)" % (len(vwalls), ly))
|
||||
for nr, walls in enumerate(vwalls):
|
||||
if len(walls) != lx+1:
|
||||
raise ValueError("Wrong number of vertical walls in line %i: %i (%i expected)" % (nr, len(walls), lx+1))
|
||||
|
||||
if len(walls) != lx + 1:
|
||||
raise ValueError(
|
||||
"Wrong number of vertical walls in line %i: %i (%i expected)" % (nr, len(walls), lx + 1))
|
||||
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hwalls = hwalls
|
||||
self.vwalls = vwalls
|
||||
self.floors = floors
|
||||
|
||||
class TrayLayout(Layout):
|
||||
|
||||
class TrayLayout(Layout):
|
||||
"""Type tray with each wall and floor tile being optional"""
|
||||
|
||||
webinterface = True
|
||||
|
@ -367,17 +387,17 @@ class TrayLayout(Layout):
|
|||
Boxes.__init__(self)
|
||||
self.argparser = boxes.ArgumentParser()
|
||||
self.argparser.add_argument(
|
||||
"--x", action="store", type=int, default=2,
|
||||
"--x", action="store", type=int, default=2,
|
||||
help="number of compartments side by side")
|
||||
self.argparser.add_argument(
|
||||
"--y", action="store", type=int, default=2,
|
||||
"--y", action="store", type=int, default=2,
|
||||
help="number of compartments back to front")
|
||||
|
||||
def render(self):
|
||||
return
|
||||
|
||||
class TrayLayout2(Layout):
|
||||
|
||||
class TrayLayout2(Layout):
|
||||
"""Generate a typetray from a layout file"""
|
||||
|
||||
webinterface = True
|
||||
|
@ -386,7 +406,8 @@ class TrayLayout2(Layout):
|
|||
Boxes.__init__(self)
|
||||
self.buildArgParser("h", "hi", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--layout", action="store", type=str)
|
||||
"--layout", action="store", type=str)
|
||||
|
||||
|
||||
def main():
|
||||
l = Layout()
|
||||
|
@ -404,5 +425,6 @@ def main():
|
|||
else:
|
||||
l.argparser.print_usage()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -16,22 +16,24 @@
|
|||
|
||||
from boxes import *
|
||||
|
||||
|
||||
class TypeTray(Boxes):
|
||||
"""Type tray - allows only continuous walls"""
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("sx", "sy", "h", "hi", "outside")
|
||||
self.argparser.add_argument(
|
||||
"--gripheight", action="store", type=float, default=30,
|
||||
"--gripheight", action="store", type=float, default=30,
|
||||
dest="gh", help="height of the grip hole in mm")
|
||||
self.argparser.add_argument(
|
||||
"--gripwidth", action="store", type=float, default=70,
|
||||
"--gripwidth", action="store", type=float, default=70,
|
||||
dest="gw", help="width of th grip hole in mm (zero for no hole)")
|
||||
self.argparser.set_defaults(
|
||||
fingerjointfinger=3.0,
|
||||
fingerjointspace=3.0,
|
||||
fingerjointsurrounding=0.5,
|
||||
)
|
||||
)
|
||||
|
||||
def xSlots(self):
|
||||
posx = -0.5 * self.thickness
|
||||
|
@ -67,9 +69,9 @@ class TypeTray(Boxes):
|
|||
if not self.gw:
|
||||
return
|
||||
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx)-1)
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
|
||||
r = min(self.gw, self.gh) / 2.0
|
||||
self.rectangularHole(x/2.0, self.gh*1.5, self.gw, self.gh, r)
|
||||
self.rectangularHole(x / 2.0, self.gh * 1.5, self.gw, self.gh, r)
|
||||
|
||||
def render(self):
|
||||
if self.outside:
|
||||
|
@ -79,8 +81,8 @@ class TypeTray(Boxes):
|
|||
if self.hi:
|
||||
self.hi = self.adjustSize(self.hi, e2=False)
|
||||
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx)-1)
|
||||
y = sum(self.sy) + self.thickness * (len(self.sy)-1)
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
|
||||
y = sum(self.sy) + self.thickness * (len(self.sy) - 1)
|
||||
h = self.h
|
||||
hi = self.hi = self.hi or h
|
||||
t = self.thickness
|
||||
|
@ -88,35 +90,31 @@ class TypeTray(Boxes):
|
|||
self.open()
|
||||
|
||||
# outer walls
|
||||
self.rectangularWall(x, h, "Ffef", callback=[
|
||||
self.xHoles, None, self.gripHole],
|
||||
move="right")
|
||||
self.rectangularWall(y, h, "FFeF", callback=[self.yHoles,],
|
||||
move="up")
|
||||
self.rectangularWall(y, h, "FFeF", callback=[self.yHoles,])
|
||||
self.rectangularWall(x, h, "Ffef", callback=[self.xHoles,],
|
||||
move="left up")
|
||||
|
||||
self.rectangularWall(x, h, "Ffef", callback=[self.xHoles, None, self.gripHole], move="right")
|
||||
self.rectangularWall(y, h, "FFeF", callback=[self.yHoles, ], move="up")
|
||||
self.rectangularWall(y, h, "FFeF", callback=[self.yHoles, ])
|
||||
self.rectangularWall(x, h, "Ffef", callback=[self.xHoles, ], move="left up")
|
||||
|
||||
# floor
|
||||
self.rectangularWall(x, y, "ffff",
|
||||
callback=[self.xSlots, self.ySlots],
|
||||
move="right")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.xSlots, self.ySlots],move="right")
|
||||
# Inner walls
|
||||
for i in range(len(self.sx)-1):
|
||||
e = [edges.SlottedEdge(self, self.sy, "f", slots=0.5*hi), "f", "e", "f"]
|
||||
self.rectangularWall(y, hi, e,
|
||||
move="up")
|
||||
for i in range(len(self.sy)-1):
|
||||
for i in range(len(self.sx) - 1):
|
||||
e = [edges.SlottedEdge(self, self.sy, "f", slots=0.5 * hi), "f", "e", "f"]
|
||||
self.rectangularWall(y, hi, e, move="up")
|
||||
|
||||
for i in range(len(self.sy) - 1):
|
||||
e = [edges.SlottedEdge(self, self.sx, "f"), "f",
|
||||
edges.SlottedEdge(self, self.sx[::-1], "e", slots=0.5*hi), "f"]
|
||||
self.rectangularWall(x, hi, e,
|
||||
move="up")
|
||||
edges.SlottedEdge(self, self.sx[::-1], "e", slots=0.5 * hi), "f"]
|
||||
self.rectangularWall(x, hi, e, move="up")
|
||||
|
||||
self.close()
|
||||
|
||||
|
||||
def main():
|
||||
b = TypeTray()
|
||||
b.parseArgs()
|
||||
b.render()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
from math import *
|
||||
|
||||
|
||||
def arcOnCircle(spanning_angle, outgoing_angle, r=1.0):
|
||||
angle = spanning_angle+2*outgoing_angle
|
||||
radius = r * sin(radians(0.5*spanning_angle))/sin(radians(180-outgoing_angle-0.5*spanning_angle))
|
||||
angle = spanning_angle + 2 * outgoing_angle
|
||||
radius = r * sin(radians(0.5 * spanning_angle)) / sin(radians(180 - outgoing_angle - 0.5 * spanning_angle))
|
||||
return angle, abs(radius)
|
||||
|
||||
class Parts:
|
||||
|
||||
class Parts:
|
||||
def __init__(self, boxes):
|
||||
self.boxes = boxes
|
||||
|
||||
"""
|
||||
def roundKnob(self, diameter, n=20, callback=None, move=""):
|
||||
size = diameter+diameter/n
|
||||
|
@ -22,55 +24,69 @@ class Parts:
|
|||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.boxes, name)
|
||||
|
||||
|
||||
def disc(self, diameter, hole=0, callback=None, move=""):
|
||||
size = diameter
|
||||
r = diameter/2.0
|
||||
r = diameter / 2.0
|
||||
|
||||
if self.move(size, size, move, before=True):
|
||||
return
|
||||
self.moveTo(size/2, size/2)
|
||||
|
||||
self.moveTo(size / 2, size / 2)
|
||||
|
||||
if hole:
|
||||
self.hole(0, 0, hole/2)
|
||||
self.hole(0, 0, hole / 2)
|
||||
|
||||
self.cc(callback, None, 0, 0)
|
||||
self.moveTo(r+self.burn,0, 90)
|
||||
self.moveTo(r + self.burn, 0, 90)
|
||||
self.corner(360, r)
|
||||
self.move(size, size, move)
|
||||
|
||||
|
||||
def waivyKnob(self, diameter, n=20, angle=45, hole=0, callback=None, move=""):
|
||||
size = diameter+pi*diameter/n
|
||||
size = diameter + pi * diameter / n
|
||||
|
||||
if self.move(size, size, move, before=True):
|
||||
return
|
||||
self.moveTo(size/2, size/2)
|
||||
|
||||
self.moveTo(size / 2, size / 2)
|
||||
self.cc(callback, None, 0, 0)
|
||||
|
||||
if hole:
|
||||
self.hole(0, 0, hole/2)
|
||||
self.moveTo(diameter/2, 0, angle)
|
||||
a, r = arcOnCircle(360./n, angle, diameter/2)
|
||||
a2, r2 = arcOnCircle(360./n, -angle, diameter/2)
|
||||
for i in range(n//2):
|
||||
self.hole(0, 0, hole / 2)
|
||||
|
||||
self.moveTo(diameter / 2, 0, angle)
|
||||
a, r = arcOnCircle(360. / n, angle, diameter / 2)
|
||||
a2, r2 = arcOnCircle(360. / n, -angle, diameter / 2)
|
||||
|
||||
for i in range(n // 2):
|
||||
self.boxes.corner(a, r)
|
||||
self.boxes.corner(a2, r2)
|
||||
|
||||
self.move(size, size, move)
|
||||
|
||||
def concaveKnob(self, diameter, n=3, rounded=0.2, angle=70, hole=0,
|
||||
callback=None, move=""):
|
||||
size = diameter
|
||||
|
||||
if self.move(size, size, move, before=True):
|
||||
return
|
||||
self.moveTo(size/2, size/2)
|
||||
|
||||
self.moveTo(size / 2, size / 2)
|
||||
|
||||
if hole:
|
||||
self.hole(0, 0, hole/2)
|
||||
self.hole(0, 0, hole / 2)
|
||||
|
||||
self.cc(callback, None, 0, 0)
|
||||
self.moveTo(diameter/2, 0, 90+angle)
|
||||
a, r = arcOnCircle(360./n*(1-rounded), -angle, diameter/2)
|
||||
if abs(a) < 0.01: # avoid trying to make a straight line as an arc
|
||||
a, r = arcOnCircle(360./n*(1-rounded), -angle-0.01, diameter/2)
|
||||
self.moveTo(diameter / 2, 0, 90 + angle)
|
||||
a, r = arcOnCircle(360. / n * (1 - rounded), -angle, diameter / 2)
|
||||
|
||||
if abs(a) < 0.01: # avoid trying to make a straight line as an arc
|
||||
a, r = arcOnCircle(360. / n * (1 - rounded), -angle - 0.01, diameter / 2)
|
||||
|
||||
for i in range(n):
|
||||
self.boxes.corner(a, r)
|
||||
self.corner(angle)
|
||||
self.corner(360./n*rounded, diameter/2)
|
||||
self.corner(360. / n * rounded, diameter / 2)
|
||||
self.corner(angle)
|
||||
|
||||
self.move(size, size, move)
|
||||
|
||||
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
from math import *
|
||||
from boxes.vectors import *
|
||||
|
||||
|
||||
def tooth_spaceing_curvefit(teeth, b, c, d):
|
||||
return ((c * teeth**d) / (b + teeth**d)) * teeth
|
||||
return ((c * teeth ** d) / (b + teeth ** d)) * teeth
|
||||
|
||||
|
||||
def tooth_spacing(teeth, tooth_pitch, pitch_line_offset):
|
||||
return (2*((teeth*tooth_pitch)/(3.14159265*2)-pitch_line_offset))
|
||||
return (2 * ((teeth * tooth_pitch) / (3.14159265 * 2) - pitch_line_offset))
|
||||
|
||||
|
||||
def mirrorx(points):
|
||||
return [[-x, y] for x, y in points]
|
||||
|
@ -26,36 +29,37 @@ def mirrorx(points):
|
|||
class Pulley:
|
||||
|
||||
spacing = {
|
||||
"MXL" : (False, 2.032,0.254),
|
||||
"40DP" : (False, 2.07264,0.1778),
|
||||
"XL" : (False, 5.08,0.254),
|
||||
"H" : (False, 9.525,0.381),
|
||||
"T2_5" : (True, 0.7467,0.796,1.026),
|
||||
"T5" : (True, 0.6523,1.591,1.064),
|
||||
"T10" : (False, 10,0.93),
|
||||
"AT5" : (True, 0.6523,1.591,1.064),
|
||||
"HTD_3mm" : (False, 3,0.381),
|
||||
"HTD_5mm" : (False, 5,0.5715),
|
||||
"HTD_8mm" : (False, 8,0.6858),
|
||||
"GT2_2mm" : (False, 2,0.254),
|
||||
"GT2_3mm" : (False, 3,0.381),
|
||||
"GT2_5mm" : (False, 5,0.5715),
|
||||
"MXL": (False, 2.032, 0.254),
|
||||
"40DP": (False, 2.07264, 0.1778),
|
||||
"XL": (False, 5.08, 0.254),
|
||||
"H": (False, 9.525, 0.381),
|
||||
"T2_5": (True, 0.7467, 0.796, 1.026),
|
||||
"T5": (True, 0.6523, 1.591, 1.064),
|
||||
"T10": (False, 10, 0.93),
|
||||
"AT5": (True, 0.6523, 1.591, 1.064),
|
||||
"HTD_3mm": (False, 3, 0.381),
|
||||
"HTD_5mm": (False, 5, 0.5715),
|
||||
"HTD_8mm": (False, 8, 0.6858),
|
||||
"GT2_2mm": (False, 2, 0.254),
|
||||
"GT2_3mm": (False, 3, 0.381),
|
||||
"GT2_5mm": (False, 5, 0.5715),
|
||||
}
|
||||
|
||||
profile_data = {
|
||||
"MXL" : (0.508 , 1.321 ),
|
||||
"40DP" : (0.457 , 1.226 ),
|
||||
"XL" : (1.27, 3.051 ),
|
||||
"H" : (1.905 , 5.359 ),
|
||||
"T2_5" : (0.7 , 1.678 ),
|
||||
"T5" : (1.19 , 3.264 ),
|
||||
"T10" : (2.5 , 6.13 ),
|
||||
"AT5" : (1.19 , 4.268 ),
|
||||
"HTD_3mm" : (1.289 , 2.27 ),
|
||||
"HTD_5mm" : (2.199 , 3.781 ),
|
||||
"HTD_8mm" : (3.607 , 6.603 ),
|
||||
"GT2_2mm" : (0.764 , 1.494 ),
|
||||
"GT2_3mm" : (1.169 , 2.31 ),
|
||||
"GT2_5mm" : (1.969 , 3.952 ),
|
||||
"MXL": (0.508, 1.321),
|
||||
"40DP": (0.457, 1.226),
|
||||
"XL": (1.27, 3.051),
|
||||
"H": (1.905, 5.359),
|
||||
"T2_5": (0.7, 1.678),
|
||||
"T5": (1.19, 3.264),
|
||||
"T10": (2.5, 6.13),
|
||||
"AT5": (1.19, 4.268),
|
||||
"HTD_3mm": (1.289, 2.27),
|
||||
"HTD_5mm": (2.199, 3.781),
|
||||
"HTD_8mm": (3.607, 6.603),
|
||||
"GT2_2mm": (0.764, 1.494),
|
||||
"GT2_3mm": (1.169, 2.31),
|
||||
"GT2_5mm": (1.969, 3.952),
|
||||
}
|
||||
|
||||
teeth = { "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]],
|
||||
|
@ -83,20 +87,21 @@ class Pulley:
|
|||
|
||||
def drawPoints(self, lines, kerfdir=1):
|
||||
if kerfdir != 0:
|
||||
lines = kerf(lines, self.boxes.burn*kerfdir)
|
||||
lines = kerf(lines, self.boxes.burn * kerfdir)
|
||||
self.boxes.ctx.save()
|
||||
self.boxes.ctx.move_to(*lines[0])
|
||||
|
||||
for x, y in lines[1:]:
|
||||
self.boxes.ctx.line_to(x, y)
|
||||
|
||||
self.boxes.ctx.line_to(*lines[0])
|
||||
self.boxes.ctx.restore()
|
||||
|
||||
def diameter(self, teeth, profile):
|
||||
if self.spacing[profile][0]:
|
||||
return tooth_spaceing_curvefit(
|
||||
teeth, *self.spacing[profile][1:])
|
||||
else:
|
||||
return tooth_spacing(teeth, *self.spacing[profile][1:])
|
||||
return tooth_spaceing_curvefit(teeth, *self.spacing[profile][1:])
|
||||
|
||||
return tooth_spacing(teeth, *self.spacing[profile][1:])
|
||||
|
||||
def __call__(self, teeth, profile, move="", r_axle=None, callback=None):
|
||||
|
||||
|
@ -105,31 +110,35 @@ class Pulley:
|
|||
# ********************************
|
||||
# To improve fit of belt to pulley, set the following constant. Decrease or increase by 0.1mm at a time. We are modelling the *BELT* tooth here, not the tooth on the pulley. Increasing the number will *decrease* the pulley tooth size. Increasing the tooth width will also scale proportionately the tooth depth, to maintain the shape of the tooth, and increase how far into the pulley the tooth is indented. Can be negative
|
||||
|
||||
additional_tooth_width = 0.2 #mm
|
||||
additional_tooth_width = 0.2 # mm
|
||||
|
||||
# If you need more tooth depth than this provides, adjust the following constant. However, this will cause the shape of the tooth to change.
|
||||
additional_tooth_depth = 0 #mm
|
||||
additional_tooth_depth = 0 # mm
|
||||
|
||||
pulley_OD = self.diameter(teeth, profile)
|
||||
|
||||
tooth_depth, tooth_width = self.profile_data[profile]
|
||||
tooth_distance_from_centre = ((pulley_OD/2)**2 - ((tooth_width+additional_tooth_width)/2)**2)**0.5
|
||||
tooth_width_scale = (tooth_width + additional_tooth_width ) / tooth_width
|
||||
tooth_depth_scale = ((tooth_depth + additional_tooth_depth ) / tooth_depth)
|
||||
tooth_distance_from_centre = ((pulley_OD / 2) ** 2 - ((tooth_width + additional_tooth_width) / 2) ** 2) ** 0.5
|
||||
tooth_width_scale = (tooth_width + additional_tooth_width) / tooth_width
|
||||
tooth_depth_scale = ((tooth_depth + additional_tooth_depth) / tooth_depth)
|
||||
|
||||
total_width = pulley_OD
|
||||
|
||||
if self.boxes.move(total_width, total_width, move, before=True):
|
||||
return
|
||||
self.boxes.moveTo(total_width/2, total_width/2)
|
||||
|
||||
self.boxes.moveTo(total_width / 2, total_width / 2)
|
||||
self.boxes.cc(callback, None, 0.0, 0.0)
|
||||
|
||||
if r_axle:
|
||||
self.boxes.hole(0, 0, r_axle)
|
||||
|
||||
points = []
|
||||
for i in range(teeth):
|
||||
for i in range(teeth):
|
||||
m = [[tooth_width_scale, 0, 0],
|
||||
[0, tooth_depth_scale, -tooth_distance_from_centre]]
|
||||
m = mmul(m, rotm(i*2*pi/teeth))
|
||||
m = mmul(m, rotm(i * 2 * pi / teeth))
|
||||
points.extend((vtransl(pt, m) for pt in self.teeth[profile][1:-1]))
|
||||
self.drawPoints(points)
|
||||
|
||||
self.drawPoints(points)
|
||||
self.boxes.move(total_width, total_width, move)
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
import xml.parsers.expat
|
||||
import re
|
||||
|
||||
class SVGFile(object):
|
||||
|
||||
class SVGFile(object):
|
||||
pathre = re.compile(r"[MCL]? *((-?\d+(\.\d+)?) (-?\d+(\.\d+)?) *)+")
|
||||
transformre = re.compile(r"matrix\(" + ",".join([r"(-?\d+(\.\d+)?)"] * 6) + "\)")
|
||||
|
||||
|
@ -31,29 +31,35 @@ class SVGFile(object):
|
|||
if name == "path" and "symbol" not in self.tags:
|
||||
minx = maxx = miny = maxy = None
|
||||
m = self.transformre.match(attrs.get("transform", ""))
|
||||
|
||||
if m:
|
||||
matrix = [float(m.group(i)) for i in range(1, 12, 2)]
|
||||
else:
|
||||
matrix = [1, 0,
|
||||
0, 1,
|
||||
0, 0]
|
||||
|
||||
for m in self.pathre.findall(attrs.get("d", "")):
|
||||
x = float(m[1])
|
||||
y = float(m[3])
|
||||
tx = matrix[0]*x+matrix[2]*y+matrix[4]
|
||||
ty = matrix[1]*x+matrix[3]*y+matrix[5]
|
||||
tx = matrix[0] * x + matrix[2] * y + matrix[4]
|
||||
ty = matrix[1] * x + matrix[3] * y + matrix[5]
|
||||
|
||||
if self.minx is None or self.minx > tx:
|
||||
self.minx = tx
|
||||
|
||||
if self.maxx is None or self.maxx < tx:
|
||||
self.maxx = tx
|
||||
|
||||
if self.miny is None or self.miny > ty:
|
||||
self.miny = ty
|
||||
|
||||
if self.maxy is None or self.maxy < ty:
|
||||
self.maxy = ty
|
||||
|
||||
def handleEndElement(self, name):
|
||||
last = self.tags.pop()
|
||||
|
||||
if last != name:
|
||||
raise ValueError("Got </%s> expected </%s>" % (name, last))
|
||||
|
||||
|
@ -70,27 +76,29 @@ class SVGFile(object):
|
|||
|
||||
m = re.search(r"""<svg[^>]*(width="(\d+pt)" height="(\d+pt)" viewBox="0 (0 (\d+) (\d+))") version="1.1">""", s)
|
||||
|
||||
#minx = 10*int(self.minx//10)-10
|
||||
# minx = 10*int(self.minx//10)-10
|
||||
# as we don't rewrite the left border keep it as 0
|
||||
if 0 <= self.minx <= 50:
|
||||
minx = 0
|
||||
else:
|
||||
minx = 10*int(self.minx//10)-10
|
||||
#raise ValueError("Left end of drawing at wrong place: %imm (0-50mm expected)" % self.minx)
|
||||
maxx = 10*int(self.maxx//10)+10
|
||||
miny = 10*int(self.miny//10)-10
|
||||
maxy = 10*int(self.maxy//10)+10
|
||||
minx = 10 * int(self.minx // 10) - 10
|
||||
# raise ValueError("Left end of drawing at wrong place: %imm (0-50mm expected)" % self.minx)
|
||||
maxx = 10 * int(self.maxx // 10) + 10
|
||||
miny = 10 * int(self.miny // 10) - 10
|
||||
maxy = 10 * int(self.maxy // 10) + 10
|
||||
|
||||
if m:
|
||||
f.seek(m.start(1))
|
||||
s = ('width="%imm" height="%imm" viewBox="0 %i %i %i"' %
|
||||
(maxx-minx, maxy-miny, miny, maxx, maxy-miny))
|
||||
(maxx - minx, maxy - miny, miny, maxx, maxy - miny))
|
||||
|
||||
if len(s) > len(m.group(1)):
|
||||
raise ValueError("Not enough space for size")
|
||||
f.write(s + " " * (len(m.group(1))- len(s)))
|
||||
|
||||
f.write(s + " " * (len(m.group(1)) - len(s)))
|
||||
else:
|
||||
raiseValueError("Could not understand SVG file")
|
||||
|
||||
raise ValueError("Could not understand SVG file")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
svg = SVGFile("examples/box.svg")
|
||||
|
|
|
@ -14,72 +14,86 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import math
|
||||
|
||||
|
||||
def normalize(v):
|
||||
"set lenght of vector to one"
|
||||
l = (v[0]**2+v[1]**2)**0.5
|
||||
return (v[0]/l, v[1]/l)
|
||||
l = (v[0] ** 2 + v[1] ** 2) ** 0.5
|
||||
return (v[0] / l, v[1] / l)
|
||||
|
||||
|
||||
def vlength(v):
|
||||
return (v[0]**2+v[1]**2)**0.5
|
||||
return (v[0] ** 2 + v[1] ** 2) ** 0.5
|
||||
|
||||
|
||||
def vclip(v, length):
|
||||
l = vlength(v)
|
||||
if l > length:
|
||||
return vscalmul(v, length/l)
|
||||
return vscalmul(v, length / l)
|
||||
return v
|
||||
|
||||
|
||||
def vdiff(p1, p2):
|
||||
"vector from point1 to point2"
|
||||
return (p2[0]-p1[0], p2[1]-p1[1])
|
||||
return (p2[0] - p1[0], p2[1] - p1[1])
|
||||
|
||||
|
||||
def vadd(v1, v2):
|
||||
"Sum of two vectors"
|
||||
return (v1[0]+ v2[0], v1[1]+v2[1])
|
||||
return (v1[0] + v2[0], v1[1] + v2[1])
|
||||
|
||||
|
||||
def vorthogonal(v):
|
||||
"orthogonal vector"
|
||||
"Orthogonal vector"
|
||||
return (-v[1], v[0])
|
||||
|
||||
|
||||
def vscalmul(v, a):
|
||||
"scale vector by a"
|
||||
return (a*v[0], a*v[1])
|
||||
return (a * v[0], a * v[1])
|
||||
|
||||
|
||||
def dotproduct(v1, v2):
|
||||
"Dot product"
|
||||
return v1[0]*v2[0]+v1[1]*v2[1]
|
||||
return v1[0] * v2[0] + v1[1] * v2[1]
|
||||
|
||||
|
||||
def rotm(angle):
|
||||
"Rotation matrix"
|
||||
return [[math.cos(angle), -math.sin(angle), 0],
|
||||
[math.sin(angle), math.cos(angle), 0]]
|
||||
|
||||
|
||||
def vtransl(v, m):
|
||||
m0, m1 = m
|
||||
return [m0[0]*v[0]+m0[1]*v[1]+m0[2],
|
||||
m1[0]*v[0]+m1[1]*v[1]+m1[2]]
|
||||
return [m0[0] * v[0] + m0[1] * v[1] + m0[2],
|
||||
m1[0] * v[0] + m1[1] * v[1] + m1[2]]
|
||||
|
||||
|
||||
def mmul(m0, m1):
|
||||
result = [[0,]*len(m0[0]) for i in range(len(m0))]
|
||||
result = [[0, ] * len(m0[0]) for i in range(len(m0))]
|
||||
for i in range(len(m0[0])):
|
||||
for j in range(len(m0)):
|
||||
for k in range(len(m0)):
|
||||
result[j][i] += m0[k][i] * m1[j][k]
|
||||
return result
|
||||
|
||||
|
||||
def kerf(points, k):
|
||||
"""Outset points by k
|
||||
Assumes a closed loop of points
|
||||
"""
|
||||
result = []
|
||||
lp = len(points)
|
||||
|
||||
for i in range(len(points)):
|
||||
# get normalized orthogonals of both segments
|
||||
v1 = vorthogonal(normalize(vdiff(points[i-1], points[i])))
|
||||
v2 = vorthogonal(normalize(vdiff(points[i], points[(i+1) % lp])))
|
||||
v1 = vorthogonal(normalize(vdiff(points[i - 1], points[i])))
|
||||
v2 = vorthogonal(normalize(vdiff(points[i], points[(i + 1) % lp])))
|
||||
# direction the point has to move
|
||||
d = normalize(vadd(v1, v2))
|
||||
# cos of the half the angle between the segments
|
||||
cos_alpha = dotproduct(v1, d)
|
||||
result.append(vadd(points[i], vscalmul(d, -k/cos_alpha)))
|
||||
result.append(vadd(points[i], vscalmul(d, -k / cos_alpha)))
|
||||
|
||||
return result
|
||||
|
|
Loading…
Reference in New Issue