Several cleanings

This commit is contained in:
Mario Voigt 2020-08-20 13:12:34 +02:00
parent 8bb5c35665
commit 1ce07959f3
35 changed files with 104 additions and 218 deletions

View File

@ -4,7 +4,6 @@ import inkex
from lxml import etree from lxml import etree
from math import cos, sin, pi, exp from math import cos, sin, pi, exp
__version__ = '0.1' __version__ = '0.1'
inkex.localization.localize
def line(npts=40, x0=0, y0=0, delta=.5, sgn=1): def line(npts=40, x0=0, y0=0, delta=.5, sgn=1):
#returns a list of points on a line (y = +/- x + c) starting at x0,y0 #returns a list of points on a line (y = +/- x + c) starting at x0,y0
@ -96,5 +95,4 @@ class AffineTorus(inkex.Effect): # choose a better name
curve_attribs = { 'style': styles[0], 'd': payload} curve_attribs = { 'style': styles[0], 'd': payload}
etree.SubElement(topgroup, inkex.addNS('path','svg'), curve_attribs) etree.SubElement(topgroup, inkex.addNS('path','svg'), curve_attribs)
if __name__ == '__main__': AffineTorus().run()
AffineTorus().run()

View File

@ -257,14 +257,14 @@ class AnotherPerspective(inkex.Effect):
def effect(self): def effect(self):
if len(self.options.ids) < 2: if len(self.options.ids) < 2:
inkex.errormsg(_("This extension requires two selected paths.")) inkex.errormsg("This extension requires two selected paths.")
exit() exit()
obj = self.svg.selected[self.options.ids[0]] obj = self.svg.selected[self.options.ids[0]]
envelope = self.svg.selected[self.options.ids[1]] envelope = self.svg.selected[self.options.ids[1]]
if obj.get(inkex.addNS('type','sodipodi')): if obj.get(inkex.addNS('type','sodipodi')):
inkex.errormsg(_("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type','sodipodi')))) inkex.errormsg("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type','sodipodi')))
exit() exit()
if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'): if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'):

View File

@ -5,15 +5,12 @@
<param name="active_tab" type="notebook"> <param name="active_tab" type="notebook">
<page name="title" gui-text="Settings"> <page name="title" gui-text="Settings">
<param name="depth" type="int" min="2" max="7" gui-text="Depth">3</param> <param name="depth" type="int" min="2" max="7" gui-text="Depth">3</param>
<param name="curvatures" type="description" xml:space="preserve">------------------------------</param>
<param name="c1" type="float" min="0.1" max="10.0" precision="2" gui-text="c1">2.0</param> <param name="c1" type="float" min="0.1" max="10.0" precision="2" gui-text="c1">2.0</param>
<param name="c2" type="float" min="0.1" max="10.0" precision="2" gui-text="c2">3.0</param> <param name="c2" type="float" min="0.1" max="10.0" precision="2" gui-text="c2">3.0</param>
<param name="c3" type="float" min="0.1" max="10.0" precision="2" gui-text="c3">3.0</param> <param name="c3" type="float" min="0.1" max="10.0" precision="2" gui-text="c3">3.0</param>
<param name="help" type="description" xml:space="preserve">------------------------------</param>
<param name="shrink" type="bool" gui-text="shrink circles for cutting">true</param> <param name="shrink" type="bool" gui-text="shrink circles for cutting">true</param>
</page> </page>
<page name="Usage1" gui-text="Usage"> <page name="Usage1" gui-text="Usage">
<!-- space:preserve read for neat layout -->
<param name="use1" type="description" xml:space="preserve"> <param name="use1" type="description" xml:space="preserve">
Make an apollonian gasket: Make an apollonian gasket:
@ -25,11 +22,6 @@
for details of construction. for details of construction.
</param> </param>
</page> </page>
<page name="Usage2" gui-text="Help">
<param name="use2" type="description" xml:space="preserve">
No help needed.
</param>
</page>
</param> </param>
<effect> <effect>
<object-type>all</object-type> <object-type>all</object-type>

View File

@ -6,8 +6,6 @@ from lxml import etree
__version__ = '0.0' __version__ = '0.0'
inkex.localization.localize()
def cplxs2pts(zs): def cplxs2pts(zs):
tt = [] tt = []
for z in zs: for z in zs:
@ -94,5 +92,4 @@ class Gasket(inkex.Effect): # choose a better name
cx, cy, r = scale_factor*cx , scale_factor*cy, scale_factor*r cx, cy, r = scale_factor*cx , scale_factor*cy, scale_factor*r
draw_SVG_circle(topgroup,r,cx,cy,'apo') draw_SVG_circle(topgroup,r,cx,cy,'apo')
if __name__ == '__main__': Gasket().run()
Gasket().run()

View File

@ -9,7 +9,9 @@
<effect> <effect>
<object-type>all</object-type> <object-type>all</object-type>
<effects-menu> <effects-menu>
<submenu name="Attributes"/> <submenu name="FabLab Chemnitz">
<submenu name="Various"/>
</submenu>
</effects-menu> </effects-menu>
</effect> </effect>
<script> <script>

View File

@ -16,7 +16,9 @@
<effect> <effect>
<object-type>all</object-type> <object-type>all</object-type>
<effects-menu> <effects-menu>
<submenu name="Attributes" /> <submenu name="FabLab Chemnitz">
<submenu name="Various"/>
</submenu>
</effects-menu> </effects-menu>
</effect> </effect>
<script> <script>

View File

@ -32,7 +32,6 @@ class AttribEditor(inkex.Effect):
if self.options.attributeName in el.attrib: if self.options.attributeName in el.attrib:
del el.attrib[self.options.attributeName] del el.attrib[self.options.attributeName]
else: else:
inkex.errormsg(_("Invalid mode: " + self.options.mode)) inkex.errormsg("Invalid mode: " + self.options.mode)
if __name__ == "__main__": AttribEditor().run()
AttribEditor().run()

View File

@ -9,7 +9,9 @@
<effect> <effect>
<object-type>all</object-type> <object-type>all</object-type>
<effects-menu> <effects-menu>
<submenu name="Attributes" /> <submenu name="FabLab Chemnitz">
<submenu name="Various"/>
</submenu>
</effects-menu> </effects-menu>
</effect> </effect>
<script> <script>

View File

@ -73,7 +73,7 @@ class BouwkampCodeExtension(inkex.Effect):
try: try:
self.exception_on_invalid_bouwkamp_code(bouwkamp_code) self.exception_on_invalid_bouwkamp_code(bouwkamp_code)
except ValueError as exception: except ValueError as exception:
inkex.errormsg(_(str(exception))) inkex.errormsg(str(exception))
return return
# draw the bouwkamp code # draw the bouwkamp code
@ -137,10 +137,6 @@ class BouwkampCodeExtension(inkex.Effect):
helper[i+j] += code[rectangle] helper[i+j] += code[rectangle]
def draw_rectangle(self, position, dimension, parent, center): def draw_rectangle(self, position, dimension, parent, center):
"""
Draws a rectangle with the specified parameters.
"""
rectangle_style = { rectangle_style = {
'opacity': '1', 'opacity': '1',
'stroke': '#000000', 'stroke': '#000000',
@ -164,5 +160,4 @@ class BouwkampCodeExtension(inkex.Effect):
etree.SubElement(parent, inkex.addNS('rect', 'svg'), rectangle_attributes) etree.SubElement(parent, inkex.addNS('rect', 'svg'), rectangle_attributes)
if __name__ == '__main__': BouwkampCodeExtension().run()
BouwkampCodeExtension().run()

View File

@ -74,7 +74,7 @@
<param name="spacing" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Space Between Parts">1.0</param> <param name="spacing" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Space Between Parts">1.0</param>
</vbox> </vbox>
</hbox> </hbox>
<effect needs-live-preview="false"> <effect needs-live-preview="true">
<object-type>path</object-type> <object-type>path</object-type>
<effects-menu> <effects-menu>
<submenu name="FabLab Chemnitz"> <submenu name="FabLab Chemnitz">

View File

@ -52,10 +52,8 @@ __version__ = "0.99" ### please report bugs, suggestions etc at https://github.c
import os import os
import inkex import inkex
import gettext
import math import math
from copy import deepcopy from copy import deepcopy
_ = gettext.gettext
linethickness = 1 # default unless overridden by settings linethickness = 1 # default unless overridden by settings
@ -372,31 +370,31 @@ class BoxMaker(inkex.Effect):
error=0 error=0
if min(X,Y,Z)==0: if min(X,Y,Z)==0:
inkex.errormsg(_('Error: Dimensions must be non zero')) inkex.errormsg('Error: Dimensions must be non zero')
error=1 error=1
if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test
inkex.errormsg(_('Error: Dimensions Too Large')) inkex.errormsg('Error: Dimensions Too Large')
error=1 error=1
if min(X,Y,Z)<3*nomTab: if min(X,Y,Z)<3*nomTab:
inkex.errormsg(_('Error: Tab size too large')) inkex.errormsg('Error: Tab size too large')
error=1 error=1
if nomTab<thickness: if nomTab<thickness:
inkex.errormsg(_('Error: Tab size too small')) inkex.errormsg('Error: Tab size too small')
error=1 error=1
if thickness==0: if thickness==0:
inkex.errormsg(_('Error: Thickness is zero')) inkex.errormsg('Error: Thickness is zero')
error=1 error=1
if thickness>min(X,Y,Z)/3: # crude test if thickness>min(X,Y,Z)/3: # crude test
inkex.errormsg(_('Error: Material too thick')) inkex.errormsg('Error: Material too thick')
error=1 error=1
if correction>min(X,Y,Z)/3: # crude test if correction>min(X,Y,Z)/3: # crude test
inkex.errormsg(_('Error: Kerf/Clearence too large')) inkex.errormsg('Error: Kerf/Clearence too large')
error=1 error=1
if spacing>max(X,Y,Z)*10: # crude test if spacing>max(X,Y,Z)*10: # crude test
inkex.errormsg(_('Error: Spacing too large')) inkex.errormsg('Error: Spacing too large')
error=1 error=1
if spacing<kerf: if spacing<kerf:
inkex.errormsg(_('Error: Spacing too small')) inkex.errormsg('Error: Spacing too small')
error=1 error=1
if error: exit() if error: exit()
@ -638,5 +636,4 @@ class BoxMaker(inkex.Effect):
side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivwalls*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivwalls*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c
side(group,(x,y+dy),(d,-c),(d,a),keydivfloor*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d side(group,(x,y+dy),(d,-c),(d,a),keydivfloor*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d
# Create effect instance and apply it.
BoxMaker().run() BoxMaker().run()

View File

@ -17,8 +17,6 @@ from math import *
__version__ = '0.2' __version__ = '0.2'
inkex.localization.localize
def points_to_svgd(p, close = True): def points_to_svgd(p, close = True):
""" convert list of points (x,y) pairs """ convert list of points (x,y) pairs
into a closed SVG path list into a closed SVG path list
@ -263,9 +261,7 @@ class Dose(inkex.Effect):
self.einschnitte_schreiben() self.einschnitte_schreiben()
del self.einschnitt_punkte[:] del self.einschnitt_punkte[:]
def einschnitte_schreiben(self): def einschnitte_schreiben(self):
###Schreibt die Einschnitte in die Seite ###Schreibt die Einschnitte in die Seite
@ -371,6 +367,4 @@ class Dose(inkex.Effect):
branding_line = etree.SubElement(textgroup, inkex.addNS('text','svg'), einschnitt_line_attribs) branding_line = etree.SubElement(textgroup, inkex.addNS('text','svg'), einschnitt_line_attribs)
branding_line.text = 'Die Einschnitte nur zu 70 Prozent in das Material lasern' branding_line.text = 'Die Einschnitte nur zu 70 Prozent in das Material lasern'
Dose().run()
if __name__ == '__main__':
Dose().run()

View File

@ -33,14 +33,12 @@ import math
import re import re
import inkex import inkex
from inkex.paths import CubicSuperPath, Path from inkex.paths import CubicSuperPath, Path
inkex.localization.localize()
from optparse import SUPPRESS_HELP from optparse import SUPPRESS_HELP
debug = False debug = False
class ChainPaths(inkex.Effect): class ChainPaths(inkex.Effect):
def __init__(self): def __init__(self):
# Call the base class constructor.
inkex.Effect.__init__(self) inkex.Effect.__init__(self)
# For handling an SVG viewbox attribute, we will need to know the # For handling an SVG viewbox attribute, we will need to know the
@ -140,14 +138,14 @@ class ChainPaths(inkex.Effect):
self.eps_sq = self.chain_epsilon * self.unit_factor * self.chain_epsilon * self.unit_factor self.eps_sq = self.chain_epsilon * self.unit_factor * self.chain_epsilon * self.unit_factor
if not len(self.svg.selected.items()): if not len(self.svg.selected.items()):
inkex.errormsg(_("Please select one or more objects.")) inkex.errormsg("Please select one or more objects.")
return return
segments = [] segments = []
for id in self.svg.selected: for id in self.svg.selected:
node = self.svg.selected[id] node = self.svg.selected[id]
if node.tag != inkex.addNS('path', 'svg'): if node.tag != inkex.addNS('path', 'svg'):
inkex.errormsg(_("Object " + id + " is not a path. Try\n - Path->Object to Path\n - Object->Ungroup")) inkex.errormsg("Object " + id + " is not a path. Try\n - Path->Object to Path\n - Object->Ungroup")
return return
if debug: inkex.utils.debug("id=" + str(id) + ", tag=" + str(node.tag)) if debug: inkex.utils.debug("id=" + str(id) + ", tag=" + str(node.tag))
path_d = CubicSuperPath(Path(node.get('d'))) path_d = CubicSuperPath(Path(node.get('d')))
@ -281,5 +279,4 @@ class ChainPaths(inkex.Effect):
if debug: inkex.utils.debug("min_missed_distance: "+str(math.sqrt(float(self.min_missed_distance_sq))/self.unit_factor)+'>'+str(self.chain_epsilon)+str(self.options.units)) if debug: inkex.utils.debug("min_missed_distance: "+str(math.sqrt(float(self.min_missed_distance_sq))/self.unit_factor)+'>'+str(self.chain_epsilon)+str(self.options.units))
if debug: inkex.utils.debug("Successful link operations: "+str(self.chained_count)) if debug: inkex.utils.debug("Successful link operations: "+str(self.chained_count))
if __name__ == '__main__': ChainPaths().run()
ChainPaths().run()

View File

@ -33,7 +33,7 @@ class Pathpoints2Dots(inkex.Effect):
def effect(self): def effect(self):
if len(self.svg.selected) != 2: if len(self.svg.selected) != 2:
errormsg(_("Please select exact two objects:\n1. object representing path,\n2. object representing dots.")) errormsg("Please select exact two objects:\n1. object representing path,\n2. object representing dots.")
return return
dot = self.svg.selected[0] dot = self.svg.selected[0]
@ -72,5 +72,4 @@ class Pathpoints2Dots(inkex.Effect):
clone.set('y',point.y-bb.center.y) clone.set('y',point.y-bb.center.y)
group.add(clone) group.add(clone)
if __name__ == '__main__': Pathpoints2Dots().run()
Pathpoints2Dots().run()

View File

@ -313,7 +313,6 @@ class LineShading(inkex.Effect):
node.getparent().remove(node) node.getparent().remove(node)
return return
if not image_selected_flag: if not image_selected_flag:
inkex.errormsg(_("Please select an image")) inkex.errormsg("Please select an image")
# Create effect instance and apply it.
LineShading().run() LineShading().run()

View File

@ -5,7 +5,6 @@ import sys
import math import math
import inkex import inkex
from inkex.paths import CubicSuperPath from inkex.paths import CubicSuperPath
inkex.localization.localize
class TransformExponential(inkex.Effect): class TransformExponential(inkex.Effect):
def __init__(self): def __init__(self):
@ -85,8 +84,8 @@ class TransformExponential(inkex.Effect):
def effect(self): def effect(self):
if len(self.svg.selected) == 0: if len(self.svg.selected) == 0:
inkex.errormsg(_("Please select an object to perform the " + inkex.errormsg("Please select an object to perform the " +
"exponential-distort transformation on.")) "exponential-distort transformation on.")
return return
for id, node in self.svg.selected.items(): for id, node in self.svg.selected.items():
@ -105,5 +104,4 @@ class TransformExponential(inkex.Effect):
node.set('d', str(pts)) node.set('d', str(pts))
if __name__ == '__main__': TransformExponential().run()
TransformExponential().run()

View File

@ -20,8 +20,6 @@ import math
import inkex import inkex
from lxml import etree from lxml import etree
inkex.localization.localize
# This is basically the draw method from the help guides for inkscape # 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='' ): def draw_SVG_ellipse(rx, ry, cx, cy, parent, start_end=(0,2*math.pi),transform='' ):
@ -84,6 +82,4 @@ class FibonacciSpiral(inkex.Effect):
self.options.SpreadFactor, self.options.SpreadFactor,
self.svg.get_current_layer()) self.svg.get_current_layer())
if __name__ == '__main__': FibonacciSpiral().run()
e = FibonacciSpiral()
e.run()

View File

@ -22,29 +22,16 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
''' '''
# Making an .INX file : http://wiki.inkscape.org/wiki/index.php/MakingAnINX
# see also http://codespeak.net/lxml/dev/tutorial.html#namespaces for XML namespaces manipulation
# These two lines are only needed if you don't put the script directly into the installation directory
import inkex import inkex
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from lxml import etree from lxml import etree
import gettext
_ = gettext.gettext
def printDebug(string): def printDebug(string):
inkex.errormsg(_(string)) inkex.errormsg(string)
class GridStrip_Creator(inkex.Effect): class GridStrip_Creator(inkex.Effect):
def __init__(self): def __init__(self):
inkex.Effect.__init__(self) inkex.Effect.__init__(self)
"""
Constructor.
Defines options of the script.
"""
# Call the base class constructor.
inkex.Effect.__init__(self)
self.arg_parser.add_argument('--length', type = float, default = 230.0, help = 'Length of strip') self.arg_parser.add_argument('--length', type = float, default = 230.0, help = 'Length of strip')
self.arg_parser.add_argument('--width', type = float, default = 20.0, help = 'Width of strip') self.arg_parser.add_argument('--width', type = float, default = 20.0, help = 'Width of strip')
@ -105,7 +92,6 @@ class GridStrip_Creator(inkex.Effect):
notchxcorner=False notchxcorner=False
notchycorner=False notchycorner=False
linewidth=self.svg.unittouu(str(0.2)+uunits) linewidth=self.svg.unittouu(str(0.2)+uunits)
distx=(striplength-cellnumx*cellwidth)/2 distx=(striplength-cellnumx*cellwidth)/2
@ -118,35 +104,6 @@ class GridStrip_Creator(inkex.Effect):
width = float(self.svg.unittouu(svg.attrib['width'])) width = float(self.svg.unittouu(svg.attrib['width']))
height = float(self.svg.unittouu(svg.attrib['height'])) height = float(self.svg.unittouu(svg.attrib['height']))
# maxlength=max(width,height)
# if striplength > maxlength:
# factor=striplength/maxlength+1
# inkex.utils.debug("document width="+str(self.uutounit(width,uunits)))
# inkex.utils.debug("document height="+str(self.uutounit(height,uunits)))
# inkex.utils.debug("strip length="+str(self.uutounit(striplength,uunits)))
# inkex.utils.debug("strip width="+str(self.uutounit(stripwidth,uunits)))
# inkex.utils.debug("cell width="+str(self.uutounit(cellwidth,uunits)))
# inkex.utils.debug("cell height="+str(self.uutounit(cellheight,uunits)))
# inkex.utils.debug("Number of cells horizontal="+str(cellnumx))
# inkex.utils.debug("Number of cells vertical ="+str(cellnumy))
# inkex.utils.debug("Depth of extra notch="+str(self.uutounit(notchdepth,uunits)))
# inkex.utils.debug("Width of extra notch="+str(self.uutounit(notchwidth,uunits)))
# inkex.utils.debug("Depth of notch for grid="+str(self.uutounit(notchdepth,uunits)))
# inkex.utils.debug("Width of notch for grid="+str(self.uutounit(notchwidth,uunits)))
# inkex.utils.debug("distx="+str(self.uutounit(distx,uunits)))
# inkex.utils.debug("disty="+str(self.uutounit(disty,uunits)))
# inkex.utils.debug("celldistx="+str(self.uutounit(celldistx,uunits)))
# inkex.utils.debug("celldisty="+str(self.uutounit(celldisty,uunits)))
parent = self.svg.get_current_layer() parent = self.svg.get_current_layer()
layername='' layername=''
if notchhorizontal: if notchhorizontal:
@ -385,5 +342,4 @@ class GridStrip_Creator(inkex.Effect):
'd':pathstring} 'd':pathstring}
etree.SubElement(grp, inkex.addNS('path','svg'), strip_attribs ) etree.SubElement(grp, inkex.addNS('path','svg'), strip_attribs )
if __name__ == '__main__': GridStrip_Creator().run()
GridStrip_Creator().run()

View File

@ -49,7 +49,7 @@ def convert_objects_to_paths(file, document):
(out, err) = p.communicate() (out, err) = p.communicate()
if p.returncode != 0: if p.returncode != 0:
inkex.errormsg(_("Failed to convert objects to paths. Continued without converting.")) inkex.errormsg("Failed to convert objects to paths. Continued without converting.")
inkex.errormsg(out) inkex.errormsg(out)
inkex.errormsg(err) inkex.errormsg(err)
return document.getroot() return document.getroot()

View File

@ -24,7 +24,6 @@ import os
import sys import sys
import inkex import inkex
inkex.localization.localize()
from lxml import etree from lxml import etree
import subprocess import subprocess
from fablabchemnitz_inkcut import contains_text, convert_objects_to_paths from fablabchemnitz_inkcut import contains_text, convert_objects_to_paths
@ -76,5 +75,4 @@ class InkscapeInkcutPlugin(inkex.Effect):
# https://bugs.python.org/issue26741. # https://bugs.python.org/issue26741.
p.returncode = 0 p.returncode = 0
if __name__ == '__main__': InkscapeInkcutPlugin().run()
InkscapeInkcutPlugin().run()

View File

@ -49,7 +49,7 @@ def convert_objects_to_paths(file, document):
(out, err) = p.communicate() (out, err) = p.communicate()
if p.returncode != 0: if p.returncode != 0:
inkex.errormsg(_("Failed to convert objects to paths. Continued without converting.")) inkex.errormsg("Failed to convert objects to paths. Continued without converting.")
inkex.errormsg(out) inkex.errormsg(out)
inkex.errormsg(err) inkex.errormsg(err)
return document.getroot() return document.getroot()

View File

@ -3,7 +3,6 @@
import math import math
import inkex import inkex
from inkex import Transform from inkex import Transform
inkex.localization.localize()
class IsometricProjectionTools(inkex.Effect): class IsometricProjectionTools(inkex.Effect):
""" """
@ -125,8 +124,8 @@ class IsometricProjectionTools(inkex.Effect):
conversion = "to_" + self.options.conversion conversion = "to_" + self.options.conversion
if len(self.svg.selected) == 0: if len(self.svg.selected) == 0:
inkex.errormsg(_("Please select an object to perform the " + inkex.errormsg("Please select an object to perform the " +
"isometric projection transformation on.")) "isometric projection transformation on.")
return return
# Default to the flat 2D to isometric top down view conversion if an # Default to the flat 2D to isometric top down view conversion if an

View File

@ -186,5 +186,4 @@ class JPEGExport(inkex.Effect):
else: else:
return '/tmp/' return '/tmp/'
if __name__=="__main__": JPEGExport().run()
JPEGExport().run()

View File

@ -22,8 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
''' '''
__version__ = "0.8rb" __version__ = "0.8rb"
import inkex,gettext,math import inkex
_ = gettext.gettext import math
from lxml import etree from lxml import etree
import math import math
@ -389,31 +389,31 @@ class LivingHinge(inkex.Effect):
error=0 error=0
if min(X,Y,Z)==0: if min(X,Y,Z)==0:
inkex.errormsg(_('Error: Dimensions must be non zero')) inkex.errormsg('Error: Dimensions must be non zero')
error=1 error=1
if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test
inkex.errormsg(_('Error: Dimensions Too Large')) inkex.errormsg('Error: Dimensions Too Large')
error=1 error=1
if min(X,Y,Z)<3*nomTab: if min(X,Y,Z)<3*nomTab:
inkex.errormsg(_('Error: Tab size too large')) inkex.errormsg('Error: Tab size too large')
error=1 error=1
if nomTab<thickness: if nomTab<thickness:
inkex.errormsg(_('Error: Tab size too small')) inkex.errormsg('Error: Tab size too small')
error=1 error=1
if thickness==0: if thickness==0:
inkex.errormsg(_('Error: Thickness is zero')) inkex.errormsg('Error: Thickness is zero')
error=1 error=1
if thickness>min(X,Y,Z)/3: # crude test if thickness>min(X,Y,Z)/3: # crude test
inkex.errormsg(_('Error: Material too thick')) inkex.errormsg('Error: Material too thick')
error=1 error=1
if correction>min(X,Y,Z)/3: # crude test if correction>min(X,Y,Z)/3: # crude test
inkex.errormsg(_('Error: Kerf/Clearence too large')) inkex.errormsg('Error: Kerf/Clearence too large')
error=1 error=1
if spacing>max(X,Y,Z)*10: # crude test if spacing>max(X,Y,Z)*10: # crude test
inkex.errormsg(_('Error: Spacing too large')) inkex.errormsg('Error: Spacing too large')
error=1 error=1
if spacing<kerf: #if spacing is less then kerf, the laser cuts will overlap and blast meaningful material. if spacing<kerf: #if spacing is less then kerf, the laser cuts will overlap and blast meaningful material.
inkex.errormsg(_('Error: Spacing too small')) inkex.errormsg('Error: Spacing too small')
error=1 error=1
if error: exit() if error: exit()

View File

@ -29,13 +29,13 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
''' '''
# standard library
import math import math
import tempfile, os, sys, shutil import tempfile, os, sys, shutil
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import zipfile import zipfile
import re import re
# local library
import fablabchemnitz_lyz_inkex as inkex import fablabchemnitz_lyz_inkex as inkex
import fablabchemnitz_lyz_simplestyle as simplestyle import fablabchemnitz_lyz_simplestyle as simplestyle
import fablabchemnitz_lyz_simpletransform as simpletransform import fablabchemnitz_lyz_simpletransform as simpletransform
@ -43,11 +43,6 @@ import fablabchemnitz_lyz_cubicsuperpath as cubicsuperpath
import fablabchemnitz_lyz_cspsubdiv as cspsubdiv import fablabchemnitz_lyz_cspsubdiv as cspsubdiv
from fablabchemnitz_lyz_library import LYZ_CLASS from fablabchemnitz_lyz_library import LYZ_CLASS
try:
inkex.localize()
except:
pass
## Subprocess timout stuff ###### ## Subprocess timout stuff ######
from threading import Timer from threading import Timer
def run_external(cmd, timeout_sec): def run_external(cmd, timeout_sec):
@ -61,7 +56,7 @@ def run_external(cmd, timeout_sec):
timer.cancel() timer.cancel()
################################## ##################################
class MyEffect(inkex.Effect): class LYZExport(inkex.Effect):
def __init__(self): def __init__(self):
inkex.Effect.__init__(self) inkex.Effect.__init__(self)
self.flatness = 0.01 self.flatness = 0.01
@ -273,7 +268,7 @@ class MyEffect(inkex.Effect):
rx = max(rx,ry) rx = max(rx,ry)
ry = rx ry = rx
#msg = "rx = %f ry = %f " %(rx,ry) #msg = "rx = %f ry = %f " %(rx,ry)
#inkex.errormsg(_(msg)) #inkex.errormsg(msg)
L1 = "M %f,%f %f,%f " %(x+rx , y , x+width-rx , y ) L1 = "M %f,%f %f,%f " %(x+rx , y , x+width-rx , y )
C1 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width , y+ry ) C1 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width , y+ry )
L2 = "M %f,%f %f,%f " %(x+width , y+ry , x+width , y+height-ry) L2 = "M %f,%f %f,%f " %(x+width , y+ry , x+width , y+height-ry)
@ -419,7 +414,7 @@ class MyEffect(inkex.Effect):
with open(png_temp_file, 'rb') as f: with open(png_temp_file, 'rb') as f:
self.PNG_DATA = f.read() self.PNG_DATA = f.read()
except: except:
inkex.errormsg(_("PNG generation timed out.\nTry saving again.\n\n")) inkex.errormsg("PNG generation timed out.\nTry saving again.\n\n")
#Delete the temp folder and any files #Delete the temp folder and any files
shutil.rmtree(tmp_dir) shutil.rmtree(tmp_dir)
@ -446,12 +441,12 @@ class MyEffect(inkex.Effect):
if p: if p:
retval = float(p.string[p.start():p.end()]) retval = float(p.string[p.start():p.end()])
else: else:
inkex.errormsg(_("Size was not determined returning zero value")) inkex.errormsg("Size was not determined returning zero value")
retval = 0.0 retval = 0.0
if u: if u:
retunit = u.string[u.start():u.end()] retunit = u.string[u.start():u.end()]
else: else:
inkex.errormsg(_("units not understood assuming px at %d dpi" %(self.inkscape_dpi))) inkex.errormsg("units not understood assuming px at %d dpi" %(self.inkscape_dpi))
retunit = 'px' retunit = 'px'
try: try:
@ -504,7 +499,7 @@ class MyEffect(inkex.Effect):
Dx = float(view_box_list[0]) / ( float(view_box_list[2])/w_mm ) Dx = float(view_box_list[0]) / ( float(view_box_list[2])/w_mm )
Dy = float(view_box_list[1]) / ( float(view_box_list[3])/h_mm ) Dy = float(view_box_list[1]) / ( float(view_box_list[3])/h_mm )
except: except:
#inkex.errormsg(_("Using Default Inkscape Scale")) #inkex.errormsg("Using Default Inkscape Scale")
scale = 25.4/self.inkscape_dpi scale = 25.4/self.inkscape_dpi
Dx = 0 Dx = 0
Dy = 0 Dy = 0
@ -533,7 +528,7 @@ class MyEffect(inkex.Effect):
# msg = msg + "h_uu = %f\n" %(h_uu) # msg = msg + "h_uu = %f\n" %(h_uu)
# msg = msg + "w_uu = %f\n" %(w_uu) # msg = msg + "w_uu = %f\n" %(w_uu)
#inkex.errormsg(_(msg)) #inkex.errormsg(msg)
if (area_select=="object_area"): if (area_select=="object_area"):
self.png_area = "--export-area-drawing" self.png_area = "--export-area-drawing"
@ -573,5 +568,4 @@ class MyEffect(inkex.Effect):
(self.cut_select=="zip" ): (self.cut_select=="zip" ):
self.Make_PNG() self.Make_PNG()
if __name__ == '__main__': LYZExport().affect()
MyEffect().affect()

