summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLex Neva <github.com@lexneva.name>2022-05-03 14:34:21 -0400
committerKaalleen <reni@allenka.de>2022-05-04 19:18:33 +0200
commit5a69fa3e9c582a3bc21660342cea35837ae1eb9a (patch)
treed2ce77282fdb4aa5376d490e420d7c18b5389462 /lib
parent68ee0eea8733d613543a28627bd21a4481da8b46 (diff)
add double (fermat) spiral
Diffstat (limited to 'lib')
-rw-r--r--lib/elements/fill_stitch.py2
-rw-r--r--lib/stitches/tangential_fill_stitch_line_creator.py14
-rw-r--r--lib/stitches/tangential_fill_stitch_pattern_creator.py66
3 files changed, 64 insertions, 18 deletions
diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py
index 2f8687a1..70d4f356 100644
--- a/lib/elements/fill_stitch.py
+++ b/lib/elements/fill_stitch.py
@@ -103,7 +103,7 @@ class FillStitch(EmbroideryElement):
@property
@param('tangential_strategy', _('Tangential strategy'), type='dropdown', default=1,
- options=[_("Inner to Outer"), _("Single spiral")], select_items=[('fill_method', 1)], sort_index=2)
+ options=[_("Inner to Outer"), _("Single spiral"), _("Double spiral")], select_items=[('fill_method', 1)], sort_index=2)
def tangential_strategy(self):
return self.get_int_param('tangential_strategy', 1)
diff --git a/lib/stitches/tangential_fill_stitch_line_creator.py b/lib/stitches/tangential_fill_stitch_line_creator.py
index 78213384..69bb13f2 100644
--- a/lib/stitches/tangential_fill_stitch_line_creator.py
+++ b/lib/stitches/tangential_fill_stitch_line_creator.py
@@ -84,7 +84,8 @@ def make_tree_uniform(tree, clockwise=True):
# Used to define which stitching strategy shall be used
class StitchingStrategy(IntEnum):
INNER_TO_OUTER = 0
- SPIRAL = 1
+ SINGLE_SPIRAL = 1
+ DOUBLE_SPIRAL = 2
def check_and_prepare_tree_for_valid_spiral(tree):
@@ -158,7 +159,7 @@ def offset_poly(poly, offset, join_style, stitch_distance, min_stitch_distance,
at this position
"""
- if strategy == StitchingStrategy.SPIRAL and len(poly.interiors) > 1:
+ if strategy in (StitchingStrategy.SINGLE_SPIRAL, StitchingStrategy.DOUBLE_SPIRAL) and len(poly.interiors) > 1:
raise ValueError(
"Single spiral geometry must not have more than one hole!")
@@ -293,10 +294,15 @@ def offset_poly(poly, offset, join_style, stitch_distance, min_stitch_distance,
tree, 'root', abs(offset), stitch_distance, min_stitch_distance, starting_point, offset_by_half, avoid_self_crossing)
path = [Stitch(*point) for point in connected_line.coords]
return running_stitch(path, stitch_distance), "whatever"
- elif strategy == StitchingStrategy.SPIRAL:
+ elif strategy == StitchingStrategy.SINGLE_SPIRAL:
if not check_and_prepare_tree_for_valid_spiral(tree):
raise ValueError("Geometry cannot be filled with one spiral!")
- (connected_line, connected_line_origin) = tangential_fill_stitch_pattern_creator.connect_raster_tree_spiral(
+ (connected_line, connected_line_origin) = tangential_fill_stitch_pattern_creator.connect_raster_tree_single_spiral(
+ tree, offset, stitch_distance, min_stitch_distance, starting_point, offset_by_half)
+ elif strategy == StitchingStrategy.DOUBLE_SPIRAL:
+ if not check_and_prepare_tree_for_valid_spiral(tree):
+ raise ValueError("Geometry cannot be filled with a double spiral!")
+ (connected_line, connected_line_origin) = tangential_fill_stitch_pattern_creator.connect_raster_tree_double_spiral(
tree, offset, stitch_distance, min_stitch_distance, starting_point, offset_by_half)
else:
raise ValueError("Invalid stitching stratety!")
diff --git a/lib/stitches/tangential_fill_stitch_pattern_creator.py b/lib/stitches/tangential_fill_stitch_pattern_creator.py
index 2556d58c..edc6e0af 100644
--- a/lib/stitches/tangential_fill_stitch_pattern_creator.py
+++ b/lib/stitches/tangential_fill_stitch_pattern_creator.py
@@ -1,5 +1,5 @@
-import math
from collections import namedtuple
+from itertools import chain
import networkx as nx
import numpy as np
import trimesh
@@ -259,7 +259,7 @@ def interpolate_linear_rings(ring1, ring2, max_stitch_length, start=None):
return result.simplify(constants.simplification_threshold, False)
-def connect_raster_tree_spiral(tree, used_offset, stitch_distance, min_stitch_distance, close_point, offset_by_half): # noqa: C901
+def connect_raster_tree_single_spiral(tree, used_offset, stitch_distance, min_stitch_distance, close_point, offset_by_half): # noqa: C901
"""
Takes the offsetted curves organized as tree, connects and samples them as a spiral.
It expects that each node in the tree has max. one child
@@ -281,21 +281,61 @@ def connect_raster_tree_spiral(tree, used_offset, stitch_distance, min_stitch_di
placed at this position
"""
- if not tree['root']: # if node has no children
- stitches = [Stitch(*point) for point in tree.nodes['root'].val.coords]
- return running_stitch(stitches, stitch_distance)
+ starting_point = close_point.coords[0]
+
+ rings = [tree.nodes[node].val for node in nx.dfs_preorder_nodes(tree, 'root')]
+
+ path = make_spiral(rings, stitch_distance, starting_point)
+ path = [Stitch(*stitch) for stitch in path]
+
+ return running_stitch(path, stitch_distance), None
+
+
+def connect_raster_tree_double_spiral(tree, used_offset, stitch_distance, min_stitch_distance, close_point, offset_by_half): # noqa: C901
+ """
+ Takes the offsetted curves organized as tree, connects and samples them as a spiral.
+ It expects that each node in the tree has max. one child
+ Input:
+ -tree: contains the offsetted curves in a hierarchical organized
+ data structure.
+ -used_offset: used offset when the offsetted curves were generated
+ -stitch_distance: maximum allowed distance between two points
+ after sampling
+ -min_stitch_distance stitches within a row shall be at least min_stitch_distance apart. Stitches connecting
+ offsetted paths might be shorter.
+ -close_point: defines the beginning point for stitching
+ (stitching starts always from the undisplaced curve)
+ -offset_by_half: If true the resulting points are interlaced otherwise not.
+ Return values:
+ -All offsetted curves connected to one spiral and sampled with
+ points obeying stitch_distance and offset_by_half
+ -Tag (origin) of each point to analyze why a point was
+ placed at this position
+ """
starting_point = close_point.coords[0]
- path = []
- for node in nx.dfs_preorder_nodes(tree, 'root'):
- if tree[node]:
- ring1 = tree.nodes[node].val
- child = list(tree.successors(node))[0]
- ring2 = tree.nodes[child].val
- spiral_part = interpolate_linear_rings(ring1, ring2, stitch_distance, starting_point)
- path.extend(spiral_part.coords)
+ rings = [tree.nodes[node].val for node in nx.dfs_preorder_nodes(tree, 'root')]
+ path = make_fermat_spiral(rings, stitch_distance, starting_point)
path = [Stitch(*stitch) for stitch in path]
return running_stitch(path, stitch_distance), None
+
+
+def make_fermat_spiral(rings, stitch_distance, starting_point):
+ forward = make_spiral(rings[::2], stitch_distance, starting_point)
+ back = make_spiral(rings[1::2], stitch_distance, starting_point)
+ back.reverse()
+
+ return chain(forward, back)
+
+
+def make_spiral(rings, stitch_distance, starting_point):
+ path = []
+
+ for ring1, ring2 in zip(rings[:-1], rings[1:]):
+ spiral_part = interpolate_linear_rings(ring1, ring2, stitch_distance, starting_point)
+ path.extend(spiral_part.coords)
+
+ return path