From f57d61b6e68ac9d0047361cc6fd140064b22545d Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sun, 2 Apr 2023 00:14:57 -0400 Subject: meander fixes --- lib/stitches/meander_fill.py | 14 ++++++++++---- lib/stitches/running_stitch.py | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'lib/stitches') diff --git a/lib/stitches/meander_fill.py b/lib/stitches/meander_fill.py index 0a59da72..29ec6270 100644 --- a/lib/stitches/meander_fill.py +++ b/lib/stitches/meander_fill.py @@ -2,7 +2,7 @@ from itertools import combinations import networkx as nx from inkex import errormsg -from shapely.geometry import MultiPoint, Point +from shapely.geometry import LineString, MultiPoint, Point from shapely.ops import nearest_points from .. import tiles @@ -126,10 +126,16 @@ def generate_meander_path(graph, start, end, rng): check_stop_flag() edge1, edge2 = poprandom(edge_pairs, rng) - edges_to_consider.extend(replace_edge_pair(meander_path, edge1, edge2, graph, graph_nodes)) - break + new_edges = replace_edge_pair(meander_path, edge1, edge2, graph, graph_nodes) + if new_edges: + edges_to_consider.extend(new_edges) + break + + debug.log_graph(graph, "remaining graph", "#FF0000") + points = path_to_points(meander_path) + debug.log_line_string(LineString(points), "meander path", "#00FF00") - return path_to_points(meander_path) + return points def replace_edge(path, edge, graph, graph_nodes): diff --git a/lib/stitches/running_stitch.py b/lib/stitches/running_stitch.py index 1dbfcaaf..46f3a3e9 100644 --- a/lib/stitches/running_stitch.py +++ b/lib/stitches/running_stitch.py @@ -10,6 +10,8 @@ from copy import copy import numpy as np from shapely import geometry as shgeo + +from ..debug import debug from ..utils import prng from ..utils.geometry import Point from ..utils.threading import check_stop_flag @@ -246,6 +248,7 @@ def path_to_curves(points: typing.List[Point], min_len: float): return curves +@debug.time def running_stitch(points, stitch_length, tolerance): # Turn a continuous path into a running stitch. stitches = [points[0]] -- cgit v1.3.1 From c01fb85c3d6e7d6a30282cb0a4db8d511b4d4f86 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sun, 2 Apr 2023 14:16:16 -0400 Subject: add clip option --- lib/elements/fill_stitch.py | 16 +++++++++++++--- lib/stitches/meander_fill.py | 10 ++++++---- lib/svg/tags.py | 1 + 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'lib/stitches') diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 980103a4..7b146a36 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -553,6 +553,16 @@ class FillStitch(EmbroideryElement): def expand(self): return self.get_float_param('expand_mm', 0) + @property + @param('clip', _('Clip path'), + tooltip=_('Constrain stitching to the shape. Useful when smoothing and expand are used.'), + type='boolean', + default=False, + select_items=[('fill_method', 'meander_fill')], + sort_index=6) + def clip(self): + return self.get_boolean_param('clip', False) + @property @param('underpath', _('Underpath'), @@ -648,7 +658,7 @@ class FillStitch(EmbroideryElement): elif self.fill_method == 'guided_fill': stitch_groups.extend(self.do_guided_fill(fill_shape, previous_stitch_group, start, end)) elif self.fill_method == 'meander_fill': - stitch_groups.extend(self.do_meander_fill(fill_shape, i, start, end)) + stitch_groups.extend(self.do_meander_fill(fill_shape, shape, i, start, end)) elif self.fill_method == 'circular_fill': stitch_groups.extend(self.do_circular_fill(fill_shape, previous_stitch_group, start, end)) except ExitThread: @@ -792,11 +802,11 @@ class FillStitch(EmbroideryElement): )) return [stitch_group] - def do_meander_fill(self, shape, i, starting_point, ending_point): + def do_meander_fill(self, shape, original_shape, i, starting_point, ending_point): stitch_group = StitchGroup( color=self.color, tags=("meander_fill", "meander_fill_top"), - stitches=meander_fill(self, shape, i, starting_point, ending_point)) + stitches=meander_fill(self, shape, original_shape, i, starting_point, ending_point)) return [stitch_group] @cache diff --git a/lib/stitches/meander_fill.py b/lib/stitches/meander_fill.py index 29ec6270..6fdd94b8 100644 --- a/lib/stitches/meander_fill.py +++ b/lib/stitches/meander_fill.py @@ -18,7 +18,7 @@ from ..utils.threading import check_stop_flag from .running_stitch import running_stitch -def meander_fill(fill, shape, shape_index, starting_point, ending_point): +def meander_fill(fill, shape, original_shape, shape_index, starting_point, ending_point): debug.log(f"meander pattern: {fill.meander_pattern}") tile = get_tile(fill.meander_pattern) if not tile: @@ -40,7 +40,7 @@ def meander_fill(fill, shape, shape_index, starting_point, ending_point): start, end = find_starting_and_ending_nodes(graph, shape, starting_point, ending_point) rng = iter_uniform_floats(fill.random_seed, 'meander-fill', shape_index) - return post_process(generate_meander_path(graph, start, end, rng), shape, fill) + return post_process(generate_meander_path(graph, start, end, rng), shape, original_shape, fill) def get_tile(tile_id): @@ -175,14 +175,16 @@ def replace_edge_pair(path, edge1, edge2, graph, graph_nodes): @debug.time -def post_process(points, shape, fill): +def post_process(points, shape, original_shape, fill): debug.log(f"smoothness: {fill.smoothness}") # debug.log_line_string(LineString(points), "pre-smoothed", "#FF0000") smoothed_points = smooth_path(points, fill.smoothness) smoothed_points = [InkStitchPoint.from_tuple(point) for point in smoothed_points] stitches = running_stitch(smoothed_points, fill.running_stitch_length, fill.running_stitch_tolerance) - stitches = clamp_path_to_polygon(stitches, shape) + + if fill.clip: + stitches = clamp_path_to_polygon(stitches, original_shape) return stitches diff --git a/lib/svg/tags.py b/lib/svg/tags.py index 9b5a78fb..951821b5 100644 --- a/lib/svg/tags.py +++ b/lib/svg/tags.py @@ -97,6 +97,7 @@ inkstitch_attribs = [ 'underpath', 'flip', 'expand_mm', + 'clip', # stroke 'stroke_method', 'bean_stitch_repeats', -- cgit v1.3.1 From 63effb841fa3ea507135e10331b8ecb1a64e94dd Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Mon, 3 Apr 2023 22:59:02 -0400 Subject: add meander angle --- lib/elements/fill_stitch.py | 12 ++++++++++++ lib/stitches/meander_fill.py | 2 +- lib/svg/tags.py | 1 + lib/tiles.py | 20 ++++++++++---------- 4 files changed, 24 insertions(+), 11 deletions(-) (limited to 'lib/stitches') diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 7b146a36..8f22278b 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -185,9 +185,21 @@ class FillStitch(EmbroideryElement): def meander_pattern(self): return self.get_param('meander_pattern', min(tiles.all_tiles()).id) + @property + @param('meander_angle', + _('Meander pattern angle'), + type='float', unit="degrees", + default=0, + select_items=[('fill_method', 'meander_fill')], + sort_index=4) + def meander_angle(self): + return math.radians(self.get_float_param('meander_angle', 0)) + @property @param('meander_scale_percent', _('Meander pattern scale'), + tooltip=_("Percentage to stretch or compress the meander pattern. You can scale horizontally " + + "and vertically individually by giving two percentages separated by a space. "), type='float', unit="%", default=100, select_items=[('fill_method', 'meander_fill')], diff --git a/lib/stitches/meander_fill.py b/lib/stitches/meander_fill.py index 6fdd94b8..08ff4999 100644 --- a/lib/stitches/meander_fill.py +++ b/lib/stitches/meander_fill.py @@ -27,7 +27,7 @@ def meander_fill(fill, shape, original_shape, shape_index, starting_point, endin debug.log(f"tile name: {tile.name}") debug.log_line_strings(lambda: ensure_geometry_collection(shape.boundary).geoms, 'Meander shape') - graph = tile.to_graph(shape, fill.meander_scale) + graph = tile.to_graph(shape, fill.meander_scale, fill.meander_angle) if not graph: label = fill.node.label or fill.node.get_id() diff --git a/lib/svg/tags.py b/lib/svg/tags.py index 951821b5..bbef6ebb 100644 --- a/lib/svg/tags.py +++ b/lib/svg/tags.py @@ -81,6 +81,7 @@ inkstitch_attribs = [ 'reverse', 'meander_pattern', 'meander_scale_percent', + 'meander_angle', 'expand_mm', 'fill_underlay', 'fill_underlay_angle', diff --git a/lib/tiles.py b/lib/tiles.py index 15017e91..0bf92abc 100644 --- a/lib/tiles.py +++ b/lib/tiles.py @@ -111,20 +111,20 @@ class Tile: return translated_tile - def _scale(self, x_scale, y_scale): - scaled_shift0 = self.shift0.scale(x_scale, y_scale) - scaled_shift1 = self.shift1.scale(x_scale, y_scale) + def _scale_and_rotate(self, x_scale, y_scale, angle): + transformed_shift0 = self.shift0.scale(x_scale, y_scale).rotate(angle) + transformed_shift1 = self.shift1.scale(x_scale, y_scale).rotate(angle) - scaled_tile = [] + transformed_tile = [] for start, end in self.tile: - start = start.scale(x_scale, y_scale) - end = end.scale(x_scale, y_scale) - scaled_tile.append((start, end)) + start = start.scale(x_scale, y_scale).rotate(angle) + end = end.scale(x_scale, y_scale).rotate(angle) + transformed_tile.append((start, end)) - return scaled_shift0, scaled_shift1, scaled_tile + return transformed_shift0, transformed_shift1, transformed_tile @debug.time - def to_graph(self, shape, scale): + def to_graph(self, shape, scale, angle): """Apply this tile to a shape, repeating as necessary. Return value: @@ -134,7 +134,7 @@ class Tile: """ self._load() x_scale, y_scale = scale - shift0, shift1, tile = self._scale(x_scale, y_scale) + shift0, shift1, tile = self._scale_and_rotate(x_scale, y_scale, angle) shape_center, shape_width, shape_height = self._get_center_and_dimensions(shape) prepared_shape = prep(shape) -- cgit v1.3.1