This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
mightyscape-1.1-deprecated/extensions/fablabchemnitz/apollonian_gasket/apollonian_gasket.py

101 lines
3.9 KiB
Python

#!/usr/bin/env python3
import inkex
import apolloniangasket_func
from lxml import etree
__version__ = '0.0'
def cplxs2pts(zs):
tt = []
for z in zs:
tt.extend([z.real,z.imag])
return tt
def draw_SVG_circle(parent, r, cx, cy, name):
" structure an SVG circle entity under parent "
circ_attribs = { 'cx': str(cx), 'cy': str(cy),
'r': str(r),
inkex.addNS('label','inkscape'): name}
circle = etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs)
def draw_SVG_circleAsPath(parent, r, cx, cy, name):
circ_attribs = {
"d": "M {:0.6f}, {:0.6f} a {:0.6f},{:0.6f} 0 1,0 {:0.6f},0 a {:0.6f},{:0.6f} 0 1,0 {:0.6f},0".format(
cx - r, cy, r, r, 2*r, r, r, -2*r),
inkex.addNS('label','inkscape'): name}
circle = etree.SubElement(parent, inkex.addNS('path','svg'), circ_attribs)
class Gasket(inkex.EffectExtension): # choose a better name
def add_arguments(self, pars):
pars.add_argument("--active_tab")
pars.add_argument("--depth",type=int, default=3)
pars.add_argument("--c1", type=float, default=2.0)
pars.add_argument("--c2", type=float, default=3.0)
pars.add_argument("--c3", type=float, default=3.0)
pars.add_argument("--shrink", type=inkex.Boolean, default=True)
pars.add_argument("--as_paths", type=inkex.Boolean, default=True)
def calc_unit_factor(self):
unit_factor = self.svg.unittouu(str(1.0) + self.options.units)
return unit_factor
### -------------------------------------------------------------------
### Main function and is called when the extension is run.
def effect(self):
#set up path styles
path_stroke = '#DD0000' # take color from tab3
path_fill = 'none' # no fill - just a line
path_stroke_width = self.svg.unittouu(str(0.1) + "mm")
page_id = self.options.active_tab # sometimes wrong the very first time
style_curve = { 'stroke': path_stroke,
'fill': 'none',
'stroke-width': path_stroke_width }
# This finds center of current view in inkscape
t = 'translate(%s,%s)' % (self.svg.namedview.center[0], self.svg.namedview.center[1])
# add a group to the document's current layer
#all the circles inherit style from this group
g_attribs = { inkex.addNS('label','inkscape'): 'zengon' + "_%d"%(self.options.depth),
inkex.addNS('transform-center-x','inkscape'): str(0),
inkex.addNS('transform-center-y','inkscape'): str(0),
'transform': t,
'style' : str(inkex.Style((style_curve))),
'info':'N: '}
topgroup = etree.SubElement(self.svg.get_current_layer(), 'g', g_attribs)
circles = apolloniangasket_func.main(c1=self.options.c1,
c2=self.options.c2,
c3=self.options.c3,
depth=self.options.depth)
#shrink the circles so they don't touch
#useful for laser cutting
if self.options.shrink:
circles = circles[1:]
for cc in circles:
cc.r = abs(cc.r)
if cc.r >.5:
cc.r -= .1
else:
cc.r *= .9
scale_factor = 200
for c in circles:
cx, cy, r = c.m.real, c.m.imag, abs(c.r)
#rescale and add circle to document
cx, cy, r = scale_factor * cx , scale_factor * cy, scale_factor * r
if self.options.as_paths is False:
draw_SVG_circle(topgroup, r, cx, cy, 'apollian')
else:
draw_SVG_circleAsPath(topgroup, r, cx, cy, 'apollian')
if __name__ == '__main__':
Gasket().run()