use offset curve for convert satin extension (#2775)

filter invalid rungs when merging satin sections
pull/2803/head
Kaalleen 2024-03-23 09:00:40 +01:00 zatwierdzone przez GitHub
rodzic 3bf30f6f26
commit 1112959da1
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 20 dodań i 15 usunięć

Wyświetl plik

@ -941,8 +941,20 @@ class SatinColumn(EmbroideryElement):
# add on the other satin's rungs
rungs.extend(other_rungs)
rungs = self._get_filtered_rungs(rails, rungs)
return self._csp_to_satin(point_lists_to_csp(rails + rungs))
def _get_filtered_rungs(self, rails, rungs):
# returns a filtered list of rungs which do intersect the rails exactly twice
rails = shgeo.MultiLineString(rails)
filtered_rungs = []
for rung in shgeo.MultiLineString(rungs).geoms:
intersection = rung.intersection(rails)
if intersection.geom_type == "MultiPoint" and len(intersection.geoms) == 2:
filtered_rungs.append(list(rung.coords))
return filtered_rungs
@property
@cache
def center_line(self):

Wyświetl plik

@ -12,12 +12,12 @@ import numpy
from numpy import diff, setdiff1d, sign
from shapely import geometry as shgeo
from .base import InkstitchExtension
from ..elements import SatinColumn, Stroke
from ..i18n import _
from ..svg import PIXELS_PER_MM, get_correction_transform
from ..svg.tags import INKSTITCH_ATTRIBS
from ..utils import Point
from .base import InkstitchExtension
class SelfIntersectionError(Exception):
@ -119,7 +119,7 @@ class ConvertToSatin(InkstitchExtension):
return [point for point, repeats in groupby(path)]
def join_style_args(self, element):
"""Convert svg line join style to shapely parallel offset arguments."""
"""Convert svg line join style to shapely offset_curve arguments."""
args = {
# mitre is the default per SVG spec
@ -146,16 +146,12 @@ class ConvertToSatin(InkstitchExtension):
if Point(*path[0]).distance(Point(*path[-1])) < 1:
raise SelfIntersectionError()
# Shapely is supposed to return right sided offsets in reversed direction, which it does, except for macOS.
# To avoid direction checking, we are going to rely on left side offsets only.
# Therefore we need to reverse the original path.
reversed_path = shgeo.LineString(reversed(path))
path = shgeo.LineString(path)
distance = stroke_width / 2.0
try:
left_rail = path.parallel_offset(distance, 'left', **style_args)
right_rail = reversed_path.parallel_offset(distance, 'left', **style_args)
left_rail = path.offset_curve(-distance, **style_args)
right_rail = path.offset_curve(distance, **style_args)
except ValueError:
# TODO: fix this error automatically
# Error reference: https://github.com/inkstitch/inkstitch/issues/964
@ -163,16 +159,13 @@ class ConvertToSatin(InkstitchExtension):
"Please break up your path and try again.") + '\n')
sys.exit(1)
if not isinstance(left_rail, shgeo.LineString) or \
not isinstance(right_rail, shgeo.LineString):
# If the parallel offsets come out as anything but a LineString, that means the
# path intersects itself, when taking its stroke width into consideration. See
# the last example for parallel_offset() in the Shapely documentation:
# https://shapely.readthedocs.io/en/latest/manual.html#object.parallel_offset
if left_rail.geom_type != 'LineString' or right_rail.geom_type != 'LineString':
# If the offset curve come out as anything but a LineString, that means the
# path intersects itself, when taking its stroke width into consideration.
raise SelfIntersectionError()
left_rail = list(left_rail.coords)
right_rail = list(reversed(right_rail.coords))
right_rail = list(right_rail.coords)
rungs = self.generate_rungs(path, stroke_width)