summaryrefslogtreecommitdiff
path: root/lib/stitches
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stitches')
-rw-r--r--lib/stitches/auto_fill.py2
-rw-r--r--lib/stitches/auto_run.py5
-rw-r--r--lib/stitches/contour_fill.py15
-rw-r--r--lib/stitches/fill.py13
-rw-r--r--lib/stitches/utils/autoroute.py97
5 files changed, 81 insertions, 51 deletions
diff --git a/lib/stitches/auto_fill.py b/lib/stitches/auto_fill.py
index 24ce6610..40b74d23 100644
--- a/lib/stitches/auto_fill.py
+++ b/lib/stitches/auto_fill.py
@@ -195,7 +195,7 @@ def insert_node(graph, shape, point):
edges = []
for start, end, key, data in graph.edges(keys=True, data=True):
- if key == "outline":
+ if key == "outline" and data['outline'] == outline:
edges.append(((start, end), data))
edge, data = min(edges, key=lambda edge_data: shgeo.LineString(edge_data[0]).distance(projected_point))
diff --git a/lib/stitches/auto_run.py b/lib/stitches/auto_run.py
index d833a885..b8ab84c7 100644
--- a/lib/stitches/auto_run.py
+++ b/lib/stitches/auto_run.py
@@ -5,23 +5,22 @@
from collections import defaultdict
+import inkex
import networkx as nx
from shapely.geometry import LineString, MultiLineString, MultiPoint, Point
from shapely.ops import nearest_points, substring, unary_union
-import inkex
-
from ..commands import add_commands
from ..elements import Stroke
from ..i18n import _
from ..svg import PIXELS_PER_MM, generate_unique_id
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS
+from ..utils.threading import check_stop_flag
from .utils.autoroute import (add_elements_to_group, add_jumps,
create_new_group, find_path,
get_starting_and_ending_nodes,
preserve_original_groups,
remove_original_elements)
-from ..utils.threading import check_stop_flag
class LineSegments:
diff --git a/lib/stitches/contour_fill.py b/lib/stitches/contour_fill.py
index 993fa104..e19e1aad 100644
--- a/lib/stitches/contour_fill.py
+++ b/lib/stitches/contour_fill.py
@@ -4,6 +4,7 @@ from itertools import chain
import networkx as nx
import numpy as np
import trimesh
+from shapely import offset_curve
from shapely.geometry import (GeometryCollection, LineString, MultiPolygon,
Point, Polygon)
from shapely.geometry.polygon import orient
@@ -14,7 +15,7 @@ from ..stitch_plan import Stitch
from ..utils import DotDict
from ..utils.clamp_path import clamp_path_to_polygon
from ..utils.geometry import (cut, ensure_geometry_collection,
- ensure_multi_polygon, reverse_line_string,
+ ensure_multi_line_string, reverse_line_string,
roll_linear_ring)
from ..utils.smoothing import smooth_path
from ..utils.threading import check_stop_flag
@@ -49,10 +50,10 @@ nearest_neighbor_tuple = namedtuple(
def _offset_linear_ring(ring, offset, resolution, join_style, mitre_limit):
- result = Polygon(ring).buffer(-offset, resolution, cap_style=2, join_style=join_style, mitre_limit=mitre_limit, single_sided=True)
- result = ensure_multi_polygon(result)
- rings = GeometryCollection([poly.exterior for poly in result.geoms])
- rings = rings.simplify(0.01, False)
+ ring = Polygon(ring)
+ result = offset_curve(ring, -offset, resolution, join_style=join_style, mitre_limit=mitre_limit)
+ result = ensure_multi_line_string(result)
+ rings = result.simplify(0.01, False)
return _take_only_valid_linear_rings(rings)
@@ -200,11 +201,11 @@ def _match_polygons_and_holes(outer, inners):
def _convert_polygon_to_nodes(tree, polygon, parent_polygon, child_holes):
- polygon = orient(polygon, -1)
-
if polygon.area < 0.1:
return None, None
+ polygon = orient(polygon, -1)
+
valid_rings = _take_only_valid_linear_rings(polygon.exterior)
try:
diff --git a/lib/stitches/fill.py b/lib/stitches/fill.py
index 2c5cdffc..9e9ff790 100644
--- a/lib/stitches/fill.py
+++ b/lib/stitches/fill.py
@@ -149,14 +149,13 @@ def intersect_region_with_grating(shape, angle, row_spacing, end_row_spacing=Non
res = grating_line.intersection(shape)
- if (isinstance(res, shapely.geometry.MultiLineString) or isinstance(res, shapely.geometry.GeometryCollection)):
- runs = [line_string.coords for line_string in res.geoms if isinstance(line_string, shapely.geometry.LineString)]
+ if res.geom_type in ["MultiLineString", "GeometryCollection"]:
+ runs = [line_string.coords for line_string in res.geoms if line_string.geom_type == "LineString"]
+ elif res.geom_type in ["Point", "MultiPoint"] or res.is_empty:
+ # ignore if we intersected at a single point or no points
+ runs = []
else:
- if res.is_empty or len(res.coords) == 1:
- # ignore if we intersected at a single point or no points
- runs = []
- else:
- runs = [res.coords]
+ runs = [res.coords]
if runs:
runs.sort(key=lambda seg: (InkstitchPoint(*seg[0]) - upper_left).length())
diff --git a/lib/stitches/utils/autoroute.py b/lib/stitches/utils/autoroute.py
index 3ada4299..ed07c9a4 100644
--- a/lib/stitches/utils/autoroute.py
+++ b/lib/stitches/utils/autoroute.py
@@ -5,12 +5,12 @@
from itertools import combinations
+import inkex
import networkx as nx
-from shapely.geometry import Point, MultiPoint
+from shapely.geometry import MultiPoint, Point
from shapely.ops import nearest_points
-import inkex
-
+from ...elements import SatinColumn
from ...svg import get_correction_transform
from ...svg.tags import INKSCAPE_LABEL
from ...utils.threading import check_stop_flag
@@ -83,40 +83,71 @@ def add_jumps(graph, elements, preserve_order):
Jump stitches are added to ensure that all elements can be reached. Only the
minimal number and length of jumps necessary will be added.
"""
-
if preserve_order:
- # For each sequential pair of elements, find the shortest possible jump
- # stitch between them and add it. The directions of these new edges
- # will enforce stitching the elements in order.
-
- for element1, element2 in zip(elements[:-1], elements[1:]):
- check_stop_flag()
-
- potential_edges = []
-
- nodes1 = get_nodes_on_element(graph, element1)
- nodes2 = get_nodes_on_element(graph, element2)
+ _add_ordered_jumps(graph, elements)
+ else:
+ _add_unordered_jumps(graph, elements)
+ return graph
- for node1 in nodes1:
- for node2 in nodes2:
- point1 = graph.nodes[node1]['point']
- point2 = graph.nodes[node2]['point']
- potential_edges.append((point1, point2))
- if potential_edges:
- edge = min(potential_edges, key=lambda p1_p2: p1_p2[0].distance(p1_p2[1]))
- graph.add_edge(str(edge[0]), str(edge[1]), jump=True)
- else:
- # networkx makes this super-easy! k_edge_agumentation tells us what edges
- # we need to add to ensure that the graph is fully connected. We give it a
- # set of possible edges that it can consider adding (avail). Each edge has
- # a weight, which we'll set as the length of the jump stitch. The
- # algorithm will minimize the total length of jump stitches added.
- for jump in nx.k_edge_augmentation(graph, 1, avail=list(possible_jumps(graph))):
- check_stop_flag()
- graph.add_edge(*jump, jump=True)
+def _add_ordered_jumps(graph, elements):
+ # For each sequential pair of elements, find the shortest possible jump
+ # stitch between them and add it. The directions of these new edges
+ # will enforce stitching the elements in order.
+ for element1, element2 in zip(elements[:-1], elements[1:]):
+ check_stop_flag()
+ _insert_smallest_jump(graph, element1, element2)
- return graph
+ # add jumps between subpath too, we do not care about directions here
+ for element in elements:
+ if isinstance(element, SatinColumn):
+ # don't try this for satin columns
+ continue
+ check_stop_flag()
+ geoms = list(element.as_multi_line_string().geoms)
+ i = 0
+ for line1 in geoms:
+ for line2 in geoms[i+1:]:
+ if line1.distance(line2) == 0:
+ continue
+ node1, node2 = nearest_points(line1, line2)
+ _insert_jump(graph, node1, node2)
+ i += 1
+
+
+def _insert_smallest_jump(graph, element1, element2):
+ potential_edges = []
+
+ nodes1 = get_nodes_on_element(graph, element1)
+ nodes2 = get_nodes_on_element(graph, element2)
+
+ for node1 in nodes1:
+ for node2 in nodes2:
+ point1 = graph.nodes[node1]['point']
+ point2 = graph.nodes[node2]['point']
+ potential_edges.append((point1, point2))
+
+ if potential_edges:
+ edge = min(potential_edges, key=lambda p1_p2: p1_p2[0].distance(p1_p2[1]))
+ graph.add_edge(str(edge[0]), str(edge[1]), jump=True)
+
+
+def _insert_jump(graph, node1, node2):
+ graph.add_node(str(node1), point=node1)
+ graph.add_node(str(node2), point=node2)
+ graph.add_edge(str(node1), str(node2), jump=True)
+ graph.add_edge(str(node2), str(node1), jump=True)
+
+
+def _add_unordered_jumps(graph, elements):
+ # networkx makes this super-easy! k_edge_agumentation tells us what edges
+ # we need to add to ensure that the graph is fully connected. We give it a
+ # set of possible edges that it can consider adding (avail). Each edge has
+ # a weight, which we'll set as the length of the jump stitch. The
+ # algorithm will minimize the total length of jump stitches added.
+ for jump in nx.k_edge_augmentation(graph, 1, avail=list(possible_jumps(graph))):
+ check_stop_flag()
+ graph.add_edge(*jump, jump=True)
def possible_jumps(graph):