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
	
	 Lex Neva
						Lex Neva