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 / spirograph.py < prev    next >
Text File  |  2011-07-08  |  5KB  |  117 lines

  1. #! /usr/bin/env python
  2. '''
  3. Copyright (C) 2007 Joel Holdsworth joel@airwebreathe.org.uk
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. '''
  19. import inkex, simplestyle, math
  20.  
  21. class Spirograph(inkex.Effect):
  22.     def __init__(self):
  23.         inkex.Effect.__init__(self)
  24.         self.OptionParser.add_option("-R", "--primaryr",
  25.                         action="store", type="float",
  26.                         dest="primaryr", default=60.0,
  27.                         help="The radius of the outer gear")
  28.         self.OptionParser.add_option("-r", "--secondaryr",
  29.                         action="store", type="float",
  30.                         dest="secondaryr", default=100.0,
  31.                         help="The radius of the inner gear")
  32.         self.OptionParser.add_option("-d", "--penr",
  33.                         action="store", type="float",
  34.                         dest="penr", default=50.0,
  35.                         help="The distance of the pen from the inner gear")
  36.         self.OptionParser.add_option("-p", "--gearplacement",
  37.                         action="store", type="string",
  38.                         dest="gearplacement", default=50.0,
  39.                         help="Selects whether the gear is inside or outside the ring")
  40.         self.OptionParser.add_option("-a", "--rotation",
  41.                         action="store", type="float",
  42.                         dest="rotation", default=0.0,
  43.                         help="The number of degrees to rotate the image by")
  44.         self.OptionParser.add_option("-q", "--quality",
  45.                         action="store", type="int",
  46.                         dest="quality", default=16,
  47.                         help="The quality of the calculated output")
  48.  
  49.     def effect(self):
  50.  
  51.         if self.options.secondaryr == 0:
  52.             return
  53.         if self.options.quality == 0:
  54.             return
  55.  
  56.         if(self.options.gearplacement.strip(' ').lower().startswith('outside')):
  57.             a = self.options.primaryr + self.options.secondaryr
  58.             flip = -1
  59.         else:
  60.             a = self.options.primaryr - self.options.secondaryr
  61.             flip = 1
  62.  
  63.         ratio = a / self.options.secondaryr
  64.         if ratio == 0:
  65.             return
  66.         scale = 2 * math.pi / (ratio * self.options.quality)
  67.  
  68.         rotation = - math.pi * self.options.rotation / 180;
  69.  
  70.         new = inkex.etree.Element(inkex.addNS('path','svg'))
  71.         s = { 'stroke': '#000000', 'fill': 'none' }
  72.         new.set('style', simplestyle.formatStyle(s))
  73.  
  74.         pathString = ''
  75.         maxPointCount = 1000
  76.  
  77.         for i in range(maxPointCount):
  78.  
  79.             theta = i * scale
  80.  
  81.             x = a * math.cos(theta + rotation) + \
  82.                 self.options.penr * math.cos(ratio * theta + rotation) * flip + \
  83.                 self.view_center[0]
  84.             y = a * math.sin(theta + rotation) - \
  85.                 self.options.penr * math.sin(ratio * theta + rotation) + \
  86.                 self.view_center[1]
  87.  
  88.             dx = (-a * math.sin(theta + rotation) - \
  89.                 ratio * self.options.penr * math.sin(ratio * theta + rotation) * flip) * scale / 3
  90.             dy = (a * math.cos(theta + rotation) - \
  91.                 ratio * self.options.penr * math.cos(ratio * theta + rotation)) * scale / 3
  92.  
  93.             if i <= 0:
  94.                 pathString += 'M ' + str(x) + ',' + str(y) + ' C ' + str(x + dx) + ',' + str(y + dy) + ' '
  95.             else:
  96.                 pathString += str(x - dx) + ',' + str(y - dy) + ' ' + str(x) + ',' + str(y)
  97.  
  98.                 if math.fmod(i / ratio, self.options.quality) == 0 and i % self.options.quality == 0:
  99.                     pathString += 'Z'
  100.                     break
  101.                 else:
  102.                     if i == maxPointCount - 1:
  103.                         pass # we reached the allowed maximum of points, stop here
  104.                     else:
  105.                         pathString += ' C ' + str(x + dx) + ',' + str(y + dy) + ' '
  106.  
  107.  
  108.         new.set('d', pathString)
  109.         self.current_layer.append(new)
  110.  
  111. if __name__ == '__main__':
  112.     e = Spirograph()
  113.     e.affect()
  114.  
  115.  
  116. # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
  117.