Skip to content

Commit 7af0209

Browse files
authored
Merge pull request #4 from soukupak/inkscape10_compatibility
version 1.0 updates
2 parents 34f28eb + 2dc080b commit 7af0209

File tree

5 files changed

+62
-59
lines changed

5 files changed

+62
-59
lines changed

src/unicorn.inx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,18 @@ Note: Double-check the orientation of your axes when changing these values!</_pa
4949
- All text must be converted to paths.
5050
- Curves are approximated with line segments.
5151

52-
More Info: http://github.com/martymcguire/inkscape-unicorn/</_param>
52+
More Info: https://github.com/soukupak/inkscape-unicorn-for-marlin</_param>
5353
</page>
5454
</param>
5555

5656
<output>
5757
<extension>.gcode</extension>
5858
<mimetype>application/x-gcode</mimetype>
59-
<_filetypename>MakerBot Unicorn G-Code (*.gcode)</_filetypename>
60-
<_filetypetooltip>Toolpath for the MakerBot Unicorn Pen Plotter</_filetypetooltip>
59+
<_filetypename>Marlin G-Code (*.gcode)</_filetypename>
60+
<_filetypetooltip>Toolpath for marlin based pen plotter</_filetypetooltip>
6161
<dataloss>true</dataloss>
6262
</output>
6363
<script>
64-
<command reldir="extensions" interpreter="python">unicorn.py</command>
64+
<command location="inx" interpreter="python">unicorn.py</command>
6565
</script>
6666
</inkscape-extension>

src/unicorn.py

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,70 +23,53 @@
2323
from unicorn.context import GCodeContext
2424
from unicorn.svg_parser import SvgParser
2525

