diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2019-07-27 15:48:50 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-27 15:48:50 -0400 |
| commit | 833a8a971d8a73fbc42468a89d083e37a0bd6d8d (patch) | |
| tree | 4c38fd49d7cf813a2df1d07dbd32160d0e36373f | |
| parent | 03af8b37276870efd97f7049ced006f6e01ef935 (diff) | |
| parent | 7ce4387ff6f8d4302ff374921d0b93b7b491b9a5 (diff) | |
Merge pull request #487 from inkstitch/no_import_jumps
remove additional jump stitches on import
| -rw-r--r-- | lib/commands.py | 4 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 12 | ||||
| -rw-r--r-- | lib/extensions/input.py | 19 | ||||
| -rw-r--r-- | lib/extensions/layer_commands.py | 2 | ||||
| -rw-r--r-- | lib/stitch_plan/stitch_plan.py | 8 | ||||
| -rw-r--r-- | lib/svg/rendering.py | 40 |
6 files changed, 55 insertions, 30 deletions
diff --git a/lib/commands.py b/lib/commands.py index 8e35d7ee..c735185f 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -289,6 +289,10 @@ def add_connector(document, symbol, element): start_pos = (symbol.get('x'), symbol.get('y')) end_pos = element.shape.centroid + # Make sure the element's XML node has an id so that we can reference it. + if element.node.get('id') is None: + element.node.set('id', generate_unique_id(document, "object")) + path = inkex.etree.Element(SVG_PATH_TAG, { "id": generate_unique_id(document, "connector"), diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 3ae2b143..e0a0aacc 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -1,11 +1,13 @@ import sys + import shapely.geometry -from .element import param, EmbroideryElement, Patch from ..i18n import _ -from ..utils import cache, Point from ..stitches import running_stitch, bean_stitch from ..svg import parse_length_with_units +from ..utils import cache, Point +from .element import param, EmbroideryElement, Patch + warned_about_legacy_running_stitch = False @@ -85,7 +87,11 @@ class Stroke(EmbroideryElement): @cache def shape(self): line_strings = [shapely.geometry.LineString(path) for path in self.paths] - return shapely.geometry.MultiLineString(line_strings) + + # Using convex_hull here is an important optimization. Otherwise + # complex paths cause operations on the shape to take a long time. + # This especially happens when importing machine embroidery files. + return shapely.geometry.MultiLineString(line_strings).convex_hull @property @param('manual_stitch', diff --git a/lib/extensions/input.py b/lib/extensions/input.py index 0ca85df5..a82cdfca 100644 --- a/lib/extensions/input.py +++ b/lib/extensions/input.py @@ -1,27 +1,36 @@ import os +import pyembroidery + from inkex import etree import inkex -import pyembroidery +from ..stitch_plan import StitchPlan from ..svg import PIXELS_PER_MM, render_stitch_plan from ..svg.tags import INKSCAPE_LABEL -from ..stitch_plan import StitchPlan class Input(object): def affect(self, args): embroidery_file = args[0] pattern = pyembroidery.read(embroidery_file) + pattern = pattern.get_pattern_interpolate_trim(3) stitch_plan = StitchPlan() color_block = None for raw_stitches, thread in pattern.get_as_colorblocks(): color_block = stitch_plan.new_color_block(thread) + trim_after = False for x, y, command in raw_stitches: - color_block.add_stitch(x * PIXELS_PER_MM / 10.0, y * PIXELS_PER_MM / 10.0, - jump=(command == pyembroidery.JUMP), - trim=(command == pyembroidery.TRIM)) + if command == pyembroidery.STITCH: + if trim_after: + color_block.add_stitch(trim=True) + trim_after = False + color_block.add_stitch(x * PIXELS_PER_MM / 10.0, y * PIXELS_PER_MM / 10.0) + if len(color_block) > 0 and command == pyembroidery.TRIM: + trim_after = True + + stitch_plan.delete_empty_color_blocks() extents = stitch_plan.extents svg = etree.Element("svg", nsmap=inkex.NSS, attrib={ diff --git a/lib/extensions/layer_commands.py b/lib/extensions/layer_commands.py index c124ec95..e710e351 100644 --- a/lib/extensions/layer_commands.py +++ b/lib/extensions/layer_commands.py @@ -21,7 +21,7 @@ class LayerCommands(CommandsExtension): correction_transform = get_correction_transform(self.current_layer, child=True) for i, command in enumerate(commands): - ensure_symbol(command) + ensure_symbol(self.document, command) inkex.etree.SubElement(self.current_layer, SVG_USE_TAG, { diff --git a/lib/stitch_plan/stitch_plan.py b/lib/stitch_plan/stitch_plan.py index 8e84db4d..b621ef07 100644 --- a/lib/stitch_plan/stitch_plan.py +++ b/lib/stitch_plan/stitch_plan.py @@ -70,6 +70,14 @@ class StitchPlan(object): self.color_blocks.append(color_block) return color_block + def delete_empty_color_blocks(self): + color_blocks = [] + for color_block in self.color_blocks: + if len(color_block) > 0: + color_blocks.append(color_block) + + self.color_blocks = color_blocks + def add_color_block(self, color_block): self.color_blocks.append(color_block) diff --git a/lib/svg/rendering.py b/lib/svg/rendering.py index 41ed53d7..532748bf 100644 --- a/lib/svg/rendering.py +++ b/lib/svg/rendering.py @@ -167,9 +167,7 @@ def get_correction_transform(svg): return transform -def color_block_to_realistic_stitches(color_block, svg): - paths = [] - +def color_block_to_realistic_stitches(color_block, svg, destination): for point_list in color_block_to_point_lists(color_block): if not point_list: continue @@ -177,7 +175,7 @@ def color_block_to_realistic_stitches(color_block, svg): color = color_block.color.visible_on_white.darker.to_hex_str() start = point_list[0] for point in point_list[1:]: - paths.append(inkex.etree.Element( + destination.append(inkex.etree.Element( SVG_PATH_TAG, {'style': simplestyle.formatStyle( { @@ -190,16 +188,23 @@ def color_block_to_realistic_stitches(color_block, svg): })) start = point - return paths - -def color_block_to_paths(color_block, svg): - paths = [] +def color_block_to_paths(color_block, svg, destination): # We could emit just a single path with one subpath per point list, but # emitting multiple paths makes it easier for the user to manipulate them. + first = True for point_list in color_block_to_point_lists(color_block): + if first: + first = False + else: + # If we try to import these above, we get into a mess of circular + # imports. + from ..commands import add_commands + from ..elements.stroke import Stroke + add_commands(Stroke(destination[-1]), ["trim"]) + color = color_block.color.visible_on_white.to_hex_str() - paths.append(inkex.etree.Element( + destination.append(inkex.etree.Element( SVG_PATH_TAG, {'style': simplestyle.formatStyle( {'stroke': color, @@ -207,16 +212,9 @@ def color_block_to_paths(color_block, svg): 'fill': 'none'}), 'd': "M" + " ".join(" ".join(str(coord) for coord in point) for point in point_list), 'transform': get_correction_transform(svg), - 'embroider_manual_stitch': 'true', - 'embroider_trim_after': 'true', + 'embroider_manual_stitch': 'true' })) - # no need to trim at the end of a thread color - if paths: - paths[-1].attrib.pop('embroider_trim_after') - - return paths - def render_stitch_plan(svg, stitch_plan, realistic=False): layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']") @@ -232,17 +230,17 @@ def render_stitch_plan(svg, stitch_plan, realistic=False): # make sure the layer is visible layer.set('style', 'display:inline') + svg.append(layer) + for i, color_block in enumerate(stitch_plan): group = inkex.etree.SubElement(layer, SVG_GROUP_TAG, {'id': '__color_block_%d__' % i, INKSCAPE_LABEL: "color block %d" % (i + 1)}) if realistic: - group.extend(color_block_to_realistic_stitches(color_block, svg)) + color_block_to_realistic_stitches(color_block, svg, group) else: - group.extend(color_block_to_paths(color_block, svg)) - - svg.append(layer) + color_block_to_paths(color_block, svg, group) if realistic: defs = svg.find(SVG_DEFS_TAG) |
