summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/elements/element.py12
-rw-r--r--lib/elements/satin_column.py12
-rw-r--r--lib/elements/stroke.py18
-rw-r--r--lib/extensions/fill_to_stroke.py4
-rw-r--r--lib/stitches/auto_fill.py4
-rw-r--r--lib/stitches/circular_fill.py4
-rw-r--r--lib/stitches/contour_fill.py7
-rw-r--r--lib/stitches/fill.py3
-rw-r--r--lib/stitches/guided_fill.py7
-rw-r--r--lib/stitches/linear_gradient_fill.py6
-rw-r--r--lib/stitches/meander_fill.py4
-rw-r--r--lib/stitches/ripple_stitch.py41
-rw-r--r--lib/stitches/running_stitch.py47
-rw-r--r--lib/stitches/tartan_fill.py4
-rw-r--r--lib/utils/settings.py2
-rw-r--r--lib/utils/smoothing.py2
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)