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