kopia lustrzana https://github.com/inkstitch/inkstitch
generalize get_segments and process_travel_edges
rodzic
29786dcd04
commit
f4c47a8e22
|
|
@ -155,7 +155,7 @@ def build_fill_stitch_graph(shape, angle, row_spacing, end_row_spacing, starting
|
|||
for segment in segments:
|
||||
# networkx allows us to label nodes with arbitrary data. We'll
|
||||
# mark this one as a grating segment.
|
||||
graph.add_edge(*segment, key="segment", underpath_edges=[])
|
||||
graph.add_edge(*segment, key="segment", underpath_edges=[], geometry=shgeo.LineString(segment))
|
||||
|
||||
tag_nodes_with_outline_and_projection(graph, shape, graph.nodes())
|
||||
add_edges_between_outline_nodes(graph, duplicate_every_other=True)
|
||||
|
|
@ -334,7 +334,7 @@ def get_segments(graph):
|
|||
segments = []
|
||||
for start, end, key, data in graph.edges(keys=True, data=True):
|
||||
if key == 'segment':
|
||||
segments.append(shgeo.LineString((start, end)))
|
||||
segments.append(data["geometry"])
|
||||
|
||||
return segments
|
||||
|
||||
|
|
@ -373,7 +373,8 @@ def process_travel_edges(graph, fill_stitch_graph, shape, travel_edges):
|
|||
# segments that _might_ intersect ls. Refining the result is
|
||||
# necessary but the STRTree still saves us a ton of time.
|
||||
if segment.crosses(ls):
|
||||
start, end = segment.coords
|
||||
start = segment.coords[0]
|
||||
end = segment.coords[-1]
|
||||
fill_stitch_graph[start][end]['segment']['underpath_edges'].append(edge)
|
||||
|
||||
# The weight of a travel edge is the length of the line segment.
|
||||
|
|
|
|||
|
|
@ -124,70 +124,6 @@ def build_guided_fill_stitch_graph(shape, guideline, row_spacing, starting_point
|
|||
return graph
|
||||
|
||||
|
||||
def get_segments(graph):
|
||||
segments = []
|
||||
for start, end, key, data in graph.edges(keys=True, data=True):
|
||||
if key == 'segment':
|
||||
segments.append(data["geometry"])
|
||||
|
||||
return segments
|
||||
|
||||
|
||||
def process_travel_edges(graph, fill_stitch_graph, shape, travel_edges):
|
||||
"""Weight the interior edges and pre-calculate intersection with fill stitch rows."""
|
||||
|
||||
# Set the weight equal to 5x the edge length, to encourage travel()
|
||||
# to avoid them.
|
||||
weight_edges_by_length(graph, 5)
|
||||
|
||||
segments = get_segments(fill_stitch_graph)
|
||||
|
||||
# The shapely documentation is pretty unclear on this. An STRtree
|
||||
# allows for building a set of shapes and then efficiently testing
|
||||
# the set for intersection. This allows us to do blazing-fast
|
||||
# queries of which line segments overlap each underpath edge.
|
||||
strtree = STRtree(segments)
|
||||
|
||||
# This makes the distance calculations below a bit faster. We're
|
||||
# not looking for high precision anyway.
|
||||
outline = shape.boundary.simplify(0.5 * PIXELS_PER_MM, preserve_topology=False)
|
||||
|
||||
for ls in travel_edges:
|
||||
# In most cases, ls will be a simple line segment. If we're
|
||||
# unlucky, in rare cases we can get a tiny little extra squiggle
|
||||
# at the end that can be ignored.
|
||||
points = [InkstitchPoint(*coord) for coord in ls.coords]
|
||||
p1, p2 = points[0], points[-1]
|
||||
|
||||
edge = (p1.as_tuple(), p2.as_tuple(), 'travel')
|
||||
|
||||
for segment in strtree.query(ls):
|
||||
# It seems like the STRTree only gives an approximate answer of
|
||||
# segments that _might_ intersect ls. Refining the result is
|
||||
# necessary but the STRTree still saves us a ton of time.
|
||||
if segment.crosses(ls):
|
||||
start = segment.coords[0]
|
||||
end = segment.coords[-1]
|
||||
fill_stitch_graph[start][end]['segment']['underpath_edges'].append(
|
||||
edge)
|
||||
|
||||
# The weight of a travel edge is the length of the line segment.
|
||||
weight = p1.distance(p2)
|
||||
|
||||
# Give a bonus to edges that are far from the outline of the shape.
|
||||
# This includes the outer outline and the outlines of the holes.
|
||||
# The result is that travel stitching will tend to hug the center
|
||||
# of the shape.
|
||||
weight /= ls.distance(outline) + 0.1
|
||||
|
||||
graph.add_edge(*edge, weight=weight)
|
||||
|
||||
# without this, we sometimes get exceptions like this:
|
||||
# Exception AttributeError: "'NoneType' object has no attribute 'GEOSSTRtree_destroy'" in
|
||||
# <bound method STRtree.__del__ of <shapely.strtree.STRtree instance at 0x0D2BFD50>> ignored
|
||||
del strtree
|
||||
|
||||
|
||||
def stitch_line(stitches, stitching_direction, geometry, projected_points, max_stitch_length, min_stitch_length, row_spacing, skip_last, offset_by_half):
|
||||
if stitching_direction == 1:
|
||||
stitched_line, _ = raster_line_string_with_priority_points(
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue