summaryrefslogtreecommitdiff
path: root/lib/stitch_plan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stitch_plan')
-rw-r--r--lib/stitch_plan/__init__.py7
-rw-r--r--lib/stitch_plan/color_block.py11
-rw-r--r--lib/stitch_plan/generate_stitch_plan.py74
-rw-r--r--lib/stitch_plan/stitch.py26
-rw-r--r--lib/stitch_plan/stitch_group.py4
-rw-r--r--lib/stitch_plan/stitch_plan.py33
-rw-r--r--lib/stitch_plan/ties.py2
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])