apply clip to stroke (#2283)

pull/2293/head
Kaalleen 2023-05-10 09:02:47 +02:00 zatwierdzone przez GitHub
rodzic 9d5cc6013e
commit c799b798bc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 52 dodań i 9 usunięć

Wyświetl plik

@ -23,6 +23,7 @@ from ..stitches import (auto_fill, circular_fill, contour_fill, guided_fill,
legacy_fill)
from ..stitches.meander_fill import meander_fill
from ..svg import PIXELS_PER_MM, get_node_transform
from ..svg.clip import get_clip_path
from ..svg.tags import INKSCAPE_LABEL
from ..utils import cache, version
from ..utils.param import ParamOption
@ -571,12 +572,9 @@ class FillStitch(EmbroideryElement):
if self.node.clip is None:
return self.original_shape
from .element import EmbroideryElement
clip_element = EmbroideryElement(self.node.clip)
clip_element.paths.sort(key=lambda point_list: shgeo.Polygon(point_list).area, reverse=True)
polygon = shgeo.MultiPolygon([(clip_element.paths[0], clip_element.paths[1:])])
clip_path = get_clip_path(self.node)
try:
intersection = polygon.intersection(self.original_shape)
intersection = clip_path.intersection(self.original_shape)
except TopologicalError:
return self.original_shape

Wyświetl plik

@ -5,7 +5,7 @@
from math import ceil
import shapely.geometry
import shapely.geometry as shgeo
from inkex import Transform
from ..i18n import _
@ -18,7 +18,9 @@ from ..threads import ThreadColor
from ..utils import Point, cache
from ..utils.param import ParamOption
from .element import EmbroideryElement, param
from ..svg.clip import get_clip_path
from .validation import ValidationWarning
from shapely.errors import TopologicalError
class MultipleGuideLineWarning(ValidationWarning):
@ -349,6 +351,7 @@ class Stroke(EmbroideryElement):
def paths(self):
path = self.parse_path()
flattened = self.flatten(path)
flattened = self._get_clipped_path(flattened)
# manipulate invalid path
if len(flattened[0]) == 1:
@ -366,8 +369,32 @@ class Stroke(EmbroideryElement):
@cache
def as_multi_line_string(self):
line_strings = [shapely.geometry.LineString(path) for path in self.paths]
return shapely.geometry.MultiLineString(line_strings)
line_strings = [shgeo.LineString(path) for path in self.paths]
return shgeo.MultiLineString(line_strings)
def _get_clipped_path(self, paths):
if self.node.clip is None:
return paths
clip_path = get_clip_path(self.node)
# path to linestrings
line_strings = [shgeo.LineString(path) for path in paths]
try:
intersection = clip_path.intersection(shgeo.MultiLineString(line_strings))
except TopologicalError:
return paths
coords = []
if intersection.is_empty:
return paths
elif isinstance(intersection, shgeo.MultiLineString):
for c in [intersection for intersection in intersection.geoms if isinstance(intersection, shgeo.LineString)]:
coords.append(c.coords)
elif isinstance(intersection, shgeo.LineString):
coords.append(intersection.coords)
else:
return paths
return coords
def get_ripple_target(self):
command = self.get_command('ripple_target')
@ -431,7 +458,7 @@ class Stroke(EmbroideryElement):
# apply max distances
max_len_path = [path[0]]
for points in zip(path[:-1], path[1:]):
line = shapely.geometry.LineString(points)
line = shgeo.LineString(points)
dist = line.length
if dist > self.max_stitch_length:
num_subsections = ceil(dist / self.max_stitch_length)

18
lib/svg/clip.py 100644
Wyświetl plik

@ -0,0 +1,18 @@
# Authors: see git history
#
# Copyright (c) 2023 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from shapely.geometry import MultiPolygon, Polygon
from ..elements import EmbroideryElement
def get_clip_path(node):
# get clip and apply node transform
clip = node.clip
transform = node.composed_transform()
clip.transform = transform
clip_element = EmbroideryElement(clip)
clip_element.paths.sort(key=lambda point_list: Polygon(point_list).area, reverse=True)
return MultiPolygon([(clip_element.paths[0], clip_element.paths[1:])])