View File

@ -96,7 +96,7 @@ def errormsg(msg):
import inkex import inkex
... ...
inkex.errormsg(_("This extension requires two selected paths.")) inkex.errormsg("This extension requires two selected paths.")
""" """
#if isinstance(msg, unicode): #if isinstance(msg, unicode):
# sys.stderr.write(msg.encode("utf-8") + "\n") # sys.stderr.write(msg.encode("utf-8") + "\n")
@ -164,7 +164,7 @@ class Effect:
try: try:
stream = open(filename, 'r') stream = open(filename, 'r')
except IOError: except IOError:
errormsg(_("Unable to open specified file: %s") % filename) errormsg("Unable to open specified file: %s" % filename)
sys.exit() sys.exit()
# If it wasn't specified, try to open the file specified as # If it wasn't specified, try to open the file specified as
@ -173,7 +173,7 @@ class Effect:
try: try:
stream = open(self.svg_file, 'r') stream = open(self.svg_file, 'r')
except IOError: except IOError:
errormsg(_("Unable to open object member file: %s") % self.svg_file) errormsg("Unable to open object member file: %s" % self.svg_file)
sys.exit() sys.exit()
# Finally, if the filename was not specified anywhere, use # Finally, if the filename was not specified anywhere, use
@ -283,7 +283,7 @@ class Effect:
try: try:
retval = self.document.xpath(path, namespaces=NSS)[0] retval = self.document.xpath(path, namespaces=NSS)[0]
except: except:
errormsg(_("No matching node for expression: %s") % path) errormsg("No matching node for expression: %s" % path)
retval = None retval = None
return retval return retval
@ -342,7 +342,7 @@ class Effect:
if p: if p:
width = float(p.string[p.start():p.end()]) width = float(p.string[p.start():p.end()])
else: else:
errormsg(_("SVG Width not set correctly! Assuming width = 100")) errormsg("SVG Width not set correctly! Assuming width = 100")
if u: if u:
svgwidthunit = u.string[u.start():u.end()] svgwidthunit = u.string[u.start():u.end()]

