kopia lustrzana https://github.com/inkstitch/inkstitch
Make it work well for Franklin
Add Franklin G-Code target as output. Fix issue that filled area was treated as one patch per stitch. Don't autodetect orientation; let the user choose by orienting the object. Remove empty stitches. Base generated inkscape path on output from file. Allow maximum stitch length of 10 cm. Save debug output in /tmp. Disable almost all debugging. Let hatching connect the segments.pull/3/head
rodzic
58967a4681
commit
284e6e4d21
91
PyEmb.py
91
PyEmb.py
|
@ -4,11 +4,6 @@
|
|||
|
||||
import math
|
||||
import sys
|
||||
dbg = sys.stderr
|
||||
|
||||
def abs(x):
|
||||
if (x<0): return -x
|
||||
return x
|
||||
|
||||
class Point:
|
||||
def __init__(self, x, y):
|
||||
|
@ -50,7 +45,8 @@ class Embroidery:
|
|||
self.coords = []
|
||||
|
||||
def addStitch(self, coord):
|
||||
self.coords.append(coord)
|
||||
if len(self.coords) == 0 or self.coords[-1] != coord:
|
||||
self.coords.append(coord)
|
||||
|
||||
def translate_to_origin(self):
|
||||
if (len(self.coords)==0):
|
||||
|
@ -67,12 +63,13 @@ class Embroidery:
|
|||
for p in self.coords:
|
||||
p.x -= minx
|
||||
p.y -= miny
|
||||
dbg.write("Field size %s x %s\n" % (sx,sy))
|
||||
|
||||
def scale(self, sc):
|
||||
if not isinstance(sc, (tuple, list)):
|
||||
sc = (sc, sc)
|
||||
for p in self.coords:
|
||||
p.x *= sc
|
||||
p.y *= sc
|
||||
p.x *= sc[0]
|
||||
p.y *= sc[1]
|
||||
|
||||
def export_ksm(self, dbg):
|
||||
str = ""
|
||||
|
@ -104,7 +101,7 @@ class Embroidery:
|
|||
def export_melco(self, dbg):
|
||||
self.str = ""
|
||||
self.pos = self.coords[0]
|
||||
dbg.write("stitch count: %d\n" % len(self.coords))
|
||||
#dbg.write("stitch count: %d\n" % len(self.coords))
|
||||
lastColor = None
|
||||
numColors = 0x0
|
||||
for stitch in self.coords[1:]:
|
||||
|
@ -144,29 +141,59 @@ class Embroidery:
|
|||
self.pos = stitch
|
||||
return self.str
|
||||
|
||||
def export_csv(self, dbg):
|
||||
self.str = ""
|
||||
self.str += '"#","[THREAD_NUMBER]","[RED]","[GREEN]","[BLUE]","[DESCRIPTION]","[CATALOG_NUMBER]"\n'
|
||||
self.str += '"#","[STITCH_TYPE]","[X]","[Y]"\n'
|
||||
def export_csv(self, dbg):
|
||||
self.str = ""
|
||||
self.str += '"#","[THREAD_NUMBER]","[RED]","[GREEN]","[BLUE]","[DESCRIPTION]","[CATALOG_NUMBER]"\n'
|
||||
self.str += '"#","[STITCH_TYPE]","[X]","[Y]"\n'
|
||||
|
||||
lastColor = None
|
||||
colorIndex = 0
|
||||
for stitch in self.coords:
|
||||
if lastColor == None or stitch.color != lastColor:
|
||||
colorIndex += 1
|
||||
self.str += '"$","%d","%d","%d","%d","(null)","(null)"\n' % (
|
||||
colorIndex,
|
||||
int(stitch.color[1:3], 16),
|
||||
int(stitch.color[3:5], 16),
|
||||
int(stitch.color[5:7], 16))
|
||||
if stitch.jumpStitch:
|
||||
self.str += '"*","JUMP","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
if lastColor != None and stitch.color != lastColor:
|
||||
# not first color choice, add color change record
|
||||
self.str += '"*","COLOR","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
self.str += '"*","STITCH","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
lastColor = stitch.color
|
||||
return self.str
|
||||
lastColor = None
|
||||
colorIndex = 0
|
||||
for stitch in self.coords:
|
||||
if lastColor == None or stitch.color != lastColor:
|
||||
colorIndex += 1
|
||||
self.str += '"$","%d","%d","%d","%d","(null)","(null)"\n' % (
|
||||
colorIndex,
|
||||
int(stitch.color[1:3], 16),
|
||||
int(stitch.color[3:5], 16),
|
||||
int(stitch.color[5:7], 16))
|
||||
if stitch.jumpStitch:
|
||||
self.str += '"*","JUMP","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
if lastColor != None and stitch.color != lastColor:
|
||||
# not first color choice, add color change record
|
||||
self.str += '"*","COLOR","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
self.str += '"*","STITCH","%f","%f"\n' % (stitch.x/10, stitch.y/10)
|
||||
lastColor = stitch.color
|
||||
return self.str
|
||||
|
||||
def export_gcode(self, dbg):
|
||||
ret = []
|
||||
lastColor = None
|
||||
for stitch in self.coords:
|
||||
if stitch.color != lastColor:
|
||||
ret.append('M0 ;MSG, Color change; prepare for %s\n' % stitch.color)
|
||||
lastColor = stitch.color
|
||||
ret.append('G1 X%f Y%f\n' % stitch.as_tuple())
|
||||
ret.append('M0 ;MSG, EMBROIDER stitch\n')
|
||||
return ''.join(ret)
|
||||
|
||||
def export_paths(self, dbg):
|
||||
paths = []
|
||||
lastColor = None
|
||||
lastStitch = None
|
||||
for stitch in self.coords:
|
||||
if stitch.jumpStitch:
|
||||
if lastColor == stitch.color:
|
||||
paths.append([None, []])
|
||||
if lastStitch is not None:
|
||||
paths[-1][1].append(['M', lastStitch.as_tuple()])
|
||||
paths[-1][1].append(['L', stitch.as_tuple()])
|
||||
lastColor = None
|
||||
if stitch.color != lastColor:
|
||||
paths.append([stitch.color, []])
|
||||
paths[-1][1].append(['L' if len(paths[-1][1]) > 0 else 'M', stitch.as_tuple()])
|
||||
lastColor = stitch.color
|
||||
lastStitch = stitch
|
||||
return paths
|
||||
|
||||
class Test:
|
||||
def __init__(self):
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<dependency type="executable" location="extensions">inkex.py</dependency>
|
||||
<param name="zigzag_spacing_mm" type="float" min="0.01" max="5.00" precision="2" _gui-text="Zigzag spacing (mm)">1.00</param>
|
||||
<param name="row_spacing_mm" type="float" min="0.01" max="5.00" precision="2" _gui-text="Row spacing (mm)">0.40</param>
|
||||
<param name="max_stitch_len_mm" type="float" min="0.1" max="10.0" _gui-text="Maximum stitch length (mm)">3.0</param>
|
||||
<param name="max_stitch_len_mm" type="float" min="0.1" max="100.0" _gui-text="Maximum stitch length (mm)">3.0</param>
|
||||
<param name="collapse_len_mm" type="float" min="0.0" max="10.0" _gui-text="Maximum collapse length (mm)">0.0</param>
|
||||
<param name="preserve_order" type="boolean" _gui-text="Preserve stacking order" description="if false, sorts by color, which saves thread changes. True preserves stacking order, important if you're laying colors over each other.">false</param>
|
||||
<param name="hatch_filled_paths" type="boolean" _gui-text="Hatch filled paths" description="If false, filled paths are filled using equally-spaced lines. If true, filled paths are filled using hatching lines.">false</param>
|
||||
|
@ -20,6 +20,7 @@
|
|||
<param name="output_format" type="optiongroup" _gui-text="Output file format" appearance="minimal">
|
||||
<_option value="melco">Melco</_option>
|
||||
<_option value="csv">Embroidermodder 2 CSV</_option>
|
||||
<_option value="gcode">Franklin G-Code</_option>
|
||||
</param>
|
||||
<param name="filename" type="string" _gui-text="File">embroider-output.exp</param>
|
||||
<effect>
|
||||
|
|
169
embroider.py
169
embroider.py
|
@ -34,7 +34,7 @@ import lxml.etree as etree
|
|||
from lxml.builder import E
|
||||
import shapely.geometry as shgeo
|
||||
|
||||
dbg = open("embroider-debug.txt", "w")
|
||||
dbg = open("/tmp/embroider-debug.txt", "w")
|
||||
PyEmb.dbg = dbg
|
||||
pixels_per_millimeter = 90.0 / 25.4
|
||||
|
||||
|
@ -132,8 +132,8 @@ class PatchList:
|
|||
|
||||
def partition_by_color(self):
|
||||
self.sort_by_sortorder()
|
||||
dbg.write("Sorted by sortorder:\n");
|
||||
dbg.write(" %s\n" % ("\n".join(map(lambda p: str(p.sortorder), self.patches))))
|
||||
#dbg.write("Sorted by sortorder:\n");
|
||||
#dbg.write(" %s\n" % ("\n".join(map(lambda p: str(p.sortorder), self.patches))))
|
||||
out = []
|
||||
lastPatch = None
|
||||
for patch in self.patches:
|
||||
|
@ -142,7 +142,7 @@ class PatchList:
|
|||
else:
|
||||
out.append(PatchList([patch]))
|
||||
lastPatch = patch
|
||||
dbg.write("Emitted %s partitions\n" % len(out))
|
||||
#dbg.write("Emitted %s partitions\n" % len(out))
|
||||
return out
|
||||
|
||||
def tsp_by_color(self):
|
||||
|
@ -182,7 +182,7 @@ class PatchList:
|
|||
|
||||
def try_swap(self, i, j):
|
||||
# i,j are indices;
|
||||
dbg.write("swap(%d, %d)\n" % (i,j))
|
||||
#dbg.write("swap(%d, %d)\n" % (i,j))
|
||||
oldCost = (
|
||||
self.cost(self.get(i-1), self.get(i))
|
||||
+self.cost(self.get(i), self.get(i+1))
|
||||
|
@ -216,11 +216,11 @@ class PatchList:
|
|||
else:
|
||||
success = "."
|
||||
|
||||
dbg.write("old %5.1f new %5.1f savings: %5.1f\n" % (oldCost, cost, savings))
|
||||
#dbg.write("old %5.1f new %5.1f savings: %5.1f\n" % (oldCost, cost, savings))
|
||||
return success
|
||||
|
||||
def try_reverse(self, i):
|
||||
dbg.write("reverse(%d)\n" % i)
|
||||
#dbg.write("reverse(%d)\n" % i)
|
||||
oldCost = (self.cost(self.get(i-1), self.get(i))
|
||||
+self.cost(self.get(i), self.get(i+1)))
|
||||
reversed = self.get(i).reverse()
|
||||
|
@ -265,27 +265,19 @@ class PatchList:
|
|||
sortedPatchList = PatchList([])
|
||||
def takePatchStartingAtPoint(point):
|
||||
patch = point.patch
|
||||
dbg.write("takePatchStartingAtPoint angling for patch %s--%s\n" % (
|
||||
patch.stitches[0],
|
||||
patch.stitches[-1]))
|
||||
#dbg.write("takePatchStartingAtPoint angling for patch %s--%s\n" % (patch.stitches[0],patch.stitches[-1]))
|
||||
self.pointList = filter(lambda pt: pt.patch!=patch, self.pointList)
|
||||
reversed = ""
|
||||
if (point!=patch.stitches[0]):
|
||||
reversed = " (reversed)"
|
||||
dbg.write('patch.stitches[0] %s point %s match %s\n' % (
|
||||
patch.stitches[0],
|
||||
point,
|
||||
point==patch.stitches[0]))
|
||||
#dbg.write('patch.stitches[0] %s point %s match %s\n' % (patch.stitches[0], point, point==patch.stitches[0]))
|
||||
patch = patch.reverse()
|
||||
sortedPatchList.patches.append(patch)
|
||||
dbg.write('took patch %s--%s %s\n' % (
|
||||
patch.stitches[0],
|
||||
patch.stitches[-1],
|
||||
reversed))
|
||||
#dbg.write('took patch %s--%s %s\n' % (patch.stitches[0], patch.stitches[-1], reversed))
|
||||
|
||||
# Take the patch farthest from the centroid first
|
||||
# O(n)
|
||||
dbg.write('centroid: %s\n' % self.centroid)
|
||||
#dbg.write('centroid: %s\n' % self.centroid)
|
||||
def neg_distance_from_centroid(p):
|
||||
return -(p-self.centroid).length()
|
||||
farthestPoint = linear_min(self.pointList, neg_distance_from_centroid)
|
||||
|
@ -295,9 +287,9 @@ class PatchList:
|
|||
# Then greedily take closer-and-closer patches
|
||||
# O(n^2)
|
||||
while (len(self.pointList)>0):
|
||||
dbg.write('pass %s\n' % len(self.pointList));
|
||||
#dbg.write('pass %s\n' % len(self.pointList));
|
||||
last_point = sortedPatchList.patches[-1].stitches[-1]
|
||||
dbg.write('last_point now %s\n' % last_point)
|
||||
#dbg.write('last_point now %s\n' % last_point)
|
||||
def distance_from_last_point(p):
|
||||
return (p-last_point).length()
|
||||
nearestPoint = linear_min(self.pointList, distance_from_last_point)
|
||||
|
@ -308,7 +300,7 @@ class PatchList:
|
|||
|
||||
if (1):
|
||||
# Then hill-climb.
|
||||
dbg.write("len(self.patches) = %d\n" % len(self.patches))
|
||||
#dbg.write("len(self.patches) = %d\n" % len(self.patches))
|
||||
count = 0
|
||||
successStr = ""
|
||||
while (count < 100):
|
||||
|
@ -321,7 +313,7 @@ class PatchList:
|
|||
for i in range(len(self.patches)):
|
||||
successStr += self.try_reverse(i)
|
||||
|
||||
dbg.write("success: %s\n" % successStr)
|
||||
#dbg.write("success: %s\n" % successStr)
|
||||
|
||||
class EmbroideryObject:
|
||||
def __init__(self, patchList, row_spacing_px):
|
||||
|
@ -365,8 +357,8 @@ class EmbroideryObject:
|
|||
jumpStitch = True
|
||||
for stitch in patch.stitches:
|
||||
if lastStitch and lastColor == patch.color:
|
||||
c = math.sqrt((stitch.x - lastStitch.x) ** 2 + (stitch.y + lastStitch.y) ** 2)
|
||||
dbg.write("stitch length: %f (%d/%d -> %d/%d)\n" % (c, lastStitch.x, lastStitch.y, stitch.x, stitch.y))
|
||||
c = math.sqrt((stitch.x - lastStitch.x) ** 2 + (stitch.y - lastStitch.y) ** 2)
|
||||
#dbg.write("stitch length: %f (%d/%d -> %d/%d)\n" % (c, lastStitch.x, lastStitch.y, stitch.x, stitch.y))
|
||||
|
||||
if c == 0:
|
||||
# filter out duplicate successive stitches
|
||||
|
@ -376,10 +368,10 @@ class EmbroideryObject:
|
|||
if jumpStitch:
|
||||
# consider collapsing jump stich, if it is pretty short
|
||||
if c < collapse_len_px:
|
||||
dbg.write("... collapsed\n")
|
||||
#dbg.write("... collapsed\n")
|
||||
jumpStitch = False
|
||||
|
||||
dbg.write("stitch color %s\n" % patch.color)
|
||||
#dbg.write("stitch color %s\n" % patch.color)
|
||||
|
||||
newStitch = PyEmb.Point(stitch.x, -stitch.y)
|
||||
newStitch.color = patch.color
|
||||
|
@ -400,7 +392,7 @@ class EmbroideryObject:
|
|||
except IndexError:
|
||||
# happens when the patch is very short and we increment i beyond the number of stitches
|
||||
pass
|
||||
dbg.write("preamble locations: %s\n" % locs)
|
||||
#dbg.write("preamble locations: %s\n" % locs)
|
||||
|
||||
for j in add_preamble[1:]:
|
||||
try:
|
||||
|
@ -415,8 +407,8 @@ class EmbroideryObject:
|
|||
lastStitch = newStitch
|
||||
lastColor = patch.color
|
||||
|
||||
emb.translate_to_origin()
|
||||
emb.scale(10.0/pixels_per_millimeter)
|
||||
#emb.translate_to_origin()
|
||||
emb.scale(1.0/pixels_per_millimeter)
|
||||
|
||||
fp = open(filename, "wb")
|
||||
|
||||
|
@ -424,38 +416,23 @@ class EmbroideryObject:
|
|||
fp.write(emb.export_melco(dbg))
|
||||
elif output_format == "csv":
|
||||
fp.write(emb.export_csv(dbg))
|
||||
elif output_format == "gcode":
|
||||
fp.write(emb.export_gcode(dbg))
|
||||
fp.close()
|
||||
emb.scale(pixels_per_millimeter)
|
||||
return emb
|
||||
|
||||
def emit_inkscape(self, parent):
|
||||
lastPatch = None
|
||||
for patch in self.patchList.patches:
|
||||
if (lastPatch!=None):
|
||||
# draw jump stitch
|
||||
inkex.etree.SubElement(parent,
|
||||
inkex.addNS('path', 'svg'),
|
||||
{ 'style':simplestyle.formatStyle(
|
||||
{ 'stroke': lastPatch.color,
|
||||
'stroke-width':str(self.row_spacing_px*.25),
|
||||
'stroke-dasharray':'0.99, 1.98',
|
||||
'fill': 'none' }),
|
||||
'd':simplepath.formatPath([
|
||||
['M', (lastPatch.stitches[-1].as_tuple())],
|
||||
['L', (patch.stitches[0].as_tuple())]
|
||||
]),
|
||||
})
|
||||
lastPatch = patch
|
||||
|
||||
new_path = []
|
||||
new_path.append(['M', patch.stitches[0].as_tuple()])
|
||||
for stitch in patch.stitches[1:]:
|
||||
new_path.append(['L', stitch.as_tuple()])
|
||||
def emit_inkscape(self, parent, emb):
|
||||
emb.scale((1, -1));
|
||||
for color, path in emb.export_paths(dbg):
|
||||
dbg.write('path: %s %s\n' % (color, repr(path)))
|
||||
inkex.etree.SubElement(parent,
|
||||
inkex.addNS('path', 'svg'),
|
||||
{ 'style':simplestyle.formatStyle(
|
||||
{ 'stroke': patch.color,
|
||||
'stroke-width':str(self.row_spacing_px*0.25),
|
||||
{ 'stroke': color if color is not None else '#000000',
|
||||
'stroke-width':str(self.row_spacing_px*0.5),
|
||||
'fill': 'none' }),
|
||||
'd':simplepath.formatPath(new_path),
|
||||
'd':simplepath.formatPath(path),
|
||||
})
|
||||
|
||||
def bbox(self):
|
||||
|
@ -471,10 +448,10 @@ class SortOrder:
|
|||
def __init__(self, threadcolor, stacking_order, preserve_order):
|
||||
self.threadcolor = threadcolor
|
||||
if (preserve_order):
|
||||
dbg.write("preserve_order is true:\n");
|
||||
#dbg.write("preserve_order is true:\n");
|
||||
self.sorttuple = (stacking_order, threadcolor)
|
||||
else:
|
||||
dbg.write("preserve_order is false:\n");
|
||||
#dbg.write("preserve_order is false:\n");
|
||||
self.sorttuple = (threadcolor, stacking_order)
|
||||
|
||||
def __cmp__(self, other):
|
||||
|
@ -485,7 +462,7 @@ class SortOrder:
|
|||
|
||||
class Embroider(inkex.Effect):
|
||||
def __init__(self, *args, **kwargs):
|
||||
dbg.write("args: %s\n" % repr(sys.argv))
|
||||
#dbg.write("args: %s\n" % repr(sys.argv))
|
||||
inkex.Effect.__init__(self)
|
||||
self.stacking_order_counter = 0
|
||||
self.OptionParser.add_option("-r", "--row_spacing_mm",
|
||||
|
@ -525,7 +502,7 @@ class Embroider(inkex.Effect):
|
|||
help="Add preamble")
|
||||
self.OptionParser.add_option("-O", "--output_format",
|
||||
action="store", type="choice",
|
||||
choices=["melco", "csv"],
|
||||
choices=["melco", "csv", "gcode"],
|
||||
dest="output_format", default="melco",
|
||||
help="File output format")
|
||||
self.OptionParser.add_option("-F", "--filename",
|
||||
|
@ -560,53 +537,34 @@ class Embroider(inkex.Effect):
|
|||
beg = beg + one_stitch
|
||||
|
||||
swap = False
|
||||
patches = []
|
||||
patch = Patch(color=threadcolor,sortorder=sortorder)
|
||||
for (beg,end) in segments:
|
||||
patch = Patch(color=threadcolor,sortorder=sortorder)
|
||||
if (swap):
|
||||
(beg,end)=(end,beg)
|
||||
swap = not swap
|
||||
if not self.hatching:
|
||||
swap = not swap
|
||||
small_stitches(patch, PyEmb.Point(*beg),PyEmb.Point(*end))
|
||||
patches.append(patch)
|
||||
return patches
|
||||
return [patch]
|
||||
|
||||
def intersect_region_with_grating(self, shpath):
|
||||
dbg.write("bounds = %s\n" % str(shpath.bounds))
|
||||
#dbg.write("bounds = %s\n" % str(shpath.bounds))
|
||||
bbox = shpath.bounds
|
||||
hatching = self.options.hatch_filled_paths == "true"
|
||||
dbg.write("hatching is %s\n" % hatching)
|
||||
#dbg.write("hatching is %s\n" % hatching)
|
||||
|
||||
delta = self.row_spacing_px/2.0
|
||||
bbox_sz = (bbox[2]-bbox[0],bbox[3]-bbox[1])
|
||||
if (bbox_sz[0] > bbox_sz[1]):
|
||||
# wide box, use vertical stripes
|
||||
p0 = PyEmb.Point(bbox[0]-delta,bbox[1])
|
||||
p1 = PyEmb.Point(bbox[0]-delta,bbox[3])
|
||||
p_inc = PyEmb.Point(self.row_spacing_px, 0)
|
||||
count = (bbox[2]-bbox[0])/self.row_spacing_px + 2
|
||||
else:
|
||||
# narrow box, use horizontal stripes
|
||||
p0 = PyEmb.Point(bbox[0], bbox[1]-delta)
|
||||
p1 = PyEmb.Point(bbox[2], bbox[1]-delta)
|
||||
p_inc = PyEmb.Point(0, self.row_spacing_px)
|
||||
count = (bbox[3]-bbox[1])/self.row_spacing_px + 2
|
||||
|
||||
if hatching:
|
||||
count *= 2
|
||||
p0 = PyEmb.Point(bbox[0]-delta,bbox[1])
|
||||
p1 = PyEmb.Point(bbox[0]-delta,bbox[3])
|
||||
p_inc = PyEmb.Point(self.row_spacing_px, 0)
|
||||
count = (bbox[2]-bbox[0])/self.row_spacing_px + 2
|
||||
|
||||
rows = []
|
||||
steps = 0
|
||||
while (steps < count):
|
||||
try:
|
||||
steps += 1
|
||||
if hatching:
|
||||
if steps % 2 == 1:
|
||||
p1 += p_inc
|
||||
else:
|
||||
p0 += p_inc
|
||||
else:
|
||||
p0 += p_inc
|
||||
p1 += p_inc
|
||||
p0 += p_inc
|
||||
p1 += p_inc
|
||||
endpoints = [p0.as_tuple(), p1.as_tuple()]
|
||||
shline = shgeo.LineString(endpoints)
|
||||
res = shline.intersection(shpath)
|
||||
|
@ -614,6 +572,8 @@ class Embroider(inkex.Effect):
|
|||
runs = map(shapelyLineSegmentToPyTuple, res.geoms)
|
||||
else:
|
||||
runs = [shapelyLineSegmentToPyTuple(res)]
|
||||
if self.hatching and len(rows) > 0:
|
||||
rows.append([(rows[-1][0][1], runs[0][0])])
|
||||
rows.append(runs)
|
||||
except Exception, ex:
|
||||
dbg.write("--------------\n")
|
||||
|
@ -649,13 +609,13 @@ class Embroider(inkex.Effect):
|
|||
def handle_node(self, node):
|
||||
|
||||
if (node.tag != self.svgpath):
|
||||
dbg.write("%s\n"%str((id, etree.tostring(node, pretty_print=True))))
|
||||
dbg.write("not a path; recursing:\n")
|
||||
#dbg.write("%s\n"%str((id, etree.tostring(node, pretty_print=True))))
|
||||
#dbg.write("not a path; recursing:\n")
|
||||
for child in node.iter(self.svgpath):
|
||||
self.handle_node(child)
|
||||
return
|
||||
|
||||
dbg.write("Node: %s\n"%str((id, etree.tostring(node, pretty_print=True))))
|
||||
#dbg.write("Node: %s\n"%str((id, etree.tostring(node, pretty_print=True))))
|
||||
|
||||
israw = False
|
||||
desc = node.findtext(inkex.addNS('desc', 'svg'))
|
||||
|
@ -683,6 +643,7 @@ class Embroider(inkex.Effect):
|
|||
self.zigzag_spacing_px = self.options.zigzag_spacing_mm * pixels_per_millimeter
|
||||
self.max_stitch_len_px = self.options.max_stitch_len_mm*pixels_per_millimeter
|
||||
self.collapse_len_px = self.options.collapse_len_mm*pixels_per_millimeter
|
||||
self.hatching = self.options.hatch_filled_paths == "true"
|
||||
|
||||
self.svgpath = inkex.addNS('path', 'svg')
|
||||
self.patchList = PatchList([])
|
||||
|
@ -690,15 +651,15 @@ class Embroider(inkex.Effect):
|
|||
self.handle_node(node)
|
||||
|
||||
self.patchList = self.patchList.tsp_by_color()
|
||||
dbg.write("patch count: %d\n" % len(self.patchList.patches))
|
||||
#dbg.write("patch count: %d\n" % len(self.patchList.patches))
|
||||
|
||||
eo = EmbroideryObject(self.patchList, self.row_spacing_px)
|
||||
eo.emit_file(self.options.filename, self.options.output_format,
|
||||
emb = eo.emit_file(self.options.filename, self.options.output_format,
|
||||
self.collapse_len_px, self.options.add_preamble)
|
||||
|
||||
new_group = inkex.etree.SubElement(self.current_layer,
|
||||
inkex.addNS('g', 'svg'), {})
|
||||
eo.emit_inkscape(new_group)
|
||||
eo.emit_inkscape(new_group, emb)
|
||||
|
||||
self.emit_inkscape_bbox(new_group, eo)
|
||||
|
||||
|
@ -727,8 +688,8 @@ class Embroider(inkex.Effect):
|
|||
# but let's hope px are kind of like pts?
|
||||
stroke_width_str = stroke_width_str[:-2]
|
||||
stroke_width = float(stroke_width_str)
|
||||
dbg.write("stroke_width is <%s>\n" % repr(stroke_width))
|
||||
dbg.flush()
|
||||
#dbg.write("stroke_width is <%s>\n" % repr(stroke_width))
|
||||
#dbg.flush()
|
||||
sortorder = self.get_sort_order(threadcolor)
|
||||
path = simplepath.parsePath(node.get("d"))
|
||||
|
||||
|
@ -742,7 +703,7 @@ class Embroider(inkex.Effect):
|
|||
def flush_point_list():
|
||||
STROKE_MIN = 0.5 # a 0.5pt stroke becomes a straight line.
|
||||
if (stroke_width <= STROKE_MIN):
|
||||
dbg.write("self.max_stitch_len_px = %s\n" % self.max_stitch_len_px)
|
||||
#dbg.write("self.max_stitch_len_px = %s\n" % self.max_stitch_len_px)
|
||||
patch = self.stroke_points(emb_point_list, self.max_stitch_len_px, 0.0, threadcolor, sortorder)
|
||||
else:
|
||||
patch = self.stroke_points(emb_point_list, self.zigzag_spacing_px*0.5, stroke_width, threadcolor, sortorder)
|
||||
|
@ -750,13 +711,13 @@ class Embroider(inkex.Effect):
|
|||
|
||||
close_point = None
|
||||
for (type,points) in path:
|
||||
dbg.write("path_to_patch_list parses pt %s with type=%s\n" % (points, type))
|
||||
#dbg.write("path_to_patch_list parses pt %s with type=%s\n" % (points, type))
|
||||
if type == 'M' and len(emb_point_list):
|
||||
flush_point_list()
|
||||
emb_point_list = []
|
||||
|
||||
if type == 'Z':
|
||||
dbg.write("... closing patch to %s\n" % close_point)
|
||||
#dbg.write("... closing patch to %s\n" % close_point)
|
||||
emb_point_list.append(close_point)
|
||||
else:
|
||||
pointscopy = list(points)
|
||||
|
@ -764,7 +725,7 @@ class Embroider(inkex.Effect):
|
|||
emb_point_list.append(PyEmb.Point(pointscopy[0], pointscopy[1]))
|
||||
pointscopy = pointscopy[2:]
|
||||
if type == 'M':
|
||||
dbg.write("latching close_point %s\n" % emb_point_list[-1])
|
||||
#dbg.write("latching close_point %s\n" % emb_point_list[-1])
|
||||
close_point = emb_point_list[-1]
|
||||
|
||||
flush_point_list()
|
||||
|
@ -818,7 +779,7 @@ if __name__ == '__main__':
|
|||
sys.setrecursionlimit(100000);
|
||||
e = Embroider()
|
||||
e.affect()
|
||||
dbg.write("aaaand, I'm done. seeeya!\n")
|
||||
#dbg.write("aaaand, I'm done. seeeya!\n")
|
||||
dbg.flush()
|
||||
|
||||
dbg.close()
|
||||
|
|
Ładowanie…
Reference in New Issue