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