View File

@ -81,7 +81,7 @@ class NextGenerator(inkex.base.TempDirMixin, inkex.base.InkscapeExtension):
# replace any attributes and other SVG content by the values from the CSV file # replace any attributes and other SVG content by the values from the CSV file
self.new_doc = self.new_doc.replace(svg_cont, row[key]) self.new_doc = self.new_doc.replace(svg_cont, row[key])
else: else:
inkex.errormsg(_("The replacements in the generated images may be incomplete. Please check your entry '{key}' in the field for the non-text values.").format(key=key)) inkex.errormsg("The replacements in the generated images may be incomplete. Please check your entry '{key}' in the field for the non-text values.").format(key=key)
if self.export(export_base_name) != True: if self.export(export_base_name) != True:
return return
@ -92,7 +92,7 @@ class NextGenerator(inkex.base.TempDirMixin, inkex.base.InkscapeExtension):
if os.path.exists(self.options.output_folder): if os.path.exists(self.options.output_folder):
export_file_path = os.path.join(self.options.output_folder, export_file_name) export_file_path = os.path.join(self.options.output_folder, export_file_name)
else: else:
inkex.errormsg(_("The selected output folder does not exist.")) inkex.errormsg("The selected output folder does not exist.")
return False return False

View File

@ -107,8 +107,8 @@ class PasteLengthEffect(inkex.Effect):
scaleFrom = scaleFrom) scaleFrom = scaleFrom)
selections[key].set('d', CubicSuperPath(cspath)) selections[key].set('d', CubicSuperPath(cspath))
else: else:
inkex.errormsg(_("Please select at least two paths, with the path whose \ inkex.errormsg("Please select at least two paths, with the path whose \
length is to be copied at the top. You may have to convert the shape \ length is to be copied at the top. You may have to convert the shape \
to path with path->Object to Path.")) to path with path->Object to Path.")
PasteLengthEffect().run() PasteLengthEffect().run()

View File

@ -117,7 +117,6 @@ import os
import sys import sys
import os.path import os.path
import inkex import inkex
import inkex.localization
import inkex.paths import inkex.paths
import inkex.bezier import inkex.bezier
from inkex.transforms import Transform from inkex.transforms import Transform
@ -1483,6 +1482,4 @@ module chamfer_sphere(rad=chamfer, res=chamfer_fn)
inkex.errmsg("STDERR: {}".format(stderr)) inkex.errmsg("STDERR: {}".format(stderr))
inkex.errormsg("= " * 24) inkex.errormsg("= " * 24)
OpenSCAD().run()
if __name__ == "__main__":
OpenSCAD().run()

View File

@ -22,8 +22,6 @@ from inkex import Transform
from inkex.paths import CubicSuperPath from inkex.paths import CubicSuperPath
from lxml import etree from lxml import etree
inkex.localization.localize
### Scale Ruler ### Scale Ruler
# inches = [1, 2, 4, 8, 16, 24, 32, 48, 64, 96, 128] # inches = [1, 2, 4, 8, 16, 24, 32, 48, 64, 96, 128]
# metric = [1,2,5,10,20,50,100,200,250,500,1000,1250,2500] # metric = [1,2,5,10,20,50,100,200,250,500,1000,1250,2500]
@ -169,7 +167,7 @@ class Realscale(inkex.Effect):
def effect(self): def effect(self):
if len(self.options.ids) != 2: if len(self.options.ids) != 2:
inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes.")) inkex.errormsg("This extension requires two selected objects. The first selected object must be the straight line with two nodes.")
exit() exit()
# drawing that will be scaled is selected second, must be a single object # drawing that will be scaled is selected second, must be a single object
@ -177,7 +175,7 @@ class Realscale(inkex.Effect):
drawing = self.svg.selected[self.options.ids[1]] drawing = self.svg.selected[self.options.ids[1]]
if scalepath.tag != inkex.addNS('path','svg'): if scalepath.tag != inkex.addNS('path','svg'):
inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")) inkex.errormsg("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")
exit() exit()
# apply its transforms to the scaling path, so we get the correct coordinates to calculate path length # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length
@ -185,7 +183,7 @@ class Realscale(inkex.Effect):
path = CubicSuperPath(scalepath.get('d')) path = CubicSuperPath(scalepath.get('d'))
if len(path) < 1 or len(path[0]) < 2: if len(path) < 1 or len(path[0]) < 2:
inkex.errormsg(_("This extension requires that the first selected path be two nodes long.")) inkex.errormsg("This extension requires that the first selected path be two nodes long.")
exit() exit()
# calculate path length # calculate path length

View File

@ -82,7 +82,7 @@ class SubdividePathEffect(inkex.Effect):
if(self.options.unit != 'perc' and self.options.unit != 'count'): if(self.options.unit != 'perc' and self.options.unit != 'count'):
maxL = self.options.maxLength * self.svg.unittouu('1'+self.options.unit) maxL = self.options.maxLength * self.svg.unittouu('1'+self.options.unit)
# ~ inkex.errormsg(_(str(maxL))) # ~ inkex.errormsg(str(maxL))
tolerance = 10 ** (-1 * self.options.precision) tolerance = 10 ** (-1 * self.options.precision)
selections = self.svg.selected selections = self.svg.selected

View File

@ -35,8 +35,6 @@ from inkex.paths import Path
from inkex import Transform from inkex import Transform
from math import * from math import *
from lxml import etree from lxml import etree
import gettext
_ = gettext.gettext
def poltocar(r, rad, negx=False, negy=False): def poltocar(r, rad, negx=False, negy=False):
# converts polar coords to cartesian # converts polar coords to cartesian
@ -108,7 +106,7 @@ def getPathData(obj):
def stockErrorMsg(bygtrac): def stockErrorMsg(bygtrac):
inkex.errormsg(_("Please select exactly two circles and try again! %s" % bygtrac)) inkex.errormsg("Please select exactly two circles and try again! %s" % bygtrac)
exit() exit()
class Tangent(inkex.Effect): class Tangent(inkex.Effect):
@ -218,5 +216,4 @@ class Tangent(inkex.Effect):
'd':'m '+str(llx1+conversionBottom[0])+','+str(lly1+conversionBottom[1])+' l '+str(ll2x2)+','+str(ll2y2)} 'd':'m '+str(llx1+conversionBottom[0])+','+str(lly1+conversionBottom[1])+' l '+str(ll2x2)+','+str(ll2y2)}
etree.SubElement(parent, inkex.addNS('path','svg'), attribsLine1 ) etree.SubElement(parent, inkex.addNS('path','svg'), attribsLine1 )
if __name__ == '__main__': Tangent().run()
Tangent().run()

