mightyscape-1.2/extensions/fablabchemnitz/fibonacci_pattern/fibonacci_pattern.py

86 lines
3.6 KiB
Python

#!/usr/bin/env python3
'''
Copyright (C) 2015-2015 Carlos Mostek carlosmostek@gmail.com
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 math
import inkex
from lxml import etree
# This is basically the draw method from the help guides for inkscape
def draw_SVG_ellipse(rx, ry, cx, cy, parent, start_end=(0,2*math.pi),transform='' ):
style = { 'stroke' : '#000000',
'stroke-width' : '1',
'fill' : 'none' }
ell_attribs = {'style':str(inkex.Style(style)),
inkex.addNS('cx','sodipodi') :str(cx),
inkex.addNS('cy','sodipodi') :str(cy),
inkex.addNS('rx','sodipodi') :str(rx),
inkex.addNS('ry','sodipodi') :str(ry),
inkex.addNS('start','sodipodi') :str(start_end[0]),
inkex.addNS('end','sodipodi') :str(start_end[1]),
inkex.addNS('open','sodipodi') :'true', #all ellipse sectors we will draw are open
inkex.addNS('type','sodipodi') :'arc',
'transform' :transform
}
ell = etree.SubElement(parent, inkex.addNS('path','svg'), ell_attribs )
# This is the workhorse, it draws the circle based on which node number
def drawKthCircle(k,firstRadius, lastRadius, numNodes, spreadFactor, parent):
# Use golden circle phi
phi = (math.sqrt(5) - 1)/2
# Calculate the node radius
growth = lastRadius - firstRadius
nodeRadius = firstRadius + growth * float(k - 1) / float(numNodes)
# Calculate X and Y from theta = 2 pi phi k and radius = sqrt(k)
r = spreadFactor * math.sqrt(k)
theta = 2 * math.pi * phi * k
# use simple trig to get cx and cy
x = r * math.cos(theta)
y = r * math.sin(theta)
# Add the px to the size
nodeRadiusTxt = "%spx" % nodeRadius
# Draw the node
draw_SVG_ellipse(nodeRadiusTxt, nodeRadiusTxt , x, y, parent)
class FibonacciPattern(inkex.EffectExtension):
def add_arguments(self, pars):
pars.add_argument("-f", "--FirstRadius", type=int, default="5", help="The radius of the first layer of circles in pixels.")
pars.add_argument("-l", "--LastRadius", type=int, default="10", help="The radius of the last layer of circles in pixels.")
pars.add_argument("-n", "--NumberOfNodes", type=int, default="5", help="The number of layers in the fibonacci spiral")
pars.add_argument("-s", "--SpreadFactor",type=int, default="10", help="This will create a larger spread between the nodes from the center.")
def effect(self):
group = self.document.getroot().add(inkex.Group(id="fibonacci-pattern-" + self.svg.get_unique_id("")))
for k in range(1,self.options.NumberOfNodes):
drawKthCircle(k,
self.options.FirstRadius,
self.options.LastRadius,
self.options.NumberOfNodes,
self.options.SpreadFactor,
group)
if __name__ == '__main__':
FibonacciPattern().run()