Logo Search packages:      
Sourcecode: inkscape version File versions

gears.py

#!/usr/bin/env python 
'''
Copyright (C) 2007 Aaron Spike  (aaron @ ekips.org)
Copyright (C) 2007 Tavmjong Bah (tavmjong @ free.fr)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'''

import inkex
import simplestyle, sys
from math import *

def involute_intersect_angle(Rb, R):
    Rb, R = float(Rb), float(R)
    return (sqrt(R**2 - Rb**2) / (Rb)) - (acos(Rb / R))

def point_on_circle(radius, angle):
    x = radius * cos(angle)
    y = radius * sin(angle)
    return (x, y)

def points_to_svgd(p):
    f = p[0]
    p = p[1:]
    svgd = 'M%.3f,%.3f' % f
    for x in p:
        svgd += 'L%.3f,%.3f' % x
    svgd += 'z'
    return svgd

class Gears(inkex.Effect):
    def __init__(self):
        inkex.Effect.__init__(self)
        self.OptionParser.add_option("-t", "--teeth",
                        action="store", type="int", 
                        dest="teeth", default=24,
                        help="Number of teeth")
        self.OptionParser.add_option("-p", "--pitch",
                        action="store", type="float", 
                        dest="pitch", default=20.0,
                        help="Circular Pitch (length of arc from one tooth to next)")
        self.OptionParser.add_option("-a", "--angle",
                        action="store", type="float", 
                        dest="angle", default=20.0,
                        help="Pressure Angle (common values: 14.5, 20, 25 degrees)")
    def effect(self):
    
        teeth = self.options.teeth
        pitch = self.options.pitch
        angle = self.options.angle  # Angle of tangent to tooth at circular pitch wrt radial line.

        # print >>sys.stderr, "Teeth: %s\n"        % teeth

        two_pi = 2.0 * pi
        
        # Pitch (circular pitch): Length of the arc from one tooth to the next)
        # Pitch diameter: Diameter of pitch circle.
        pitch_diameter = float( teeth ) * pitch / pi
        pitch_radius   = pitch_diameter / 2.0
       
        # Base Circle
        base_diameter = pitch_diameter * cos( radians( angle ) )
        base_radius   = base_diameter / 2.0
    
        # Diametrial pitch: Number of teeth per unit length.
        pitch_diametrial = float( teeth )/ pitch_diameter

        # Addendum: Radial distance from pitch circle to outside circle.
        addendum = 1.0 / pitch_diametrial
    
        # Outer Circle
        outer_radius = pitch_radius + addendum
        outer_diameter = outer_radius * 2.0
    
        # Tooth thickness: Tooth width along pitch circle.
        tooth  = ( pi * pitch_diameter ) / ( 2.0 * float( teeth ) )
    
        # Undercut?
        undercut = (2.0 / ( sin( radians( angle ) ) ** 2))
        needs_undercut = teeth < undercut

    
        # Clearance: Radial distance between top of tooth on one gear to bottom of gap on another.
        clearance = 0.0

        # Dedendum: Radial distance from pitch circle to root diameter.
        dedendum = addendum + clearance
    
        # Root diameter: Diameter of bottom of tooth spaces. 
        root_radius =  pitch_radius - dedendum
        root_diameter = root_radius * 2.0
    
        half_thick_angle = two_pi / (4.0 * float( teeth ) )
        pitch_to_base_angle  = involute_intersect_angle( base_radius, pitch_radius )
        pitch_to_outer_angle = involute_intersect_angle( base_radius, outer_radius ) - pitch_to_base_angle
    
        centers = [(x * two_pi / float( teeth) ) for x in range( teeth ) ]
    
        points = []

        for c in centers:

             # Angles
             pitch1 = c - half_thick_angle
             base1  = pitch1 - pitch_to_base_angle
             outer1 = pitch1 + pitch_to_outer_angle
        
             pitch2 = c + half_thick_angle
             base2  = pitch2 + pitch_to_base_angle
             outer2 = pitch2 - pitch_to_outer_angle
        
             # Points
             b1 = point_on_circle( base_radius,  base1  )
             p1 = point_on_circle( pitch_radius, pitch1 )
             o1 = point_on_circle( outer_radius, outer1 )

             b2 = point_on_circle( base_radius,  base2  )
             p2 = point_on_circle( pitch_radius, pitch2 )
             o2 = point_on_circle( outer_radius, outer2 )

             if root_radius > base_radius:
                 pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle(base_radius, root_radius )
                 root1 = pitch1 - pitch_to_root_angle
                 root2 = pitch2 + pitch_to_root_angle
                 r1 = point_on_circle(root_radius, root1)
                 r2 = point_on_circle(root_radius, root2)
                 p_tmp = [r1,p1,o1,o2,p2,r2]
             else:
                 r1 = point_on_circle(root_radius, base1)
                 r2 = point_on_circle(root_radius, base2)
                 p_tmp = [r1,b1,p1,o1,o2,p2,b2,r2]
            
             points.extend( p_tmp )

        path = points_to_svgd( points )

        # Embed gear in group to make animation easier:
        #  Translate group, Rotate path.
        t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
        g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ),
                   'transform':t }
        g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)

        # Create SVG Path for gear
        style = { 'stroke': '#000000', 'fill': 'none' }
        gear_attribs = {'style':simplestyle.formatStyle(style), 'd':path}
        gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs )

e = Gears()
e.affect()


Generated by  Doxygen 1.6.0   Back to index