View File

@ -5,8 +5,6 @@
import inkex import inkex
from lxml import etree from lxml import etree
import math import math
inkex.localization.localize
class Point(object): class Point(object):
def __init__(self, x, y): def __init__(self, x, y):
@ -30,9 +28,9 @@ class Point(object):
class Vpoint(Point): class Vpoint(Point):
''' '''
(x, y)座標と方向(rad)を持つ点 A point with (x, y) coordinates and direction (rad)
rad: 方向(真上: 0, : math.pi / 2, ..) rad: Direction (true up: 0, right: math.pi / 2, ...)
''' '''
def __init__(self, x, y, rad=0): def __init__(self, x, y, rad=0):
super(Vpoint, self).__init__(x, y) super(Vpoint, self).__init__(x, y)
@ -221,11 +219,11 @@ class Part1(object):
self.needle_tf = needle_tf self.needle_tf = needle_tf
self.needle_corner_rotation = needle_corner_rotation self.needle_corner_rotation = needle_corner_rotation
# グループ作成 # Group Creation
attr = {inkex.addNS('label', 'inkscape'): 'Part1'} attr = {inkex.addNS('label', 'inkscape'): 'Part1'}
self.g = etree.SubElement(self.parent, 'g', attr) self.g = etree.SubElement(self.parent, 'g', attr)
# 図形作成 # drawing
self.points_outline = self.create_points_outline() self.points_outline = self.create_points_outline()
self.svg_outline = SvgPart1Outline(self.g, self.points_outline, self.svg_outline = SvgPart1Outline(self.g, self.points_outline,
(self.bw * self.bf)) (self.bw * self.bf))
@ -241,9 +239,8 @@ class Part1(object):
self.svgs_needle_hole.append((svg_nh, v)) self.svgs_needle_hole.append((svg_nh, v))
def create_points_outline(self): def create_points_outline(self):
''' #Generate the coordinates of the outer frame
外枠の座標を生成
'''
points = [] points = []
(x0, y0) = (-(self.w2 / 2), 0) (x0, y0) = (-(self.w2 / 2), 0)
@ -294,7 +291,7 @@ class Part1(object):
a2 = self.d1 / math.tan(rad2a) a2 = self.d1 / math.tan(rad2a)
# #
# 頂点 # summit
# #
vpoints1 = [] vpoints1 = []
for i, p in enumerate(self.points_outline): for i, p in enumerate(self.points_outline):
@ -326,7 +323,7 @@ class Part1(object):
if i > 5: if i > 5:
break break
# 頂点を補完する点を生成 # Generate a point that completes a vertex
vpoints2 = [] vpoints2 = []
for i in range(len(vpoints1)-1): for i in range(len(vpoints1)-1):
d = vpoints1[i].distance(vpoints1[i+1]) d = vpoints1[i].distance(vpoints1[i+1])
@ -338,9 +335,8 @@ class Part1(object):
return vpoints2 return vpoints2
def split_vpoints(self, v1, v2, n): def split_vpoints(self, v1, v2, n):
''' #v1, v2 Generate a list by dividing the space between the two into n pieces
v1, v2間をn個に分割してリストを生成
'''
if n == 0: if n == 0:
return [v1] return [v1]
(dx, dy) = ((v2.x - v1.x) / n, (v2.y - v1.y) / n) (dx, dy) = ((v2.x - v1.x) / n, (v2.y - v1.y) / n)
@ -378,28 +374,25 @@ class Part2(object):
self.part1 = part1 self.part1 = part1
self.dia2 = dia2 self.dia2 = dia2
# グループ作成 # Group Creation
attr = {inkex.addNS('label', 'inkscape'): 'Part2'} attr = {inkex.addNS('label', 'inkscape'): 'Part2'}
self.g = etree.SubElement(self.parent, 'g', attr) self.g = etree.SubElement(self.parent, 'g', attr)
# 外枠 # outer frame > Mirroring the points_outline in Part1, and use the first six points.
# ``Part1``の``points_outline``をミラーして、
# 最初の6つのポイントを利用
self.points_outline = [] self.points_outline = []
for i in range(6): for i in range(6):
self.points_outline.append(self.part1.points_outline[i].mirror()) self.points_outline.append(self.part1.points_outline[i].mirror())
self.svg_outline = SvgPolygon(self.g, self.points_outline) self.svg_outline = SvgPolygon(self.g, self.points_outline)
# 留め具 # clasp
self.svg_hole = SvgCircle(self.g, self.dia2 / 2) self.svg_hole = SvgCircle(self.g, self.dia2 / 2)
# 針穴 # pinhole -> Mirroring the vpoints_needle in Part1
# ``Part1``の``vpoints_needle``をミラーして利用
self.svgs_needle_hole = [] self.svgs_needle_hole = []
for v in self.part1.vpoints_needle: for v in self.part1.vpoints_needle:
v.mirror() v.mirror()
# ``SvgNeedleHole``もミラーする # Mirror also SvgNeedleHole
svg_nh = SvgNeedleHole(self.g, svg_nh = SvgNeedleHole(self.g,
self.part1.needle_w, self.part1.needle_w,
self.part1.needle_h, self.part1.needle_h,
@ -473,7 +466,7 @@ class PliersCover(inkex.Effect):
# #
origin_vpoint = Vpoint(self.DEF_OFFSET_X, self.DEF_OFFSET_Y) origin_vpoint = Vpoint(self.DEF_OFFSET_X, self.DEF_OFFSET_Y)
# グループ作成 # Group Creation
attr = {inkex.addNS('label', 'inkscape'): 'PliersCover'} attr = {inkex.addNS('label', 'inkscape'): 'PliersCover'}
self.g = etree.SubElement(self.svg.get_current_layer(), 'g', attr) self.g = etree.SubElement(self.svg.get_current_layer(), 'g', attr)
@ -490,6 +483,4 @@ class PliersCover(inkex.Effect):
part2 = Part2(self.g, part1, opt.dia2) part2 = Part2(self.g, part1, opt.dia2)
part2.draw(origin_vpoint) part2.draw(origin_vpoint)
PliersCover().run()
if __name__ == '__main__':
PliersCover().run()

View File

@ -38,11 +38,8 @@ log10 = np.log10
pi = np.pi pi = np.pi
__version__ = '0.1' __version__ = '0.1'
inkex.localization.localize
def split(l, sizes): def split(l, sizes):
"""Split a list into sublists of specific sizes.""" """Split a list into sublists of specific sizes."""
if not sum(sizes) == len(l): if not sum(sizes) == len(l):
@ -273,5 +270,4 @@ class Travel(inkex.Effect):
attribs['d'] = str(Path(path)) attribs['d'] = str(Path(path))
obj_copy = etree.SubElement(group, obj.tag, attribs) obj_copy = etree.SubElement(group, obj.tag, attribs)
if __name__ == '__main__': Travel().run()
Travel().run()

View File

@ -11,16 +11,12 @@ Neon22 - github 2016
MIT license MIT license
''' '''
import inkex # Required import inkex
from lxml import etree from lxml import etree
from math import cos, sin, radians, pi from math import cos, sin, radians, pi
__version__ = '0.2' __version__ = '0.2'
inkex.localization.localize
### Helper functions
def point_on_circle(radius, angle): def point_on_circle(radius, angle):
" return xy coord of the point at distance radius from origin at angle " " return xy coord of the point at distance radius from origin at angle "
x = radius * cos(angle) x = radius * cos(angle)
@ -233,6 +229,4 @@ class Zoetrope(inkex.Effect):
text = etree.SubElement(templategroup, 'text', text_atts) text = etree.SubElement(templategroup, 'text', text_atts)
text.text = "At %d dpi. Image = %d x %d pixels" % (self.options.dpi, w, h) text.text = "At %d dpi. Image = %d x %d pixels" % (self.options.dpi, w, h)
if __name__ == '__main__': Zoetrope().run()
e = Zoetrope()
e.run()