summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKaalleen <36401965+kaalleen@users.noreply.github.com>2025-05-20 16:12:50 +0200
committerGitHub <noreply@github.com>2025-05-20 16:12:50 +0200
commiteebf69947f8616b25113d147dbf179697be803cf (patch)
treefc44ed767419823b9b57f2bb0f9e5a26d1a02af9 /lib
parent72dc85d3dd4fb6813b3ae610f651fe2a1800122b (diff)
Manual stitch: apply clipping (#3734)
* manual stitch: apply clipping * add clip to cache
Diffstat (limited to 'lib')
-rw-r--r--lib/elements/element.py8
-rw-r--r--lib/elements/fill_stitch.py6
-rw-r--r--lib/elements/stroke.py10
-rw-r--r--lib/svg/clip.py4
4 files changed, 18 insertions, 10 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py
index 6f2c52e9..df2b0205 100644
--- a/lib/elements/element.py
+++ b/lib/elements/element.py
@@ -3,6 +3,7 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from __future__ import annotations
+
import json
import sys
from contextlib import contextmanager
@@ -26,6 +27,7 @@ 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.clip import get_clip_path
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS
from ..utils import DotDict, Point, cache
from ..utils.cache import (CacheKeyGenerator, get_stitch_plan_cache,
@@ -610,6 +612,7 @@ class EmbroideryElement(object):
cache_key_generator.update(self.__class__.__name__)
cache_key_generator.update(self.get_params_and_values())
cache_key_generator.update(self.parse_path())
+ cache_key_generator.update(self.clip_shape)
cache_key_generator.update(list(self._get_specified_style().items()))
cache_key_generator.update(self._get_gradient_cache_key_data())
cache_key_generator.update(previous_stitch)
@@ -674,6 +677,11 @@ class EmbroideryElement(object):
pass
return next_stitch
+ @property
+ @cache
+ def clip_shape(self):
+ return get_clip_path(self.node)
+
def fatal(self, message, point_to_troubleshoot=False):
label = self.node.get(INKSCAPE_LABEL)
id = self.node.get("id")
diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py
index fa4ce845..555c7e09 100644
--- a/lib/elements/fill_stitch.py
+++ b/lib/elements/fill_stitch.py
@@ -23,7 +23,6 @@ from ..stitches import (auto_fill, circular_fill, contour_fill, guided_fill,
tartan_fill)
from ..stitches.linear_gradient_fill import gradient_angle
from ..svg import PIXELS_PER_MM
-from ..svg.clip import get_clip_path
from ..svg.tags import INKSCAPE_LABEL
from ..tartan.utils import get_tartan_settings, get_tartan_stripes
from ..utils import cache
@@ -789,12 +788,11 @@ class FillStitch(EmbroideryElement):
return ensure_multi_polygon(set_precision(shape, 0.00000000001), 3)
def _get_clipped_path(self):
- clip_path = get_clip_path(self.node)
- if clip_path is None:
+ if self.clip_shape is None:
return self.original_shape
# make sure clip path and shape are valid
- clip_path = make_valid(clip_path)
+ clip_path = make_valid(self.clip_shape)
shape = make_valid(self.original_shape)
try:
diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py
index 5143c020..6e01151d 100644
--- a/lib/elements/stroke.py
+++ b/lib/elements/stroke.py
@@ -15,7 +15,6 @@ from ..stitches.ripple_stitch import ripple_stitch
from ..stitches.running_stitch import (bean_stitch, running_stitch,
zigzag_stitch)
from ..svg import parse_length_with_units
-from ..svg.clip import get_clip_path
from ..threads import ThreadColor
from ..utils import Point, cache
from ..utils.param import ParamOption
@@ -496,7 +495,9 @@ class Stroke(EmbroideryElement):
return [[[flattened[0][0][0], flattened[0][0][1]], [flattened[0][0][0] + 1.0, flattened[0][0][1]]]]
if self.stroke_method == 'manual_stitch':
- return [self.strip_control_points(subpath) for subpath in path]
+ coords = [shgeo.LineString(self.strip_control_points(subpath)).coords for subpath in path]
+ coords = self._get_clipped_path(coords)
+ return coords
else:
return flattened
@@ -515,14 +516,13 @@ class Stroke(EmbroideryElement):
return shgeo.Point(self.as_multi_line_string().geoms[0].coords[0])
def _get_clipped_path(self, paths):
- clip_path = get_clip_path(self.node)
- if clip_path is None:
+ if self.clip_shape is None:
return paths
# path to linestrings
line_strings = [shgeo.LineString(path) for path in paths]
try:
- intersection = clip_path.intersection(shgeo.MultiLineString(line_strings))
+ intersection = self.clip_shape.intersection(shgeo.MultiLineString(line_strings))
except GEOSException:
return paths
diff --git a/lib/svg/clip.py b/lib/svg/clip.py
index b8c97894..cc773d21 100644
--- a/lib/svg/clip.py
+++ b/lib/svg/clip.py
@@ -6,7 +6,6 @@
from shapely.geometry import MultiPolygon, Polygon
from shapely.validation import make_valid
-from ..elements import EmbroideryElement
from ..utils import ensure_multi_polygon
from .tags import SVG_GROUP_TAG, SVG_PATH_TAG
@@ -33,6 +32,9 @@ def get_clip_path(node):
def _clip_paths(node_or_group):
+ # avoid circular import for EmbroideryElement
+ from ..elements import EmbroideryElement
+
clip = node_or_group.clip
if clip is None:
return