diff --git a/extensions/fablabchemnitz_eggbot_twist.inx b/extensions/fablabchemnitz_eggbot_twist.inx
new file mode 100644
index 00000000..682bf1b5
--- /dev/null
+++ b/extensions/fablabchemnitz_eggbot_twist.inx
@@ -0,0 +1,38 @@
+
+
+ <_name>Twist
+ fablabchemnitz.de.twist
+ <_param name="Header" type="description" xml:space="preserve">
+Iteratively twist and self-inscribe
+a polygon within itself.
+
+The number of twists is how many
+iterations to perform.
+
+The step ratio is the fractional
+distance along an edge to move each
+vertex.
+
+***
+This extension is intended as an
+example of how to write an Inkscape
+extension for use with the Eggbot.
+See the eggbot_twist.py file in the
+Inkscape extensions directory for
+this extensions' Python code.
+***
+
+ 8
+ 0.15
+
+ all
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/fablabchemnitz_eggbot_twist.py b/extensions/fablabchemnitz_eggbot_twist.py
new file mode 100644
index 00000000..66648141
--- /dev/null
+++ b/extensions/fablabchemnitz_eggbot_twist.py
@@ -0,0 +1,520 @@
+#!/usr/bin/env python3
+
+# twist.py -- Primarily a simple example of writing an Inkscape extension
+# which manipulates objects in a drawing.
+#
+# For a polygon with vertices V[0], V[1], V[2], ..., V[n-1] iteratively
+# move each vertex V[i] by a constant factor 0 < s < 1.0 along the edge
+# between V[i] and V[i+1 modulo n] for 0 <= i <= n-1.
+#
+# This extension operates on every selected closed path, or, if no paths
+# are selected, then every closed path in the document. Since the "twisting"
+# effect only concerns itself with individual paths, no effort is made to
+# worry about the transforms applied to the paths. That is, it is not
+# necessary to worry about tracking SVG transforms as all the work can be
+# done using the untransformed coordinates of each path.
+
+# Written by Daniel C. Newman ( dan dot newman at mtbaldy dot us )
+# 19 October 2010
+
+# 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
+
+from inkex import bezier
+import cspsubdiv
+from inkex.paths import Path, CubicSuperPath
+import inkex
+from inkex import Transform
+from lxml import etree
+
+def subdivideCubicPath(sp, flat, i=1):
+ """
+ [ Lifted from eggbot.py with impunity ]
+
+ Break up a bezier curve into smaller curves, each of which
+ is approximately a straight line within a given tolerance
+ (the "smoothness" defined by [flat]).
+
+ This is a modified version of cspsubdiv.cspsubdiv(): rewritten
+ because recursion-depth errors on complicated line segments
+ could occur with cspsubdiv.cspsubdiv().
+ """
+
+ while True:
+ while True:
+ if i >= len(sp):
+ return
+
+ p0 = sp[i - 1][1]
+ p1 = sp[i - 1][2]
+ p2 = sp[i][0]
+ p3 = sp[i][1]
+
+ b = (p0, p1, p2, p3)
+
+ if bezier.maxdist(b) > flat:
+ break
+
+ i += 1
+
+ one, two = bezier.beziersplitatt(b, 0.5)
+ sp[i - 1][2] = one[1]
+ sp[i][0] = two[2]
+ p = [one[2], one[3], two[1]]
+ sp[i:1] = [p]
+
+
+def distanceSquared(p1, p2):
+ """
+ Pythagorean distance formula WITHOUT the square root. Since
+ we just want to know if the distance is less than some fixed
+ fudge factor, we can just square the fudge factor once and run
+ with it rather than compute square roots over and over.
+ """
+
+ dx = p2[0] - p1[0]
+ dy = p2[1] - p1[1]
+
+ return dx * dx + dy * dy
+
+
+class Twist(inkex.Effect):
+
+ def __init__(self):
+
+ inkex.Effect.__init__(self)
+ self.arg_parser.add_argument("--nSteps", type=int, default=8, help="Number of iterations to take")
+ self.arg_parser.add_argument("--fRatio", type=float, default=0.2, help="Some ratio")
+
+ """
+ Store each path in an associative array (dictionary) indexed
+ by the lxml.etree pointer for the SVG document element
+ containing the path. Looking up the path in the dictionary
+ yields a list of lists. Each of these lists is a subpath
+ # of the path. E.g., for the SVG path
+
+
+
+ we'd have two subpaths which will be reduced to absolute
+ coordinates.
+
+ subpath_1 = [ [10, 10], [10, 15], [15, 15], [15, 10], [10,10] ]
+ subpath_2 = [ [30, 30], [30, 60] ]
+ self.paths[] = [ subpath_1, subpath_2 ]
+
+ All of the paths and their subpaths could be drawn as follows:
+
+ for path in self.paths:
+ for subpath in self.paths[path]:
+ first = True
+ for vertex in subpath:
+ if first:
+ moveto( vertex[0], vertex[1] )
+ first = False
+ else:
+ lineto( vertex[0], vertex[1] )
+
+ NOTE: drawing all the paths like the above would not in general
+ give the correct rendering of the document UNLESS path transforms
+ were also tracked and applied.
+ """
+
+ self.paths = {}
+ self.paths_clone_transform = {}
+
+ def addPathVertices(self, path, node=None, transform=None, clone_transform=None):
+
+ """
+ Decompose the path data from an SVG element into individual
+ subpaths, each subpath consisting of absolute move to and line
+ to coordinates. Place these coordinates into a list of polygon
+ vertices.
+ """
+
+ if (not path) or (len(path) == 0):
+ # Nothing to do
+ return
+
+ sp = Path(path)
+ if (not sp) or (len(sp) == 0):
+ # Path must have been devoid of any real content
+ return
+
+ # Get a cubic super path
+ p = CubicSuperPath(sp)
+ if (not p) or (len(p) == 0):
+ # Probably never happens, but...
+ return
+
+ # Now traverse the cubic super path
+ subpath_list = []
+ subpath_vertices = []
+ for sp in p:
+ if len(subpath_vertices):
+ # There's a prior subpath: see if it is closed and should be saved
+ if distanceSquared(subpath_vertices[0], subpath_vertices[-1]) < 1:
+ # Keep the prior subpath: it appears to be a closed path
+ subpath_list.append(subpath_vertices)
+ subpath_vertices = []
+ subdivideCubicPath(sp, 0.2)
+ for csp in sp:
+ # Add this vertex to the list of vertices
+ subpath_vertices.append(csp[1])
+
+ # Handle final subpath
+ if len(subpath_vertices):
+ if distanceSquared(subpath_vertices[0], subpath_vertices[-1]) < 1:
+ # Path appears to be closed so let's keep it
+ subpath_list.append(subpath_vertices)
+
+ # Empty path?
+ if not subpath_list:
+ return
+
+ # Store the list of subpaths in a dictionary keyed off of the path's node pointer
+ self.paths[node] = subpath_list
+ self.paths_clone_transform[node] = clone_transform
+
+ def recursivelyTraverseSvg(self, a_node_list, mat_current=None, parent_visibility='visible', clone_transform=None):
+
+ """
+ [ This too is largely lifted from eggbot.py ]
+
+ Recursively walk the SVG document, building polygon vertex lists
+ for each graphical element we support.
+
+ Rendered SVG elements:
+ , , , , , ,
+
+ Supported SVG elements:
+ ,