diff options
Diffstat (limited to 'lib/elements')
| -rw-r--r-- | lib/elements/element.py | 159 | ||||
| -rw-r--r-- | lib/elements/fill_stitch.py | 14 | ||||
| -rw-r--r-- | lib/elements/polyline.py | 6 | ||||
| -rw-r--r-- | lib/elements/satin_column.py | 12 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 13 |
5 files changed, 165 insertions, 39 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py index 3a9f331c..ba15d943 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -4,9 +4,9 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. import sys from copy import deepcopy -import numpy as np import inkex +import numpy as np from inkex import bezier from ..commands import find_commands @@ -14,6 +14,8 @@ from ..debug import debug from ..i18n import _ from ..marker import get_marker_elements_cache_key_data from ..patterns import apply_patterns, get_patterns_cache_key_data +from ..stitch_plan.lock_stitch import (LOCK_DEFAULTS, AbsoluteLock, CustomLock, + LockStitch, SVGLock) from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length, get_node_transform) from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS @@ -262,6 +264,119 @@ class EmbroideryElement(object): return self.get_boolean_param('force_lock_stitches', False) @property + @param('lock_start', + _('Tack stitch'), + tooltip=_('Tack down stitch type'), + type='combo', + default='half_stitch', + options=LOCK_DEFAULTS['start'], + sort_index=52) + def lock_start(self): + return self.get_param('lock_start', "half_stitch") + + @property + @param('lock_custom_start', + _('Custom path'), + tooltip=_("Enter a custom path. For svg paths The last node will not be embroidered, but represents the first stitch of the element."), + type="string", + default="", + select_items=[('lock_start', 'custom')], + sort_index=53) + def lock_custom_start(self): + return self.get_param('lock_custom_start', '') + + @property + @param('lock_start_scale_mm', + _('Scale tack stitch'), + tooltip=_('Set stitch length. A 1 in a custom path equals this values.'), + type='float', + unit="mm", + default=0.7, + select_items=[('lock_start', lock.id) for lock in LOCK_DEFAULTS['start'] if isinstance(lock, (AbsoluteLock, CustomLock))], + sort_index=54) + def lock_start_scale_mm(self): + return self.get_float_param('lock_start_scale_mm', 0.7) + + @property + @param('lock_start_scale_percent', + _('Scale tack stitch'), + tooltip=_('Scale tack stitch by this percentage.'), + type='float', + unit="%", + default=100, + select_items=[('lock_start', lock.id) for lock in LOCK_DEFAULTS['start'] if isinstance(lock, (SVGLock, CustomLock))], + sort_index=54) + def lock_start_scale_percent(self): + return self.get_float_param('lock_start_scale_percent', 100) + + @property + @param('lock_end', + _('Lock stitch'), + tooltip=_('Lock stitch type'), + type='combo', + default='half_stitch', + options=LOCK_DEFAULTS['end'], + sort_index=55) + def lock_end(self): + return self.get_param('lock_end', "half_stitch") + + @property + @param('lock_custom_end', + _('Custom path'), + tooltip=_("Enter a custom path. For svg paths the first node will not be embroidered, but represents the last stitch of the element."), + type="string", + default="", + select_items=[('lock_end', 'custom')], + sort_index=56) + def lock_custom_end(self): + return self.get_param('lock_custom_end', '') + + @property + @param('lock_end_scale_mm', + _('Scale lock stitch'), + tooltip=_('Set length of lock stitches (mm).'), + type='float', + unit="mm", + default=0.7, + select_items=[('lock_end', lock.id) for lock in LOCK_DEFAULTS['end'] if isinstance(lock, (AbsoluteLock, CustomLock))], + sort_index=57) + def lock_end_scale_mm(self): + return self.get_float_param('lock_end_scale_mm', 0.7) + + @property + @param('lock_end_scale_percent', + _('Scale lock stitch'), + tooltip=_('Scale lock stitch by this percentage.'), + type='float', + unit="%", + default=100, + select_items=[('lock_end', lock.id) for lock in LOCK_DEFAULTS['end'] if isinstance(lock, (SVGLock, CustomLock))], + sort_index=57) + @cache + def lock_end_scale_percent(self): + return self.get_float_param('lock_end_scale_percent', 100) + + @property + @param('trim_after', + _('Trim After'), + tooltip=_('Add a TRIM command after stitching this object.'), + type='boolean', + default=False, + sort_index=60) + def trim_after(self): + return self.get_boolean_param('trim_after', False) + + @property + @param('stop_after', + _('Stop After'), + tooltip=_('Add a STOP command after stitching this object.'), + type='boolean', + default=False, + sort_index=60) + def stop_after(self): + return self.get_boolean_param('stop_after', False) + + @property @param('random_seed', _('Random seed'), tooltip=_('Use a specific seed for randomized attributes. Uses the element ID if empty.'), @@ -314,7 +429,7 @@ class EmbroideryElement(object): if not d: self.fatal(_("Object %(id)s has an empty 'd' attribute. Please delete this object from your document.") % dict(id=self.node.get("id"))) - return inkex.paths.Path(d).to_superpath() + return inkex.Path(d).to_superpath() @cache def parse_path(self): @@ -369,24 +484,26 @@ class EmbroideryElement(object): return self.strip_control_points(path[0]) @property - @param('trim_after', - _('Trim After'), - tooltip=_('Add a TRIM command after stitching this object.'), - type='boolean', - default=False, - sort_index=52) - def trim_after(self): - return self.get_boolean_param('trim_after', False) + @cache + def lock_stitches(self): + lock_start = None + lock_end = None - @property - @param('stop_after', - _('Stop After'), - tooltip=_('Add a STOP command after stitching this object.'), - type='boolean', - default=False, - sort_index=53) - def stop_after(self): - return self.get_boolean_param('stop_after', False) + # Ties: 0 = Both | 1 = Before | 2 = After | 3 = Neither + tie_modus = self.ties + force = self.force_lock_stitches + + if tie_modus in [0, 1]: + lock_start = LockStitch('start', self.lock_start, scale_percent=self.lock_start_scale_percent, scale_absolute=self.lock_start_scale_mm) + if self.lock_start == "custom": + lock_start.path = self.lock_custom_start + + if tie_modus in [0, 2] or force: + lock_end = LockStitch('end', self.lock_end, scale_percent=self.lock_end_scale_percent, scale_absolute=self.lock_end_scale_mm) + if self.lock_end == "custom": + lock_end.path = self.lock_custom_end + + return lock_start, lock_end def to_stitch_groups(self, last_patch): raise NotImplementedError("%s must implement to_stitch_groups()" % self.__class__.__name__) @@ -477,10 +594,6 @@ class EmbroideryElement(object): stitch_groups = self.to_stitch_groups(last_stitch_group) apply_patterns(stitch_groups, self.node) - for stitch_group in stitch_groups: - stitch_group.tie_modus = self.ties - stitch_group.force_lock_stitches = self.force_lock_stitches - if stitch_groups: stitch_groups[-1].trim_after = self.has_command("trim") or self.trim_after stitch_groups[-1].stop_after = self.has_command("stop") or self.stop_after diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 1897c8bf..8eb12af2 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -673,7 +673,10 @@ class FillStitch(EmbroideryElement): self.flip, self.staggers, self.skip_last) - return [StitchGroup(stitches=stitch_list, color=self.color) for stitch_list in stitch_lists] + return [StitchGroup(stitches=stitch_list, + color=self.color, + force_lock_stitches=self.force_lock_stitches, + lock_stitches=self.lock_stitches) for stitch_list in stitch_lists] def do_underlay(self, shape, starting_point): stitch_groups = [] @@ -681,6 +684,7 @@ class FillStitch(EmbroideryElement): underlay = StitchGroup( color=self.color, tags=("auto_fill", "auto_fill_underlay"), + lock_stitches=self.lock_stitches, stitches=auto_fill( shape, self.fill_underlay_angle[i], @@ -702,6 +706,8 @@ class FillStitch(EmbroideryElement): stitch_group = StitchGroup( color=self.color, tags=("auto_fill", "auto_fill_top"), + force_lock_stitches=self.force_lock_stitches, + lock_stitches=self.lock_stitches, stitches=auto_fill( shape, self.angle, @@ -755,7 +761,9 @@ class FillStitch(EmbroideryElement): stitch_group = StitchGroup( color=self.color, tags=("auto_fill", "auto_fill_top"), - stitches=stitches) + stitches=stitches, + force_lock_stitches=self.force_lock_stitches, + lock_stitches=self.lock_stitches,) stitch_groups.append(stitch_group) return stitch_groups @@ -770,6 +778,8 @@ class FillStitch(EmbroideryElement): stitch_group = StitchGroup( color=self.color, tags=("guided_fill", "auto_fill_top"), + force_lock_stitches=self.force_lock_stitches, + lock_stitches=self.lock_stitches, stitches=guided_fill( shape, guide_line.geoms[0], diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py index 5086c705..a33b75de 100644 --- a/lib/elements/polyline.py +++ b/lib/elements/polyline.py @@ -6,12 +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, param +from .validation import ValidationWarning class PolylineWarning(ValidationWarning): @@ -95,7 +95,7 @@ class Polyline(EmbroideryElement): yield PolylineWarning(self.path[0][0][0]) def to_stitch_groups(self, last_patch): - patch = StitchGroup(color=self.color) + patch = StitchGroup(color=self.color, lock_stitches=(None, None)) 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 eba63c6c..b5086171 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -3,10 +3,10 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from copy import deepcopy import itertools -from itertools import chain import typing +from copy import deepcopy +from itertools import chain import numpy as np from inkex import paths @@ -16,10 +16,10 @@ from shapely.ops import nearest_points from ..i18n import _ from ..stitch_plan import StitchGroup +from ..stitches import running_stitch from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, cut, cut_multiple, prng -from ..stitches import running_stitch -from .element import EmbroideryElement, param, PIXELS_PER_MM +from .element import PIXELS_PER_MM, EmbroideryElement, param from .validation import ValidationError, ValidationWarning from ..utils.threading import check_stop_flag @@ -1092,7 +1092,9 @@ class SatinColumn(EmbroideryElement): # beziers. The boundary points between beziers serve as "checkpoints", # allowing the user to control how the zigzags flow around corners. - patch = StitchGroup(color=self.color) + patch = StitchGroup(color=self.color, + force_lock_stitches=self.force_lock_stitches, + lock_stitches=self.lock_stitches) if self.center_walk_underlay: patch += self.do_center_walk() diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 6aca3847..c633a2c6 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -6,19 +6,18 @@ import sys import shapely.geometry - from inkex import Transform from ..i18n import _ from ..marker import get_marker_elements from ..stitch_plan import StitchGroup -from ..stitches.running_stitch import bean_stitch, running_stitch from ..stitches.ripple_stitch import ripple_stitch +from ..stitches.running_stitch import bean_stitch, running_stitch from ..svg import get_node_transform, parse_length_with_units +from ..threads import ThreadColor from ..utils import Point, cache from .element import EmbroideryElement, param from .validation import ValidationWarning -from ..threads import ThreadColor warned_about_legacy_running_stitch = False @@ -445,13 +444,15 @@ class Stroke(EmbroideryElement): repeated_stitches.extend(this_path) - return StitchGroup(self.color, repeated_stitches) + return StitchGroup(self.color, repeated_stitches, lock_stitches=self.lock_stitches, force_lock_stitches=self.force_lock_stitches) def ripple_stitch(self): return StitchGroup( color=self.color, tags=["ripple_stitch"], - stitches=ripple_stitch(self)) + stitches=ripple_stitch(self), + lock_stitches=self.lock_stitches, + force_lock_stitches=self.force_lock_stitches) def do_bean_repeats(self, stitches): return bean_stitch(stitches, self.bean_stitch_repeats) @@ -471,7 +472,7 @@ class Stroke(EmbroideryElement): path = [Point(x, y) for x, y in path] # manual stitch if self.manual_stitch_mode: - patch = StitchGroup(color=self.color, stitches=path, stitch_as_is=True) + patch = StitchGroup(color=self.color, stitches=path, lock_stitches=(None, None)) # running stitch elif self.is_running_stitch(): patch = self.running_stitch(path, self.running_stitch_length, self.running_stitch_tolerance) |
