home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Inkscape / Inkscape-0.48.2-1-win32.exe / share / extensions / gears.py < prev    next >
Text File  |  2011-07-08  |  6KB  |  167 lines

  1. #! /usr/bin/env python
  2. '''
  3. Copyright (C) 2007 Aaron Spike  (aaron @ ekips.org)
  4. Copyright (C) 2007 Tavmjong Bah (tavmjong @ free.fr)
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. '''
  20.  
  21. import inkex
  22. import simplestyle, sys
  23. from math import *
  24.  
  25. def involute_intersect_angle(Rb, R):
  26.     Rb, R = float(Rb), float(R)
  27.     return (sqrt(R**2 - Rb**2) / (Rb)) - (acos(Rb / R))
  28.  
  29. def point_on_circle(radius, angle):
  30.     x = radius * cos(angle)
  31.     y = radius * sin(angle)
  32.     return (x, y)
  33.  
  34. def points_to_svgd(p):
  35.     f = p[0]
  36.     p = p[1:]
  37.     svgd = 'M%.3f,%.3f' % f
  38.     for x in p:
  39.         svgd += 'L%.3f,%.3f' % x
  40.     svgd += 'z'
  41.     return svgd
  42.  
  43. class Gears(inkex.Effect):
  44.     def __init__(self):
  45.         inkex.Effect.__init__(self)
  46.         self.OptionParser.add_option("-t", "--teeth",
  47.                         action="store", type="int",
  48.                         dest="teeth", default=24,
  49.                         help="Number of teeth")
  50.         self.OptionParser.add_option("-p", "--pitch",
  51.                         action="store", type="float",
  52.                         dest="pitch", default=20.0,
  53.                         help="Circular Pitch (length of arc from one tooth to next)")
  54.         self.OptionParser.add_option("-a", "--angle",
  55.                         action="store", type="float",
  56.                         dest="angle", default=20.0,
  57.                         help="Pressure Angle (common values: 14.5, 20, 25 degrees)")
  58.     def effect(self):
  59.  
  60.         teeth = self.options.teeth
  61.         pitch = self.options.pitch
  62.         angle = self.options.angle  # Angle of tangent to tooth at circular pitch wrt radial line.
  63.  
  64.         # print >>sys.stderr, "Teeth: %s\n"        % teeth
  65.  
  66.         two_pi = 2.0 * pi
  67.  
  68.         # Pitch (circular pitch): Length of the arc from one tooth to the next)
  69.         # Pitch diameter: Diameter of pitch circle.
  70.         pitch_diameter = float( teeth ) * pitch / pi
  71.         pitch_radius   = pitch_diameter / 2.0
  72.  
  73.         # Base Circle
  74.         base_diameter = pitch_diameter * cos( radians( angle ) )
  75.         base_radius   = base_diameter / 2.0
  76.  
  77.         # Diametrial pitch: Number of teeth per unit length.
  78.         pitch_diametrial = float( teeth )/ pitch_diameter
  79.  
  80.         # Addendum: Radial distance from pitch circle to outside circle.
  81.         addendum = 1.0 / pitch_diametrial
  82.  
  83.         # Outer Circle
  84.         outer_radius = pitch_radius + addendum
  85.         outer_diameter = outer_radius * 2.0
  86.  
  87.         # Tooth thickness: Tooth width along pitch circle.
  88.         tooth  = ( pi * pitch_diameter ) / ( 2.0 * float( teeth ) )
  89.  
  90.         # Undercut?
  91.         undercut = (2.0 / ( sin( radians( angle ) ) ** 2))
  92.         needs_undercut = teeth < undercut
  93.  
  94.  
  95.         # Clearance: Radial distance between top of tooth on one gear to bottom of gap on another.
  96.         clearance = 0.0
  97.  
  98.         # Dedendum: Radial distance from pitch circle to root diameter.
  99.         dedendum = addendum + clearance
  100.  
  101.         # Root diameter: Diameter of bottom of tooth spaces. 
  102.         root_radius =  pitch_radius - dedendum
  103.         root_diameter = root_radius * 2.0
  104.  
  105.         half_thick_angle = two_pi / (4.0 * float( teeth ) )
  106.         pitch_to_base_angle  = involute_intersect_angle( base_radius, pitch_radius )
  107.         pitch_to_outer_angle = involute_intersect_angle( base_radius, outer_radius ) - pitch_to_base_angle
  108.  
  109.         centers = [(x * two_pi / float( teeth) ) for x in range( teeth ) ]
  110.  
  111.         points = []
  112.  
  113.         for c in centers:
  114.  
  115.             # Angles
  116.             pitch1 = c - half_thick_angle
  117.             base1  = pitch1 - pitch_to_base_angle
  118.             outer1 = pitch1 + pitch_to_outer_angle
  119.  
  120.             pitch2 = c + half_thick_angle
  121.             base2  = pitch2 + pitch_to_base_angle
  122.             outer2 = pitch2 - pitch_to_outer_angle
  123.  
  124.             # Points
  125.             b1 = point_on_circle( base_radius,  base1  )
  126.             p1 = point_on_circle( pitch_radius, pitch1 )
  127.             o1 = point_on_circle( outer_radius, outer1 )
  128.  
  129.             b2 = point_on_circle( base_radius,  base2  )
  130.             p2 = point_on_circle( pitch_radius, pitch2 )
  131.             o2 = point_on_circle( outer_radius, outer2 )
  132.  
  133.             if root_radius > base_radius:
  134.                 pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle(base_radius, root_radius )
  135.                 root1 = pitch1 - pitch_to_root_angle
  136.                 root2 = pitch2 + pitch_to_root_angle
  137.                 r1 = point_on_circle(root_radius, root1)
  138.                 r2 = point_on_circle(root_radius, root2)
  139.                 p_tmp = [r1,p1,o1,o2,p2,r2]
  140.             else:
  141.                 r1 = point_on_circle(root_radius, base1)
  142.                 r2 = point_on_circle(root_radius, base2)
  143.                 p_tmp = [r1,b1,p1,o1,o2,p2,b2,r2]
  144.  
  145.             points.extend( p_tmp )
  146.  
  147.         path = points_to_svgd( points )
  148.  
  149.         # Embed gear in group to make animation easier:
  150.         #  Translate group, Rotate path.
  151.         t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
  152.         g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ),
  153.                      'transform':t }
  154.         g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
  155.  
  156.         # Create SVG Path for gear
  157.         style = { 'stroke': '#000000', 'fill': 'none' }
  158.         gear_attribs = {'style':simplestyle.formatStyle(style), 'd':path}
  159.         gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs )
  160.  
  161. if __name__ == '__main__':
  162.     e = Gears()
  163.     e.affect()
  164.  
  165.  
  166. # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
  167.