Jump to strokes connect subpaths (#2750)

pull/2761/head
Kaalleen 2024-03-07 17:57:51 +01:00 zatwierdzone przez GitHub
rodzic 0573772b60
commit d43f2e2ff9
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 90 dodań i 27 usunięć

Wyświetl plik

@ -3,12 +3,10 @@
# Copyright (c) 2023 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from inkex import (Boolean, DirectedLineSegment, Path, PathElement, Transform,
errormsg)
from inkex import Boolean, DirectedLineSegment, Path, PathElement, Transform
from ..elements import Stroke
from ..i18n import _
from ..svg import PIXELS_PER_MM, get_correction_transform
from ..svg import PIXELS_PER_MM, generate_unique_id, get_correction_transform
from ..svg.tags import INKSTITCH_ATTRIBS, SVG_GROUP_TAG
from .base import InkstitchExtension
@ -29,32 +27,32 @@ class JumpToStroke(InkstitchExtension):
self.arg_parser.add_argument("--exclude-force-lock-stitch", type=Boolean, default=True, dest="exclude_forced_lock")
self.arg_parser.add_argument("-m", "--merge", type=Boolean, default=False, dest="merge")
self.arg_parser.add_argument("--merge_subpaths", type=Boolean, default=False, dest="merge_subpaths")
self.arg_parser.add_argument("-l", "--stitch-length", type=float, default=2.5, dest="running_stitch_length_mm")
self.arg_parser.add_argument("-t", "--tolerance", type=float, default=2.0, dest="running_stitch_tolerance_mm")
def effect(self):
if not self.svg.selection or not self.get_elements() or len(self.elements) < 2:
errormsg(_("Please select at least two elements to convert the jump stitch to a running stitch."))
return
self._set_selection()
self.get_elements()
if self.options.merge_subpaths:
# when we merge stroke elements we are going to replace original path elements
# which would be bad in the case that the element has more subpaths
self._split_stroke_elements_with_subpaths()
last_group = None
last_layer = None
last_element = None
last_stitch_group = None
for element in self.elements:
group = None
layer = None
for ancestor in element.node.iterancestors(SVG_GROUP_TAG):
if group is None:
group = ancestor
if ancestor.groupmode == "layer":
layer = ancestor
break
layer, group = self._get_element_layer_and_group(element)
stitch_groups = element.to_stitch_groups(last_stitch_group)
stitch_group = element.to_stitch_groups(last_stitch_group)
if not self.options.merge_subpaths and stitch_groups:
stitch_groups = [stitch_groups[-1]]
if (last_stitch_group is None or
element.color != last_element.color or
if (not stitch_groups or
last_element is None or
(self.options.connect == "layer" and last_layer != layer) or
(self.options.connect == "group" and last_group != group) or
(self.options.exclude_trim and (last_element.has_command("trim") or last_element.trim_after)) or
@ -62,19 +60,83 @@ class JumpToStroke(InkstitchExtension):
(self.options.exclude_forced_lock and last_element.force_lock_stitches)):
last_layer = layer
last_group = group
last_stitch_group = stitch_group[-1]
last_element = element
if stitch_groups:
last_stitch_group = stitch_groups[-1]
continue
start = last_stitch_group.stitches[-1]
end = stitch_group[-1].stitches[0]
self.generate_stroke(last_element, element, start, end)
for stitch_group in stitch_groups:
if last_stitch_group is None or stitch_group.color != last_stitch_group.color:
last_layer = layer
last_group = group
last_stitch_group = stitch_group
continue
start = last_stitch_group.stitches[-1]
end = stitch_group.stitches[0]
self.generate_stroke(last_element, element, start, end)
last_stitch_group = stitch_group
last_group = group
last_layer = layer
last_stitch_group = stitch_group[-1]
last_element = element
def _set_selection(self):
if not self.svg.selection:
self.svg.selection.clear()
def _get_element_layer_and_group(self, element):
layer = None
group = None
for ancestor in element.node.iterancestors(SVG_GROUP_TAG):
if group is None:
group = ancestor
if ancestor.groupmode == "layer":
layer = ancestor
break
return layer, group
def _split_stroke_elements_with_subpaths(self):
elements = []
for element in self.elements:
if isinstance(element, Stroke) and len(element.paths) > 1:
if element.get_param('stroke_method', None) in ['ripple_stitch']:
elements.append(element)
continue
node = element.node
parent = node.getparent()
index = parent.index(node)
paths = node.get_path().break_apart()
paths.reverse()
block_ids = []
for path in paths:
subpath_element = node.copy()
subpath_id = generate_unique_id(node, f'{node.get_id()}_', block_ids)
subpath_element.set('id', subpath_id)
subpath_element.set('d', str(path))
block_ids.append(subpath_id)
parent.insert(index, subpath_element)
elements.append(Stroke(subpath_element))
parent.remove(node)
else:
elements.append(element)
self.elements = elements
def _is_mergable(self, element1, element2):
if not (isinstance(element1, Stroke)):
return False
if (self.options.merge_subpaths and
element1.node.get_id() not in self.svg.selection.ids and
element2.node.get_id() not in self.svg.selection.ids):
return True
if (self.options.merge and
element1.node.TAG == "path" and
element1.get_param('stroke_method', None) == element2.get_param('stroke_method', None) and
not element1.get_param('stroke_method', '') == 'ripple_stitch'):
return True
return False
def generate_stroke(self, last_element, element, start, end):
node = element.node
parent = node.getparent()
@ -91,13 +153,13 @@ class JumpToStroke(InkstitchExtension):
path = Path([(start.x, start.y), (end.x, end.y)])
# option: merge line with paths
merged = False
if self.options.merge and isinstance(last_element, Stroke) and last_element.node.TAG == "path":
if self._is_mergable(last_element, element):
path.transform(Transform(get_correction_transform(last_element.node)), True)
path = last_element.node.get_path() + path[1:]
last_element.node.set('d', str(path))
path.transform(-Transform(get_correction_transform(last_element.node)), True)
merged = True
if self.options.merge and isinstance(element, Stroke) and node.TAG == "path":
if self._is_mergable(element, last_element):
path.transform(Transform(get_correction_transform(node)), True)
path = path + node.get_path()[1:]
node.set('d', str(path))

Wyświetl plik

@ -28,11 +28,12 @@
<param name="exclude-force-lock-stitch" indent="1" type="bool" gui-text="Force lock stitch">true</param>
</page>
<page name="output-settings" gui-text="Output settings">
<param name="merge" type="bool" gui-text="Merge consecutive strokes">false</param>
<param name="merge" type="bool" gui-text="Merge consecutive strokes of same type">false</param>
<param name="merge_subpaths" type="bool" gui-text="Merge subpaths of stroke elements">false</param>
<spacer />
<separator />
<spacer />
<label>These settings only apply when merging is disabled</label>
<label>These settings only apply for unmerged connectors</label>
<param name="stitch-length" type="float" indent="1" gui-text="Running stitch length (mm)">2.5</param>
<param name="tolerance" type="float" indent="1" gui-text="Running stitch tolerance (mm)">2.0</param>
</page>