26+
#self.arg_parser.add_argument
27+
2628
class MyEffect(inkex.Effect):
2729
def __init__(self):
2830
inkex.Effect.__init__(self)
29-
self.OptionParser.add_option("--pen-up-angle",
30-
action="store", type="float",
31+
self.arg_parser.add_argument("--pen-up-angle", type=float,
3132
dest="pen_up_angle", default="50.0",
3233
help="Pen Up Angle")
33-
self.OptionParser.add_option("--pen-down-angle",
34-
action="store", type="float",
34+
self.arg_parser.add_argument("--pen-down-angle", type=float,
3535
dest="pen_down_angle", default="30.0",
3636
help="Pen Down Angle")
37-
self.OptionParser.add_option("--start-delay",
38-
action="store", type="float",
37+
self.arg_parser.add_argument("--start-delay", type=float,
3938
dest="start_delay", default="150.0",
4039
help="Delay after pen down command before movement in milliseconds")
41-
self.OptionParser.add_option("--stop-delay",
42-
action="store", type="float",
40+
self.arg_parser.add_argument("--stop-delay", type=float,
4341
dest="stop_delay", default="150.0",
4442
help="Delay after pen up command before movement in milliseconds")
45-
self.OptionParser.add_option("--xy-feedrate",
46-
action="store", type="float",
43+
self.arg_parser.add_argument("--xy-feedrate", type=float,
4744
dest="xy_feedrate", default="3500.0",
4845
help="XY axes feedrate in mm/min")
49-
self.OptionParser.add_option("--z-feedrate",
50-
action="store", type="float",
46+
self.arg_parser.add_argument("--z-feedrate", type=float,
5147
dest="z_feedrate", default="150.0",
5248
help="Z axis feedrate in mm/min")
53-
self.OptionParser.add_option("--z-height",
54-
action="store", type="float",
49+
self.arg_parser.add_argument("--z-height", type=float,
5550
dest="z_height", default="0.0",
5651
help="Z axis print height in mm")
57-
self.OptionParser.add_option("--finished-height",
58-
action="store", type="float",
52+
self.arg_parser.add_argument("--finished-height", type=float,
5953
dest="finished_height", default="0.0",
6054
help="Z axis height after printing in mm")
61-
self.OptionParser.add_option("--register-pen",
62-
action="store", type="string",
55+
self.arg_parser.add_argument("--register-pen", type=str,
6356
dest="register_pen", default="true",
6457
help="Add pen registration check(s)")
65-
self.OptionParser.add_option("--x-home",
66-
action="store", type="float",
58+
self.arg_parser.add_argument("--x-home", type=float,
6759
dest="x_home", default="0.0",
6860
help="Starting X position")
69-
self.OptionParser.add_option("--y-home",
70-
action="store", type="float",
61+
self.arg_parser.add_argument("--y-home", type=float,
7162
dest="y_home", default="0.0",
7263
help="Starting Y position")
73-
self.OptionParser.add_option("--num-copies",
74-
action="store", type="int",
64+
self.arg_parser.add_argument("--num-copies", type=int,
7565
dest="num_copies", default="1")
76-
self.OptionParser.add_option("--continuous",
77-
action="store", type="string",
66+
self.arg_parser.add_argument("--continuous", type=str,
7867
dest="continuous", default="false",
7968
help="Plot continuously until stopped.")
80-
self.OptionParser.add_option("--pause-on-layer-change",
81-
action="store", type="string",
69+
self.arg_parser.add_argument("--pause-on-layer-change", type=str,
8270
dest="pause_on_layer_change", default="false",
8371
help="Pause on layer changes.")
84-
self.OptionParser.add_option("--tab",
85-
action="store", type="string",
86-
dest="tab")
87-
88-
def output(self):
89-
self.context.generate()
72+
self.arg_parser.add_argument("--tab", type=str, dest="tab")
9073

9174
def effect(self):
9275
self.context = GCodeContext(self.options.xy_feedrate, self.options.z_feedrate,
@@ -97,12 +80,20 @@ def effect(self):
9780
self.options.register_pen,
9881
self.options.num_copies,
9982
self.options.continuous,
100-
self.svg_file)
83+
self.options.input_file)
10184
parser = SvgParser(self.document.getroot(), self.options.pause_on_layer_change)
10285
parser.parse()
10386
for entity in parser.entities:
10487
entity.get_gcode(self.context)
88+
89+
self.context.generate()
90+
MyEffect.save_raw(self, self.context.generate())
91+
92+
#self.save_raw(self, self.context.generate())
93+
94+
# def output(self):
95+
# self.context.generate()
96+
10597

10698
if __name__ == '__main__': #pragma: no cover
107-
e = MyEffect()
108-
e.affect()
99+
MyEffect().run()

src/unicorn/context.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ def generate(self):
106106
codesets.append(self.loop_forever)
107107
for codeset in codesets:
108108
for line in codeset:
109-
print line
109+
print(line)
110110
else:
111111
for p in range(0,self.num_pages):
112112
for codeset in codesets:
113113
for line in codeset:
114-
print line
114+
print(line)
115115
for line in self.postscript:
116-
print line
116+
print(line)
117117

118118
def start(self):
119119
self.codes.append("M400 (finish all movement)")

src/unicorn/entities.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
from math import cos, sin, radians
22
import pprint
3+
import warnings
34

45
class Entity:
6+
def __getattr__(self, name):
7+
''' will only get called for undefined attributes '''
8+
warnings.warn('No member "%s" contained in settings config.' % name)
9+
return ''
510
def get_gcode(self,context):
611
#raise NotImplementedError()
712
return "NIE"
@@ -86,4 +91,3 @@ def get_gcode(self,context):
8691
context.last = point
8792
context.stop()
8893
context.codes.append("")
89-

src/unicorn/svg_parser.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import inkex, cubicsuperpath, simplepath, simplestyle, cspsubdiv
1+
import inkex
22
from simpletransform import *
33
from bezmisc import *
4-
import entities
4+
from lxml import etree
5+
import unicorn.entities as entities
56
from math import radians
67
import sys, pprint
78

@@ -51,12 +52,12 @@ def subdivideCubicPath( sp, flat, i=1 ):
5152

5253
b = ( p0, p1, p2, p3 )
5354

54-
if cspsubdiv.maxdist( b ) > flat:
55+
if inkex.bezier.maxdist(b) > flat:
5556
break
5657

5758
i += 1
5859

59-
one, two = beziersplitatt( b, 0.5 )
60+
one, two = inkex.bezier.beziersplitatt( b, 0.5 )
6061
sp[i - 1][2] = one[1]
6162
sp[i][0] = two[2]
6263
p = [one[2], one[3], two[1]]
@@ -75,23 +76,25 @@ def get_gcode(self,context):
7576
class SvgPath(entities.PolyLine):
7677
def load(self, node, mat):
7778
d = node.get('d')
78-
if len(simplepath.parsePath(d)) == 0:
79+
80+
if(len(d) == 0):
7981
return
80-
p = cubicsuperpath.parsePath(d)
81-
applyTransformToPath(mat, p)
82+
83+
p = inkex.Path.to_superpath(d)
84+
p_transformed = p.transform(mat)
8285

8386
# p is now a list of lists of cubic beziers [ctrl p1, ctrl p2, endpoint]
8487
# where the start-point is the last point in the previous segment
8588
self.segments = []
86-
for sp in p:
89+
for sp in p_transformed:
8790
points = []
8891
subdivideCubicPath(sp,0.2) # TODO: smoothness preference
8992
for csp in sp:
9093
points.append((csp[1][0],csp[1][1]))
9194
self.segments.append(points)
9295

9396
def new_path_from_node(self, node):
94-
newpath = inkex.etree.Element(inkex.addNS('path','svg'))
97+
newpath = etree.Element(inkex.addNS('path','svg'))
9598
s = node.get('style')
9699
if s:
97100
newpath.set('style',s)
@@ -113,7 +116,7 @@ def load(self, node, mat):
113116
a.append([' l ', [0,h]])
114117
a.append([' l ', [-w,0]])
115118
a.append([' Z', []])
116-
newpath.set('d', simplepath.formatPath(a))
119+
newpath.set('d', formatPath(a))
117120
SvgPath.load(self,newpath,mat)
118121

119122
class SvgLine(SvgPath):
@@ -126,7 +129,7 @@ def load(self, node, mat):
126129
a = []
127130
a.append(['M ', [x1,y1]])
128131
a.append([' L ', [x2,y2]])
129-
newpath.set('d', simplepath.formatPath(a))
132+
newpath.set('d', formatPath(a))
130133
SvgPath.load(self,newpath,mat)
131134

132135
class SvgPolyLine(SvgPath):
@@ -264,7 +267,8 @@ def recursivelyTraverseSvg(self, nodeList,
264267
pass
265268

266269
# first apply the current matrix transform to this node's transform
267-
matNew = composeTransform(matCurrent, parseTransform(node.get("transform")))
270+
# matNew = composeTransform(matCurrent, parseTransform(node.get("transform")))
271+
matNew = inkex.Transform(matCurrent) * inkex.Transform(node.get("transform"))
268272

269273
if node.tag == inkex.addNS('g','svg') or node.tag == 'g':
270274
if (node.get(inkex.addNS('groupmode','inkscape')) == 'layer'):
@@ -283,7 +287,7 @@ def recursivelyTraverseSvg(self, nodeList,
283287
y = float(node.get('y','0'))
284288
# Note: the transform has already been applied
285289
if (x!=0) or (y!=0):
286-
matNew2 = composeTransform(matNew,parseTransform('translate(%f,%f)' % (x,y)))
290+
matNew2 = inkex.Transform(matNew) * inkex.Transform.add_translate(x,y)
287291
else:
288292
matNew2 = matNew
289293
v = node.get('visibility',v)
@@ -292,7 +296,7 @@ def recursivelyTraverseSvg(self, nodeList,
292296
pass
293297
else:
294298
pass
295-
elif not isinstance(node.tag, basestring):
299+
elif not isinstance(node.tag, str):
296300
pass
297301
else:
298302
entity = self.make_entity(node, matNew)
@@ -313,3 +317,7 @@ def make_entity(self,node,mat):
313317
self.entities.append(entity)
314318
return entity
315319
return None
320+
321+
def formatPath(a):
322+
"""Format SVG path data from an array"""
323+
return "".join([cmd + " ".join([str(p) for p in params]) for cmd, params in a])

0 commit comments

Comments
 (0)