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/extensions/__init__.py | 2 ++ lib/extensions/apply_satin_pattern.py | 39 +++++++++++++++++++++++++++++++++++ lib/extensions/base.py | 7 ++++--- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 lib/extensions/apply_satin_pattern.py (limited to 'lib/extensions') diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index 25f835c3..70df7c37 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -5,6 +5,7 @@ from lib.extensions.troubleshoot import Troubleshoot +from .apply_satin_pattern import ApplySatinPattern from .auto_satin import AutoSatin from .break_apart import BreakApart from .cleanup import Cleanup @@ -45,6 +46,7 @@ __all__ = extensions = [StitchPlanPreview, GlobalCommands, ConvertToSatin, CutSatin, + ApplySatinPattern, AutoSatin, Lettering, LetteringGenerateJson, diff --git a/lib/extensions/apply_satin_pattern.py b/lib/extensions/apply_satin_pattern.py new file mode 100644 index 00000000..9da81075 --- /dev/null +++ b/lib/extensions/apply_satin_pattern.py @@ -0,0 +1,39 @@ +# Authors: see git history +# +# Copyright (c) 2021 Authors +# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +import inkex + +from ..i18n import _ +from ..svg.tags import INKSTITCH_ATTRIBS +from .base import InkstitchExtension +from ..elements import SatinColumn + + +class ApplySatinPattern(InkstitchExtension): + # Add inkstitch:pattern attribute to selected patterns. The patterns will be projected on a satin column, which must be in the selection too + + def effect(self): + if not self.get_elements(): + return + + if not self.svg.selected or not any(isinstance(item, SatinColumn) for item in self.elements) or len(self.svg.selected) < 2: + inkex.errormsg(_("Please select at least one satin column and a pattern.")) + return + + if sum(isinstance(item, SatinColumn) for item in self.elements) > 1: + inkex.errormsg(_("Please select only one satin column.")) + return + + satin_id = self.get_satin_column().node.get('id', None) + patterns = self.get_patterns() + + for pattern in patterns: + pattern.node.set(INKSTITCH_ATTRIBS['pattern'], satin_id) + + def get_satin_column(self): + return list(filter(lambda satin: isinstance(satin, SatinColumn), self.elements))[0] + + def get_patterns(self): + return list(filter(lambda satin: not isinstance(satin, SatinColumn), self.elements)) diff --git a/lib/extensions/base.py b/lib/extensions/base.py index 70ca4701..f23ec5e2 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -18,7 +18,8 @@ from ..elements.clone import is_clone from ..i18n import _ from ..svg import generate_unique_id from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE, - NOT_EMBROIDERABLE_TAGS, SVG_DEFS_TAG, SVG_GROUP_TAG) + INKSTITCH_ATTRIBS, NOT_EMBROIDERABLE_TAGS, + SVG_DEFS_TAG, SVG_GROUP_TAG) SVG_METADATA_TAG = inkex.addNS("metadata", "svg") @@ -170,9 +171,9 @@ class InkstitchExtension(inkex.Effect): if selected: if node.tag == SVG_GROUP_TAG: pass - elif getattr(node, "get_path", None): + elif (node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not node.get(INKSTITCH_ATTRIBS['pattern']): nodes.append(node) - elif troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or node.tag in EMBROIDERABLE_TAGS or is_clone(node)): + elif troubleshoot and node.tag in NOT_EMBROIDERABLE_TAGS: nodes.append(node) return nodes -- cgit v1.3.1 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 +++++-- lib/extensions/apply_satin_pattern.py | 44 +++++++++++++++++++++++++++++++++-- lib/extensions/base.py | 2 +- lib/extensions/lettering.py | 4 +++- lib/extensions/params.py | 4 +++- 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 lib/elements/pattern.py (limited to 'lib/extensions') 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) diff --git a/lib/extensions/apply_satin_pattern.py b/lib/extensions/apply_satin_pattern.py index 9da81075..47eb4d83 100644 --- a/lib/extensions/apply_satin_pattern.py +++ b/lib/extensions/apply_satin_pattern.py @@ -4,11 +4,12 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. import inkex +from lxml import etree +from ..elements import SatinColumn from ..i18n import _ -from ..svg.tags import INKSTITCH_ATTRIBS +from ..svg.tags import INKSTITCH_ATTRIBS, SVG_DEFS_TAG from .base import InkstitchExtension -from ..elements import SatinColumn class ApplySatinPattern(InkstitchExtension): @@ -31,9 +32,48 @@ class ApplySatinPattern(InkstitchExtension): for pattern in patterns: pattern.node.set(INKSTITCH_ATTRIBS['pattern'], satin_id) + self.set_marker(pattern.node) def get_satin_column(self): return list(filter(lambda satin: isinstance(satin, SatinColumn), self.elements))[0] def get_patterns(self): return list(filter(lambda satin: not isinstance(satin, SatinColumn), self.elements)) + + def set_marker(self, node): + document = node.getroottree().getroot() + xpath = ".//marker[@id='inkstitch-pattern-marker']" + pattern_marker = document.xpath(xpath) + if not pattern_marker: + # get or create def element + defs = document.find(SVG_DEFS_TAG) + if defs is None: + defs = etree.SubElement(document, SVG_DEFS_TAG) + + # insert marker + marker = """ + + + + + """ # noqa: E501 + defs.append(etree.fromstring(marker)) + + # attach marker to node + style = node.get('style', '').split(";") + import sys + print(style, file=sys.stderr) + style = [i for i in style if not i.startswith('marker-start')] + style.append('marker-start:url(#inkstitch-pattern-marker)') + node.set('style', ";".join(style)) diff --git a/lib/extensions/base.py b/lib/extensions/base.py index f23ec5e2..00d4a00d 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -173,7 +173,7 @@ class InkstitchExtension(inkex.Effect): pass elif (node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not node.get(INKSTITCH_ATTRIBS['pattern']): nodes.append(node) - elif troubleshoot and node.tag in NOT_EMBROIDERABLE_TAGS: + elif troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or node.get(INKSTITCH_ATTRIBS['pattern'])): nodes.append(node) return nodes diff --git a/lib/extensions/lettering.py b/lib/extensions/lettering.py index e55365c6..cf627fe5 100644 --- a/lib/extensions/lettering.py +++ b/lib/extensions/lettering.py @@ -31,9 +31,11 @@ class LetteringFrame(wx.Frame): def __init__(self, *args, **kwargs): # This is necessary because of https://github.com/inkstitch/inkstitch/issues/1186 - if sys.platform.startswith('win'): + if sys.platform.startswith('win32'): import locale locale.setlocale(locale.LC_ALL, "C") + lc = wx.Locale() + lc.Init(wx.LANGUAGE_DEFAULT) # begin wxGlade: MyFrame.__init__ self.group = kwargs.pop('group') diff --git a/lib/extensions/params.py b/lib/extensions/params.py index 40494ec7..7775aed1 100644 --- a/lib/extensions/params.py +++ b/lib/extensions/params.py @@ -331,9 +331,11 @@ class ParamsTab(ScrolledPanel): class SettingsFrame(wx.Frame): def __init__(self, *args, **kwargs): # This is necessary because of https://github.com/inkstitch/inkstitch/issues/1186 - if sys.platform.startswith('win'): + if sys.platform.startswith('win32'): import locale locale.setlocale(locale.LC_ALL, "C") + lc = wx.Locale() + lc.Init(wx.LANGUAGE_DEFAULT) # begin wxGlade: MyFrame.__init__ self.tabs_factory = kwargs.pop('tabs_factory', []) -- cgit v1.3.1 From c602c4c517cab40dfc2dc7dbc5c29c037cccafae Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 27 Jun 2021 22:29:57 +0200 Subject: group patterns --- lib/commands.py | 11 ++++- lib/elements/satin_column.py | 10 +++-- lib/elements/utils.py | 4 +- lib/extensions/__init__.py | 2 - lib/extensions/apply_satin_pattern.py | 79 ----------------------------------- lib/extensions/base.py | 9 ++-- symbols/inkstitch.svg | 23 ++++++++++ templates/apply_satin_pattern.xml | 17 -------- 8 files changed, 49 insertions(+), 106 deletions(-) delete mode 100644 lib/extensions/apply_satin_pattern.py delete mode 100644 templates/apply_satin_pattern.xml (limited to 'lib/extensions') diff --git a/lib/commands.py b/lib/commands.py index f2ab8c3e..ea6d3509 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -46,10 +46,12 @@ COMMANDS = { # L10N command attached to an object "satin_cut_point": N_("Satin cut point (use with Cut Satin Column)"), - # L10N command that affects a layer "ignore_layer": N_("Ignore layer (do not stitch any objects in this layer)"), + # L10N command that affects a group + "pattern_group": N_("Strokes in this group will be interpretet as a pattern"), + # L10N command that affects entire document "origin": N_("Origin for exported embroidery files"), @@ -58,6 +60,7 @@ COMMANDS = { } OBJECT_COMMANDS = ["fill_start", "fill_end", "satin_start", "satin_end", "stop", "trim", "ignore_object", "satin_cut_point"] +GROUP_COMMANDS = ["pattern_group"] LAYER_COMMANDS = ["ignore_layer"] GLOBAL_COMMANDS = ["origin", "stop_position"] @@ -184,6 +187,12 @@ def find_commands(node): return commands +def group_commands(node, command): + xpath = "./ancestor::svg:g/svg:use[@xlink:href='#inkstitch_%(command)s']" % dict(id=node.get('id'), command=command) + group_command = node.xpath(xpath, namespaces=inkex.NSS) + return group_command + + def layer_commands(layer, command): """Find standalone (unconnected) command symbols in this layer.""" 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: diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index 70df7c37..25f835c3 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -5,7 +5,6 @@ from lib.extensions.troubleshoot import Troubleshoot -from .apply_satin_pattern import ApplySatinPattern from .auto_satin import AutoSatin from .break_apart import BreakApart from .cleanup import Cleanup @@ -46,7 +45,6 @@ __all__ = extensions = [StitchPlanPreview, GlobalCommands, ConvertToSatin, CutSatin, - ApplySatinPattern, AutoSatin, Lettering, LetteringGenerateJson, diff --git a/lib/extensions/apply_satin_pattern.py b/lib/extensions/apply_satin_pattern.py deleted file mode 100644 index 47eb4d83..00000000 --- a/lib/extensions/apply_satin_pattern.py +++ /dev/null @@ -1,79 +0,0 @@ -# Authors: see git history -# -# Copyright (c) 2021 Authors -# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - -import inkex -from lxml import etree - -from ..elements import SatinColumn -from ..i18n import _ -from ..svg.tags import INKSTITCH_ATTRIBS, SVG_DEFS_TAG -from .base import InkstitchExtension - - -class ApplySatinPattern(InkstitchExtension): - # Add inkstitch:pattern attribute to selected patterns. The patterns will be projected on a satin column, which must be in the selection too - - def effect(self): - if not self.get_elements(): - return - - if not self.svg.selected or not any(isinstance(item, SatinColumn) for item in self.elements) or len(self.svg.selected) < 2: - inkex.errormsg(_("Please select at least one satin column and a pattern.")) - return - - if sum(isinstance(item, SatinColumn) for item in self.elements) > 1: - inkex.errormsg(_("Please select only one satin column.")) - return - - satin_id = self.get_satin_column().node.get('id', None) - patterns = self.get_patterns() - - for pattern in patterns: - pattern.node.set(INKSTITCH_ATTRIBS['pattern'], satin_id) - self.set_marker(pattern.node) - - def get_satin_column(self): - return list(filter(lambda satin: isinstance(satin, SatinColumn), self.elements))[0] - - def get_patterns(self): - return list(filter(lambda satin: not isinstance(satin, SatinColumn), self.elements)) - - def set_marker(self, node): - document = node.getroottree().getroot() - xpath = ".//marker[@id='inkstitch-pattern-marker']" - pattern_marker = document.xpath(xpath) - if not pattern_marker: - # get or create def element - defs = document.find(SVG_DEFS_TAG) - if defs is None: - defs = etree.SubElement(document, SVG_DEFS_TAG) - - # insert marker - marker = """ - - - - - """ # noqa: E501 - defs.append(etree.fromstring(marker)) - - # attach marker to node - style = node.get('style', '').split(";") - import sys - print(style, file=sys.stderr) - style = [i for i in style if not i.startswith('marker-start')] - style.append('marker-start:url(#inkstitch-pattern-marker)') - node.set('style', ";".join(style)) diff --git a/lib/extensions/base.py b/lib/extensions/base.py index 00d4a00d..ce5f8b1d 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -12,7 +12,7 @@ import inkex from lxml import etree from stringcase import snakecase -from ..commands import is_command, layer_commands +from ..commands import is_command, layer_commands, group_commands from ..elements import EmbroideryElement, nodes_to_elements from ..elements.clone import is_clone from ..i18n import _ @@ -171,9 +171,12 @@ class InkstitchExtension(inkex.Effect): if selected: if node.tag == SVG_GROUP_TAG: pass - elif (node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not node.get(INKSTITCH_ATTRIBS['pattern']): + elif ((node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not + (len(list(group_commands(node, 'pattern_group'))) and not node.get(INKSTITCH_ATTRIBS['satin_column']))): nodes.append(node) - elif troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or node.get(INKSTITCH_ATTRIBS['pattern'])): + # add images, text and patterns for the troubleshoot extension + elif (troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or + (len(list(group_commands(node, 'pattern_group'))) and not node.get(INKSTITCH_ATTRIBS['satin_column'])))): nodes.append(node) return nodes diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg index 4a67ae1c..f380d106 100644 --- a/symbols/inkstitch.svg +++ b/symbols/inkstitch.svg @@ -58,6 +58,21 @@ id="title9425">Ink/Stitch Commands + + Pattern group + + + + <use + xlink:href="#inkstitch_pattern_group" + id="use9462" + x="0" + y="0" + width="100%" + height="100%" + transform="translate(189.0002,37.680421)" /> <use xlink:href="#inkstitch_trim" id="use9461" diff --git a/templates/apply_satin_pattern.xml b/templates/apply_satin_pattern.xml deleted file mode 100644 index e52fb1a4..00000000 --- a/templates/apply_satin_pattern.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> - <name>{% trans %}Apply Satin Pattern{% endtrans %}</name> - <id>org.inkstitch.apply_satin_pattern.{{ locale }}</id> - <param name="extension" type="string" gui-hidden="true">apply_satin_pattern</param> - <effect> - <object-type>all</object-type> - <effects-menu> - <submenu name="Ink/Stitch"> - <submenu name="{% trans %}Satin Tools{% endtrans %}" /> - </submenu> - </effects-menu> - </effect> - <script> - {{ command_tag | safe }} - </script> -</inkscape-extension> -- cgit v1.3.1 From 2f54ff2a436f2774bfdc730b6e95c43f18ed81ac Mon Sep 17 00:00:00 2001 From: Kaalleen <reni@allenka.de> Date: Sun, 27 Jun 2021 22:47:43 +0200 Subject: group command extension --- lib/elements/satin_column.py | 2 +- lib/elements/utils.py | 3 +-- lib/extensions/__init__.py | 2 ++ lib/extensions/base.py | 2 +- lib/extensions/group_commands.py | 41 ++++++++++++++++++++++++++++++++++++++++ lib/inx/extensions.py | 9 +++++++-- templates/group_commands.xml | 21 ++++++++++++++++++++ 7 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 lib/extensions/group_commands.py create mode 100644 templates/group_commands.xml (limited to 'lib/extensions') 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 diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index 25f835c3..a6d25d2c 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -14,6 +14,7 @@ from .duplicate_params import DuplicateParams from .embroider_settings import EmbroiderSettings from .flip import Flip from .global_commands import GlobalCommands +from .group_commands import GroupCommands from .import_threadlist import ImportThreadlist from .input import Input from .install import Install @@ -41,6 +42,7 @@ __all__ = extensions = [StitchPlanPreview, Zip, Flip, ObjectCommands, + GroupCommands, LayerCommands, GlobalCommands, ConvertToSatin, diff --git a/lib/extensions/base.py b/lib/extensions/base.py index ce5f8b1d..353e433c 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -12,7 +12,7 @@ import inkex from lxml import etree from stringcase import snakecase -from ..commands import is_command, layer_commands, group_commands +from ..commands import group_commands, is_command, layer_commands from ..elements import EmbroideryElement, nodes_to_elements from ..elements.clone import is_clone from ..i18n import _ diff --git a/lib/extensions/group_commands.py b/lib/extensions/group_commands.py new file mode 100644 index 00000000..af1f9fb1 --- /dev/null +++ b/lib/extensions/group_commands.py @@ -0,0 +1,41 @@ +# 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 lxml import etree + +from ..commands import GROUP_COMMANDS, ensure_symbol, get_command_description +from ..i18n import _ +from ..svg import get_correction_transform +from ..svg.tags import INKSCAPE_LABEL, SVG_USE_TAG, XLINK_HREF +from .commands import CommandsExtension + + +class GroupCommands(CommandsExtension): + COMMANDS = GROUP_COMMANDS + + def effect(self): + commands = [command for command in self.COMMANDS if getattr(self.options, command)] + + if not commands: + inkex.errormsg(_("Please choose one or more commands to add.")) + return + + correction_transform = get_correction_transform(self.svg.get_current_layer(), child=True) + + for i, command in enumerate(commands): + ensure_symbol(self.document, command) + + etree.SubElement(self.svg.get_current_layer(), SVG_USE_TAG, + { + "id": self.uniqueId("use"), + INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command), + XLINK_HREF: "#inkstitch_%s" % command, + "height": "100%", + "width": "100%", + "x": str(i * 20), + "y": "-10", + "transform": correction_transform + }) diff --git a/lib/inx/extensions.py b/lib/inx/extensions.py index 9a197c5d..8ca0addc 100755 --- a/lib/inx/extensions.py +++ b/lib/inx/extensions.py @@ -5,8 +5,8 @@ import pyembroidery -from ..commands import (COMMANDS, GLOBAL_COMMANDS, LAYER_COMMANDS, - OBJECT_COMMANDS) +from ..commands import (COMMANDS, GLOBAL_COMMANDS, GROUP_COMMANDS, + LAYER_COMMANDS, OBJECT_COMMANDS) from ..extensions import Input, Output, extensions from ..threads import ThreadCatalog from .outputs import pyembroidery_output_formats @@ -24,6 +24,10 @@ def global_commands(): return [(command, COMMANDS[command]) for command in GLOBAL_COMMANDS] +def group_commands(): + return [(command, COMMANDS[command]) for command in GROUP_COMMANDS] + + def object_commands(): return [(command, COMMANDS[command]) for command in OBJECT_COMMANDS] @@ -51,6 +55,7 @@ def generate_extension_inx_files(): write_inx_file(name, template.render(formats=pyembroidery_output_formats(), debug_formats=pyembroidery_debug_formats(), threadcatalog=threadcatalog(), + group_commands=group_commands(), layer_commands=layer_commands(), object_commands=object_commands(), global_commands=global_commands())) diff --git a/templates/group_commands.xml b/templates/group_commands.xml new file mode 100644 index 00000000..2a67c5b7 --- /dev/null +++ b/templates/group_commands.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>{% trans %}Add Group Commands{% endtrans %}</name> + <id>org.inkstitch.group_commands.{{ locale }}</id> + <param name="description" type="description">{% trans %}Commands will be added to the currently-selected group.{% endtrans %}</param> + {% for command, description in group_commands %} + <param name="{{ command }}" type="boolean" _gui-text="{{ _(description) }}">false</param> + {% endfor %} + <param name="extension" type="string" gui-hidden="true">group_commands</param> + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu name="Ink/Stitch"> + <submenu name="{% trans %}Commands{% endtrans %}" /> + </submenu> + </effects-menu> + </effect> + <script> + {{ command_tag | safe }} + </script> +</inkscape-extension> -- cgit v1.3.1 From ecacb9829e9c2b7050486707211f9d176aafdf75 Mon Sep 17 00:00:00 2001 From: Kaalleen <reni@allenka.de> Date: Mon, 28 Jun 2021 20:05:50 +0200 Subject: pattern markers --- lib/commands.py | 7 ----- lib/elements/pattern.py | 4 +++ lib/elements/satin_column.py | 7 +++-- lib/elements/utils.py | 11 ++++--- lib/extensions/__init__.py | 4 +-- lib/extensions/apply_pattern.py | 62 ++++++++++++++++++++++++++++++++++++++++ lib/extensions/base.py | 12 ++++---- lib/extensions/group_commands.py | 41 -------------------------- lib/inx/extensions.py | 9 ++---- templates/apply_pattern.xml | 15 ++++++++++ templates/group_commands.xml | 21 -------------- 11 files changed, 100 insertions(+), 93 deletions(-) create mode 100644 lib/extensions/apply_pattern.py delete mode 100644 lib/extensions/group_commands.py create mode 100644 templates/apply_pattern.xml delete mode 100644 templates/group_commands.xml (limited to 'lib/extensions') diff --git a/lib/commands.py b/lib/commands.py index ea6d3509..cb2a74d5 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -60,7 +60,6 @@ COMMANDS = { } OBJECT_COMMANDS = ["fill_start", "fill_end", "satin_start", "satin_end", "stop", "trim", "ignore_object", "satin_cut_point"] -GROUP_COMMANDS = ["pattern_group"] LAYER_COMMANDS = ["ignore_layer"] GLOBAL_COMMANDS = ["origin", "stop_position"] @@ -187,12 +186,6 @@ def find_commands(node): return commands -def group_commands(node, command): - xpath = "./ancestor::svg:g/svg:use[@xlink:href='#inkstitch_%(command)s']" % dict(id=node.get('id'), command=command) - group_command = node.xpath(xpath, namespaces=inkex.NSS) - return group_command - - def layer_commands(layer, command): """Find standalone (unconnected) command symbols in this layer.""" 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: diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index a6d25d2c..3bd2fef6 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -5,6 +5,7 @@ from lib.extensions.troubleshoot import Troubleshoot +from .apply_pattern import ApplyPattern from .auto_satin import AutoSatin from .break_apart import BreakApart from .cleanup import Cleanup @@ -14,7 +15,6 @@ from .duplicate_params import DuplicateParams from .embroider_settings import EmbroiderSettings from .flip import Flip from .global_commands import GlobalCommands -from .group_commands import GroupCommands from .import_threadlist import ImportThreadlist from .input import Input from .install import Install @@ -41,8 +41,8 @@ __all__ = extensions = [StitchPlanPreview, Output, Zip, Flip, + ApplyPattern, ObjectCommands, - GroupCommands, LayerCommands, GlobalCommands, ConvertToSatin, diff --git a/lib/extensions/apply_pattern.py b/lib/extensions/apply_pattern.py new file mode 100644 index 00000000..ad881604 --- /dev/null +++ b/lib/extensions/apply_pattern.py @@ -0,0 +1,62 @@ +# Authors: see git history +# +# Copyright (c) 2021 Authors +# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +import inkex +from lxml import etree + +from ..i18n import _ +from ..svg.tags import SVG_DEFS_TAG +from .base import InkstitchExtension + + +class ApplyPattern(InkstitchExtension): + # This extension will mark selected + + def effect(self): + if not self.get_elements(): + return + + if not self.svg.selected: + inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) + return + + for pattern in self.svg.selected.values(): + self.set_marker(pattern) + + def set_marker(self, node): + xpath = ".//marker[@id='inkstitch-pattern-marker']" + pattern_marker = self.document.xpath(xpath) + + if not pattern_marker: + # get or create def element + defs = self.document.find(SVG_DEFS_TAG) + if defs is None: + defs = etree.SubElement(self.document, SVG_DEFS_TAG) + + # insert marker + marker = """<marker + refX="10" + refY="5" + orient="auto" + id="inkstitch-pattern-marker"> + <g + id="inkstitch-pattern-group"> + <path + style="fill:#fafafa;stroke:#ff5500;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1;fill-opacity:0.8;" + d="M 10.12911,5.2916678 A 4.8374424,4.8374426 0 0 1 5.2916656,10.12911 4.8374424,4.8374426 0 0 1 0.45422399,5.2916678 4.8374424,4.8374426 0 0 1 5.2916656,0.45422399 4.8374424,4.8374426 0 0 1 10.12911,5.2916678 Z" + id="inkstitch-pattern-marker-circle" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.4;stroke-linecap:round;stroke-miterlimit:4;" + id="inkstitch-pattern-marker-spiral" + d="M 4.9673651,5.7245662 C 4.7549848,5.7646159 4.6247356,5.522384 4.6430021,5.3419847 4.6765851,5.0103151 5.036231,4.835347 5.3381858,4.8987426 5.7863901,4.9928495 6.0126802,5.4853625 5.9002872,5.9065088 5.7495249,6.4714237 5.1195537,6.7504036 4.5799191,6.5874894 3.898118,6.3816539 3.5659013,5.6122905 3.7800789,4.9545192 4.0402258,4.1556558 4.9498996,3.7699484 5.7256318,4.035839 6.6416744,4.3498087 7.0810483,5.4003986 6.7631909,6.2939744 6.395633,7.3272552 5.2038143,7.8204128 4.1924535,7.4503931 3.0418762,7.0294421 2.4948761,5.6961604 2.9171752,4.567073 3.3914021,3.2991406 4.8663228,2.6982592 6.1130974,3.1729158 7.4983851,3.7003207 8.1531869,5.3169977 7.6260947,6.6814205 7.0456093,8.1841025 5.2870784,8.8928844 3.8050073,8.3132966 2.1849115,7.6797506 1.4221671,5.7793073 2.0542715,4.1796074 2.7408201,2.4420977 4.7832541,1.6253548 6.5005435,2.310012 8.3554869,3.0495434 9.2262638,5.2339874 8.4890181,7.0688861 8.4256397,7.2266036 8.3515789,7.379984 8.2675333,7.5277183" /> + </g> + </marker>""" # noqa: E501 + defs.append(etree.fromstring(marker)) + + # attach marker to node + style = node.get('style', '').split(";") + style = [i for i in style if not i.startswith('marker-start')] + style.append('marker-start:url(#inkstitch-pattern-marker)') + node.set('style', ";".join(style)) diff --git a/lib/extensions/base.py b/lib/extensions/base.py index 353e433c..1c10cd4a 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -12,14 +12,14 @@ import inkex from lxml import etree from stringcase import snakecase -from ..commands import group_commands, is_command, layer_commands +from ..commands import is_command, layer_commands from ..elements import EmbroideryElement, nodes_to_elements from ..elements.clone import is_clone +from ..elements.pattern import is_pattern from ..i18n import _ from ..svg import generate_unique_id from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE, - INKSTITCH_ATTRIBS, NOT_EMBROIDERABLE_TAGS, - SVG_DEFS_TAG, SVG_GROUP_TAG) + NOT_EMBROIDERABLE_TAGS, SVG_DEFS_TAG, SVG_GROUP_TAG) SVG_METADATA_TAG = inkex.addNS("metadata", "svg") @@ -171,12 +171,10 @@ class InkstitchExtension(inkex.Effect): if selected: if node.tag == SVG_GROUP_TAG: pass - elif ((node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not - (len(list(group_commands(node, 'pattern_group'))) and not node.get(INKSTITCH_ATTRIBS['satin_column']))): + elif (node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not is_pattern(node): nodes.append(node) # add images, text and patterns for the troubleshoot extension - elif (troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or - (len(list(group_commands(node, 'pattern_group'))) and not node.get(INKSTITCH_ATTRIBS['satin_column'])))): + elif troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or is_pattern(node)): nodes.append(node) return nodes diff --git a/lib/extensions/group_commands.py b/lib/extensions/group_commands.py deleted file mode 100644 index af1f9fb1..00000000 --- a/lib/extensions/group_commands.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 lxml import etree - -from ..commands import GROUP_COMMANDS, ensure_symbol, get_command_description -from ..i18n import _ -from ..svg import get_correction_transform -from ..svg.tags import INKSCAPE_LABEL, SVG_USE_TAG, XLINK_HREF -from .commands import CommandsExtension - - -class GroupCommands(CommandsExtension): - COMMANDS = GROUP_COMMANDS - - def effect(self): - commands = [command for command in self.COMMANDS if getattr(self.options, command)] - - if not commands: - inkex.errormsg(_("Please choose one or more commands to add.")) - return - - correction_transform = get_correction_transform(self.svg.get_current_layer(), child=True) - - for i, command in enumerate(commands): - ensure_symbol(self.document, command) - - etree.SubElement(self.svg.get_current_layer(), SVG_USE_TAG, - { - "id": self.uniqueId("use"), - INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command), - XLINK_HREF: "#inkstitch_%s" % command, - "height": "100%", - "width": "100%", - "x": str(i * 20), - "y": "-10", - "transform": correction_transform - }) diff --git a/lib/inx/extensions.py b/lib/inx/extensions.py index 8ca0addc..9a197c5d 100755 --- a/lib/inx/extensions.py +++ b/lib/inx/extensions.py @@ -5,8 +5,8 @@ import pyembroidery -from ..commands import (COMMANDS, GLOBAL_COMMANDS, GROUP_COMMANDS, - LAYER_COMMANDS, OBJECT_COMMANDS) +from ..commands import (COMMANDS, GLOBAL_COMMANDS, LAYER_COMMANDS, + OBJECT_COMMANDS) from ..extensions import Input, Output, extensions from ..threads import ThreadCatalog from .outputs import pyembroidery_output_formats @@ -24,10 +24,6 @@ def global_commands(): return [(command, COMMANDS[command]) for command in GLOBAL_COMMANDS] -def group_commands(): - return [(command, COMMANDS[command]) for command in GROUP_COMMANDS] - - def object_commands(): return [(command, COMMANDS[command]) for command in OBJECT_COMMANDS] @@ -55,7 +51,6 @@ def generate_extension_inx_files(): write_inx_file(name, template.render(formats=pyembroidery_output_formats(), debug_formats=pyembroidery_debug_formats(), threadcatalog=threadcatalog(), - group_commands=group_commands(), layer_commands=layer_commands(), object_commands=object_commands(), global_commands=global_commands())) diff --git a/templates/apply_pattern.xml b/templates/apply_pattern.xml new file mode 100644 index 00000000..cbd83dbc --- /dev/null +++ b/templates/apply_pattern.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>{% trans %}Apply Pattern{% endtrans %}</name> + <id>org.inkstitch.apply_pattern.{{ locale }}</id> + <param name="extension" type="string" gui-hidden="true">apply_pattern</param> + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu name="Ink/Stitch" /> + </effects-menu> + </effect> + <script> + {{ command_tag | safe }} + </script> +</inkscape-extension> diff --git a/templates/group_commands.xml b/templates/group_commands.xml deleted file mode 100644 index 2a67c5b7..00000000 --- a/templates/group_commands.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> - <name>{% trans %}Add Group Commands{% endtrans %}</name> - <id>org.inkstitch.group_commands.{{ locale }}</id> - <param name="description" type="description">{% trans %}Commands will be added to the currently-selected group.{% endtrans %}</param> - {% for command, description in group_commands %} - <param name="{{ command }}" type="boolean" _gui-text="{{ _(description) }}">false</param> - {% endfor %} - <param name="extension" type="string" gui-hidden="true">group_commands</param> - <effect> - <object-type>all</object-type> - <effects-menu> - <submenu name="Ink/Stitch"> - <submenu name="{% trans %}Commands{% endtrans %}" /> - </submenu> - </effects-menu> - </effect> - <script> - {{ command_tag | safe }} - </script> -</inkscape-extension> -- cgit v1.3.1 From 52d9ee6a6d97b2ea752f5fdd3080a160a3574f82 Mon Sep 17 00:00:00 2001 From: Kaalleen <reni@allenka.de> 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 +- lib/extensions/__init__.py | 4 +-- lib/extensions/apply_pattern.py | 62 -------------------------------- lib/extensions/base.py | 2 +- lib/extensions/selection_to_pattern.py | 61 +++++++++++++++++++++++++++++++ lib/patterns.py | 66 ++++++++++++++++++++++++++++++++++ templates/apply_pattern.xml | 15 -------- templates/selection_to_pattern.xml | 17 +++++++++ 10 files changed, 151 insertions(+), 136 deletions(-) delete mode 100644 lib/extensions/apply_pattern.py create mode 100644 lib/extensions/selection_to_pattern.py create mode 100644 lib/patterns.py delete mode 100644 templates/apply_pattern.xml create mode 100644 templates/selection_to_pattern.xml (limited to 'lib/extensions') 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 diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index 3bd2fef6..7996770d 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -5,7 +5,6 @@ from lib.extensions.troubleshoot import Troubleshoot -from .apply_pattern import ApplyPattern from .auto_satin import AutoSatin from .break_apart import BreakApart from .cleanup import Cleanup @@ -29,6 +28,7 @@ from .params import Params from .print_pdf import Print from .remove_embroidery_settings import RemoveEmbroiderySettings from .reorder import Reorder +from .selection_to_pattern import SelectionToPattern from .simulator import Simulator from .stitch_plan_preview import StitchPlanPreview from .zip import Zip @@ -41,7 +41,7 @@ __all__ = extensions = [StitchPlanPreview, Output, Zip, Flip, - ApplyPattern, + SelectionToPattern, ObjectCommands, LayerCommands, GlobalCommands, diff --git a/lib/extensions/apply_pattern.py b/lib/extensions/apply_pattern.py deleted file mode 100644 index ad881604..00000000 --- a/lib/extensions/apply_pattern.py +++ /dev/null @@ -1,62 +0,0 @@ -# Authors: see git history -# -# Copyright (c) 2021 Authors -# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - -import inkex -from lxml import etree - -from ..i18n import _ -from ..svg.tags import SVG_DEFS_TAG -from .base import InkstitchExtension - - -class ApplyPattern(InkstitchExtension): - # This extension will mark selected - - def effect(self): - if not self.get_elements(): - return - - if not self.svg.selected: - inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) - return - - for pattern in self.svg.selected.values(): - self.set_marker(pattern) - - def set_marker(self, node): - xpath = ".//marker[@id='inkstitch-pattern-marker']" - pattern_marker = self.document.xpath(xpath) - - if not pattern_marker: - # get or create def element - defs = self.document.find(SVG_DEFS_TAG) - if defs is None: - defs = etree.SubElement(self.document, SVG_DEFS_TAG) - - # insert marker - marker = """<marker - refX="10" - refY="5" - orient="auto" - id="inkstitch-pattern-marker"> - <g - id="inkstitch-pattern-group"> - <path - style="fill:#fafafa;stroke:#ff5500;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1;fill-opacity:0.8;" - d="M 10.12911,5.2916678 A 4.8374424,4.8374426 0 0 1 5.2916656,10.12911 4.8374424,4.8374426 0 0 1 0.45422399,5.2916678 4.8374424,4.8374426 0 0 1 5.2916656,0.45422399 4.8374424,4.8374426 0 0 1 10.12911,5.2916678 Z" - id="inkstitch-pattern-marker-circle" /> - <path - style="fill:none;stroke:#000000;stroke-width:0.4;stroke-linecap:round;stroke-miterlimit:4;" - id="inkstitch-pattern-marker-spiral" - d="M 4.9673651,5.7245662 C 4.7549848,5.7646159 4.6247356,5.522384 4.6430021,5.3419847 4.6765851,5.0103151 5.036231,4.835347 5.3381858,4.8987426 5.7863901,4.9928495 6.0126802,5.4853625 5.9002872,5.9065088 5.7495249,6.4714237 5.1195537,6.7504036 4.5799191,6.5874894 3.898118,6.3816539 3.5659013,5.6122905 3.7800789,4.9545192 4.0402258,4.1556558 4.9498996,3.7699484 5.7256318,4.035839 6.6416744,4.3498087 7.0810483,5.4003986 6.7631909,6.2939744 6.395633,7.3272552 5.2038143,7.8204128 4.1924535,7.4503931 3.0418762,7.0294421 2.4948761,5.6961604 2.9171752,4.567073 3.3914021,3.2991406 4.8663228,2.6982592 6.1130974,3.1729158 7.4983851,3.7003207 8.1531869,5.3169977 7.6260947,6.6814205 7.0456093,8.1841025 5.2870784,8.8928844 3.8050073,8.3132966 2.1849115,7.6797506 1.4221671,5.7793073 2.0542715,4.1796074 2.7408201,2.4420977 4.7832541,1.6253548 6.5005435,2.310012 8.3554869,3.0495434 9.2262638,5.2339874 8.4890181,7.0688861 8.4256397,7.2266036 8.3515789,7.379984 8.2675333,7.5277183" /> - </g> - </marker>""" # noqa: E501 - defs.append(etree.fromstring(marker)) - - # attach marker to node - style = node.get('style', '').split(";") - style = [i for i in style if not i.startswith('marker-start')] - style.append('marker-start:url(#inkstitch-pattern-marker)') - node.set('style', ";".join(style)) diff --git a/lib/extensions/base.py b/lib/extensions/base.py index 1c10cd4a..862d031e 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -15,8 +15,8 @@ from stringcase import snakecase from ..commands import is_command, layer_commands from ..elements import EmbroideryElement, nodes_to_elements from ..elements.clone import is_clone -from ..elements.pattern import is_pattern from ..i18n import _ +from ..patterns import is_pattern from ..svg import generate_unique_id from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE, NOT_EMBROIDERABLE_TAGS, SVG_DEFS_TAG, SVG_GROUP_TAG) diff --git a/lib/extensions/selection_to_pattern.py b/lib/extensions/selection_to_pattern.py new file mode 100644 index 00000000..3527cc5e --- /dev/null +++ b/lib/extensions/selection_to_pattern.py @@ -0,0 +1,61 @@ +# Authors: see git history +# +# Copyright (c) 2021 Authors +# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +import inkex +from lxml import etree + +from ..i18n import _ +from ..svg.tags import SVG_DEFS_TAG +from .base import InkstitchExtension + + +class SelectionToPattern(InkstitchExtension): + + def effect(self): + if not self.get_elements(): + return + + if not self.svg.selected: + inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) + return + + for pattern in self.svg.selected.values(): + self.set_marker(pattern) + + def set_marker(self, node): + xpath = ".//marker[@id='inkstitch-pattern-marker']" + pattern_marker = self.document.xpath(xpath) + + if not pattern_marker: + # get or create def element + defs = self.document.find(SVG_DEFS_TAG) + if defs is None: + defs = etree.SubElement(self.document, SVG_DEFS_TAG) + + # insert marker + marker = """<marker + refX="10" + refY="5" + orient="auto" + id="inkstitch-pattern-marker"> + <g + id="inkstitch-pattern-group"> + <path + style="fill:#fafafa;stroke:#ff5500;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1;fill-opacity:0.8;" + d="M 10.12911,5.2916678 A 4.8374424,4.8374426 0 0 1 5.2916656,10.12911 4.8374424,4.8374426 0 0 1 0.45422399,5.2916678 4.8374424,4.8374426 0 0 1 5.2916656,0.45422399 4.8374424,4.8374426 0 0 1 10.12911,5.2916678 Z" + id="inkstitch-pattern-marker-circle" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.4;stroke-linecap:round;stroke-miterlimit:4;" + id="inkstitch-pattern-marker-spiral" + d="M 4.9673651,5.7245662 C 4.7549848,5.7646159 4.6247356,5.522384 4.6430021,5.3419847 4.6765851,5.0103151 5.036231,4.835347 5.3381858,4.8987426 5.7863901,4.9928495 6.0126802,5.4853625 5.9002872,5.9065088 5.7495249,6.4714237 5.1195537,6.7504036 4.5799191,6.5874894 3.898118,6.3816539 3.5659013,5.6122905 3.7800789,4.9545192 4.0402258,4.1556558 4.9498996,3.7699484 5.7256318,4.035839 6.6416744,4.3498087 7.0810483,5.4003986 6.7631909,6.2939744 6.395633,7.3272552 5.2038143,7.8204128 4.1924535,7.4503931 3.0418762,7.0294421 2.4948761,5.6961604 2.9171752,4.567073 3.3914021,3.2991406 4.8663228,2.6982592 6.1130974,3.1729158 7.4983851,3.7003207 8.1531869,5.3169977 7.6260947,6.6814205 7.0456093,8.1841025 5.2870784,8.8928844 3.8050073,8.3132966 2.1849115,7.6797506 1.4221671,5.7793073 2.0542715,4.1796074 2.7408201,2.4420977 4.7832541,1.6253548 6.5005435,2.310012 8.3554869,3.0495434 9.2262638,5.2339874 8.4890181,7.0688861 8.4256397,7.2266036 8.3515789,7.379984 8.2675333,7.5277183" /> + </g> + </marker>""" # noqa: E501 + defs.append(etree.fromstring(marker)) + + # attach marker to node + style = node.get('style', '').split(";") + style = [i for i in style if not i.startswith('marker-start')] + style.append('marker-start:url(#inkstitch-pattern-marker)') + node.set('style', ";".join(style)) diff --git a/lib/patterns.py b/lib/patterns.py new file mode 100644 index 00000000..8872a8ce --- /dev/null +++ b/lib/patterns.py @@ -0,0 +1,66 @@ +# 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 shapely import geometry as shgeo + +from .svg import apply_transforms +from .svg.tags import EMBROIDERABLE_TAGS +from .utils import Point + + +def is_pattern(node): + if node.tag not in EMBROIDERABLE_TAGS: + return False + return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') + + +def apply_patterns(patches, node): + patterns = _get_patterns(node) + 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 = _get_pattern_points(stitch, patch.stitches[i+1], patterns) + for point in intersection_points: + patch_points.append(point) + patch.stitches = patch_points + + +def _get_patterns(node): + xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" + patterns = 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) + inkex.bezier.cspsubdiv(path, 0.1) + path = [[point for control_before, point, control_after in subpath] for subpath in path] + lines = [shgeo.LineString(p) for p in path] + for line in lines: + line_strings.append(line) + return shgeo.MultiLineString(line_strings) + + +def _get_pattern_points(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 diff --git a/templates/apply_pattern.xml b/templates/apply_pattern.xml deleted file mode 100644 index cbd83dbc..00000000 --- a/templates/apply_pattern.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> - <name>{% trans %}Apply Pattern{% endtrans %}</name> - <id>org.inkstitch.apply_pattern.{{ locale }}</id> - <param name="extension" type="string" gui-hidden="true">apply_pattern</param> - <effect> - <object-type>all</object-type> - <effects-menu> - <submenu name="Ink/Stitch" /> - </effects-menu> - </effect> - <script> - {{ command_tag | safe }} - </script> -</inkscape-extension> diff --git a/templates/selection_to_pattern.xml b/templates/selection_to_pattern.xml new file mode 100644 index 00000000..859a51ed --- /dev/null +++ b/templates/selection_to_pattern.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>{% trans %}Selection to pattern{% endtrans %}</name> + <id>org.inkstitch.selection_to_pattern.{{ locale }}</id> + <param name="extension" type="string" gui-hidden="true">selection_to_pattern</param> + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu name="Ink/Stitch"> + <submenu name="{% trans %}Edit{% endtrans %}" /> + </submenu> + </effects-menu> + </effect> + <script> + {{ command_tag | safe }} + </script> +</inkscape-extension> -- cgit v1.3.1 From a1581202646172707768d24bb5dcba63bd5d4538 Mon Sep 17 00:00:00 2001 From: Kaalleen <reni@allenka.de> Date: Wed, 30 Jun 2021 16:36:25 +0200 Subject: fix selection in selection to pattern --- lib/extensions/selection_to_pattern.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/extensions') diff --git a/lib/extensions/selection_to_pattern.py b/lib/extensions/selection_to_pattern.py index 3527cc5e..52a0404b 100644 --- a/lib/extensions/selection_to_pattern.py +++ b/lib/extensions/selection_to_pattern.py @@ -7,7 +7,7 @@ import inkex from lxml import etree from ..i18n import _ -from ..svg.tags import SVG_DEFS_TAG +from ..svg.tags import EMBROIDERABLE_TAGS, SVG_DEFS_TAG from .base import InkstitchExtension @@ -21,8 +21,9 @@ class SelectionToPattern(InkstitchExtension): inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) return - for pattern in self.svg.selected.values(): - self.set_marker(pattern) + for pattern in self.get_nodes(): + if pattern.tag in EMBROIDERABLE_TAGS: + self.set_marker(pattern) def set_marker(self, node): xpath = ".//marker[@id='inkstitch-pattern-marker']" -- cgit v1.3.1 From a5d7ffaffd0b73b5848b7d55ea1f571ea94fd5a7 Mon Sep 17 00:00:00 2001 From: Kaalleen <reni@allenka.de> Date: Wed, 7 Jul 2021 20:07:04 +0200 Subject: add or remove stitches (stroke or fill) --- lib/extensions/selection_to_pattern.py | 3 +- lib/patterns.py | 108 ++++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 36 deletions(-) (limited to 'lib/extensions') diff --git a/lib/extensions/selection_to_pattern.py b/lib/extensions/selection_to_pattern.py index 52a0404b..41f89a83 100644 --- a/lib/extensions/selection_to_pattern.py +++ b/lib/extensions/selection_to_pattern.py @@ -56,7 +56,8 @@ class SelectionToPattern(InkstitchExtension): defs.append(etree.fromstring(marker)) # attach marker to node - style = node.get('style', '').split(";") + style = node.get('style') or '' + style = style.split(";") style = [i for i in style if not i.startswith('marker-start')] style.append('marker-start:url(#inkstitch-pattern-marker)') node.set('style', ";".join(style)) diff --git a/lib/patterns.py b/lib/patterns.py index 8872a8ce..5ae763fc 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -5,8 +5,8 @@ import inkex from shapely import geometry as shgeo +import math -from .svg import apply_transforms from .svg.tags import EMBROIDERABLE_TAGS from .utils import Point @@ -14,53 +14,91 @@ from .utils import Point def is_pattern(node): if node.tag not in EMBROIDERABLE_TAGS: return False - return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') + style = node.get('style') or '' + return "marker-start:url(#inkstitch-pattern-marker)" in style def apply_patterns(patches, node): patterns = _get_patterns(node) - if not patterns: - return patches + _apply_stroke_patterns(patterns['stroke_patterns'], patches) + _apply_fill_patterns(patterns['fill_patterns'], 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 = _get_pattern_points(stitch, patch.stitches[i+1], patterns) - for point in intersection_points: - patch_points.append(point) - patch.stitches = patch_points + +def _apply_stroke_patterns(patterns, patches): + for pattern in patterns: + for patch in patches: + patch_points = [] + for i, stitch in enumerate(patch.stitches): + patch_points.append(stitch) + if i == len(patch.stitches) - 1: + continue + intersection_points = _get_pattern_points(stitch, patch.stitches[i+1], pattern) + for point in intersection_points: + patch_points.append(point) + patch.stitches = patch_points + + +def _apply_fill_patterns(patterns, patches): + for pattern in patterns: + for patch in patches: + patch_points = [] + for i, stitch in enumerate(patch.stitches): + # keep points outside the fill patter + if not shgeo.Point(stitch).within(pattern): + patch_points.append(stitch) + # keep start and end points + elif i - 1 < 0 or i >= len(patch.stitches) - 1: + patch_points.append(stitch) + # keep points if they have an angle + # the necessary angle can be variable with certain stitch types (later on) + # but they don't need to use filled patterns for those + elif not 179 < get_angle(patch.stitches[i-1], stitch, patch.stitches[i+1]) < 181: + patch_points.append(stitch) + patch.stitches = patch_points def _get_patterns(node): + from .elements import EmbroideryElement + from .elements.fill import Fill + from .elements.stroke import Stroke + + fills = [] + strokes = [] xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" patterns = 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) - inkex.bezier.cspsubdiv(path, 0.1) - path = [[point for control_before, point, control_after in subpath] for subpath in path] - lines = [shgeo.LineString(p) for p in path] - for line in lines: - line_strings.append(line) - return shgeo.MultiLineString(line_strings) - - -def _get_pattern_points(first, second, patterns): + + element = EmbroideryElement(pattern) + fill = element.get_style('fill') + stroke = element.get_style('stroke') + + if fill is not None: + fill_pattern = Fill(pattern).shape + fills.append(fill_pattern) + + if stroke is not None: + stroke_pattern = Stroke(pattern).paths + line_strings = [shgeo.LineString(path) for path in stroke_pattern] + strokes.append(shgeo.MultiLineString(line_strings)) + + return {'fill_patterns': fills, 'stroke_patterns': strokes} + + +def _get_pattern_points(first, second, pattern): 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 + 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 first points.sort(key=lambda point: point.distance(first)) return points + + +def get_angle(a, b, c): + ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])) + return ang + 360 if ang < 0 else ang -- cgit v1.3.1 From 173548dee569b0503ba1ddeba5cb8aae74c44c46 Mon Sep 17 00:00:00 2001 From: Lex Neva <github.com@lexneva.name> Date: Sat, 7 Aug 2021 12:18:55 -0400 Subject: rename more patch references --- lib/api/stitch_plan.py | 4 ++-- lib/extensions/output.py | 4 ++-- lib/extensions/print_pdf.py | 4 ++-- lib/extensions/stitch_plan_preview.py | 4 ++-- lib/extensions/zip.py | 4 ++-- lib/gui/simulator.py | 4 ++-- lib/stitch_plan/__init__.py | 2 +- lib/stitch_plan/stitch_plan.py | 30 +++++++++++++++--------------- 8 files changed, 28 insertions(+), 28 deletions(-) (limited to 'lib/extensions') diff --git a/lib/api/stitch_plan.py b/lib/api/stitch_plan.py index 2011b592..9c9bb4ac 100644 --- a/lib/api/stitch_plan.py +++ b/lib/api/stitch_plan.py @@ -5,7 +5,7 @@ from flask import Blueprint, g, jsonify -from ..stitch_plan import patches_to_stitch_plan +from ..stitch_plan import stitch_groups_to_stitch_plan stitch_plan = Blueprint('stitch_plan', __name__) @@ -19,6 +19,6 @@ def get_stitch_plan(): metadata = g.extension.get_inkstitch_metadata() collapse_len = metadata['collapse_len_mm'] patches = g.extension.elements_to_patches(g.extension.elements) - stitch_plan = patches_to_stitch_plan(patches, collapse_len=collapse_len) + stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) return jsonify(stitch_plan) diff --git a/lib/extensions/output.py b/lib/extensions/output.py index e621f1b6..f993f79f 100644 --- a/lib/extensions/output.py +++ b/lib/extensions/output.py @@ -8,7 +8,7 @@ import sys import tempfile from ..output import write_embroidery_file -from ..stitch_plan import patches_to_stitch_plan +from ..stitch_plan import stitch_groups_to_stitch_plan from .base import InkstitchExtension @@ -53,7 +53,7 @@ class Output(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] patches = self.elements_to_patches(self.elements) - stitch_plan = patches_to_stitch_plan(patches, collapse_len=collapse_len, disable_ties=self.settings.get('laser_mode', False)) + stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len, disable_ties=self.settings.get('laser_mode', False)) temp_file = tempfile.NamedTemporaryFile(suffix=".%s" % self.file_extension, delete=False) diff --git a/lib/extensions/print_pdf.py b/lib/extensions/print_pdf.py index 0facdf92..ed796bc7 100644 --- a/lib/extensions/print_pdf.py +++ b/lib/extensions/print_pdf.py @@ -23,7 +23,7 @@ from werkzeug.serving import make_server from ..gui import open_url from ..i18n import get_languages from ..i18n import translation as inkstitch_translation -from ..stitch_plan import patches_to_stitch_plan +from ..stitch_plan import stitch_groups_to_stitch_plan from ..svg import render_stitch_plan from ..svg.tags import INKSCAPE_GROUPMODE from ..threads import ThreadCatalog @@ -303,7 +303,7 @@ class Print(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] patches = self.elements_to_patches(self.elements) - stitch_plan = patches_to_stitch_plan(patches, collapse_len=collapse_len) + stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) palette = ThreadCatalog().match_and_apply_palette(stitch_plan, self.get_inkstitch_metadata()['thread-palette']) overview_svg, color_block_svgs = self.render_svgs(stitch_plan, realistic=False) diff --git a/lib/extensions/stitch_plan_preview.py b/lib/extensions/stitch_plan_preview.py index 40ad6a2a..ac1a4a67 100644 --- a/lib/extensions/stitch_plan_preview.py +++ b/lib/extensions/stitch_plan_preview.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 ..stitch_plan import patches_to_stitch_plan +from ..stitch_plan import stitch_groups_to_stitch_plan from ..svg import render_stitch_plan from .base import InkstitchExtension @@ -24,7 +24,7 @@ class StitchPlanPreview(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] patches = self.elements_to_patches(self.elements) - stitch_plan = patches_to_stitch_plan(patches, collapse_len=collapse_len) + stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) render_stitch_plan(svg, stitch_plan, realistic) # translate stitch plan to the right side of the canvas diff --git a/lib/extensions/zip.py b/lib/extensions/zip.py index 605b4573..3f81af71 100644 --- a/lib/extensions/zip.py +++ b/lib/extensions/zip.py @@ -16,7 +16,7 @@ import pyembroidery from ..i18n import _ from ..output import write_embroidery_file -from ..stitch_plan import patches_to_stitch_plan +from ..stitch_plan import stitch_groups_to_stitch_plan from ..threads import ThreadCatalog from .base import InkstitchExtension @@ -44,7 +44,7 @@ class Zip(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] patches = self.elements_to_patches(self.elements) - stitch_plan = patches_to_stitch_plan(patches, collapse_len=collapse_len) + stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) base_file_name = self.get_base_file_name() path = tempfile.mkdtemp() diff --git a/lib/gui/simulator.py b/lib/gui/simulator.py index 94be66db..d031590b 100644 --- a/lib/gui/simulator.py +++ b/lib/gui/simulator.py @@ -11,7 +11,7 @@ import wx from wx.lib.intctrl import IntCtrl from ..i18n import _ -from ..stitch_plan import patches_to_stitch_plan, stitch_plan_from_file +from ..stitch_plan import stitch_groups_to_stitch_plan, stitch_plan_from_file from ..svg import PIXELS_PER_MM # L10N command label at bottom of simulator window @@ -789,7 +789,7 @@ class SimulatorPreview(Thread): return if patches and not self.refresh_needed.is_set(): - stitch_plan = patches_to_stitch_plan(patches) + stitch_plan = stitch_groups_to_stitch_plan(patches) # GUI stuff needs to happen in the main thread, so we ask the main # thread to call refresh_simulator(). diff --git a/lib/stitch_plan/__init__.py b/lib/stitch_plan/__init__.py index ba4729bb..d4b43ace 100644 --- a/lib/stitch_plan/__init__.py +++ b/lib/stitch_plan/__init__.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 .stitch_plan import patches_to_stitch_plan, StitchPlan +from .stitch_plan import stitch_groups_to_stitch_plan, StitchPlan from .color_block import ColorBlock from .stitch_group import StitchGroup from .stitch import Stitch diff --git a/lib/stitch_plan/stitch_plan.py b/lib/stitch_plan/stitch_plan.py index f5981fb9..7e7621c1 100644 --- a/lib/stitch_plan/stitch_plan.py +++ b/lib/stitch_plan/stitch_plan.py @@ -8,49 +8,49 @@ from .color_block import ColorBlock from ..svg import PIXELS_PER_MM -def patches_to_stitch_plan(patches, collapse_len=None, disable_ties=False): # noqa: C901 +def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=False): # noqa: C901 - """Convert a collection of inkstitch.element.StitchGroup objects to a StitchPlan. + """Convert a collection of StitchGroups to a StitchPlan. * applies instructions embedded in the StitchGroup such as trim_after and stop_after * adds tie-ins and tie-offs - * adds jump-stitches between patches if necessary + * adds jump-stitches between stitch_group if necessary """ if collapse_len is None: collapse_len = 3.0 collapse_len = collapse_len * PIXELS_PER_MM stitch_plan = StitchPlan() - color_block = stitch_plan.new_color_block(color=patches[0].color) + color_block = stitch_plan.new_color_block(color=stitch_groups[0].color) - for patch in patches: - if not patch.stitches: + for stitch_group in stitch_groups: + if not stitch_group.stitches: continue - if color_block.color != patch.color: + if color_block.color != stitch_group.color: if len(color_block) == 0: # We just processed a stop, which created a new color block. # We'll just claim this new block as ours: - color_block.color = patch.color + color_block.color = stitch_group.color else: # end the previous block with a color change color_block.add_stitch(color_change=True) # make a new block of our color - color_block = stitch_plan.new_color_block(color=patch.color) + 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(patch.stitches[0], jump=True) + color_block.add_stitch(stitch_group.stitches[0], jump=True) else: - if len(color_block) and (patch.stitches[0] - color_block.stitches[-1]).length() > collapse_len: - color_block.add_stitch(patch.stitches[0], jump=True) + 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) - color_block.add_stitches(stitches=patch.stitches, tie_modus=patch.tie_modus, no_ties=patch.stitch_as_is) + color_block.add_stitches(stitches=stitch_group.stitches, tie_modus=stitch_group.tie_modus, no_ties=stitch_group.stitch_as_is) - if patch.trim_after: + if stitch_group.trim_after: color_block.add_stitch(trim=True) - if patch.stop_after: + if stitch_group.stop_after: color_block.add_stitch(stop=True) color_block = stitch_plan.new_color_block(color_block.color) -- cgit v1.3.1 From 923ff3cb97c764f9999ac908c9b3aa321fd02301 Mon Sep 17 00:00:00 2001 From: Lex Neva <github.com@lexneva.name> Date: Sat, 7 Aug 2021 12:37:17 -0400 Subject: fix more patch references --- lib/api/stitch_plan.py | 2 +- 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 +- lib/extensions/base.py | 2 +- lib/extensions/output.py | 2 +- lib/extensions/print_pdf.py | 2 +- lib/extensions/stitch_plan_preview.py | 2 +- lib/extensions/zip.py | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) (limited to 'lib/extensions') diff --git a/lib/api/stitch_plan.py b/lib/api/stitch_plan.py index 9c9bb4ac..6d64d781 100644 --- a/lib/api/stitch_plan.py +++ b/lib/api/stitch_plan.py @@ -18,7 +18,7 @@ def get_stitch_plan(): metadata = g.extension.get_inkstitch_metadata() collapse_len = metadata['collapse_len_mm'] - patches = g.extension.elements_to_patches(g.extension.elements) + patches = g.extension.elements_to_stitch_groups(g.extension.elements) stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) return jsonify(stitch_plan) 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 [] diff --git a/lib/extensions/base.py b/lib/extensions/base.py index 476e4969..828e3685 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -188,7 +188,7 @@ class InkstitchExtension(inkex.Effect): selected.append(node) return selected - def elements_to_patches(self, elements): + def elements_to_stitch_groups(self, elements): patches = [] for element in elements: if patches: diff --git a/lib/extensions/output.py b/lib/extensions/output.py index f993f79f..7cc12ee0 100644 --- a/lib/extensions/output.py +++ b/lib/extensions/output.py @@ -52,7 +52,7 @@ class Output(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] - patches = self.elements_to_patches(self.elements) + patches = self.elements_to_stitch_groups(self.elements) stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len, disable_ties=self.settings.get('laser_mode', False)) temp_file = tempfile.NamedTemporaryFile(suffix=".%s" % self.file_extension, delete=False) diff --git a/lib/extensions/print_pdf.py b/lib/extensions/print_pdf.py index ed796bc7..e5cb25d8 100644 --- a/lib/extensions/print_pdf.py +++ b/lib/extensions/print_pdf.py @@ -302,7 +302,7 @@ class Print(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] - patches = self.elements_to_patches(self.elements) + patches = self.elements_to_stitch_groups(self.elements) stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) palette = ThreadCatalog().match_and_apply_palette(stitch_plan, self.get_inkstitch_metadata()['thread-palette']) diff --git a/lib/extensions/stitch_plan_preview.py b/lib/extensions/stitch_plan_preview.py index ac1a4a67..c50fa738 100644 --- a/lib/extensions/stitch_plan_preview.py +++ b/lib/extensions/stitch_plan_preview.py @@ -23,7 +23,7 @@ class StitchPlanPreview(InkstitchExtension): realistic = False self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] - patches = self.elements_to_patches(self.elements) + patches = self.elements_to_stitch_groups(self.elements) stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) render_stitch_plan(svg, stitch_plan, realistic) diff --git a/lib/extensions/zip.py b/lib/extensions/zip.py index 3f81af71..22654560 100644 --- a/lib/extensions/zip.py +++ b/lib/extensions/zip.py @@ -43,7 +43,7 @@ class Zip(InkstitchExtension): self.metadata = self.get_inkstitch_metadata() collapse_len = self.metadata['collapse_len_mm'] - patches = self.elements_to_patches(self.elements) + patches = self.elements_to_stitch_groups(self.elements) stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len) base_file_name = self.get_base_file_name() -- cgit v1.3.1