From 8d5ef5b6635b5b84f12409b535114853954680d1 Mon Sep 17 00:00:00 2001 From: Kaalleen <36401965+kaalleen@users.noreply.github.com> Date: Thu, 30 Jun 2022 19:22:33 +0200 Subject: Fixes (#1703) * guide line position * use direction from line to shape * optimize intersection detection * fix flapack elf * handle weird guide lines better * update starting point for self crossing (multiple) fills * ripple: fixes and non circular join style * avoid jumps in ripple stitch * fallback only necessary if shape does not intersect grating * make valid may return a polygon * add profiling * Stitch.__init__ didn't work right and was super slow * shrink or grow to multipolygon Co-authored-by: Lex Neva --- lib/elements/fill_stitch.py | 50 ++++++++++++++++++++++++++++----------------- lib/elements/stroke.py | 17 +++++++++++++-- 2 files changed, 46 insertions(+), 21 deletions(-) (limited to 'lib/elements') diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 157169ab..a0ab0d33 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -266,6 +266,10 @@ class FillStitch(EmbroideryElement): valid_shape = make_valid(shape) logger.setLevel(level) + + if isinstance(valid_shape, shgeo.Polygon): + return shgeo.MultiPolygon([valid_shape]) + polygons = [] for polygon in valid_shape.geoms: if isinstance(polygon, shgeo.Polygon): @@ -499,15 +503,18 @@ class FillStitch(EmbroideryElement): return self.get_boolean_param('underlay_underpath', True) def shrink_or_grow_shape(self, shape, amount, validate=False): + new_shape = shape if amount: - shape = shape.buffer(amount) + new_shape = shape.buffer(amount) # changing the size can empty the shape # in this case we want to use the original shape rather than returning an error - if shape.is_empty and not validate: - return shape - if not isinstance(shape, shgeo.MultiPolygon): - shape = shgeo.MultiPolygon([shape]) - return shape + if (new_shape.is_empty and not validate): + new_shape = shape + + if not isinstance(new_shape, shgeo.MultiPolygon): + new_shape = shgeo.MultiPolygon([new_shape]) + + return new_shape def underlay_shape(self, shape): return self.shrink_or_grow_shape(shape, -self.fill_underlay_inset) @@ -532,26 +539,31 @@ class FillStitch(EmbroideryElement): else: return None - def to_stitch_groups(self, last_patch): + def to_stitch_groups(self, last_patch): # noqa: C901 # backwards compatibility: legacy_fill used to be inkstitch:auto_fill == False if not self.auto_fill or self.fill_method == 3: return self.do_legacy_fill() else: stitch_groups = [] - start = self.get_starting_point(last_patch) end = self.get_ending_point() for shape in self.shape.geoms: + start = self.get_starting_point(last_patch) try: if self.fill_underlay: - underlay_stitch_groups, start = self.do_underlay(shape, start) - stitch_groups.extend(underlay_stitch_groups) - if self.fill_method == 0: - stitch_groups.extend(self.do_auto_fill(shape, last_patch, start, end)) - if self.fill_method == 1: - stitch_groups.extend(self.do_contour_fill(self.fill_shape(shape), last_patch, start)) - elif self.fill_method == 2: - stitch_groups.extend(self.do_guided_fill(shape, last_patch, start, end)) + underlay_shapes = self.underlay_shape(shape) + for underlay_shape in underlay_shapes.geoms: + underlay_stitch_groups, start = self.do_underlay(underlay_shape, start) + stitch_groups.extend(underlay_stitch_groups) + + fill_shapes = self.fill_shape(shape) + for fill_shape in fill_shapes.geoms: + if self.fill_method == 0: + stitch_groups.extend(self.do_auto_fill(fill_shape, last_patch, start, end)) + if self.fill_method == 1: + stitch_groups.extend(self.do_contour_fill(fill_shape, last_patch, start)) + elif self.fill_method == 2: + stitch_groups.extend(self.do_guided_fill(fill_shape, last_patch, start, end)) except Exception: self.fatal_fill_error() last_patch = stitch_groups[-1] @@ -576,7 +588,7 @@ class FillStitch(EmbroideryElement): color=self.color, tags=("auto_fill", "auto_fill_underlay"), stitches=auto_fill( - self.underlay_shape(shape), + shape, self.fill_underlay_angle[i], self.fill_underlay_row_spacing, self.fill_underlay_row_spacing, @@ -597,7 +609,7 @@ class FillStitch(EmbroideryElement): color=self.color, tags=("auto_fill", "auto_fill_top"), stitches=auto_fill( - self.fill_shape(shape), + shape, self.angle, self.row_spacing, self.end_row_spacing, @@ -663,7 +675,7 @@ class FillStitch(EmbroideryElement): color=self.color, tags=("guided_fill", "auto_fill_top"), stitches=guided_fill( - self.fill_shape(shape), + shape, guide_line.geoms[0], self.angle, self.row_spacing, diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index bf5e1d35..ce973c0e 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -150,7 +150,7 @@ class Stroke(EmbroideryElement): return max(self.get_int_param("line_count", 10), 1) def get_line_count(self): - if self.is_closed: + if self.is_closed or self.join_style == 1: return self.line_count + 1 return self.line_count @@ -246,7 +246,7 @@ class Stroke(EmbroideryElement): type='dropdown', default=0, # 0: xy, 1: x, 2: y, 3: none - options=[_("X Y"), _("X"), _("Y"), _("None")], + options=["X Y", "X", "Y", _("None")], select_items=[('stroke_method', 1)], sort_index=12) def scale_axis(self): @@ -286,6 +286,19 @@ class Stroke(EmbroideryElement): def rotate_ripples(self): return self.get_boolean_param("rotate_ripples", True) + @property + @param('join_style', + _('Join style'), + tooltip=_('Join style for non circular ripples.'), + type='dropdown', + default=0, + options=(_("flat"), _("point")), + select_items=[('stroke_method', 1)], + sort_index=16) + @cache + def join_style(self): + return self.get_int_param('join_style', 0) + @property @cache def is_closed(self): -- cgit v1.2.3