From 1adfa87a68be6bcc92d9521b97ab59dc022ab3be Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 22 Jun 2021 20:04:39 +0200 Subject: satin pattern and split stitch --- lib/elements/satin_column.py | 98 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 778fc88a..3f5f05e5 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -12,7 +12,8 @@ from shapely import geometry as shgeo from shapely.ops import nearest_points from ..i18n import _ -from ..svg import line_strings_to_csp, point_lists_to_csp +from ..svg import (PIXELS_PER_MM, apply_transforms, line_strings_to_csp, + point_lists_to_csp) from ..utils import Point, cache, collapse_duplicate_point, cut from .element import EmbroideryElement, Patch, param from .validation import ValidationError, ValidationWarning @@ -74,12 +75,31 @@ class SatinColumn(EmbroideryElement): def satin_column(self): return self.get_boolean_param("satin_column") + # I18N: Split stitch divides a satin column into equal with parts if the maximum stitch length is exceeded + @property + @param('split_stitch', + _('Split stitch'), + tooltip=_('Sets additional stitches if the satin column exceeds the maximum stitch length.'), + type='boolean', + default='false') + def split_stitch(self): + return self.get_boolean_param("split_stitch") + # I18N: "E" stitch is so named because it looks like the letter E. @property @param('e_stitch', _('"E" stitch'), type='boolean', default='false') def e_stitch(self): return self.get_boolean_param("e_stitch") + @property + @param('max_stitch_length_mm', + _('Maximum stitch length'), + tooltip=_('Maximum stitch length for split stitches.'), + type='float', unit="mm", + default=12.1) + def max_stitch_length(self): + return max(self.get_float_param("max_stitch_length_mm", 12.4), 0.1 * PIXELS_PER_MM) + @property def color(self): return self.get_style("stroke") @@ -556,6 +576,20 @@ class SatinColumn(EmbroideryElement): return SatinColumn(node) + def get_patterns(self): + xpath = ".//*[@inkstitch:pattern='%(id)s']" % dict(id=self.node.get('id')) + patterns = self.node.getroottree().getroot().xpath(xpath) + line_strings = [] + for pattern in patterns: + d = pattern.get_path() + path = paths.Path(d).to_superpath() + path = apply_transforms(path, pattern) + path = self.flatten(path) + lines = [shgeo.LineString(p) for p in path] + for line in lines: + line_strings.append(line) + return shgeo.MultiLineString(line_strings) + @property @cache def center_line(self): @@ -787,6 +821,63 @@ class SatinColumn(EmbroideryElement): return patch + def do_pattern_satin(self, patterns): + # elements with the attribute 'inkstitch:pattern' set to this elements id will cause extra stitches to be added + patch = Patch(color=self.color) + sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) + for i, (left, right) in enumerate(zip(*sides)): + patch.add_stitch(left) + for point in self._get_pattern_points(left, right, patterns): + patch.add_stitch(point) + patch.add_stitch(right) + if not i+1 >= len(sides[0]): + for point in self._get_pattern_points(right, sides[0][i+1], patterns): + patch.add_stitch(point) + return patch + + def do_split_stitch(self): + # stitches exceeding the maximum stitch length will be divided into equal parts through additional stitches + patch = Patch(color=self.color) + sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) + for i, (left, right) in enumerate(zip(*sides)): + patch.add_stitch(left) + points, count = self._get_split_points(left, right) + for point in points: + patch.add_stitch(point) + patch.add_stitch(right) + # it is possible that the way back has a different length from the first + # but it looks ugly if the points differ too much + # so let's make sure they have at least the same amount of divisions + if not i+1 >= len(sides[0]): + points, count = self._get_split_points(right, sides[0][i+1], count) + for point in points: + patch.add_stitch(point) + + return patch + + def _get_pattern_points(self, left, right, patterns): + points = [] + for pattern in patterns: + intersection = shgeo.LineString([left, right]).intersection(pattern) + if isinstance(intersection, shgeo.Point): + points.append(Point(intersection.x, intersection.y)) + if isinstance(intersection, shgeo.MultiPoint): + for point in intersection: + points.append(Point(point.x, point.y)) + # sort points after their distance to left + points.sort(key=lambda point: point.distance(left)) + return points + + def _get_split_points(self, left, right, count=None): + points = [] + distance = left.distance(right) + split_count = count or int(distance / self.max_stitch_length) + for i in range(split_count): + line = shgeo.LineString((left, right)) + split_point = line.interpolate((i+1)/split_count, normalized=True) + points.append(Point(split_point.x, split_point.y)) + return [points, split_count] + def to_patches(self, last_patch): # Stitch a variable-width satin column, zig-zagging between two paths. @@ -807,8 +898,13 @@ class SatinColumn(EmbroideryElement): # zigzags sit on the contour walk underlay like rail ties on rails. patch += self.do_zigzag_underlay() + patterns = self.get_patterns() if self.e_stitch: patch += self.do_e_stitch() + elif self.split_stitch: + patch += self.do_split_stitch() + elif self.get_patterns(): + patch += self.do_pattern_satin(patterns) else: patch += self.do_satin() -- cgit v1.2.3 From d6df8084f4a0fe8c8e174ea230d158512bd8f094 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Thu, 24 Jun 2021 22:25:13 +0200 Subject: add start markers, add troubleshoot pattern warning and fix wxpython language issue --- lib/elements/pattern.py | 32 ++++++++++++++++++++++++++++++++ lib/elements/utils.py | 8 ++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 lib/elements/pattern.py (limited to 'lib/elements') diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py new file mode 100644 index 00000000..98f29456 --- /dev/null +++ b/lib/elements/pattern.py @@ -0,0 +1,32 @@ +# 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 inkex + +from ..i18n import _ +from .element import EmbroideryElement +from .validation import ObjectTypeWarning + + +class PatternWarning(ObjectTypeWarning): + name = _("Pattern Element") + description = _("This element will only be stitched out as a pattern within the specified object.") + steps_to_solve = [ + _("If you want to remove the pattern configuration for a pattern object follow these steps:"), + _("* Select pattern element(s)"), + _('* Run Extensions > Ink/Stitch > Troubleshoot > Remove embroidery settings...'), + _('* Make sure "Remove params" is enables'), + _('* Click "Apply"') + ] + + +class PatternObject(EmbroideryElement): + + def validation_warnings(self): + repr_point = next(inkex.Path(self.parse_path()).end_points) + yield PatternWarning(repr_point) + + def to_patches(self, last_patch): + return [] diff --git a/lib/elements/utils.py b/lib/elements/utils.py index aceab485..03ea48d4 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -4,14 +4,15 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. from ..commands import is_command -from ..svg.tags import (EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG, - SVG_POLYLINE_TAG, SVG_TEXT_TAG) +from ..svg.tags import (EMBROIDERABLE_TAGS, INKSTITCH_ATTRIBS, SVG_IMAGE_TAG, + SVG_PATH_TAG, SVG_POLYLINE_TAG, SVG_TEXT_TAG) from .auto_fill import AutoFill from .clone import Clone, is_clone from .element import EmbroideryElement from .empty_d_object import EmptyDObject from .fill import Fill from .image import ImageObject +from .pattern import PatternObject from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke @@ -28,6 +29,9 @@ def node_to_elements(node): # noqa: C901 elif node.tag == SVG_PATH_TAG and not node.get('d', ''): return [EmptyDObject(node)] + elif node.get(INKSTITCH_ATTRIBS['pattern']): + return [PatternObject(node)] + elif node.tag in EMBROIDERABLE_TAGS: element = EmbroideryElement(node) -- cgit v1.2.3 From c602c4c517cab40dfc2dc7dbc5c29c037cccafae Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 27 Jun 2021 22:29:57 +0200 Subject: group patterns --- lib/elements/satin_column.py | 10 +++++++--- lib/elements/utils.py | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 3f5f05e5..43948e42 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -6,7 +6,7 @@ from copy import deepcopy from itertools import chain -from inkex import paths +from inkex import paths, NSS from shapely import affinity as shaffinity from shapely import geometry as shgeo from shapely.ops import nearest_points @@ -14,6 +14,7 @@ from shapely.ops import nearest_points from ..i18n import _ from ..svg import (PIXELS_PER_MM, apply_transforms, line_strings_to_csp, point_lists_to_csp) +from ..svg.tags import EMBROIDERABLE_TAGS from ..utils import Point, cache, collapse_duplicate_point, cut from .element import EmbroideryElement, Patch, param from .validation import ValidationError, ValidationWarning @@ -577,10 +578,13 @@ class SatinColumn(EmbroideryElement): return SatinColumn(node) def get_patterns(self): - xpath = ".//*[@inkstitch:pattern='%(id)s']" % dict(id=self.node.get('id')) - patterns = self.node.getroottree().getroot().xpath(xpath) + xpath = "./ancestor::svg:g[svg:use[@xlink:href='#inkstitch_pattern_group']]//*[not(@inkstitch:satin_column='true')]" + patterns = self.node.xpath(xpath, namespaces=NSS) line_strings = [] for pattern in patterns: + # TODO: exclude fills in case we will want to use them with the pattern too + if pattern.tag not in EMBROIDERABLE_TAGS: + continue d = pattern.get_path() path = paths.Path(d).to_superpath() path = apply_transforms(path, pattern) diff --git a/lib/elements/utils.py b/lib/elements/utils.py index 03ea48d4..cbac3d40 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -17,6 +17,7 @@ from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke from .text import TextObject +from ..commands import group_commands def node_to_elements(node): # noqa: C901 @@ -29,7 +30,8 @@ def node_to_elements(node): # noqa: C901 elif node.tag == SVG_PATH_TAG and not node.get('d', ''): return [EmptyDObject(node)] - elif node.get(INKSTITCH_ATTRIBS['pattern']): + # TODO: exclude fills + elif group_commands(node, 'pattern_group') and not node.get(INKSTITCH_ATTRIBS['satin_column']): return [PatternObject(node)] elif node.tag in EMBROIDERABLE_TAGS: -- cgit v1.2.3 From 2f54ff2a436f2774bfdc730b6e95c43f18ed81ac Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 27 Jun 2021 22:47:43 +0200 Subject: group command extension --- lib/elements/satin_column.py | 2 +- lib/elements/utils.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 43948e42..65e523d4 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -6,7 +6,7 @@ from copy import deepcopy from itertools import chain -from inkex import paths, NSS +from inkex import NSS, paths from shapely import affinity as shaffinity from shapely import geometry as shgeo from shapely.ops import nearest_points diff --git a/lib/elements/utils.py b/lib/elements/utils.py index cbac3d40..78dace6a 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -3,7 +3,7 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from ..commands import is_command +from ..commands import group_commands, is_command from ..svg.tags import (EMBROIDERABLE_TAGS, INKSTITCH_ATTRIBS, SVG_IMAGE_TAG, SVG_PATH_TAG, SVG_POLYLINE_TAG, SVG_TEXT_TAG) from .auto_fill import AutoFill @@ -17,7 +17,6 @@ from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke from .text import TextObject -from ..commands import group_commands def node_to_elements(node): # noqa: C901 -- cgit v1.2.3 From ecacb9829e9c2b7050486707211f9d176aafdf75 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Mon, 28 Jun 2021 20:05:50 +0200 Subject: pattern markers --- lib/elements/pattern.py | 4 ++++ lib/elements/satin_column.py | 7 +++++-- lib/elements/utils.py | 11 +++++------ 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index 98f29456..c66ffbdc 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -30,3 +30,7 @@ class PatternObject(EmbroideryElement): def to_patches(self, last_patch): return [] + + +def is_pattern(node): + return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 65e523d4..77cb7d22 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -578,11 +578,14 @@ class SatinColumn(EmbroideryElement): return SatinColumn(node) def get_patterns(self): - xpath = "./ancestor::svg:g[svg:use[@xlink:href='#inkstitch_pattern_group']]//*[not(@inkstitch:satin_column='true')]" + # TODO: which one is better?!? + # All child groups of pattern + # xpath = "./ancestor::svg:g//*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" + # Only direct siblings of pattern + xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" patterns = self.node.xpath(xpath, namespaces=NSS) line_strings = [] for pattern in patterns: - # TODO: exclude fills in case we will want to use them with the pattern too if pattern.tag not in EMBROIDERABLE_TAGS: continue d = pattern.get_path() diff --git a/lib/elements/utils.py b/lib/elements/utils.py index 78dace6a..cd87cec8 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -3,16 +3,16 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from ..commands import group_commands, is_command -from ..svg.tags import (EMBROIDERABLE_TAGS, INKSTITCH_ATTRIBS, SVG_IMAGE_TAG, - SVG_PATH_TAG, SVG_POLYLINE_TAG, SVG_TEXT_TAG) +from ..commands import is_command +from ..svg.tags import (EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG, + SVG_POLYLINE_TAG, SVG_TEXT_TAG) from .auto_fill import AutoFill from .clone import Clone, is_clone from .element import EmbroideryElement from .empty_d_object import EmptyDObject from .fill import Fill from .image import ImageObject -from .pattern import PatternObject +from .pattern import PatternObject, is_pattern from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke @@ -29,8 +29,7 @@ def node_to_elements(node): # noqa: C901 elif node.tag == SVG_PATH_TAG and not node.get('d', ''): return [EmptyDObject(node)] - # TODO: exclude fills - elif group_commands(node, 'pattern_group') and not node.get(INKSTITCH_ATTRIBS['satin_column']): + elif is_pattern(node): return [PatternObject(node)] elif node.tag in EMBROIDERABLE_TAGS: -- cgit v1.2.3 From aa24b3a3a215cc536bdac94d8ace667f692ffc45 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 29 Jun 2021 19:17:12 +0200 Subject: everywhere patterns --- lib/elements/element.py | 48 ++++++++++++++++++++++++++++++++++++++++++++ lib/elements/satin_column.py | 35 -------------------------------- 2 files changed, 48 insertions(+), 35 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/element.py b/lib/elements/element.py index 9b894d89..aa0c4795 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -9,6 +9,7 @@ from copy import deepcopy import inkex import tinycss2 from inkex import bezier +from shapely import geometry as shgeo from ..commands import find_commands from ..i18n import _ @@ -330,6 +331,52 @@ class EmbroideryElement(object): else: return None + @cache + def get_patterns(self): + xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" + patterns = self.node.xpath(xpath, namespaces=inkex.NSS) + line_strings = [] + for pattern in patterns: + if pattern.tag not in EMBROIDERABLE_TAGS: + continue + d = pattern.get_path() + path = inkex.paths.Path(d).to_superpath() + path = apply_transforms(path, pattern) + path = self.flatten(path) + lines = [shgeo.LineString(p) for p in path] + for line in lines: + line_strings.append(line) + return shgeo.MultiLineString(line_strings) + + def _apply_patterns(self, patches): + patterns = self.get_patterns() + if not patterns: + return patches + + patch_points = [] + for patch in patches: + for i, stitch in enumerate(patch.stitches): + patch_points.append(stitch) + if i == len(patch.stitches) - 1: + continue + intersection_points = self._get_pattern_points(stitch, patch.stitches[i+1], patterns) + for point in intersection_points: + patch_points.append(point) + patch.stitches = patch_points + + def _get_pattern_points(self, first, second, patterns): + points = [] + for pattern in patterns: + intersection = shgeo.LineString([first, second]).intersection(pattern) + if isinstance(intersection, shgeo.Point): + points.append(Point(intersection.x, intersection.y)) + if isinstance(intersection, shgeo.MultiPoint): + for point in intersection: + points.append(Point(point.x, point.y)) + # sort points after their distance to left + points.sort(key=lambda point: point.distance(first)) + return points + def strip_control_points(self, subpath): return [point for control_before, point, control_after in subpath] @@ -362,6 +409,7 @@ class EmbroideryElement(object): self.validate() patches = self.to_patches(last_patch) + self._apply_patterns(patches) for patch in patches: patch.tie_modus = self.ties diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 77cb7d22..00a8500a 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -578,10 +578,6 @@ class SatinColumn(EmbroideryElement): return SatinColumn(node) def get_patterns(self): - # TODO: which one is better?!? - # All child groups of pattern - # xpath = "./ancestor::svg:g//*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" - # Only direct siblings of pattern xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" patterns = self.node.xpath(xpath, namespaces=NSS) line_strings = [] @@ -828,20 +824,6 @@ class SatinColumn(EmbroideryElement): return patch - def do_pattern_satin(self, patterns): - # elements with the attribute 'inkstitch:pattern' set to this elements id will cause extra stitches to be added - patch = Patch(color=self.color) - sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) - for i, (left, right) in enumerate(zip(*sides)): - patch.add_stitch(left) - for point in self._get_pattern_points(left, right, patterns): - patch.add_stitch(point) - patch.add_stitch(right) - if not i+1 >= len(sides[0]): - for point in self._get_pattern_points(right, sides[0][i+1], patterns): - patch.add_stitch(point) - return patch - def do_split_stitch(self): # stitches exceeding the maximum stitch length will be divided into equal parts through additional stitches patch = Patch(color=self.color) @@ -859,22 +841,8 @@ class SatinColumn(EmbroideryElement): points, count = self._get_split_points(right, sides[0][i+1], count) for point in points: patch.add_stitch(point) - return patch - def _get_pattern_points(self, left, right, patterns): - points = [] - for pattern in patterns: - intersection = shgeo.LineString([left, right]).intersection(pattern) - if isinstance(intersection, shgeo.Point): - points.append(Point(intersection.x, intersection.y)) - if isinstance(intersection, shgeo.MultiPoint): - for point in intersection: - points.append(Point(point.x, point.y)) - # sort points after their distance to left - points.sort(key=lambda point: point.distance(left)) - return points - def _get_split_points(self, left, right, count=None): points = [] distance = left.distance(right) @@ -905,13 +873,10 @@ class SatinColumn(EmbroideryElement): # zigzags sit on the contour walk underlay like rail ties on rails. patch += self.do_zigzag_underlay() - patterns = self.get_patterns() if self.e_stitch: patch += self.do_e_stitch() elif self.split_stitch: patch += self.do_split_stitch() - elif self.get_patterns(): - patch += self.do_pattern_satin(patterns) else: patch += self.do_satin() -- cgit v1.2.3 From 20176008f761d0bdcc1a2ab4f863229ed0c32e52 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 29 Jun 2021 20:42:16 +0200 Subject: update split pattern --- lib/elements/satin_column.py | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 00a8500a..dd7df7d1 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -76,16 +76,6 @@ class SatinColumn(EmbroideryElement): def satin_column(self): return self.get_boolean_param("satin_column") - # I18N: Split stitch divides a satin column into equal with parts if the maximum stitch length is exceeded - @property - @param('split_stitch', - _('Split stitch'), - tooltip=_('Sets additional stitches if the satin column exceeds the maximum stitch length.'), - type='boolean', - default='false') - def split_stitch(self): - return self.get_boolean_param("split_stitch") - # I18N: "E" stitch is so named because it looks like the letter E. @property @param('e_stitch', _('"E" stitch'), type='boolean', default='false') @@ -96,10 +86,12 @@ class SatinColumn(EmbroideryElement): @param('max_stitch_length_mm', _('Maximum stitch length'), tooltip=_('Maximum stitch length for split stitches.'), - type='float', unit="mm", - default=12.1) + type='float', unit="mm") def max_stitch_length(self): - return max(self.get_float_param("max_stitch_length_mm", 12.4), 0.1 * PIXELS_PER_MM) + max_stitch_length = self.get_float_param("max_stitch_length_mm") or None + if max_stitch_length: + max_stitch_length *= PIXELS_PER_MM + return self.get_float_param("max_stitch_length_mm") or None @property def color(self): @@ -793,6 +785,9 @@ class SatinColumn(EmbroideryElement): # print >> dbg, "satin", self.zigzag_spacing, self.pull_compensation + if self.max_stitch_length: + return self.do_split_stitch() + patch = Patch(color=self.color) sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) @@ -846,7 +841,7 @@ class SatinColumn(EmbroideryElement): def _get_split_points(self, left, right, count=None): points = [] distance = left.distance(right) - split_count = count or int(distance / self.max_stitch_length) + split_count = count or int(-(-distance // self.max_stitch_length)) for i in range(split_count): line = shgeo.LineString((left, right)) split_point = line.interpolate((i+1)/split_count, normalized=True) @@ -875,8 +870,6 @@ class SatinColumn(EmbroideryElement): if self.e_stitch: patch += self.do_e_stitch() - elif self.split_stitch: - patch += self.do_split_stitch() else: patch += self.do_satin() -- cgit v1.2.3 From 9604e411d4e50b011e4ae41bdcfdf95c45640684 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 29 Jun 2021 20:52:46 +0200 Subject: remove get_pattern from satin_column --- lib/elements/satin_column.py | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index dd7df7d1..a3cc527f 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -6,15 +6,13 @@ from copy import deepcopy from itertools import chain -from inkex import NSS, paths +from inkex import paths from shapely import affinity as shaffinity from shapely import geometry as shgeo from shapely.ops import nearest_points from ..i18n import _ -from ..svg import (PIXELS_PER_MM, apply_transforms, line_strings_to_csp, - point_lists_to_csp) -from ..svg.tags import EMBROIDERABLE_TAGS +from ..svg import PIXELS_PER_MM, line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, collapse_duplicate_point, cut from .element import EmbroideryElement, Patch, param from .validation import ValidationError, ValidationWarning @@ -569,22 +567,6 @@ class SatinColumn(EmbroideryElement): return SatinColumn(node) - def get_patterns(self): - xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" - patterns = self.node.xpath(xpath, namespaces=NSS) - line_strings = [] - for pattern in patterns: - if pattern.tag not in EMBROIDERABLE_TAGS: - continue - d = pattern.get_path() - path = paths.Path(d).to_superpath() - path = apply_transforms(path, pattern) - path = self.flatten(path) - lines = [shgeo.LineString(p) for p in path] - for line in lines: - line_strings.append(line) - return shgeo.MultiLineString(line_strings) - @property @cache def center_line(self): -- cgit v1.2.3 From a152e1edea19ae16f8226032f9cd2ded004b168c Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 29 Jun 2021 21:00:45 +0200 Subject: only check embroiderable tags for pattern marker --- lib/elements/pattern.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/elements') diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index c66ffbdc..fa54b7ba 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -6,6 +6,7 @@ import inkex from ..i18n import _ +from ..svg.tags import EMBROIDERABLE_TAGS from .element import EmbroideryElement from .validation import ObjectTypeWarning @@ -33,4 +34,6 @@ class PatternObject(EmbroideryElement): def is_pattern(node): + if node.tag not in EMBROIDERABLE_TAGS: + return False return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') -- cgit v1.2.3 From 52d9ee6a6d97b2ea752f5fdd3080a160a3574f82 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 30 Jun 2021 14:05:13 +0200 Subject: structuring --- lib/elements/element.py | 50 ++----------------------------------------------- lib/elements/pattern.py | 7 ------- lib/elements/utils.py | 3 ++- 3 files changed, 4 insertions(+), 56 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/element.py b/lib/elements/element.py index aa0c4795..dc466fbf 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -9,10 +9,10 @@ from copy import deepcopy import inkex import tinycss2 from inkex import bezier -from shapely import geometry as shgeo from ..commands import find_commands from ..i18n import _ +from ..patterns import apply_patterns from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length, get_node_transform) from ..svg.tags import (EMBROIDERABLE_TAGS, INKSCAPE_LABEL, INKSTITCH_ATTRIBS, @@ -331,52 +331,6 @@ class EmbroideryElement(object): else: return None - @cache - def get_patterns(self): - xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" - patterns = self.node.xpath(xpath, namespaces=inkex.NSS) - line_strings = [] - for pattern in patterns: - if pattern.tag not in EMBROIDERABLE_TAGS: - continue - d = pattern.get_path() - path = inkex.paths.Path(d).to_superpath() - path = apply_transforms(path, pattern) - path = self.flatten(path) - lines = [shgeo.LineString(p) for p in path] - for line in lines: - line_strings.append(line) - return shgeo.MultiLineString(line_strings) - - def _apply_patterns(self, patches): - patterns = self.get_patterns() - if not patterns: - return patches - - patch_points = [] - for patch in patches: - for i, stitch in enumerate(patch.stitches): - patch_points.append(stitch) - if i == len(patch.stitches) - 1: - continue - intersection_points = self._get_pattern_points(stitch, patch.stitches[i+1], patterns) - for point in intersection_points: - patch_points.append(point) - patch.stitches = patch_points - - def _get_pattern_points(self, first, second, patterns): - points = [] - for pattern in patterns: - intersection = shgeo.LineString([first, second]).intersection(pattern) - if isinstance(intersection, shgeo.Point): - points.append(Point(intersection.x, intersection.y)) - if isinstance(intersection, shgeo.MultiPoint): - for point in intersection: - points.append(Point(point.x, point.y)) - # sort points after their distance to left - points.sort(key=lambda point: point.distance(first)) - return points - def strip_control_points(self, subpath): return [point for control_before, point, control_after in subpath] @@ -409,7 +363,7 @@ class EmbroideryElement(object): self.validate() patches = self.to_patches(last_patch) - self._apply_patterns(patches) + apply_patterns(patches, self.node) for patch in patches: patch.tie_modus = self.ties diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index fa54b7ba..98f29456 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -6,7 +6,6 @@ import inkex from ..i18n import _ -from ..svg.tags import EMBROIDERABLE_TAGS from .element import EmbroideryElement from .validation import ObjectTypeWarning @@ -31,9 +30,3 @@ class PatternObject(EmbroideryElement): def to_patches(self, last_patch): return [] - - -def is_pattern(node): - if node.tag not in EMBROIDERABLE_TAGS: - return False - return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') diff --git a/lib/elements/utils.py b/lib/elements/utils.py index cd87cec8..99df7002 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -4,6 +4,7 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. from ..commands import is_command +from ..patterns import is_pattern from ..svg.tags import (EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG, SVG_POLYLINE_TAG, SVG_TEXT_TAG) from .auto_fill import AutoFill @@ -12,7 +13,7 @@ from .element import EmbroideryElement from .empty_d_object import EmptyDObject from .fill import Fill from .image import ImageObject -from .pattern import PatternObject, is_pattern +from .pattern import PatternObject from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke -- cgit v1.2.3 From 8e229770a5b5d28f68e065f61af3452f7e25c6b5 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 30 Jun 2021 14:12:27 +0200 Subject: corrections --- lib/elements/satin_column.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index a3cc527f..02d7a36c 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -12,7 +12,7 @@ from shapely import geometry as shgeo from shapely.ops import nearest_points from ..i18n import _ -from ..svg import PIXELS_PER_MM, line_strings_to_csp, point_lists_to_csp +from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, collapse_duplicate_point, cut from .element import EmbroideryElement, Patch, param from .validation import ValidationError, ValidationWarning @@ -86,9 +86,6 @@ class SatinColumn(EmbroideryElement): tooltip=_('Maximum stitch length for split stitches.'), type='float', unit="mm") def max_stitch_length(self): - max_stitch_length = self.get_float_param("max_stitch_length_mm") or None - if max_stitch_length: - max_stitch_length *= PIXELS_PER_MM return self.get_float_param("max_stitch_length_mm") or None @property -- cgit v1.2.3 From 8eba84a239ce655f32f131d6a82e3142693edd47 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 30 Jun 2021 21:47:33 +0200 Subject: update pattern troubleshoot description --- lib/elements/pattern.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index 98f29456..a32e72c0 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -12,13 +12,14 @@ from .validation import ObjectTypeWarning class PatternWarning(ObjectTypeWarning): name = _("Pattern Element") - description = _("This element will only be stitched out as a pattern within the specified object.") + description = _("This element will not be embroidered. " + "It will appear as a pattern in objects of it's group in the object panel. " + "Sub-group objects will be ignored.") steps_to_solve = [ - _("If you want to remove the pattern configuration for a pattern object follow these steps:"), - _("* Select pattern element(s)"), - _('* Run Extensions > Ink/Stitch > Troubleshoot > Remove embroidery settings...'), - _('* Make sure "Remove params" is enables'), - _('* Click "Apply"') + _("Turn the pattern marker off:"), + _('* Open the Fill and Stroke panel (Objects > Fill and Stroke)'), + _('* Go to the Stroke style tab'), + _('* Under "Markers" choose the first (empty) option in the first dropdown list.') ] -- cgit v1.2.3 From 736e10240a5c8357fac449371f8ac7451b7696b0 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 30 Jun 2021 19:48:51 -0400 Subject: slight wording adjustment --- lib/elements/pattern.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index a32e72c0..95ce81a1 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -13,10 +13,10 @@ from .validation import ObjectTypeWarning class PatternWarning(ObjectTypeWarning): name = _("Pattern Element") description = _("This element will not be embroidered. " - "It will appear as a pattern in objects of it's group in the object panel. " - "Sub-group objects will be ignored.") + "It will appear as a pattern applied to objects in the same group as it. " + "Objects in sub-groups will be ignored.") steps_to_solve = [ - _("Turn the pattern marker off:"), + _("To disable pattern mode, remove the pattern marker:"), _('* Open the Fill and Stroke panel (Objects > Fill and Stroke)'), _('* Go to the Stroke style tab'), _('* Under "Markers" choose the first (empty) option in the first dropdown list.') -- cgit v1.2.3 From c1e6558f7852def419adfbeb087b2194e6030a2c Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 7 Aug 2021 10:57:53 -0400 Subject: rename Patch to StitchGroup --- lib/elements/auto_fill.py | 4 ++-- lib/elements/element.py | 10 +++++----- lib/elements/fill.py | 4 ++-- lib/elements/polyline.py | 4 ++-- lib/elements/satin_column.py | 16 ++++++++-------- lib/elements/stroke.py | 6 +++--- 6 files changed, 22 insertions(+), 22 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py index 69533f62..29ca3545 100644 --- a/lib/elements/auto_fill.py +++ b/lib/elements/auto_fill.py @@ -12,7 +12,7 @@ from shapely import geometry as shgeo from ..i18n import _ from ..stitches import auto_fill from ..utils import cache, version -from .element import Patch, param +from .element import StitchGroup, param from .fill import Fill from .validation import ValidationWarning @@ -260,7 +260,7 @@ class AutoFill(Fill): self.fatal(message) - return [Patch(stitches=stitches, color=self.color)] + return [StitchGroup(stitches=stitches, color=self.color)] def validation_warnings(self): if self.shape.area < 20: diff --git a/lib/elements/element.py b/lib/elements/element.py index dc466fbf..bcb59bf4 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -20,7 +20,7 @@ from ..svg.tags import (EMBROIDERABLE_TAGS, INKSCAPE_LABEL, INKSTITCH_ATTRIBS, from ..utils import Point, cache -class Patch: +class StitchGroup: """A raw collection of stitches with attached instructions.""" def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False): @@ -32,10 +32,10 @@ class Patch: self.stitch_as_is = stitch_as_is def __add__(self, other): - if isinstance(other, Patch): - return Patch(self.color, self.stitches + other.stitches) + if isinstance(other, StitchGroup): + return StitchGroup(self.color, self.stitches + other.stitches) else: - raise TypeError("Patch can only be added to another Patch") + raise TypeError("StitchGroup can only be added to another StitchGroup") def __len__(self): # This method allows `len(patch)` and `if patch: @@ -45,7 +45,7 @@ class Patch: self.stitches.append(stitch) def reverse(self): - return Patch(self.color, self.stitches[::-1]) + return StitchGroup(self.color, self.stitches[::-1]) class Param(object): diff --git a/lib/elements/fill.py b/lib/elements/fill.py index b6799165..75a86ffd 100644 --- a/lib/elements/fill.py +++ b/lib/elements/fill.py @@ -14,7 +14,7 @@ from ..i18n import _ from ..stitches import legacy_fill from ..svg import PIXELS_PER_MM from ..utils import cache -from .element import EmbroideryElement, Patch, param +from .element import EmbroideryElement, StitchGroup, param from .validation import ValidationError @@ -198,4 +198,4 @@ class Fill(EmbroideryElement): self.flip, self.staggers, self.skip_last) - return [Patch(stitches=stitch_list, color=self.color) for stitch_list in stitch_lists] + return [StitchGroup(stitches=stitch_list, color=self.color) for stitch_list in stitch_lists] diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py index 5ea00508..f63dfc3b 100644 --- a/lib/elements/polyline.py +++ b/lib/elements/polyline.py @@ -9,7 +9,7 @@ from shapely import geometry as shgeo from ..i18n import _ from ..utils import cache from ..utils.geometry import Point -from .element import EmbroideryElement, Patch, param +from .element import EmbroideryElement, StitchGroup, param from .validation import ValidationWarning @@ -101,7 +101,7 @@ class Polyline(EmbroideryElement): yield PolylineWarning(self.points[0]) def to_patches(self, last_patch): - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) for stitch in self.stitches: patch.add_stitch(Point(*stitch)) diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 02d7a36c..3d0e7ff5 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -14,7 +14,7 @@ from shapely.ops import nearest_points from ..i18n import _ from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, collapse_duplicate_point, cut -from .element import EmbroideryElement, Patch, param +from .element import EmbroideryElement, StitchGroup, param from .validation import ValidationError, ValidationWarning @@ -716,7 +716,7 @@ class SatinColumn(EmbroideryElement): # other. forward, back = self.plot_points_on_rails(self.contour_underlay_stitch_length, -self.contour_underlay_inset) - return Patch(color=self.color, stitches=(forward + list(reversed(back)))) + return StitchGroup(color=self.color, stitches=(forward + list(reversed(back)))) def do_center_walk(self): # Center walk underlay is just a running stitch down and back on the @@ -725,7 +725,7 @@ class SatinColumn(EmbroideryElement): # Do it like contour underlay, but inset all the way to the center. forward, back = self.plot_points_on_rails(self.center_walk_underlay_stitch_length, -100000) - return Patch(color=self.color, stitches=(forward + list(reversed(back)))) + return StitchGroup(color=self.color, stitches=(forward + list(reversed(back)))) def do_zigzag_underlay(self): # zigzag underlay, usually done at a much lower density than the @@ -738,7 +738,7 @@ class SatinColumn(EmbroideryElement): # "German underlay" described here: # http://www.mrxstitch.com/underlay-what-lies-beneath-machine-embroidery/ - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) sides = self.plot_points_on_rails(self.zigzag_underlay_spacing / 2.0, -self.zigzag_underlay_inset) @@ -767,7 +767,7 @@ class SatinColumn(EmbroideryElement): if self.max_stitch_length: return self.do_split_stitch() - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) @@ -785,7 +785,7 @@ class SatinColumn(EmbroideryElement): # print >> dbg, "satin", self.zigzag_spacing, self.pull_compensation - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) @@ -800,7 +800,7 @@ class SatinColumn(EmbroideryElement): def do_split_stitch(self): # stitches exceeding the maximum stitch length will be divided into equal parts through additional stitches - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) for i, (left, right) in enumerate(zip(*sides)): patch.add_stitch(left) @@ -834,7 +834,7 @@ class SatinColumn(EmbroideryElement): # beziers. The boundary points between beziers serve as "checkpoints", # allowing the user to control how the zigzags flow around corners. - patch = Patch(color=self.color) + patch = StitchGroup(color=self.color) if self.center_walk_underlay: patch += self.do_center_walk() diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index cf034d21..edd5525a 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -11,7 +11,7 @@ from ..i18n import _ from ..stitches import bean_stitch, running_stitch from ..svg import parse_length_with_units from ..utils import Point, cache -from .element import EmbroideryElement, Patch, param +from .element import EmbroideryElement, StitchGroup, param warned_about_legacy_running_stitch = False @@ -190,7 +190,7 @@ class Stroke(EmbroideryElement): stitches = running_stitch(repeated_path, stitch_length) - return Patch(self.color, stitches) + return StitchGroup(self.color, stitches) def to_patches(self, last_patch): patches = [] @@ -198,7 +198,7 @@ class Stroke(EmbroideryElement): for path in self.paths: path = [Point(x, y) for x, y in path] if self.manual_stitch_mode: - patch = Patch(color=self.color, stitches=path, stitch_as_is=True) + patch = StitchGroup(color=self.color, stitches=path, stitch_as_is=True) elif self.is_running_stitch(): patch = self.running_stitch(path, self.running_stitch_length) -- cgit v1.2.3 From 84cb4e2c333d331eb863714797a55589f41e51b2 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 7 Aug 2021 11:21:13 -0400 Subject: move StitchGroup into lib.stitch_plan --- lib/elements/auto_fill.py | 7 ++++--- lib/elements/element.py | 28 ---------------------------- lib/elements/fill.py | 5 +++-- lib/elements/polyline.py | 5 +++-- lib/elements/satin_column.py | 5 +++-- lib/elements/stroke.py | 3 ++- 6 files changed, 15 insertions(+), 38 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py index 3c13a081..e72af1ef 100644 --- a/lib/elements/auto_fill.py +++ b/lib/elements/auto_fill.py @@ -9,13 +9,14 @@ import traceback from shapely import geometry as shgeo +from .element import param +from .fill import Fill +from .validation import ValidationWarning from ..i18n import _ +from ..stitch_plan import StitchGroup from ..stitches import auto_fill from ..svg.tags import INKSCAPE_LABEL from ..utils import cache, version -from .element import StitchGroup, param -from .fill import Fill -from .validation import ValidationWarning class SmallShapeWarning(ValidationWarning): diff --git a/lib/elements/element.py b/lib/elements/element.py index 17ed9167..a3577a5c 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -18,34 +18,6 @@ from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS from ..utils import Point, cache -class StitchGroup: - """A raw collection of stitches with attached instructions.""" - - def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False): - self.color = color - self.stitches = stitches or [] - self.trim_after = trim_after - self.stop_after = stop_after - self.tie_modus = tie_modus - self.stitch_as_is = stitch_as_is - - def __add__(self, other): - if isinstance(other, StitchGroup): - return StitchGroup(self.color, self.stitches + other.stitches) - else: - raise TypeError("StitchGroup can only be added to another StitchGroup") - - def __len__(self): - # This method allows `len(patch)` and `if patch: - return len(self.stitches) - - def add_stitch(self, stitch): - self.stitches.append(stitch) - - def reverse(self): - return StitchGroup(self.color, self.stitches[::-1]) - - class Param(object): def __init__(self, name, description, unit=None, values=[], type=None, group=None, inverse=False, options=[], default=None, tooltip=None, sort_index=0): diff --git a/lib/elements/fill.py b/lib/elements/fill.py index 75a86ffd..2d2ae2ed 100644 --- a/lib/elements/fill.py +++ b/lib/elements/fill.py @@ -10,12 +10,13 @@ import re from shapely import geometry as shgeo from shapely.validation import explain_validity +from .element import EmbroideryElement, param +from .validation import ValidationError from ..i18n import _ +from ..stitch_plan import StitchGroup from ..stitches import legacy_fill from ..svg import PIXELS_PER_MM from ..utils import cache -from .element import EmbroideryElement, StitchGroup, param -from .validation import ValidationError class UnconnectedError(ValidationError): diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py index f63dfc3b..aeae17d9 100644 --- a/lib/elements/polyline.py +++ b/lib/elements/polyline.py @@ -6,11 +6,12 @@ from inkex import Path from shapely import geometry as shgeo +from .element import EmbroideryElement, param +from .validation import ValidationWarning from ..i18n import _ +from ..stitch_plan import StitchGroup from ..utils import cache from ..utils.geometry import Point -from .element import EmbroideryElement, StitchGroup, param -from .validation import ValidationWarning class PolylineWarning(ValidationWarning): diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 1f28cb45..e066f3fb 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -11,11 +11,12 @@ from shapely import affinity as shaffinity from shapely import geometry as shgeo from shapely.ops import nearest_points +from .element import EmbroideryElement, param +from .validation import ValidationError, ValidationWarning from ..i18n import _ +from ..stitch_plan import StitchGroup from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, collapse_duplicate_point, cut -from .element import EmbroideryElement, StitchGroup, param -from .validation import ValidationError, ValidationWarning class SatinHasFillError(ValidationError): diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 76e80688..9fcb4e21 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -7,11 +7,12 @@ import sys import shapely.geometry +from .element import EmbroideryElement, param from ..i18n import _ +from ..stitch_plan import StitchGroup from ..stitches import bean_stitch, running_stitch from ..svg import parse_length_with_units from ..utils import Point, cache -from .element import EmbroideryElement, StitchGroup, param warned_about_legacy_running_stitch = False -- cgit v1.2.3 From 923ff3cb97c764f9999ac908c9b3aa321fd02301 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 7 Aug 2021 12:37:17 -0400 Subject: fix more patch references --- lib/elements/auto_fill.py | 2 +- lib/elements/clone.py | 4 ++-- lib/elements/element.py | 6 +++--- lib/elements/empty_d_object.py | 2 +- lib/elements/fill.py | 2 +- lib/elements/image.py | 2 +- lib/elements/pattern.py | 2 +- lib/elements/polyline.py | 2 +- lib/elements/satin_column.py | 2 +- lib/elements/stroke.py | 2 +- lib/elements/text.py | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py index e72af1ef..f5558cbb 100644 --- a/lib/elements/auto_fill.py +++ b/lib/elements/auto_fill.py @@ -213,7 +213,7 @@ class AutoFill(Fill): else: return None - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): stitches = [] starting_point = self.get_starting_point(last_patch) diff --git a/lib/elements/clone.py b/lib/elements/clone.py index 6dafa63d..a9e10d94 100644 --- a/lib/elements/clone.py +++ b/lib/elements/clone.py @@ -93,7 +93,7 @@ class Clone(EmbroideryElement): return elements - def to_patches(self, last_patch=None): + def to_stitch_groups(self, last_patch=None): patches = [] source_node = get_clone_source(self.node) @@ -123,7 +123,7 @@ class Clone(EmbroideryElement): elements = self.clone_to_element(self.node) for element in elements: - patches.extend(element.to_patches(last_patch)) + patches.extend(element.to_stitch_groups(last_patch)) return patches diff --git a/lib/elements/element.py b/lib/elements/element.py index a3577a5c..f06982b2 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -301,13 +301,13 @@ class EmbroideryElement(object): def stop_after(self): return self.get_boolean_param('stop_after', False) - def to_patches(self, last_patch): - raise NotImplementedError("%s must implement to_patches()" % self.__class__.__name__) + def to_stitch_groups(self, last_patch): + raise NotImplementedError("%s must implement to_stitch_groups()" % self.__class__.__name__) def embroider(self, last_patch): self.validate() - patches = self.to_patches(last_patch) + patches = self.to_stitch_groups(last_patch) apply_patterns(patches, self.node) for patch in patches: diff --git a/lib/elements/empty_d_object.py b/lib/elements/empty_d_object.py index 19fb58a4..3c24f333 100644 --- a/lib/elements/empty_d_object.py +++ b/lib/elements/empty_d_object.py @@ -23,5 +23,5 @@ class EmptyDObject(EmbroideryElement): label = self.node.get(INKSCAPE_LABEL) or self.node.get("id") yield EmptyD((0, 0), label) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): return [] diff --git a/lib/elements/fill.py b/lib/elements/fill.py index 2d2ae2ed..442922b6 100644 --- a/lib/elements/fill.py +++ b/lib/elements/fill.py @@ -190,7 +190,7 @@ class Fill(EmbroideryElement): else: yield InvalidShapeError((x, y)) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): stitch_lists = legacy_fill(self.shape, self.angle, self.row_spacing, diff --git a/lib/elements/image.py b/lib/elements/image.py index 0828b5ef..73a46871 100644 --- a/lib/elements/image.py +++ b/lib/elements/image.py @@ -29,5 +29,5 @@ class ImageObject(EmbroideryElement): def validation_warnings(self): yield ImageTypeWarning(self.center()) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): return [] diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py index 95ce81a1..4b92d366 100644 --- a/lib/elements/pattern.py +++ b/lib/elements/pattern.py @@ -29,5 +29,5 @@ class PatternObject(EmbroideryElement): repr_point = next(inkex.Path(self.parse_path()).end_points) yield PatternWarning(repr_point) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): return [] diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py index aeae17d9..c7a9ea48 100644 --- a/lib/elements/polyline.py +++ b/lib/elements/polyline.py @@ -101,7 +101,7 @@ class Polyline(EmbroideryElement): def validation_warnings(self): yield PolylineWarning(self.points[0]) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): patch = StitchGroup(color=self.color) for stitch in self.stitches: diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index e066f3fb..b11bb2c3 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -828,7 +828,7 @@ class SatinColumn(EmbroideryElement): points.append(Point(split_point.x, split_point.y)) return [points, split_count] - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): # Stitch a variable-width satin column, zig-zagging between two paths. # The algorithm will draw zigzags between each consecutive pair of diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 9fcb4e21..763167ad 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -193,7 +193,7 @@ class Stroke(EmbroideryElement): return StitchGroup(self.color, stitches) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): patches = [] for path in self.paths: diff --git a/lib/elements/text.py b/lib/elements/text.py index dbf76c85..8a3846c0 100644 --- a/lib/elements/text.py +++ b/lib/elements/text.py @@ -29,5 +29,5 @@ class TextObject(EmbroideryElement): def validation_warnings(self): yield TextTypeWarning(self.pointer()) - def to_patches(self, last_patch): + def to_stitch_groups(self, last_patch): return [] -- cgit v1.2.3 From dd865008356d1e04b29a5eb59a8480900f255628 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sun, 15 Aug 2021 17:24:59 -0400 Subject: keep underlay, underpath, and border travel --- lib/elements/auto_fill.py | 82 +++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 35 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py index f5558cbb..fbbd86d3 100644 --- a/lib/elements/auto_fill.py +++ b/lib/elements/auto_fill.py @@ -214,7 +214,7 @@ class AutoFill(Fill): return None def to_stitch_groups(self, last_patch): - stitches = [] + stitch_groups = [] starting_point = self.get_starting_point(last_patch) ending_point = self.get_ending_point() @@ -222,29 +222,40 @@ class AutoFill(Fill): try: if self.fill_underlay: for i in range(len(self.fill_underlay_angle)): - stitches.extend(auto_fill(self.underlay_shape, - self.fill_underlay_angle[i], - self.fill_underlay_row_spacing, - self.fill_underlay_row_spacing, - self.fill_underlay_max_stitch_length, - self.running_stitch_length, - self.staggers, - self.fill_underlay_skip_last, - starting_point, - underpath=self.underlay_underpath)) - starting_point = stitches[-1] - - stitches.extend(auto_fill(self.fill_shape, - self.angle, - self.row_spacing, - self.end_row_spacing, - self.max_stitch_length, - self.running_stitch_length, - self.staggers, - self.skip_last, - starting_point, - ending_point, - self.underpath)) + underlay = StitchGroup( + color=self.color, + tags=("auto_fill", "auto_fill_underlay"), + stitches=auto_fill( + self.underlay_shape, + self.fill_underlay_angle[i], + self.fill_underlay_row_spacing, + self.fill_underlay_row_spacing, + self.fill_underlay_max_stitch_length, + self.running_stitch_length, + self.staggers, + self.fill_underlay_skip_last, + starting_point, + underpath=self.underlay_underpath)) + stitch_groups.append(underlay) + + starting_point = underlay.stitches[-1] + + stitch_group = StitchGroup( + color=self.color, + tags=("auto_fill", "auto_fill_top"), + stitches=auto_fill( + self.fill_shape, + self.angle, + self.row_spacing, + self.end_row_spacing, + self.max_stitch_length, + self.running_stitch_length, + self.staggers, + self.skip_last, + starting_point, + ending_point, + self.underpath)) + stitch_groups.append(stitch_group) except Exception: if hasattr(sys, 'gettrace') and sys.gettrace(): # if we're debugging, let the exception bubble up @@ -262,18 +273,19 @@ class AutoFill(Fill): self.fatal(message) - return [StitchGroup(stitches=stitches, color=self.color)] + return stitch_groups - def validation_warnings(self): - if self.shape.area < 20: - label = self.node.get(INKSCAPE_LABEL) or self.node.get("id") - yield SmallShapeWarning(self.shape.centroid, label) - if self.shrink_or_grow_shape(self.expand, True).is_empty: - yield ExpandWarning(self.shape.centroid) +def validation_warnings(self): + if self.shape.area < 20: + label = self.node.get(INKSCAPE_LABEL) or self.node.get("id") + yield SmallShapeWarning(self.shape.centroid, label) - if self.shrink_or_grow_shape(-self.fill_underlay_inset, True).is_empty: - yield UnderlayInsetWarning(self.shape.centroid) + if self.shrink_or_grow_shape(self.expand, True).is_empty: + yield ExpandWarning(self.shape.centroid) - for warning in super(AutoFill, self).validation_warnings(): - yield warning + if self.shrink_or_grow_shape(-self.fill_underlay_inset, True).is_empty: + yield UnderlayInsetWarning(self.shape.centroid) + + for warning in super(AutoFill, self).validation_warnings(): + yield warning -- cgit v1.2.3 From b49f7d28314f30727f9f963bddb795b88a95f2bd Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Mon, 16 Aug 2021 16:30:22 +0200 Subject: keep satin column edges --- lib/elements/satin_column.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index b11bb2c3..cf31c2af 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -717,7 +717,10 @@ class SatinColumn(EmbroideryElement): # other. forward, back = self.plot_points_on_rails(self.contour_underlay_stitch_length, -self.contour_underlay_inset) - return StitchGroup(color=self.color, stitches=(forward + list(reversed(back)))) + return StitchGroup( + color=self.color, + tags=("satin_column", "satin_column_underlay", "satin_contour_underlay"), + stitches=(forward + list(reversed(back)))) def do_center_walk(self): # Center walk underlay is just a running stitch down and back on the @@ -726,7 +729,10 @@ class SatinColumn(EmbroideryElement): # Do it like contour underlay, but inset all the way to the center. forward, back = self.plot_points_on_rails(self.center_walk_underlay_stitch_length, -100000) - return StitchGroup(color=self.color, stitches=(forward + list(reversed(back)))) + return StitchGroup( + color=self.color, + tags=("satin_column", "satin_column_underlay", "satin_center_walk"), + stitches=(forward + list(reversed(back)))) def do_zigzag_underlay(self): # zigzag underlay, usually done at a much lower density than the @@ -754,6 +760,7 @@ class SatinColumn(EmbroideryElement): for point in chain.from_iterable(zip(*sides)): patch.add_stitch(point) + patch.add_tags(("satin_column", "satin_column_underlay", "satin_zigzag_underlay")) return patch def do_satin(self): @@ -776,6 +783,7 @@ class SatinColumn(EmbroideryElement): for point in chain.from_iterable(zip(*sides)): patch.add_stitch(point) + patch.add_tags(("satin_column", "satin_column_edge")) return patch def do_e_stitch(self): @@ -797,6 +805,7 @@ class SatinColumn(EmbroideryElement): patch.add_stitch(right) patch.add_stitch(left) + patch.add_tags(("satin_column", "e_stitch")) return patch def do_split_stitch(self): @@ -805,10 +814,13 @@ class SatinColumn(EmbroideryElement): sides = self.plot_points_on_rails(self.zigzag_spacing, self.pull_compensation) for i, (left, right) in enumerate(zip(*sides)): patch.add_stitch(left) + patch.stitches[-1].add_tags(("satin_column", "satin_column_edge")) points, count = self._get_split_points(left, right) for point in points: patch.add_stitch(point) + patch.stitches[-1].add_tags(("satin_column", "satin_split_stitch")) patch.add_stitch(right) + patch.stitches[-1].add_tags(("satin_column", "satin_column_edge")) # it is possible that the way back has a different length from the first # but it looks ugly if the points differ too much # so let's make sure they have at least the same amount of divisions @@ -816,6 +828,7 @@ class SatinColumn(EmbroideryElement): points, count = self._get_split_points(right, sides[0][i+1], count) for point in points: patch.add_stitch(point) + patch.stitches[-1].add_tags(("satin_column", "satin_split_stitch")) return patch def _get_split_points(self, left, right, count=None): -- cgit v1.2.3