diff options
| author | Kaalleen <36401965+kaalleen@users.noreply.github.com> | 2025-11-07 17:10:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-07 17:10:03 +0100 |
| commit | 5a9ae03dc14ea5b68a99581c21a5d8085f1a3243 (patch) | |
| tree | 4b729fbdc8656f3ba75b7dfdd2ccfecdd8718fee /lib | |
| parent | 383f164b6d90c0819d49f4fb16deb9efa3e11df2 (diff) | |
Running stitch length sequence (#4034)
* allow running stitch length sequences
* contour fill: fix error message for long stitch length
* satin: fix center underlay stitch length
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/elements/element.py | 12 | ||||
| -rw-r--r-- | lib/elements/satin_column.py | 12 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 18 | ||||
| -rw-r--r-- | lib/extensions/fill_to_stroke.py | 4 | ||||
| -rw-r--r-- | lib/stitches/auto_fill.py | 4 | ||||
| -rw-r--r-- | lib/stitches/circular_fill.py | 4 | ||||
| -rw-r--r-- | lib/stitches/contour_fill.py | 7 | ||||
| -rw-r--r-- | lib/stitches/fill.py | 3 | ||||
| -rw-r--r-- | lib/stitches/guided_fill.py | 7 | ||||
| -rw-r--r-- | lib/stitches/linear_gradient_fill.py | 6 | ||||
| -rw-r--r-- | lib/stitches/meander_fill.py | 4 | ||||
| -rw-r--r-- | lib/stitches/ripple_stitch.py | 41 | ||||
| -rw-r--r-- | lib/stitches/running_stitch.py | 47 | ||||
| -rw-r--r-- | lib/stitches/tartan_fill.py | 4 | ||||
| -rw-r--r-- | lib/utils/settings.py | 2 | ||||
| -rw-r--r-- | lib/utils/smoothing.py | 2 |
16 files changed, 121 insertions, 56 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py index 8e66db58..9b438f56 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -161,7 +161,11 @@ class EmbroideryElement(object): try: params = [int(param) for param in params if param] except (TypeError, ValueError): - return [int(default)] + params = [int(default)] + + if param.endswith('_mm'): + params = [value * PIXELS_PER_MM for value in params] + return params # returns an array of multiple space separated float values @@ -171,7 +175,11 @@ class EmbroideryElement(object): try: params = [float(param) for param in params if param] except (TypeError, ValueError): - return [float(default)] + params = [float(default)] + + if param.endswith('_mm'): + params = [value * PIXELS_PER_MM for value in params] + return params def get_json_param(self, param, default=None): diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 6babc851..277c4f84 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1117,14 +1117,16 @@ class SatinColumn(EmbroideryElement): linestring = shgeo.LineString(stitches) return linestring - def _get_center_line_stitches(self, position): + def _get_center_line_stitches(self, position, stitch_length=None): inset_prop = -np.array([position, 100-position]) / 100 + if stitch_length is None: + stitch_length = self.running_stitch_length # Do it like contour underlay, but inset all the way to the center. pairs = self.plot_points_on_rails(self.running_stitch_tolerance, (0, 0), inset_prop) points = [points[0] for points in pairs] - stitches = running_stitch.even_running_stitch(points, self.running_stitch_length, self.running_stitch_tolerance) + stitches = running_stitch.even_running_stitch(points, [stitch_length], self.running_stitch_tolerance) if len(stitches) == 1: stitches.append(stitches[0]) @@ -1338,12 +1340,12 @@ class SatinColumn(EmbroideryElement): first_side = running_stitch.even_running_stitch( [points[0] for points in pairs], - self.contour_underlay_stitch_length, + [self.contour_underlay_stitch_length], self.contour_underlay_stitch_tolerance ) second_side = running_stitch.even_running_stitch( [points[1] for points in pairs], - self.contour_underlay_stitch_length, + [self.contour_underlay_stitch_length], self.contour_underlay_stitch_tolerance ) @@ -1381,7 +1383,7 @@ class SatinColumn(EmbroideryElement): repeats = self.center_walk_underlay_repeats stitch_groups = [] - stitches = self._get_center_line_stitches(self.center_walk_underlay_position) + stitches = self._get_center_line_stitches(self.center_walk_underlay_position, self.center_walk_underlay_stitch_length) if end_point: tags = ("satin_column", "satin_column_underlay", "satin_center_walk") stitches = shgeo.LineString(stitches) diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 58cc5756..f0f44827 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -118,14 +118,15 @@ class Stroke(EmbroideryElement): @property @param('running_stitch_length_mm', _('Running stitch length'), - tooltip=_('Length of stitches. Stitches can be shorter according to the stitch tolerance setting.'), + tooltip=_('Length of stitches. Stitches can be shorter according to the stitch tolerance setting.\n' + 'It is possible to create stitch length patterns by adding multiple values separated by a space.'), unit='mm', - type='float', + type='string', select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch')], - default=2.5, + default="2.5", sort_index=4) def running_stitch_length(self): - return max(self.get_float_param("running_stitch_length_mm", 2.5), 0.01) + return [max(value, 0.01) for value in self.get_multiple_float_param("running_stitch_length_mm", "2.5")] @property @param('running_stitch_tolerance_mm', @@ -185,13 +186,13 @@ class Stroke(EmbroideryElement): _('Zig-zag spacing (peak-to-peak)'), tooltip=_('Length of stitches in zig-zag mode.'), unit='mm', - type='float', - default=0.4, + type='string', + default="0.4", select_items=[('stroke_method', 'zigzag_stitch')], sort_index=6) @cache def zigzag_spacing(self): - return max(self.get_float_param("zigzag_spacing_mm", 0.4), 0.01) + return [max(value, 0.01) for value in self.get_multiple_float_param("zigzag_spacing_mm", "0.4")] @property @param('stroke_pull_compensation_mm', @@ -551,7 +552,8 @@ class Stroke(EmbroideryElement): # `self.zigzag_spacing` is the length for a zig and a zag # together (a V shape). Start with running stitch at half # that length: - stitch_group = self.running_stitch(path, zigzag_spacing / 2.0, self.running_stitch_tolerance, False, 0, "") + spacing = [value / 2 for value in zigzag_spacing] + stitch_group = self.running_stitch(path, spacing, self.running_stitch_tolerance, False, 0, "") stitch_group.stitches = zigzag_stitch(stitch_group.stitches, zigzag_spacing, stroke_width, pull_compensation) return stitch_group diff --git a/lib/extensions/fill_to_stroke.py b/lib/extensions/fill_to_stroke.py index c1b5ce9d..f1d32cbe 100644 --- a/lib/extensions/fill_to_stroke.py +++ b/lib/extensions/fill_to_stroke.py @@ -110,11 +110,11 @@ class FillToStroke(InkstitchExtension): def _get_high_res_polygon(self, polygon): # use running stitch method - runs = [even_running_stitch(line_string_to_point_list(polygon.exterior), 1, 0.1)] + runs = [even_running_stitch(line_string_to_point_list(polygon.exterior), [1], 0.1)] if len(runs[0]) < 3: return for interior in polygon.interiors: - shape = even_running_stitch(line_string_to_point_list(interior), 1, 0.1) + shape = even_running_stitch(line_string_to_point_list(interior), [1], 0.1) if len(shape) >= 3: runs.append(shape) return MultiPolygon([(runs[0], runs[1:])]) diff --git a/lib/stitches/auto_fill.py b/lib/stitches/auto_fill.py index bcde63e7..2573bf88 100644 --- a/lib/stitches/auto_fill.py +++ b/lib/stitches/auto_fill.py @@ -391,7 +391,7 @@ def fallback(shape, running_stitch_length, running_stitch_tolerance): boundary = ensure_multi_line_string(shape.boundary) outline = boundary.geoms[0] - return even_running_stitch(line_string_to_point_list(outline), running_stitch_length, running_stitch_tolerance) + return even_running_stitch(line_string_to_point_list(outline), [running_stitch_length], running_stitch_tolerance) @debug.time @@ -941,7 +941,7 @@ def path_to_stitches(shape, path, travel_graph, fill_stitch_graph, angle, row_sp if fill_stitch_graph.has_edge(edge[0], edge[1], key='segment'): travel_graph.remove_edges_from(fill_stitch_graph[edge[0]][edge[1]]['segment'].get('underpath_edges', [])) else: - stitches.extend(travel(shape, travel_graph, edge, running_stitch_length, running_stitch_tolerance, skip_last, underpath)) + stitches.extend(travel(shape, travel_graph, edge, [running_stitch_length], running_stitch_tolerance, skip_last, underpath)) check_stop_flag() diff --git a/lib/stitches/circular_fill.py b/lib/stitches/circular_fill.py index 26b48f24..fb6303ea 100644 --- a/lib/stitches/circular_fill.py +++ b/lib/stitches/circular_fill.py @@ -79,7 +79,7 @@ def circular_fill(shape, if isinstance(line, shgeo.LineString): # use running stitch here to adjust the stitch length coords = running_stitch([Point(*point) for point in line.coords], - running_stitch_length, + [running_stitch_length], running_stitch_tolerance, enable_random_stitch_length, running_stitch_length_jitter, @@ -162,6 +162,6 @@ def path_to_stitches(shape, path, travel_graph, fill_stitch_graph, running_stitc travel_graph.remove_edges_from(fill_stitch_graph[edge[0]][edge[1]]['segment'].get('underpath_edges', [])) else: - stitches.extend(travel(shape, travel_graph, edge, running_stitch_length, running_stitch_tolerance, skip_last, underpath)) + stitches.extend(travel(shape, travel_graph, edge, [running_stitch_length], running_stitch_tolerance, skip_last, underpath)) return stitches diff --git a/lib/stitches/contour_fill.py b/lib/stitches/contour_fill.py index 0665aacb..6a3ed4ff 100644 --- a/lib/stitches/contour_fill.py +++ b/lib/stitches/contour_fill.py @@ -422,7 +422,7 @@ def inner_to_outer(tree, polygon, offset, smoothed = smooth_path(points, smoothness) points = clamp_path_to_polygon(smoothed, polygon) - stitches = running_stitch(points, stitch_length, tolerance, enable_random_stitch_length, random_sigma, random_seed) + stitches = running_stitch(points, [stitch_length], tolerance, enable_random_stitch_length, random_sigma, random_seed) return stitches @@ -460,6 +460,9 @@ def _interpolate_linear_rings(ring1, ring2, max_stitch_length, start=None): # orders of magnitude faster because we're not building and querying a KDTree. num_points = int(20 * ring1.length / max_stitch_length) + if num_points <= 1: + return LineString() + ring1_resampled = trimesh.path.traversal.resample_path(np.array(ring1.coords), count=num_points) ring2_resampled = trimesh.path.traversal.resample_path(np.array(ring2.coords), count=num_points) @@ -535,7 +538,7 @@ def _spiral_fill(tree, stitch_length, tolerance, close_point, enable_random_stit path = spiral_maker(rings, stitch_length, starting_point) path = [Stitch(*stitch) for stitch in path] - return running_stitch(path, stitch_length, tolerance, enable_random_stitch_length, random_sigma, random_seed) + return running_stitch(path, [stitch_length], tolerance, enable_random_stitch_length, random_sigma, random_seed) def _get_spiral_rings(tree): diff --git a/lib/stitches/fill.py b/lib/stitches/fill.py index ad082b2d..e50c4007 100644 --- a/lib/stitches/fill.py +++ b/lib/stitches/fill.py @@ -63,7 +63,8 @@ def stitch_row(stitches, beg, end, angle, row_spacing, max_stitch_length, stagge stitches.append(beg) if enable_random_stitch_length: - stitches += split_segment_random_phase(beg, end, max_stitch_length, random_sigma, random_seed) + stitched_line = split_segment_random_phase(beg, end, max_stitch_length, random_sigma, random_seed) + stitches.extend([Stitch(stitch, tags=('fill_row',)) for stitch in stitched_line]) else: # We want our stitches to look like this: # diff --git a/lib/stitches/guided_fill.py b/lib/stitches/guided_fill.py index 16f0f2e8..84d7600e 100644 --- a/lib/stitches/guided_fill.py +++ b/lib/stitches/guided_fill.py @@ -102,7 +102,7 @@ def path_to_stitches(shape, path, travel_graph, fill_stitch_graph, travel_graph.remove_edges_from(fill_stitch_graph[edge[0]][edge[1]]['segment'].get('underpath_edges', [])) else: - stitches.extend(travel(shape, travel_graph, edge, running_stitch_length, running_stitch_tolerance, skip_last, underpath)) + stitches.extend(travel(shape, travel_graph, edge, [running_stitch_length], running_stitch_tolerance, skip_last, underpath)) return stitches @@ -166,6 +166,7 @@ def take_only_line_strings(thing): def apply_stitches(line, max_stitch_length, num_staggers, row_spacing, row_num, threshold=None) -> shgeo.LineString: if num_staggers == 0: num_staggers = 1 # sanity check to avoid division by zero. + max_stitch_length = max_stitch_length[0] start = ((row_num / num_staggers) % 1) * max_stitch_length projections = np.arange(start, line.length, max_stitch_length) points = np.array([line.interpolate(projection).coords[0] for projection in projections]) @@ -275,9 +276,9 @@ def intersect_region_with_grating_guideline(shape, line, row_spacing, num_stagge if enable_random_stitch_length: points = [InkstitchPoint(*x) for x in offset_line.coords] stitched_line = shgeo.LineString(random_running_stitch( - points, max_stitch_length, tolerance, random_sigma, prng.join_args(random_seed, row))) + points, [max_stitch_length], tolerance, random_sigma, prng.join_args(random_seed, row))) else: - stitched_line = apply_stitches(offset_line, max_stitch_length, num_staggers, row_spacing, row) + stitched_line = apply_stitches(offset_line, [max_stitch_length], num_staggers, row_spacing, row) intersection = shape.intersection(stitched_line) if not intersection.is_empty and shape_envelope.intersects(stitched_line): diff --git a/lib/stitches/linear_gradient_fill.py b/lib/stitches/linear_gradient_fill.py index 589a1f23..4f2f3f74 100644 --- a/lib/stitches/linear_gradient_fill.py +++ b/lib/stitches/linear_gradient_fill.py @@ -127,9 +127,11 @@ def _get_lines(fill, shape, bounding_box, angle): if fill.enable_random_stitch_length: points = [InkstitchPoint(*x) for x in line] staggered_line = LineString(random_running_stitch( - points, fill.max_stitch_length, fill.running_stitch_tolerance, fill.random_stitch_length_jitter, prng.join_args(fill.random_seed, i))) + points, + [fill.max_stitch_length], fill.running_stitch_tolerance, fill.random_stitch_length_jitter, prng.join_args(fill.random_seed, i)) + ) else: - staggered_line = apply_stitches(LineString(line), fill.max_stitch_length, fill.staggers, fill.row_spacing, i) + staggered_line = apply_stitches(LineString(line), [fill.max_stitch_length], fill.staggers, fill.row_spacing, i) staggered_lines.append(staggered_line) return staggered_lines, bottom_line diff --git a/lib/stitches/meander_fill.py b/lib/stitches/meander_fill.py index 87c52e17..1883c97f 100644 --- a/lib/stitches/meander_fill.py +++ b/lib/stitches/meander_fill.py @@ -179,10 +179,10 @@ def post_process(points, shape, original_shape, fill): smoothed_points = [InkStitchPoint.from_tuple(point) for point in smoothed_points] if fill.zigzag_spacing > 0: - stitches = even_running_stitch(smoothed_points, fill.zigzag_spacing / 2, fill.running_stitch_tolerance) + stitches = even_running_stitch(smoothed_points, [fill.zigzag_spacing / 2], fill.running_stitch_tolerance) stitches = zigzag_stitch(stitches, fill.zigzag_spacing, fill.zigzag_width, (0, 0)) else: - stitches = even_running_stitch(smoothed_points, fill.running_stitch_length, fill.running_stitch_tolerance) + stitches = even_running_stitch(smoothed_points, [fill.running_stitch_length], fill.running_stitch_tolerance) if fill.clip: # the stitch path may have self intersections diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py index 804e5f15..2abb5963 100644 --- a/lib/stitches/ripple_stitch.py +++ b/lib/stitches/ripple_stitch.py @@ -4,6 +4,7 @@ from math import atan2, ceil import numpy as np from shapely.affinity import rotate, scale, translate from shapely.geometry import LineString, Point +from shapely.ops import substring from ..elements import SatinColumn from ..utils import Point as InkstitchPoint @@ -80,7 +81,7 @@ def _get_staggered_stitches(stroke, lines, skip_start): stitches = [] stitch_length = stroke.running_stitch_length tolerance = stroke.running_stitch_tolerance - enable_random_stitch_length = stroke.enable_random_stitch_length + is_random = stroke.enable_random_stitch_length length_sigma = stroke.random_stitch_length_jitter random_seed = stroke.random_seed last_point = None @@ -98,14 +99,18 @@ def _get_staggered_stitches(stroke, lines, skip_start): elif stroke.join_style == 1: should_reverse = (i + skip_start) % 2 == 1 - if enable_random_stitch_length or stroke.staggers == 0: + if stroke.staggers == 0: if should_reverse and stroke.flip_copies: line.reverse() - points = running_stitch(line, stitch_length, tolerance, enable_random_stitch_length, length_sigma, prng.join_args(random_seed, i)) - stitched_line = connector + points + stitched_line = running_stitch(line, stitch_length, tolerance, is_random, length_sigma, prng.join_args(random_seed, i)) else: - # uses the guided fill alforithm to stagger rows of stitches - points = list(apply_stitches(LineString(line), stitch_length, stroke.staggers, 0.5, i, tolerance).coords) + if len(stitch_length) > 1: + points = list( + apply_stagger(line, stitch_length, stroke.staggers, i, tolerance, is_random, length_sigma, prng.join_args(random_seed, i)).coords + ) + else: + # uses the guided fill alforithm to stagger rows of stitches + points = list(apply_stitches(LineString(line), stitch_length, stroke.staggers, 0.5, i, tolerance).coords) # simplifying the path in apply_stitches could have removed the start or end point # we can simply add it again, the minimum stitch length value will take care to remove possible duplicates @@ -114,13 +119,33 @@ def _get_staggered_stitches(stroke, lines, skip_start): stitched_line = [InkstitchPoint(*point) for point in points] if should_reverse and stroke.flip_copies: stitched_line.reverse() - stitched_line = connector + stitched_line + + stitched_line = connector + stitched_line last_point = stitched_line[-1] stitches.extend(stitched_line) return stitches +def apply_stagger(line, stitch_length, num_staggers, row_num, tolerance, is_random, stitch_length_sigma, random_seed): + if num_staggers == 0: + num_staggers = 1 # sanity check to avoid division by zero. + start = ((row_num / num_staggers) % 1) * sum(stitch_length) + first_segment = LineString(line[:2]) + segment_length = max(first_segment.length, 0.1) + target_length = segment_length + 2 * start + scale_factor = target_length / segment_length + extended_line = scale(first_segment, scale_factor, scale_factor) + + line = [InkstitchPoint(*extended_line.coords[0])] + line + stitched_row = running_stitch(line, stitch_length, tolerance, is_random, stitch_length_sigma, random_seed) + if len(stitched_row) <= 1: + return LineString() + + stitched_line = LineString(stitched_row) + return substring(stitched_line, start, stitched_line.length) + + def _adjust_skip(stroke, num_lines, skip): if stroke.skip_start + stroke.skip_end >= num_lines: return 0 @@ -202,7 +227,7 @@ def _get_helper_lines(stroke): def _get_satin_ripple_helper_lines(stroke): # if grid_size has a number use this, otherwise use running_stitch_length - length = stroke.grid_size or stroke.running_stitch_length + length = stroke.grid_size or min(stroke.running_stitch_length) # use satin column points for satin like build ripple stitches rail_pairs = SatinColumn(stroke.node).plot_points_on_rails(length) diff --git a/lib/stitches/running_stitch.py b/lib/stitches/running_stitch.py index 8b8add7e..058ee565 100644 --- a/lib/stitches/running_stitch.py +++ b/lib/stitches/running_stitch.py @@ -210,11 +210,12 @@ def take_stitch(start: Point, points: typing.Sequence[Point], idx: int, stitch_l return points[-1], None -def stitch_curve_evenly(points: typing.Sequence[Point], stitch_length: float, tolerance: float) -> typing.List[Point]: +def stitch_curve_evenly(points: typing.Sequence[Point], stitch_length: typing.List[float], tolerance: float, stitch_length_pos: int = 0) -> \ + typing.Tuple[typing.List[Point], int]: # Will split a straight line into even-length stitches while still handling curves correctly. # Includes end point but not start point. if len(points) < 2: - return [] + return [], stitch_length_pos distLeft = [0] * len(points) for j in reversed(range(0, len(points) - 1)): distLeft[j] = distLeft[j + 1] + points[j].distance(points[j+1]) @@ -225,26 +226,33 @@ def stitch_curve_evenly(points: typing.Sequence[Point], stitch_length: float, to while i is not None and i < len(points): d = last.distance(points[i]) + distLeft[i] if d == 0: - return stitches - stitch_len = d / math.ceil(d / stitch_length) + 0.000001 # correction for rounding error + return stitches, stitch_length_pos + stitch_len = d / math.ceil(d / stitch_length[stitch_length_pos]) + 0.000001 # correction for rounding error stitch, newidx = take_stitch(last, points, i, stitch_len, tolerance) i = newidx if stitch is not None: stitches.append(stitch) last = stitch - return stitches + stitch_length_pos += 1 + if stitch_length_pos > len(stitch_length) - 1: + stitch_length_pos = 0 + return stitches, stitch_length_pos + + +def stitch_curve_randomly( + points: typing.Sequence[Point], + stitch_length: typing.List[float], tolerance: float, stitch_length_sigma: float, + random_seed: str, stitch_length_pos: int = 0) -> typing.Tuple[typing.List[Point], int]: + min_stitch_length = max(0, stitch_length[stitch_length_pos] * (1 - stitch_length_sigma)) + max_stitch_length = stitch_length[stitch_length_pos] * (1 + stitch_length_sigma) -def stitch_curve_randomly(points: typing.Sequence[Point], stitch_length: float, tolerance: float, stitch_length_sigma: float, random_seed: str) ->\ - typing.List[Point]: - min_stitch_length = max(0, stitch_length * (1 - stitch_length_sigma)) - max_stitch_length = stitch_length * (1 + stitch_length_sigma) # Will split a straight line into stitches of random length within the range. # Attempts to randomize phase so that the distribution of outputs does not depend on direction. # Includes end point but not start point. if len(points) < 2: - return [] + return [], stitch_length_pos i: typing.Optional[int] = 1 last = points[0] @@ -252,6 +260,13 @@ def stitch_curve_randomly(points: typing.Sequence[Point], stitch_length: float, stitches = [] rand_iter = iter(prng.iter_uniform_floats(random_seed)) while i is not None and i < len(points): + if len(stitch_length) > 1: + min_stitch_length = max(0, stitch_length[stitch_length_pos] * (1 - stitch_length_sigma)) + max_stitch_length = stitch_length[stitch_length_pos] * (1 + stitch_length_sigma) + stitch_length_pos += 1 + if stitch_length_pos > len(stitch_length) - 1: + stitch_length_pos = 0 + r = next(rand_iter) # If the last stitch was shortened due to tolerance (or this is the first stitch), # reduce the lower length limit to randomize the phase. This prevents moiré and asymmetry. @@ -263,7 +278,7 @@ def stitch_curve_randomly(points: typing.Sequence[Point], stitch_length: float, stitches.append(stitch) last_shortened = min(last.distance(stitch) / stitch_len, 1.0) last = stitch - return stitches + return stitches, stitch_length_pos def path_to_curves(points: typing.List[Point], min_len: float): @@ -309,10 +324,12 @@ def even_running_stitch(points, stitch_length, tolerance): if not points: return stitches = [points[0]] + last_stitch_length_pos = 0 for curve in path_to_curves(points, 2 * tolerance): # segments longer than twice the tolerance will usually be forced by it, so set that as the minimum for corner detection check_stop_flag() - stitches.extend(stitch_curve_evenly(curve, stitch_length, tolerance)) + stitched_curve, last_stitch_length_pos = stitch_curve_evenly(curve, stitch_length, tolerance, last_stitch_length_pos) + stitches.extend(stitched_curve) return stitches @@ -323,10 +340,14 @@ def random_running_stitch(points, stitch_length, tolerance, stitch_length_sigma, if not points: return stitches = [points[0]] + last_stitch_length_pos = 0 for i, curve in enumerate(path_to_curves(points, 2 * tolerance)): # segments longer than twice the tolerance will usually be forced by it, so set that as the minimum for corner detection check_stop_flag() - stitches.extend(stitch_curve_randomly(curve, stitch_length, tolerance, stitch_length_sigma, prng.join_args(random_seed, i))) + stitched_curve, last_stitch_length_pos = stitch_curve_randomly( + curve, stitch_length, tolerance, stitch_length_sigma, prng.join_args(random_seed, i), last_stitch_length_pos + ) + stitches.extend(stitched_curve) return stitches diff --git a/lib/stitches/tartan_fill.py b/lib/stitches/tartan_fill.py index c25bb435..521919a0 100644 --- a/lib/stitches/tartan_fill.py +++ b/lib/stitches/tartan_fill.py @@ -155,7 +155,7 @@ def _generate_herringbone_lines( staggered_lines = [] for i, line in enumerate(lines): linestring = LineString(line) - staggered_line = apply_stitches(linestring, fill.max_stitch_length, fill.staggers, fill.row_spacing, i) + staggered_line = apply_stitches(linestring, [fill.max_stitch_length], fill.staggers, fill.row_spacing, i) # make sure we do not ommit the very first or very last point (it would confuse our sorting algorithm) staggered_line = LineString([linestring.coords[0]] + list(staggered_line.coords) + [linestring.coords[-1]]) staggered_lines.append(staggered_line) @@ -205,7 +205,7 @@ def _generate_tartan_lines( staggered_lines = [] for i, line in enumerate(lines): linestring = LineString(line) - staggered_line = apply_stitches(linestring, fill.max_stitch_length, fill.staggers, fill.row_spacing, i) + staggered_line = apply_stitches(linestring, [fill.max_stitch_length], fill.staggers, fill.row_spacing, i) # make sure we do not ommit the very first or very last point (it would confuse our sorting algorithm) staggered_line = LineString([linestring.coords[0]] + list(staggered_line.coords) + [linestring.coords[-1]]) staggered_lines.append(staggered_line) diff --git a/lib/utils/settings.py b/lib/utils/settings.py index b2220ef9..82d8938a 100644 --- a/lib/utils/settings.py +++ b/lib/utils/settings.py @@ -49,7 +49,7 @@ class GlobalSettings(MutableMapping): # We set create=False here because this code is executed on module load # and via imports also runs on generate-inx-files, which with the Nix # package manager is executed with a non-writable home directory. - user_dir = get_user_dir(create=False) + user_dir = get_user_dir(create=True) self._settings_file = os.path.join(user_dir, "settings.json") self._settings = {} diff --git a/lib/utils/smoothing.py b/lib/utils/smoothing.py index 1511b0a3..c451140c 100644 --- a/lib/utils/smoothing.py +++ b/lib/utils/smoothing.py @@ -44,7 +44,7 @@ def smooth_path(path, smoothness=1.0, iterations=5): # # Fortunately, we can convert the path to segments that are mostly the same # length by using the running stitch algorithm. - points = stitch_curve_evenly(points, smoothness * 5, smoothness * 2) + points, _ = stitch_curve_evenly(points, [smoothness * 5], smoothness * 2) points = np.array(points) for _ in range(iterations): ll = points.repeat(2, axis=0) |
