diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2024-06-20 10:45:53 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-20 19:45:53 +0200 |
| commit | e8017e0bcc0be2ef128bcea187f6528ed0a3d197 (patch) | |
| tree | 8196bb69d5ce4fee839056f24abe181fd773afb3 /lib/stitches | |
| parent | c017cae01aa33a876795ec5da1438e8ec0f11fc5 (diff) | |
auto-fill pull compensation (#2891)
Diffstat (limited to 'lib/stitches')
| -rw-r--r-- | lib/stitches/auto_fill.py | 46 | ||||
| -rw-r--r-- | lib/stitches/fill.py | 4 |
2 files changed, 42 insertions, 8 deletions
diff --git a/lib/stitches/auto_fill.py b/lib/stitches/auto_fill.py index d3db978a..84832fc8 100644 --- a/lib/stitches/auto_fill.py +++ b/lib/stitches/auto_fill.py @@ -11,8 +11,8 @@ from typing import Iterator import networkx from shapely import geometry as shgeo -from shapely import segmentize -from shapely.ops import snap +from shapely import make_valid, segmentize +from shapely.ops import snap, unary_union from shapely.strtree import STRtree from ..debug.debug import debug @@ -22,7 +22,8 @@ from ..utils import cache from ..utils.clamp_path import clamp_path_to_polygon from ..utils.geometry import Point as InkstitchPoint from ..utils.geometry import (ensure_multi_line_string, - line_string_to_point_list) + line_string_to_point_list, offset_points) +from ..utils.list import is_all_zeroes from ..utils.prng import join_args from ..utils.smoothing import smooth_path from ..utils.threading import check_stop_flag @@ -82,12 +83,18 @@ def auto_fill(shape, gap_fill_rows=0, enable_random_stitch_length=False, random_sigma=0.0, - random_seed=""): + random_seed="", + pull_compensation_px=(0, 0), + pull_compensation_percent=(0, 0)): + has_pull_compensation = not is_all_zeroes(pull_compensation_px) or not is_all_zeroes(pull_compensation_percent) + if has_pull_compensation: + spacing = min(row_spacing, end_row_spacing or row_spacing) + shape = adjust_shape_for_pull_compensation(shape, angle, spacing, pull_compensation_px, pull_compensation_percent) + rows = intersect_region_with_grating(shape, angle, row_spacing, end_row_spacing) if not rows: # Small shapes may not intersect with the grating at all. return fallback(shape, running_stitch_length, running_stitch_tolerance) - segments = [segment for row in rows for segment in row] fill_stitch_graph = build_fill_stitch_graph(shape, segments, starting_point, ending_point) @@ -120,6 +127,34 @@ def round_to_multiple_of_2(number): return number +@debug.time +def adjust_shape_for_pull_compensation(shape, angle, row_spacing, pull_compensation_px, pull_compensation_percent): + rows = intersect_region_with_grating(shape, angle, row_spacing) + if not rows: + return shape + segments = [segment for row in rows for segment in row] + segments = apply_pull_compensation(segments, pull_compensation_px, pull_compensation_percent) + + lines = [shgeo.LineString((start, end)) for start, end in segments] + buffer_amount = row_spacing/2 + 0.01 + buffered_lines = [line.buffer(buffer_amount) for line in lines] + + polygon = unary_union(buffered_lines) + return make_valid(polygon) + + +def apply_pull_compensation(segments, pull_compensation_px, pull_compensation_percent): + new_segments = [] + for segment in segments: + start = InkstitchPoint.from_tuple(segment[0]) + end = InkstitchPoint.from_tuple(segment[1]) + end = InkstitchPoint.from_tuple(segment[1]) + new_start, new_end = offset_points(start, end, pull_compensation_px, pull_compensation_percent) + new_segments.append((new_start.as_tuple(), new_end.as_tuple())) + + return new_segments + + def which_outline(shape, coords): """return the index of the outline on which the point resides @@ -374,7 +409,6 @@ def build_travel_graph(fill_stitch_graph, shape, fill_stitch_angle, underpath): calculation. We also weight the interior edges extra proportional to how close they are to the boundary. """ - graph = networkx.MultiGraph() # Add all the nodes from the main graph. This will be all of the endpoints diff --git a/lib/stitches/fill.py b/lib/stitches/fill.py index 4f3e2208..8480ea0b 100644 --- a/lib/stitches/fill.py +++ b/lib/stitches/fill.py @@ -113,10 +113,10 @@ def intersect_region_with_grating(shape, angle, row_spacing, end_row_spacing=Non # Now get a unit vector rotated to the requested angle. I use -angle # because shapely rotates clockwise, but my geometry textbooks taught # me to consider angles as counter-clockwise from the X axis. - direction = InkstitchPoint(1, 0).rotate(-angle) + direction = InkstitchPoint(-1, 0).rotate(-angle) # and get a normal vector - normal = direction.rotate(math.pi / 2) + normal = direction.rotate(-math.pi / 2) # I'll start from the center, move in the normal direction some amount, # and then walk left and right half_length in each direction to create |
