# ADAPTED BY FRANCISCO FOR FAB 9000 MOTOR GEAR
# ORIGINAL FILE FROM MATT KEETER KOKOPELLI GEAR EXAMPLE
# Released under MIT license http://opensource.org/licenses/MIT
from math import *
import operator
from koko.lib.shapes import *
flat = False
"""
Involute gear based on the tutorial at
http://www.cartertools.com/involute.html
"""
P = 16. # diametral pitch
PA = 14.5#PA.value # pressure angle
N = 20#int(N.value) # number of teeth
R = N/P/2 # pitch radius
RB = R*cos(radians(PA)) # base circle radius
a = 1/P # addendum
d = 1.157/P # dedendum
RO = R+a # outer radius
RR = R-d # root radius
print 'R0=',RO
print 'RB=',RB
print 'a=',a
print 'd=',d
print 'RR=',RR
print (RO-RR)*2.54
print 'eje:',25.4*2*pi*(.0*RO+1*RR)/20
# MathTree expressions for r and r**2
r_2 = MathTree.square(X) + MathTree.square(Y)
r = MathTree.sqrt(r_2)
# See note (1) for derivation of tooth rotation
t = sqrt(R**2/RB**2 -1)
rot = atan2(sin(t)-t*cos(t), cos(t)+t*sin(t)) + pi/2/N
# See note (2) for derivation of involute curve
tooth = MathTree.sqrt(r_2-RB**2) - \
RB*(MathTree.atan(Y/X) + MathTree.acos(RB/r)) - \
RB*rot
tooth.shape = True
tooth &= reflect_y(tooth)
if N % 2:
tooth &= -X
teeth = reduce(operator.add, [rotate(tooth, i*360/N)
for i in range(N)])
else:
teeth = reduce(operator.add, [rotate(tooth, i*360/N)
for i in range(N/2)])
teeth += circle(0, 0, RR)
teeth &= circle(0, 0, RO) - circle(0, 0, RR*0.9)
teeth.bounds = circle(0, 0, RO).bounds
teeth.color = 'red'
# Create a base for the gear
base = circle(0, 0, RR*1) - circle(0, 0, 0.195/2)
base.color = 'red'
gear1=teeth+base
if not flat:
gear1=extrusion(gear1,0,0.1)
gear.xmin = -.7
gear.xmax = 2.3
gear.ymin = -1
gear.ymax = 1
cad.function = gear1
"""
Notes:
(1)
We want to find the angle such that the involute curve
intersects a circle of radius R, where the involute is being
unwound from a circle of radius RB (and RB < R)
The involute has coordinates
x, y = RB*(cos(t)+t*sin(t)), RB*(sin(t)-t*cos(t))
where t is a parameter.
Solving x**2 + y**2 = R**2 gives
t = sqrt(R**2/RB**2 -1)
We take atan2(y(t), x(t)) to find the angle, then add another
(2*pi)/(4*N) so that we can mirror the tooth about the x axis.
(2)
[Clever math & explanation by Peter Fedak, HMC 2013]
Assuming that restricting to x and y greater than
R is not interesting/challenging, an expression
separating one side of a portion of a circle involute
from another is
R(atan(y/x) + acos( R/sqrt(x^2+y^2) )) - sqrt(x^2+y^2-R^2)
which is 0 on the curve and negative for points to the northeast.
This assumes the involute starts at (1,0), if you want to rotate it,
or deal with a different turn of the involute, subtract R*rotation
angle.
For points P=(x,y) in the first quadrant, atan(y/x) accurately gives
the angle between the x-axis and the ray from O=(0,0) to P. Assuming
we are "unwinding" the involute counterclockwise, the place where the
"string" meets the circle, Q, will be the more-counterclockwise
tangent from P to the circle. Then O,P,Q is a right triangle, and the
length of the string, PQ, is sqrt(x^2+y^2-R^2) (right angle between
the tangent and the radius OQ).
The angle of OQ from the x-axis is, again restricted to P in the first
quadrant, the sum of the angle of OP from the x-axis and one of the
angles in teh triangle. the cosine of the relevant angle is
R/sqrt(x^2+y^2), and as this angle will always be smaller than a right
angle, can by given by the inverse cosine of this ratio directly. The
condition for a point to lie on the involute is for the length of the
"string" to be equal to the amount unwound. The amount unwound is the
angle from OQ to the x-axis times R, which is the first term in the
expression. The length of the string is the expression after the minus
sign. Thus the involute is where this F=0, whereas if the point is too
close to the origin, the expression will be positive.
"""