diff options
Diffstat (limited to 'lib/stitch_plan')
| -rw-r--r-- | lib/stitch_plan/__init__.py | 7 | ||||
| -rw-r--r-- | lib/stitch_plan/color_block.py | 11 | ||||
| -rw-r--r-- | lib/stitch_plan/generate_stitch_plan.py | 74 | ||||
| -rw-r--r-- | lib/stitch_plan/stitch.py | 26 | ||||
| -rw-r--r-- | lib/stitch_plan/stitch_group.py | 4 | ||||
| -rw-r--r-- | lib/stitch_plan/stitch_plan.py | 33 | ||||
| -rw-r--r-- | lib/stitch_plan/ties.py | 2 |
7 files changed, 133 insertions, 24 deletions
diff --git a/lib/stitch_plan/__init__.py b/lib/stitch_plan/__init__.py index d4b43ace..9764e66a 100644 --- a/lib/stitch_plan/__init__.py +++ b/lib/stitch_plan/__init__.py @@ -3,8 +3,9 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from .stitch_plan import stitch_groups_to_stitch_plan, StitchPlan from .color_block import ColorBlock -from .stitch_group import StitchGroup -from .stitch import Stitch +from .generate_stitch_plan import generate_stitch_plan from .read_file import stitch_plan_from_file +from .stitch import Stitch +from .stitch_group import StitchGroup +from .stitch_plan import StitchPlan, stitch_groups_to_stitch_plan diff --git a/lib/stitch_plan/color_block.py b/lib/stitch_plan/color_block.py index 86edaff2..cd7b9c6d 100644 --- a/lib/stitch_plan/color_block.py +++ b/lib/stitch_plan/color_block.py @@ -63,6 +63,15 @@ class ColorBlock(object): return len(self.stitches) @property + def estimated_thread(self): + previous_stitch = self.stitches[0] + length = 0 + for stitch in self.stitches[1:]: + length += (stitch - previous_stitch).length() + previous_stitch = stitch + return length + + @property def num_trims(self): """Number of trims in this color block.""" @@ -119,7 +128,7 @@ class ColorBlock(object): raise ValueError("internal error: can't add a command to an empty stitch block") self.stitches.append(Stitch(*args, **kwargs)) if isinstance(args[0], Stitch): - self.stitches.append(args[0]) + self.stitches.append(Stitch(*args, **kwargs)) elif isinstance(args[0], Point): self.stitches.append(Stitch(args[0].x, args[0].y, *args[1:], **kwargs)) diff --git a/lib/stitch_plan/generate_stitch_plan.py b/lib/stitch_plan/generate_stitch_plan.py new file mode 100644 index 00000000..2d8ceeff --- /dev/null +++ b/lib/stitch_plan/generate_stitch_plan.py @@ -0,0 +1,74 @@ +# Authors: see git history +# +# Copyright (c) 2010 Authors +# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +import os +import sys + +import inkex + +import pyembroidery + +from ..i18n import _ +from ..svg import PIXELS_PER_MM, render_stitch_plan +from ..svg.tags import INKSCAPE_LABEL +from .stitch import Stitch +from .stitch_plan import StitchPlan + + +def generate_stitch_plan(embroidery_file, import_commands=True): # noqa: C901 + validate_file_path(embroidery_file) + pattern = pyembroidery.read(embroidery_file) + stitch_plan = StitchPlan() + color_block = None + + for raw_stitches, thread in pattern.get_as_colorblocks(): + color_block = stitch_plan.new_color_block(thread) + for x, y, command in raw_stitches: + if command == pyembroidery.STITCH: + color_block.add_stitch(Stitch(x * PIXELS_PER_MM / 10.0, y * PIXELS_PER_MM / 10.0)) + if len(color_block) > 0: + if not import_commands and command in [pyembroidery.TRIM, pyembroidery.STOP]: + # Importing commands is not wanted: + # start a new color block without inserting the command + color_block = stitch_plan.new_color_block(thread) + elif command == pyembroidery.TRIM: + color_block.add_stitch(trim=True) + elif command == pyembroidery.STOP: + color_block.add_stitch(stop=True) + color_block = stitch_plan.new_color_block(thread) + + stitch_plan.delete_empty_color_blocks() + + if stitch_plan.last_color_block: + if stitch_plan.last_color_block.last_stitch: + if stitch_plan.last_color_block.last_stitch.stop: + # ending with a STOP command is redundant, so remove it + del stitch_plan.last_color_block[-1] + + extents = stitch_plan.extents + svg = inkex.SvgDocumentElement("svg", nsmap=inkex.NSS, attrib={ + "width": str(extents[0] * 2), + "height": str(extents[1] * 2), + "viewBox": "0 0 %s %s" % (extents[0] * 2, extents[1] * 2), + }) + render_stitch_plan(svg, stitch_plan) + + # rename the Stitch Plan layer so that it doesn't get overwritten by Embroider + layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']") + layer.set(INKSCAPE_LABEL, os.path.basename(embroidery_file)) + layer.attrib.pop('id') + + # Shift the design so that its origin is at the center of the canvas + # Note: this is NOT the same as centering the design in the canvas! + layer.set('transform', 'translate(%s,%s)' % (extents[0], extents[1])) + + return svg + + +def validate_file_path(path): + # Check if the file exists + if not os.path.isfile(path): + inkex.errormsg(_('File does not exist and cannot be opened. Please correct the file path and try again.\r%s') % path) + sys.exit(1) diff --git a/lib/stitch_plan/stitch.py b/lib/stitch_plan/stitch.py index f163d09c..a4c50b60 100644 --- a/lib/stitch_plan/stitch.py +++ b/lib/stitch_plan/stitch.py @@ -10,7 +10,8 @@ from copy import deepcopy class Stitch(Point): """A stitch is a Point with extra information telling how to sew it.""" - def __init__(self, x, y=None, color=None, jump=False, stop=False, trim=False, color_change=False, tie_modus=0, no_ties=False, tags=None): + def __init__(self, x, y=None, color=None, jump=False, stop=False, trim=False, color_change=False, + tie_modus=0, force_lock_stitches=False, no_ties=False, tags=None): if isinstance(x, Stitch): # Allow creating a Stitch from another Stitch. Attributes passed as # arguments will override any existing attributes. @@ -28,6 +29,7 @@ class Stitch(Point): self.trim = trim self.stop = stop self.color_change = color_change + self.force_lock_stitches = force_lock_stitches self.tie_modus = tie_modus self.no_ties = no_ties self.tags = set() @@ -35,15 +37,16 @@ class Stitch(Point): self.add_tags(tags or []) def __repr__(self): - return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.x, - self.y, - self.color, - "JUMP" if self.jump else " ", - "TRIM" if self.trim else " ", - "STOP" if self.stop else " ", - "TIE MODUS" if self.tie_modus else " ", - "NO TIES" if self.no_ties else " ", - "COLOR CHANGE" if self.color_change else " ") + return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.x, + self.y, + self.color, + "JUMP" if self.jump else " ", + "TRIM" if self.trim else " ", + "STOP" if self.stop else " ", + "TIE MODUS" if self.tie_modus else " ", + "FORCE LOCK STITCHES" if self.force_lock_stitches else " ", + "NO TIES" if self.no_ties else " ", + "COLOR CHANGE" if self.color_change else " ") def add_tags(self, tags): for tag in tags: @@ -68,7 +71,8 @@ class Stitch(Point): return tag in self.tags def copy(self): - return Stitch(self.x, self.y, self.color, self.jump, self.stop, self.trim, self.color_change, self.tie_modus, self.no_ties, self.tags) + return Stitch(self.x, self.y, self.color, self.jump, self.stop, self.trim, self.color_change, + self.tie_modus, self.force_lock_stitches, self.no_ties, self.tags) def __json__(self): attributes = dict(vars(self)) diff --git a/lib/stitch_plan/stitch_group.py b/lib/stitch_plan/stitch_group.py index 98d9799e..21beebe1 100644 --- a/lib/stitch_plan/stitch_group.py +++ b/lib/stitch_plan/stitch_group.py @@ -17,11 +17,13 @@ class StitchGroup: between them by the stitch plan generation code. """ - def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False, tags=None): + def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, + tie_modus=0, force_lock_stitches=False, stitch_as_is=False, tags=None): self.color = color self.trim_after = trim_after self.stop_after = stop_after self.tie_modus = tie_modus + self.force_lock_stitches = force_lock_stitches self.stitch_as_is = stitch_as_is self.stitches = [] diff --git a/lib/stitch_plan/stitch_plan.py b/lib/stitch_plan/stitch_plan.py index 7e7621c1..4593781a 100644 --- a/lib/stitch_plan/stitch_plan.py +++ b/lib/stitch_plan/stitch_plan.py @@ -3,9 +3,14 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from .ties import add_ties -from .color_block import ColorBlock +from sys import exit + +from inkex import errormsg + +from ..i18n import _ from ..svg import PIXELS_PER_MM +from .color_block import ColorBlock +from .ties import add_ties def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=False): # noqa: C901 @@ -17,6 +22,11 @@ def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties= * adds jump-stitches between stitch_group if necessary """ + if not stitch_groups: + errormsg(_("There is no selected stitchable element. Please run " + "Extensions > Ink/Stitch > Troubleshoot > Troubleshoot objects in case you have expected a stitchout.")) + exit(1) + if collapse_len is None: collapse_len = 3.0 collapse_len = collapse_len * PIXELS_PER_MM @@ -40,12 +50,15 @@ def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties= color_block = stitch_plan.new_color_block(color=stitch_group.color) # always start a color with a JUMP to the first stitch position - color_block.add_stitch(stitch_group.stitches[0], jump=True) + color_block.add_stitch(stitch_group.stitches[0], jump=True, tie_modus=stitch_group.tie_modus) else: - if len(color_block) and (stitch_group.stitches[0] - color_block.stitches[-1]).length() > collapse_len: - color_block.add_stitch(stitch_group.stitches[0], jump=True) + if (len(color_block) and + ((stitch_group.stitches[0] - color_block.stitches[-1]).length() > collapse_len or + color_block.stitches[-1].force_lock_stitches)): + color_block.add_stitch(stitch_group.stitches[0], jump=True, tie_modus=stitch_group.tie_modus) - color_block.add_stitches(stitches=stitch_group.stitches, tie_modus=stitch_group.tie_modus, no_ties=stitch_group.stitch_as_is) + color_block.add_stitches(stitches=stitch_group.stitches, tie_modus=stitch_group.tie_modus, + force_lock_stitches=stitch_group.force_lock_stitches, no_ties=stitch_group.stitch_as_is) if stitch_group.trim_after: color_block.add_stitch(trim=True) @@ -110,7 +123,8 @@ class StitchPlan(object): num_stops=self.num_stops, num_trims=self.num_trims, num_stitches=self.num_stitches, - bounding_box=self.bounding_box + bounding_box=self.bounding_box, + estimated_thread=self.estimated_thread ) @property @@ -145,6 +159,11 @@ class StitchPlan(object): return minx, miny, maxx, maxy @property + def estimated_thread(self): + thread_meter = sum(block.estimated_thread for block in self) / PIXELS_PER_MM / 1000 + return round(thread_meter, 2) + + @property def dimensions(self): minx, miny, maxx, maxy = self.bounding_box return (maxx - minx, maxy - miny) diff --git a/lib/stitch_plan/ties.py b/lib/stitch_plan/ties.py index c649ee44..a95f9805 100644 --- a/lib/stitch_plan/ties.py +++ b/lib/stitch_plan/ties.py @@ -37,7 +37,7 @@ def add_tie(stitches, tie_path): def add_tie_off(stitches): # tie_modus: 0 = both | 1 = before | 2 = after | 3 = neither - if stitches[-1].tie_modus not in [1, 3]: + if stitches[-1].tie_modus not in [1, 3] or stitches[-1].force_lock_stitches: add_tie(stitches, stitches[-1:-3:-1]) |
