Make generate_spokes a method and port it to boxes
This commit is contained in:
parent
ff8117b8ba
commit
b86146fe1c
139
boxes/gears.py
139
boxes/gears.py
|
@ -43,7 +43,7 @@ from os import devnull # for debugging
|
||||||
from math import pi, cos, sin, tan, radians, degrees, ceil, asin, acos, sqrt
|
from math import pi, cos, sin, tan, radians, degrees, ceil, asin, acos, sqrt
|
||||||
two_pi = 2 * pi
|
two_pi = 2 * pi
|
||||||
import argparse
|
import argparse
|
||||||
from boxes.vectors import kerf
|
from boxes.vectors import kerf, vdiff, vlength
|
||||||
|
|
||||||
__version__ = '0.9'
|
__version__ = '0.9'
|
||||||
|
|
||||||
|
@ -282,69 +282,6 @@ def generate_spur_points(teeth, base_radius, pitch_radius, outer_radius, root_ra
|
||||||
points.extend( p_tmp )
|
points.extend( p_tmp )
|
||||||
return (points)
|
return (points)
|
||||||
|
|
||||||
def generate_spokes_path(root_radius, spoke_width, spoke_count, mount_radius, mount_hole,
|
|
||||||
unit_factor, unit_label):
|
|
||||||
""" given a set of constraints
|
|
||||||
- generate the svg path for the gear spokes
|
|
||||||
- lies between mount_radius (inner hole) and root_radius (bottom of the teeth)
|
|
||||||
- spoke width also defines the spacing at the root_radius
|
|
||||||
- mount_radius is adjusted so that spokes fit if there is room
|
|
||||||
- if no room (collision) then spokes not drawn
|
|
||||||
"""
|
|
||||||
# Spokes
|
|
||||||
collision = False # assume we draw spokes
|
|
||||||
messages = [] # messages to send back about changes.
|
|
||||||
path = ''
|
|
||||||
r_outer = root_radius - spoke_width
|
|
||||||
# checks for collision with spokes
|
|
||||||
# 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
|
|
||||||
else:
|
|
||||||
mount_radius = mount_hole/2 + adj_factor # small fix
|
|
||||||
messages.append("Mount support too small. Auto increased to %2.2f%s." % (mount_radius/unit_factor*2, unit_label))
|
|
||||||
|
|
||||||
# then check to see if cross-over on spoke width
|
|
||||||
if spoke_width * spoke_count +0.5 >= two_pi * mount_radius:
|
|
||||||
adj_factor = 1.2 # wrong value. its probably one of the points distances calculated below
|
|
||||||
mount_radius += adj_factor
|
|
||||||
messages.append("Too many spokes. Increased Mount support by %2.3f%s" % (adj_factor/unit_factor, unit_label))
|
|
||||||
|
|
||||||
# check for collision with outer rim
|
|
||||||
if r_outer <= mount_radius:
|
|
||||||
# not enough room to draw spokes so cancel
|
|
||||||
collision = True
|
|
||||||
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):
|
|
||||||
points = []
|
|
||||||
start_a, end_a = i * two_pi / spoke_count, (i+1) * two_pi / spoke_count
|
|
||||||
# inner circle around mount
|
|
||||||
asin_factor = spoke_width/mount_radius/2
|
|
||||||
# check if need to clamp radius
|
|
||||||
asin_factor = max(-1.0, min(1.0, asin_factor)) # no longer needed - resized above
|
|
||||||
a = asin(asin_factor)
|
|
||||||
points += [ point_on_circle(mount_radius, start_a + a), point_on_circle(mount_radius, end_a - a)]
|
|
||||||
# is inner circle too small
|
|
||||||
asin_factor = spoke_width/r_outer/2
|
|
||||||
# check if need to clamp radius
|
|
||||||
asin_factor = max(-1.0, min(1.0, asin_factor)) # no longer needed - resized above
|
|
||||||
a = asin(asin_factor)
|
|
||||||
points += [point_on_circle(r_outer, end_a - a), point_on_circle(r_outer, start_a + a) ]
|
|
||||||
|
|
||||||
path += (
|
|
||||||
"M %f,%f" % points[0] +
|
|
||||||
"A %f,%f %s %s %s %f,%f" % tuple((mount_radius, mount_radius, 0, 0 if spoke_count!=1 else 1, 1 ) + points[1]) +
|
|
||||||
"L %f,%f" % points[2] +
|
|
||||||
"A %f,%f %s %s %s %f,%f" % tuple((r_outer, r_outer, 0, 0 if spoke_count!=1 else 1, 0 ) + points[3]) +
|
|
||||||
"Z"
|
|
||||||
)
|
|
||||||
return (path, messages)
|
|
||||||
|
|
||||||
def inkbool(val):
|
def inkbool(val):
|
||||||
return val not in ("False", False, "0", 0, "None", None)
|
return val not in ("False", False, "0", 0, "None", None)
|
||||||
|
|
||||||
|
@ -553,6 +490,73 @@ class Gears():
|
||||||
# it is independent of the doc_units!
|
# it is independent of the doc_units!
|
||||||
return circular_pitch # XXX / uutounit(self, 1.0, 'in')
|
return circular_pitch # XXX / uutounit(self, 1.0, 'in')
|
||||||
|
|
||||||
|
def generate_spokes(self, root_radius, spoke_width, spoke_count, mount_radius, mount_hole,
|
||||||
|
unit_factor, unit_label):
|
||||||
|
""" given a set of constraints
|
||||||
|
- generate the svg path for the gear spokes
|
||||||
|
- lies between mount_radius (inner hole) and root_radius (bottom of the teeth)
|
||||||
|
- spoke width also defines the spacing at the root_radius
|
||||||
|
- mount_radius is adjusted so that spokes fit if there is room
|
||||||
|
- if no room (collision) then spokes not drawn
|
||||||
|
"""
|
||||||
|
# Spokes
|
||||||
|
collision = False # assume we draw spokes
|
||||||
|
messages = [] # messages to send back about changes.
|
||||||
|
spoke_holes = []
|
||||||
|
r_outer = root_radius - spoke_width
|
||||||
|
# checks for collision with spokes
|
||||||
|
# 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
|
||||||
|
else:
|
||||||
|
mount_radius = mount_hole/2 + adj_factor # small fix
|
||||||
|
messages.append("Mount support too small. Auto increased to %2.2f%s." % (mount_radius/unit_factor*2, unit_label))
|
||||||
|
|
||||||
|
# then check to see if cross-over on spoke width
|
||||||
|
if spoke_width * spoke_count +0.5 >= two_pi * mount_radius:
|
||||||
|
adj_factor = 1.2 # wrong value. its probably one of the points distances calculated below
|
||||||
|
mount_radius += adj_factor
|
||||||
|
messages.append("Too many spokes. Increased Mount support by %2.3f%s" % (adj_factor/unit_factor, unit_label))
|
||||||
|
|
||||||
|
# check for collision with outer rim
|
||||||
|
if r_outer <= mount_radius:
|
||||||
|
# not enough room to draw spokes so cancel
|
||||||
|
collision = True
|
||||||
|
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 = i * two_pi / spoke_count, (i+1) * two_pi / spoke_count
|
||||||
|
# inner circle around mount
|
||||||
|
asin_factor = spoke_width/mount_radius/2
|
||||||
|
# check if need to clamp radius
|
||||||
|
asin_factor = max(-1.0, min(1.0, asin_factor)) # no longer needed - resized above
|
||||||
|
a = asin(asin_factor)
|
||||||
|
|
||||||
|
# is inner circle too small
|
||||||
|
asin_factor = spoke_width/r_outer/2
|
||||||
|
# check if need to clamp radius
|
||||||
|
asin_factor = max(-1.0, min(1.0, asin_factor)) # no longer needed - resized above
|
||||||
|
a2 = asin(asin_factor)
|
||||||
|
l = vlength(vdiff(point_on_circle(mount_radius, start_a + a),
|
||||||
|
point_on_circle(r_outer, start_a + a2)))
|
||||||
|
self.boxes.moveTo(*point_on_circle(mount_radius, start_a - a), degrees=degrees(start_a))
|
||||||
|
self.boxes.polyline(
|
||||||
|
l,
|
||||||
|
-90-degrees(a2), 0,
|
||||||
|
(-degrees(two_pi / spoke_count-2*a2), r_outer), 0,
|
||||||
|
-90-degrees(a2),
|
||||||
|
l, -90+degrees(a), 0,
|
||||||
|
(degrees(two_pi / spoke_count-2*a), mount_radius),
|
||||||
|
0, -90-degrees(a2), 0
|
||||||
|
)
|
||||||
|
|
||||||
|
self.boxes.ctx.restore()
|
||||||
|
return messages
|
||||||
|
|
||||||
|
|
||||||
def __call__(self, **kw):
|
def __call__(self, **kw):
|
||||||
|
@ -663,19 +667,18 @@ class Gears():
|
||||||
## points.extend( p_tmp )
|
## points.extend( p_tmp )
|
||||||
|
|
||||||
self.drawPoints(points)
|
self.drawPoints(points)
|
||||||
return
|
|
||||||
bbox_center = points_to_bbox_center( points )
|
bbox_center = points_to_bbox_center( points )
|
||||||
path = ""
|
path = ""
|
||||||
# Spokes (add to current path)
|
# Spokes (add to current path)
|
||||||
if not self.options.internal_ring: # only draw internals if spur gear
|
if not self.options.internal_ring: # only draw internals if spur gear
|
||||||
spokes_path, msg = generate_spokes_path(root_radius, spoke_width, spoke_count, mount_radius, mount_hole,
|
msg = self.generate_spokes(root_radius, spoke_width, spoke_count, mount_radius, mount_hole,
|
||||||
unit_factor, self.options.units)
|
unit_factor, self.options.units)
|
||||||
warnings.extend(msg)
|
warnings.extend(msg)
|
||||||
path += spokes_path
|
|
||||||
|
|
||||||
# Draw mount hole
|
# Draw mount hole
|
||||||
# A : rx,ry x-axis-rotation, large-arch-flag, sweepflag x,y
|
# A : rx,ry x-axis-rotation, large-arch-flag, sweepflag x,y
|
||||||
r = mount_hole / 2
|
r = mount_hole / 2
|
||||||
|
self.boxes.hole(0, 0, r)
|
||||||
path += (
|
path += (
|
||||||
"M %f,%f" % (0,r) +
|
"M %f,%f" % (0,r) +
|
||||||
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,-r) +
|
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,-r) +
|
||||||
|
@ -690,7 +693,7 @@ class Gears():
|
||||||
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,-r) +
|
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,-r) +
|
||||||
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,r)
|
"A %f,%f %s %s %s %f,%f" % (r,r, 0,0,0, 0,r)
|
||||||
)
|
)
|
||||||
|
return
|
||||||
# Embed gear in group to make animation easier:
|
# Embed gear in group to make animation easier:
|
||||||
# Translate group, Rotate path.
|
# Translate group, Rotate path.
|
||||||
t = "" # XXX 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
|
t = "" # XXX 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
|
||||||
|
|
|
@ -18,6 +18,9 @@ def normalize(v):
|
||||||
l = (v[0]**2+v[1]**2)**0.5
|
l = (v[0]**2+v[1]**2)**0.5
|
||||||
return (v[0]/l, v[1]/l)
|
return (v[0]/l, v[1]/l)
|
||||||
|
|
||||||
|
def vlength(v):
|
||||||
|
return (v[0]**2+v[1]**2)**0.5
|
||||||
|
|
||||||
def vdiff(p1, p2):
|
def vdiff(p1, p2):
|
||||||
"vector from point1 to point2"
|
"vector from point1 to point2"
|
||||||
return (p2[0]-p1[0], p2[1]-p1[1])
|
return (p2[0]-p1[0], p2[1]-p1[1])
|
||||||
|
|
Loading…
Reference in New Issue