kopia lustrzana https://github.com/inkstitch/inkstitch
really fix "preserve order"
My previous fix didn't really do the job. It took patches in Z-order, but runs of patches of the same color were fed into the TSP algorithm and it could embroider them in whatever order it chose. This resulted in underlays for my fill regions being embroidered AFTER the fill. Now, the "preserve order" option has been changed to "preserve layers". Patches on different layers are gauranteed to be stitched in layer order. Patches of the same color within the same layer can be stitched in any order as chosen by the TSP algorithm.pull/1/head
rodzic
3e3d540089
commit
521be47402
|
@ -9,8 +9,9 @@
|
|||
<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="running_stitch_len_mm" type="float" min="0.1" max="100.0" _gui-text="Running 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="preserve_layers" type="boolean" _gui-text="Stitch layers in order" description="if false, sorts by color, which saves thread changes. True preserves layer order, important if you're laying colors over each other.">true</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>
|
||||
<param name="hide_layers" type="boolean" _gui-text="Hide other layers" description="Hide all other top-level layers when the embroidery layer is generated, in order to make stitching discernable.">true</param>
|
||||
<param name="add_preamble" type="optiongroup" _gui-text="Add preamble" appearance="minimal">
|
||||
<_option value="0">None</_option>
|
||||
<_option value="010">0-1-0</_option>
|
||||
|
|
77
embroider.py
77
embroider.py
|
@ -217,7 +217,7 @@ class PatchList:
|
|||
out = []
|
||||
lastPatch = None
|
||||
for patch in self.patches:
|
||||
if (lastPatch!=None and patch.color==lastPatch.color):
|
||||
if (lastPatch!=None and patch.sortorder==lastPatch.sortorder):
|
||||
out[-1].patches.append(patch)
|
||||
else:
|
||||
out.append(PatchList([patch]))
|
||||
|
@ -511,7 +511,7 @@ class EmbroideryObject:
|
|||
inkex.addNS('path', 'svg'),
|
||||
{ 'style':simplestyle.formatStyle(
|
||||
{ 'stroke': color if color is not None else '#000000',
|
||||
'stroke-width':str(self.row_spacing_px*0.5),
|
||||
'stroke-width':"1",
|
||||
'fill': 'none' }),
|
||||
'd':simplepath.formatPath(path),
|
||||
})
|
||||
|
@ -526,14 +526,14 @@ class EmbroideryObject:
|
|||
return (min(x), min(y), max(x), max(y))
|
||||
|
||||
class SortOrder:
|
||||
def __init__(self, threadcolor, stacking_order, preserve_order):
|
||||
def __init__(self, threadcolor, layer, preserve_layers):
|
||||
self.threadcolor = threadcolor
|
||||
if (preserve_order):
|
||||
dbg.write("preserve_order is true: %s %s\n" % (stacking_order, threadcolor));
|
||||
self.sorttuple = (stacking_order, threadcolor)
|
||||
if (preserve_layers):
|
||||
#dbg.write("preserve_layers is true: %s %s\n" % (layer, threadcolor));
|
||||
self.sorttuple = (layer, threadcolor)
|
||||
else:
|
||||
#dbg.write("preserve_order is false:\n");
|
||||
self.sorttuple = (threadcolor, stacking_order)
|
||||
#dbg.write("preserve_layers is false:\n");
|
||||
self.sorttuple = (threadcolor,)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.sorttuple, other.sorttuple)
|
||||
|
@ -570,16 +570,21 @@ class Embroider(inkex.Effect):
|
|||
action="store", type="float",
|
||||
dest="flat", default=0.1,
|
||||
help="Minimum flatness of the subdivided curves")
|
||||
self.OptionParser.add_option("-o", "--preserve_order",
|
||||
self.OptionParser.add_option("-o", "--preserve_layers",
|
||||
action="store", type="choice",
|
||||
choices=["true","false"],
|
||||
dest="preserve_order", default="false",
|
||||
dest="preserve_layers", default="false",
|
||||
help="Sort by stacking order instead of color")
|
||||
self.OptionParser.add_option("-H", "--hatch_filled_paths",
|
||||
action="store", type="choice",
|
||||
choices=["true","false"],
|
||||
dest="hatch_filled_paths", default="false",
|
||||
help="Use hatching lines instead of equally-spaced lines to fill paths")
|
||||
self.OptionParser.add_option("--hide_layers",
|
||||
action="store", type="choice",
|
||||
choices=["true","false"],
|
||||
dest="hide_layers", default="true",
|
||||
help="Hide all other layers when the embroidery layer is generated")
|
||||
self.OptionParser.add_option("-p", "--add_preamble",
|
||||
action="store", type="choice",
|
||||
choices=["0","010","01010","01210","012101210"],
|
||||
|
@ -595,10 +600,11 @@ class Embroider(inkex.Effect):
|
|||
dest="filename", default="embroider-output.exp",
|
||||
help="Name (and possibly path) of output file")
|
||||
self.patches = []
|
||||
self.stacking_order = {}
|
||||
self.layer_cache = {}
|
||||
|
||||
def get_sort_order(self, threadcolor, node):
|
||||
return SortOrder(threadcolor, self.stacking_order.get(node.get("id")), self.options.preserve_order=="true")
|
||||
#print >> sys.stderr, "node", node.get("id"), self.layer_cache.get(node.get("id"))
|
||||
return SortOrder(threadcolor, self.layer_cache.get(node.get("id")), self.options.preserve_layers=="true")
|
||||
|
||||
def process_one_path(self, node, shpath, threadcolor, sortorder, angle):
|
||||
#self.add_shapely_geo_to_svg(shpath.boundary, color="#c0c000")
|
||||
|
@ -732,15 +738,33 @@ class Embroider(inkex.Effect):
|
|||
return None
|
||||
return value
|
||||
|
||||
def cache_stacking_order(self):
|
||||
output = subprocess.check_output('inkscape --query-all "%s" 2>/dev/null' % self.args[-1], shell=True)
|
||||
def cache_layers(self):
|
||||
self.layer_cache = {}
|
||||
|
||||
ids = [line.split(',')[0] for line in output.splitlines()]
|
||||
self.stacking_order = {id: order for order, id in enumerate(ids)}
|
||||
layer_tag = inkex.addNS("g", "svg")
|
||||
group_attr = inkex.addNS('groupmode', 'inkscape')
|
||||
|
||||
|
||||
def is_layer(node):
|
||||
return node.tag == layer_tag and node.get(group_attr) == "layer"
|
||||
|
||||
def process(node, layer=0):
|
||||
if is_layer(node):
|
||||
layer += 1
|
||||
else:
|
||||
self.layer_cache[node.get("id")] = layer
|
||||
|
||||
for child in node:
|
||||
layer = process(child, layer)
|
||||
|
||||
return layer
|
||||
|
||||
process(self.document.getroot())
|
||||
|
||||
def effect(self):
|
||||
if self.options.preserve_order == "true":
|
||||
self.cache_stacking_order()
|
||||
if self.options.preserve_layers == "true":
|
||||
self.cache_layers()
|
||||
#print >> sys.stderr, "cached stacking order:", self.stacking_order
|
||||
|
||||
self.row_spacing_px = self.options.row_spacing_mm * pixels_per_millimeter
|
||||
self.zigzag_spacing_px = self.options.zigzag_spacing_mm * pixels_per_millimeter
|
||||
|
@ -761,15 +785,19 @@ class Embroider(inkex.Effect):
|
|||
self.patchList = self.patchList.tsp_by_color()
|
||||
#dbg.write("patch count: %d\n" % len(self.patchList.patches))
|
||||
|
||||
if self.options.hide_layers:
|
||||
self.hide_layers()
|
||||
|
||||
eo = EmbroideryObject(self.patchList, self.row_spacing_px)
|
||||
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,
|
||||
new_layer = inkex.etree.SubElement(self.document.getroot(),
|
||||
inkex.addNS('g', 'svg'), {})
|
||||
eo.emit_inkscape(new_group, emb)
|
||||
|
||||
self.emit_inkscape_bbox(new_group, eo)
|
||||
new_layer.set('id', self.uniqueId("embroidery"))
|
||||
new_layer.set(inkex.addNS('label', 'inkscape'), 'Embroidery')
|
||||
new_layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
|
||||
eo.emit_inkscape(new_layer, emb)
|
||||
|
||||
def emit_inkscape_bbox(self, parent, eo):
|
||||
(x0, y0, x1, y1) = eo.bbox()
|
||||
|
@ -788,6 +816,11 @@ class Embroider(inkex.Effect):
|
|||
'd':simplepath.formatPath(new_path),
|
||||
})
|
||||
|
||||
def hide_layers(self):
|
||||
for g in self.document.getroot().findall(inkex.addNS("g","svg")):
|
||||
if g.get(inkex.addNS("groupmode", "inkscape")) == "layer":
|
||||
g.set("style", "display:none")
|
||||
|
||||
def path_to_patch_list(self, node):
|
||||
threadcolor = simplestyle.parseStyle(node.get("style"))["stroke"]
|
||||
stroke_width_str = simplestyle.parseStyle(node.get("style"))["stroke-width"]
|
||||
|
|
Ładowanie…
Reference in New Issue