Code

Extensions. Gear extension with center hole (see Bug #692719, gear extension should...
[inkscape.git] / share / extensions / gears.py
index c60f63b8312b24cb68d42a2f039d2ddc7028047a..a1b3ee666d4b6bb4cd02390f2bd6dd261d7a7556 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python 
+#! /usr/bin/env python
 '''
 Copyright (C) 2007 Aaron Spike  (aaron @ ekips.org)
 Copyright (C) 2007 Tavmjong Bah (tavmjong @ free.fr)
@@ -16,11 +16,12 @@ 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
-'''\r
+'''
 
 import inkex
 import simplestyle, sys
 from math import *
+import string
 
 def involute_intersect_angle(Rb, R):
     Rb, R = float(Rb), float(R)
@@ -44,120 +45,141 @@ class Gears(inkex.Effect):
     def __init__(self):
         inkex.Effect.__init__(self)
         self.OptionParser.add_option("-t", "--teeth",
-                        action="store", type="int", 
+                        action="store", type="int",
                         dest="teeth", default=24,
                         help="Number of teeth")
         self.OptionParser.add_option("-p", "--pitch",
-                        action="store", type="float", 
+                        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", 
+                        action="store", type="float",
                         dest="angle", default=20.0,
                         help="Pressure Angle (common values: 14.5, 20, 25 degrees)")
+        self.OptionParser.add_option("-c", "--centerdiameter",
+                        action="store", type="float",
+                        dest="centerdiameter", default=10.0,
+                        help="Diameter of central hole - 0.0 for no hole")
+        self.OptionParser.add_option("-u", "--unit",
+                        action="store", type="string",
+                        dest="unit", default="px",
+                        help="unit of measure for circular pitch and center diameter")
     def effect(self):
-    
+
         teeth = self.options.teeth
-        pitch = self.options.pitch
+        pitch = inkex.unittouu( str(self.options.pitch) + self.options.unit)
         angle = self.options.angle  # Angle of tangent to tooth at circular pitch wrt radial line.
+       centerdiameter = inkex.unittouu( str(self.options.centerdiameter) + self.options.unit)
 
         # 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 )
+            # 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.\r
-        t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'\r
-        g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ),\r
-                   'transform':t }
+        #  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\r
-        style = { 'stroke': '#000000', 'fill': 'none' }\r
+        # 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 )\r
-
-e = Gears()
-e.affect()
-
+        gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs )
+        if(centerdiameter > 0.0):
+            center_attribs = {'style':simplestyle.formatStyle(style), 
+                inkex.addNS('cx','sodipodi')        :'0.0',
+                inkex.addNS('cy','sodipodi')        :'0.0',
+                inkex.addNS('rx','sodipodi')        :str(centerdiameter/2),
+                inkex.addNS('ry','sodipodi')        :str(centerdiameter/2),
+                inkex.addNS('type','sodipodi')      :'arc'
+            }
+            center = inkex.etree.SubElement(g, inkex.addNS('path','svg'), center_attribs )
+
+if __name__ == '__main__':
+    e = Gears()
+    e.affect()
+
+
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99