Added "IFS Fractals"

This commit is contained in:
Mario Voigt 2020-12-09 10:17:32 +01:00
parent 070ad1e737
commit bae7704db2
2 changed files with 152 additions and 0 deletions

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>IFS Fractals</name>
<id>fablabchemnitz.de.ifs_fractals</id>
<param name="tab" type="notebook">
<page name="Options" gui-text="Options">
<param name="iter" type="int" min="0" max="100" gui-text="Number of iterations:">3</param>
<label appearance="header">Transform Matrices</label>
<param name="tab" type="notebook">
<page name="0" gui-text="1">
<param name="xform0" type="bool" gui-text="Enabled:">true</param>
<param name="A0" type="float" min="-10000" max="10000" precision="3" gui-text="A:">0.5</param>
<param name="B0" type="float" min="-10000" max="10000" precision="3" gui-text="B:">0</param>
<param name="C0" type="float" min="-10000" max="10000" precision="3" gui-text="C:">0</param>
<param name="D0" type="float" min="-10000" max="10000" precision="3" gui-text="D:">0.5</param>
<param name="E0" type="float" min="-10000" max="10000" precision="3" gui-text="E:">0</param>
<param name="F0" type="float" min="-10000" max="10000" precision="3" gui-text="F:">0</param>
</page>
<page name="1" gui-text="2">
<param name="xform1" type="bool" gui-text="Enabled:">false</param>
<param name="A1" type="float" min="-10000" max="10000" precision="3" gui-text="A:">0.5</param>
<param name="B1" type="float" min="-10000" max="10000" precision="3" gui-text="B:">0</param>
<param name="C1" type="float" min="-10000" max="10000" precision="3" gui-text="C:">0</param>
<param name="D1" type="float" min="-10000" max="10000" precision="3" gui-text="D:">0.5</param>
<param name="E1" type="float" min="-10000" max="10000" precision="3" gui-text="E:">1</param>
<param name="F1" type="float" min="-10000" max="10000" precision="3" gui-text="F:">0</param>
</page>
<page name="2" gui-text="3">
<param name="xform2" type="bool" gui-text="Enabled:">false</param>
<param name="A2" type="float" min="-10000" max="10000" precision="3" gui-text="A:">0.5</param>
<param name="B2" type="float" min="-10000" max="10000" precision="3" gui-text="B:">0</param>
<param name="C2" type="float" min="-10000" max="10000" precision="3" gui-text="C:">0</param>
<param name="D2" type="float" min="-10000" max="10000" precision="3" gui-text="D:">0.5</param>
<param name="E2" type="float" min="-10000" max="10000" precision="3" gui-text="E:">0.5</param>
<param name="F2" type="float" min="-10000" max="10000" precision="3" gui-text="F:">1</param>
</page>
<page name="3" gui-text="4">
<param name="xform3" type="bool" gui-text="Enabled:">false</param>
<param name="A3" type="float" min="-10000" max="10000" precision="3" gui-text="A:">0.5</param>
<param name="B3" type="float" min="-10000" max="10000" precision="3" gui-text="B:">0</param>
<param name="C3" type="float" min="-10000" max="10000" precision="3" gui-text="C:">0</param>
<param name="D3" type="float" min="-10000" max="10000" precision="3" gui-text="D:">0.5</param>
<param name="E3" type="float" min="-10000" max="10000" precision="3" gui-text="E:">0</param>
<param name="F3" type="float" min="-10000" max="10000" precision="3" gui-text="F:">0</param>
</page>
<page name="4" gui-text="5">
<param name="xform4" type="bool" gui-text="Enabled:">false</param>
<param name="A4" type="float" min="-10000" max="10000" precision="3" gui-text="A:">0.5</param>
<param name="B4" type="float" min="-10000" max="10000" precision="3" gui-text="B:">0</param>
<param name="C4" type="float" min="-10000" max="10000" precision="3" gui-text="C:">0</param>
<param name="D4" type="float" min="-10000" max="10000" precision="3" gui-text="D:">0.5</param>
<param name="E4" type="float" min="-10000" max="10000" precision="3" gui-text="E:">0</param>
<param name="F4" type="float" min="-10000" max="10000" precision="3" gui-text="F:">0</param>
</page>
</param>
</page>
<page name="Help" gui-text="Help">
<label>
This performs an Iterated Function System by repeating one or more duplicate-and-transform operations on the selected objects.
</label>
<label>
The transformations are specified using matrices, in the same form as the transformation dialog, each of which should be contractive (i.e., shrinking).
</label>
<label>
For example, if you set N transforms, it will make N duplicates and transform each in the first iteration, and then N^2 duplicates of those, and so on, for a total of (N^(I+1)-1)/(N-1) duplicates.
</label>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="FabLab Chemnitz">
<submenu name="Shape/Pattern from Generator"/>
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">ifs_fractals.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python3
# coding=utf-8
#
# Copyright (C) 2020 Dylan Simon, dylan@dylex.net
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
"""
Perform fixed-depth IFS repeated duplicate-and-transform.
"""
import inkex
class IFS(inkex.EffectExtension):
NXFORM = 5
XFORM_PARAMS = list("ABCDEF")
def add_arguments(self, pars):
pars.add_argument("--tab")
pars.add_argument("--iter", type=int, default=3, help="number of iterations")
for i in range(self.NXFORM):
pars.add_argument("--xform%d"%i, type=inkex.Boolean, default=False, help="enable transformation %d"%i)
for p in self.XFORM_PARAMS:
pars.add_argument("--%s%d"%(p,i), type=float, help="transformation matrix %d %s"%(i,p))
def effect(self):
xforms = []
for i in range(self.NXFORM):
if getattr(self.options,'xform%d'%i):
t = [getattr(self.options,"%s%d"%(p,i)) for p in self.XFORM_PARAMS]
xforms.append(inkex.Transform(t))
if not xforms:
inkex.errormsg(_('There are no transforms to apply'))
return False
if not self.svg.selected:
inkex.errormsg(_('There is no selection to duplicate'))
return False
nodes = self.svg.selected.values()
grp = inkex.Group('IFS')
layer = self.svg.get_current_layer().add(grp)
for i in range(self.options.iter):
n = []
for node in nodes:
for x in xforms:
d = node.copy()
d.transform = x * d.transform
n.append(d)
g = inkex.Group('IFS iter %d'%i)
g.add(*n)
grp.add(g)
nodes = n
return True
if __name__ == '__main__':
IFS().run()