kopia lustrzana https://github.com/inkstitch/inkstitch
fix fills without underpath and bad start-end positions (#3141)
rodzic
5e387d76a7
commit
404c483cc7
|
@ -111,7 +111,7 @@ def auto_fill(shape,
|
|||
if not travel_graph:
|
||||
return fallback(shape, running_stitch_length, running_stitch_tolerance)
|
||||
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, underpath)
|
||||
path = fill_gaps(path, round_to_multiple_of_2(gap_fill_rows))
|
||||
result = path_to_stitches(shape, path, travel_graph, fill_stitch_graph, angle, row_spacing,
|
||||
max_stitch_length, running_stitch_length, running_stitch_tolerance,
|
||||
|
@ -375,13 +375,13 @@ def graph_make_valid(graph):
|
|||
graph.add_edge(start, end, key=f'segment-{key}', **data)
|
||||
elif 'outline' in graph_edges.keys():
|
||||
data = graph_edges['outline']
|
||||
graph.add_edge(start, end, key='outline-{key}', **data)
|
||||
graph.add_edge(start, end, key=f'outline-{key}', **data)
|
||||
elif 'extra' in graph_edges.keys():
|
||||
data = graph_edges['extra']
|
||||
graph.add_edge(start, end, key='extra-{key}', **data)
|
||||
graph.add_edge(start, end, key=f'extra-{key}', **data)
|
||||
elif 'initial' in graph_edges.keys():
|
||||
data = graph_edges['initial']
|
||||
graph.add_edge(start, end, key='initial-{key}', **data)
|
||||
graph.add_edge(start, end, key=f'initial-{key}', **data)
|
||||
|
||||
|
||||
def fallback(shape, running_stitch_length, running_stitch_tolerance):
|
||||
|
@ -600,7 +600,7 @@ def nearest_node(nodes, point, attr=None):
|
|||
|
||||
|
||||
@debug.time
|
||||
def find_stitch_path(graph, travel_graph, starting_point=None, ending_point=None):
|
||||
def find_stitch_path(graph, travel_graph, starting_point=None, ending_point=None, underpath=True):
|
||||
"""find a path that visits every grating segment exactly once
|
||||
|
||||
Theoretically, we just need to find an Eulerian Path in the graph.
|
||||
|
@ -623,6 +623,7 @@ def find_stitch_path(graph, travel_graph, starting_point=None, ending_point=None
|
|||
"""
|
||||
|
||||
graph = graph.copy()
|
||||
composed_graph = networkx.compose(graph, travel_graph)
|
||||
|
||||
if not starting_point:
|
||||
starting_point = list(graph.nodes.keys())[0]
|
||||
|
@ -641,6 +642,10 @@ def find_stitch_path(graph, travel_graph, starting_point=None, ending_point=None
|
|||
last_vertex = None
|
||||
last_key = None
|
||||
|
||||
# get the outline index for starting and ending node
|
||||
outline_start = travel_graph[starting_node][list(travel_graph[starting_node])[0]]['outline']['outline']
|
||||
outline_end = travel_graph[ending_node][list(travel_graph[ending_node])[0]]['outline']['outline']
|
||||
|
||||
while vertex_stack:
|
||||
current_vertex, current_key = vertex_stack[-1]
|
||||
if graph.degree(current_vertex) == 0:
|
||||
|
@ -664,8 +669,21 @@ def find_stitch_path(graph, travel_graph, starting_point=None, ending_point=None
|
|||
# Note, it's quite possible that part of this PathEdge will be eliminated by
|
||||
# collapse_sequential_outline_edges().
|
||||
|
||||
if starting_node is not ending_node:
|
||||
path.insert(0, PathEdge((starting_node, ending_node), key="initial"))
|
||||
if underpath or outline_start == outline_end:
|
||||
if starting_node is not ending_node:
|
||||
path.insert(0, PathEdge((starting_node, ending_node), key="initial"))
|
||||
else:
|
||||
# If underpath is disabled, we only have the option travel along the outline edges.
|
||||
# The user chose to start and end on different oultines, so there is no way to travel
|
||||
# along the edge from start to end. Add an additional path from start to end along existing
|
||||
# graph and travel edges (they will be duplicated).
|
||||
start_path = networkx.shortest_path(composed_graph, starting_node, ending_node, weight='weight')
|
||||
for i, edge in enumerate(list(zip(start_path, start_path[1:]))):
|
||||
# add as segment so it won't be collapsed
|
||||
if 'segment' in composed_graph[edge[0]][edge[1]].keys():
|
||||
path.insert(i, PathEdge(edge, key=f'segment-start{i}'))
|
||||
else:
|
||||
path.insert(i, PathEdge(edge, key=f'outline-start{i}'))
|
||||
|
||||
# If the starting and/or ending point falls far away from the end of a row
|
||||
# of stitches (like can happen at the top of a square), then we need to
|
||||
|
@ -872,10 +890,8 @@ def travel(shape, travel_graph, edge, running_stitch_length, running_stitch_tole
|
|||
try:
|
||||
path = networkx.shortest_path(travel_graph, start, end, weight='weight')
|
||||
except networkx.NetworkXNoPath:
|
||||
# TODO: find a better solution, this may produce unwanted jump stitches
|
||||
# but at least it renders the requested shape
|
||||
# test case: underpath disabled, starts and ends on different outlines
|
||||
return
|
||||
# This may not look good, but it prevents the fill from failing (which hopefully never happens)
|
||||
path = [start, end]
|
||||
|
||||
if underpath and path != (start, end):
|
||||
path = smooth_path(path, 2)
|
||||
|
|
|
@ -93,7 +93,7 @@ def circular_fill(shape,
|
|||
graph_make_valid(fill_stitch_graph)
|
||||
|
||||
travel_graph = build_travel_graph(fill_stitch_graph, shape, angle, underpath)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, underpath)
|
||||
result = path_to_stitches(shape, path, travel_graph, fill_stitch_graph, running_stitch_length, running_stitch_tolerance, skip_last, underpath)
|
||||
result = _apply_bean_stitch_and_repeats(result, repeats, bean_stitch_repeats)
|
||||
return result
|
||||
|
|
|
@ -53,7 +53,7 @@ def guided_fill(shape,
|
|||
graph_make_valid(fill_stitch_graph)
|
||||
|
||||
travel_graph = build_travel_graph(fill_stitch_graph, shape, angle, underpath)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, underpath)
|
||||
result = path_to_stitches(shape, path, travel_graph, fill_stitch_graph,
|
||||
max_stitch_length, running_stitch_length, running_stitch_tolerance, skip_last,
|
||||
underpath)
|
||||
|
|
|
@ -289,7 +289,7 @@ def _get_stitch_groups(fill, shape, colors, color_lines, starting_point, ending_
|
|||
graph_make_valid(fill_stitch_graph)
|
||||
|
||||
travel_graph = build_travel_graph(fill_stitch_graph, shape, fill.angle, False)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, False)
|
||||
stitches = path_to_stitches(
|
||||
shape,
|
||||
path,
|
||||
|
|
|
@ -781,7 +781,7 @@ def _segments_to_stitch_group(
|
|||
return None
|
||||
graph_make_valid(fill_stitch_graph)
|
||||
travel_graph = build_travel_graph(fill_stitch_graph, shape, fill.angle, False)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, False)
|
||||
stitches = path_to_stitches(
|
||||
shape,
|
||||
path,
|
||||
|
|
|
@ -224,7 +224,7 @@ class TartanSvgGroup:
|
|||
return []
|
||||
graph_make_valid(fill_stitch_graph)
|
||||
travel_graph = build_travel_graph(fill_stitch_graph, outline_shape, 0, False)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point)
|
||||
path = find_stitch_path(fill_stitch_graph, travel_graph, starting_point, ending_point, False)
|
||||
return self._path_to_shapes(path, fill_stitch_graph, polygons, geometry_type, outline_shape)
|
||||
|
||||
def _path_to_shapes(
|
||||
|
|
Ładowanie…
Reference in New Issue