summaryrefslogtreecommitdiff
path: root/lib/stitches
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stitches')
-rw-r--r--lib/stitches/auto_fill.py21
-rw-r--r--lib/stitches/contour_fill.py16
-rw-r--r--lib/stitches/ripple_stitch.py8
-rw-r--r--lib/stitches/running_stitch.py11
4 files changed, 30 insertions, 26 deletions
diff --git a/lib/stitches/auto_fill.py b/lib/stitches/auto_fill.py
index 65b1e06d..ac1e477b 100644
--- a/lib/stitches/auto_fill.py
+++ b/lib/stitches/auto_fill.py
@@ -53,6 +53,7 @@ def auto_fill(shape,
end_row_spacing,
max_stitch_length,
running_stitch_length,
+ running_stitch_tolerance,
staggers,
skip_last,
starting_point,
@@ -64,15 +65,16 @@ def auto_fill(shape,
fill_stitch_graph = build_fill_stitch_graph(shape, segments, starting_point, ending_point)
except ValueError:
# Small shapes will cause the graph to fail - min() arg is an empty sequence through insert node
- return fallback(shape, running_stitch_length)
+ return fallback(shape, running_stitch_length, running_stitch_tolerance)
if not graph_is_valid(fill_stitch_graph, shape, max_stitch_length):
- return fallback(shape, running_stitch_length)
+ return fallback(shape, running_stitch_length, running_stitch_tolerance)
travel_graph = build_travel_graph(fill_stitch_graph, shape, angle, underpath)
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
result = path_to_stitches(path, travel_graph, fill_stitch_graph, angle, row_spacing,
- max_stitch_length, running_stitch_length, staggers, skip_last)
+ max_stitch_length, running_stitch_length, running_stitch_tolerance,
+ staggers, skip_last)
return result
@@ -251,7 +253,7 @@ def graph_is_valid(graph, shape, max_stitch_length):
return not networkx.is_empty(graph) and networkx.is_eulerian(graph)
-def fallback(shape, running_stitch_length):
+def fallback(shape, running_stitch_length, running_stitch_tolerance):
"""Generate stitches when the auto-fill algorithm fails.
If graph_is_valid() returns False, we're not going to be able to run the
@@ -263,7 +265,7 @@ def fallback(shape, running_stitch_length):
boundary = ensure_multi_line_string(shape.boundary)
outline = boundary.geoms[0]
- return running_stitch(line_string_to_point_list(outline), running_stitch_length)
+ return running_stitch(line_string_to_point_list(outline), running_stitch_length, running_stitch_tolerance)
@debug.time
@@ -583,12 +585,12 @@ def collapse_sequential_outline_edges(path):
return new_path
-def travel(travel_graph, start, end, running_stitch_length, skip_last):
+def travel(travel_graph, start, end, running_stitch_length, running_stitch_tolerance, skip_last):
"""Create stitches to get from one point on an outline of the shape to another."""
path = networkx.shortest_path(travel_graph, start, end, weight='weight')
path = [Stitch(*p) for p in path]
- stitches = running_stitch(path, running_stitch_length)
+ stitches = running_stitch(path, running_stitch_length, running_stitch_tolerance)
for stitch in stitches:
stitch.add_tag('auto_fill_travel')
@@ -610,7 +612,8 @@ def travel(travel_graph, start, end, running_stitch_length, skip_last):
@debug.time
-def path_to_stitches(path, travel_graph, fill_stitch_graph, angle, row_spacing, max_stitch_length, running_stitch_length, staggers, skip_last):
+def path_to_stitches(path, travel_graph, fill_stitch_graph, angle, row_spacing, max_stitch_length, running_stitch_length, running_stitch_tolerance,
+ staggers, skip_last):
path = collapse_sequential_outline_edges(path)
stitches = []
@@ -624,6 +627,6 @@ def path_to_stitches(path, travel_graph, fill_stitch_graph, angle, row_spacing,
stitch_row(stitches, edge[0], edge[1], angle, row_spacing, max_stitch_length, staggers, skip_last)
travel_graph.remove_edges_from(fill_stitch_graph[edge[0]][edge[1]]['segment'].get('underpath_edges', []))
else:
- stitches.extend(travel(travel_graph, edge[0], edge[1], running_stitch_length, skip_last))
+ stitches.extend(travel(travel_graph, edge[0], edge[1], running_stitch_length, running_stitch_tolerance, skip_last))
return stitches
diff --git a/lib/stitches/contour_fill.py b/lib/stitches/contour_fill.py
index c42cc6f2..f2ab2aef 100644
--- a/lib/stitches/contour_fill.py
+++ b/lib/stitches/contour_fill.py
@@ -391,12 +391,12 @@ def _find_path_inner_to_outer(tree, node, offset, starting_point, avoid_self_cro
return LineString(result_coords)
-def inner_to_outer(tree, offset, stitch_length, starting_point, avoid_self_crossing):
+def inner_to_outer(tree, offset, stitch_length, tolerance, starting_point, avoid_self_crossing):
"""Fill a shape with spirals, from innermost to outermost."""
stitch_path = _find_path_inner_to_outer(tree, 'root', offset, starting_point, avoid_self_crossing)
points = [Stitch(*point) for point in stitch_path.coords]
- stitches = running_stitch(points, stitch_length)
+ stitches = running_stitch(points, stitch_length, tolerance)
return stitches
@@ -490,24 +490,24 @@ def _check_and_prepare_tree_for_valid_spiral(tree):
return process_node('root')
-def single_spiral(tree, stitch_length, starting_point):
+def single_spiral(tree, stitch_length, tolerance, starting_point):
"""Fill a shape with a single spiral going from outside to center."""
- return _spiral_fill(tree, stitch_length, starting_point, _make_spiral)
+ return _spiral_fill(tree, stitch_length, tolerance, starting_point, _make_spiral)
-def double_spiral(tree, stitch_length, starting_point):
+def double_spiral(tree, stitch_length, tolerance, starting_point):
"""Fill a shape with a double spiral going from outside to center and back to outside. """
- return _spiral_fill(tree, stitch_length, starting_point, _make_fermat_spiral)
+ return _spiral_fill(tree, stitch_length, tolerance, starting_point, _make_fermat_spiral)
-def _spiral_fill(tree, stitch_length, close_point, spiral_maker):
+def _spiral_fill(tree, stitch_length, tolerance, close_point, spiral_maker):
starting_point = close_point.coords[0]
rings = _get_spiral_rings(tree)
path = spiral_maker(rings, stitch_length, starting_point)
path = [Stitch(*stitch) for stitch in path]
- return running_stitch(path, stitch_length)
+ return running_stitch(path, stitch_length, tolerance)
def _get_spiral_rings(tree):
diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py
index 46fc5e07..489666b0 100644
--- a/lib/stitches/ripple_stitch.py
+++ b/lib/stitches/ripple_stitch.py
@@ -30,7 +30,7 @@ def ripple_stitch(stroke):
if stroke.grid_size != 0:
ripple_points.extend(_do_grid(stroke, helper_lines))
- stitches = running_stitch(ripple_points, stroke.running_stitch_length)
+ stitches = running_stitch(ripple_points, stroke.running_stitch_length, stroke.running_stitch_tolerance)
return _repeat_coords(stitches, stroke.repeats)
@@ -57,7 +57,9 @@ def _get_helper_lines(stroke):
if len(lines) > 1:
return True, _get_satin_ripple_helper_lines(stroke)
else:
- outline = LineString(running_stitch(line_string_to_point_list(lines[0]), stroke.grid_size or stroke.running_stitch_length))
+ outline = LineString(running_stitch(line_string_to_point_list(lines[0]),
+ stroke.grid_size or stroke.running_stitch_length,
+ stroke.running_stitch_tolerance))
if stroke.is_closed:
return False, _get_circular_ripple_helper_lines(stroke, outline)
@@ -146,7 +148,7 @@ def _get_guided_helper_lines(stroke, outline, max_distance):
def _generate_guided_helper_lines(stroke, outline, max_distance, guide_line):
# helper lines are generated by making copies of the outline alog the guide line
line_point_dict = defaultdict(list)
- outline = LineString(running_stitch(line_string_to_point_list(outline), max_distance))
+ outline = LineString(running_stitch(line_string_to_point_list(outline), max_distance, stroke.running_stitch_tolerance))
center = outline.centroid
center = InkstitchPoint(center.x, center.y)
diff --git a/lib/stitches/running_stitch.py b/lib/stitches/running_stitch.py
index 98d080ba..8c86eb7c 100644
--- a/lib/stitches/running_stitch.py
+++ b/lib/stitches/running_stitch.py
@@ -3,16 +3,15 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
-from ..debug import debug
import math
from copy import copy
+
from shapely.geometry import LineString
""" Utility functions to produce running stitches. """
-@debug.time
-def running_stitch(points, stitch_length):
+def running_stitch(points, stitch_length, tolerance):
"""Generate running stitch along a path.
Given a path and a stitch length, walk along the path in increments of the
@@ -28,9 +27,9 @@ def running_stitch(points, stitch_length):
return []
# simplify will remove as many points as possible while ensuring that the
- # resulting path stays within 0.75 pixels (0.2mm) of the original path.
+ # resulting path stays within the specified tolerance of the original path.
path = LineString(points)
- simplified = path.simplify(0.75, preserve_topology=False)
+ simplified = path.simplify(tolerance, preserve_topology=False)
# save the points that simplify picked and make sure we stitch them
important_points = set(simplified.coords)
@@ -50,7 +49,7 @@ def running_stitch(points, stitch_length):
section_length = section_ls.length
if section_length > stitch_length:
# a fractional stitch needs to be rounded up, which will make all
- # of the stitches shorter
+ # the stitches shorter
num_stitches = math.ceil(section_length / stitch_length)
actual_stitch_length = section_length / num_stitches