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/stitches/running_stitch.py | |
| 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/stitches/running_stitch.py')
| -rw-r--r-- | lib/stitches/running_stitch.py | 47 |
1 files changed, 34 insertions, 13 deletions
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 |
