Code

add gears
authorbuliabyak <buliabyak@users.sourceforge.net>
Wed, 18 Apr 2007 00:04:31 +0000 (00:04 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Wed, 18 Apr 2007 00:04:31 +0000 (00:04 +0000)
share/extensions/Makefile.am
share/extensions/gears.inx [new file with mode: 0644]
share/extensions/gears.py [new file with mode: 0644]

index f0c75fa9c54c0b12c5b0f2146f220ebd909a7c51..0ce2bba4af6056625bf973141b8d3833295574bb 100644 (file)
@@ -43,6 +43,7 @@ extensions = \
        fractalize.py \
        funcplot.py \
        g2pngs.py\
+       gears.py\
        gimp_xcf.py \
        handles.py \
        ill2svg.pl \
@@ -126,6 +127,7 @@ modules = \
        fractalize.inx \
        funcplot.inx \
        g2pngs.inx\
+       gears.inx\
        gimp_xcf.inx \
        handles.inx \
        inkscape_help_commandline.inx \
diff --git a/share/extensions/gears.inx b/share/extensions/gears.inx
new file mode 100644 (file)
index 0000000..0ba1a4d
--- /dev/null
@@ -0,0 +1,18 @@
+<inkscape-extension>
+    <_name>Gear</_name>
+    <id>org.ekips.filter.gears</id>
+    <dependency type="executable" location="extensions">gears.py</dependency>
+    <dependency type="executable" location="extensions">inkex.py</dependency>
+    <param name="teeth"    type="int"   min="6"    max="360"    _gui-text="Number of teeth">24</param>
+    <param name="pitch"    type="float" min="0.0"  max="1000.0" _gui-text="Circular pitch, px">20.0</param>
+    <param name="angle"    type="float" min="10.0" max="30.0"   _gui-text="Pressure angle">20.0</param>
+    <effect>
+       <object-type>all</object-type>
+        <effects-menu>
+            <submenu _name="Render"/>
+        </effects-menu>                                                                
+    </effect>
+    <script>
+        <command reldir="extensions" interpreter="python">gears.py</command>
+    </script>
+</inkscape-extension>
diff --git a/share/extensions/gears.py b/share/extensions/gears.py
new file mode 100644 (file)
index 0000000..060cfdb
--- /dev/null
@@ -0,0 +1,166 @@
+#!/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, 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 )
+
+        # Create SVG Path for gear
+        gear = self.document.createElement( 'svg:path' )
+        style = { 'stroke': '#000000', 'fill': 'none' }
+        gear.setAttribute( 'style', simplestyle.formatStyle(style) )
+        gear.setAttribute( 'd', path )
+
+        # Embed gear in group to make animation easier:
+        #  Translate group, Rotate path.
+        g=self.document.createElement('g')
+
+        g.setAttribute( 'inkscape:label', 'Gear' + str( teeth ) )
+        t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
+        g.setAttribute( 'transform', t )
+        self.current_layer.appendChild( g )
+        g.appendChild( gear )
+
+e = Gears()
+e.affect()
+