diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2023-07-03 19:55:19 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-03 19:55:19 -0400 |
| commit | 1301b02c0d8c462810e55c39970d77535fbd1adc (patch) | |
| tree | 33962fa581ccc47cac98967948552193bbbf1471 /lib/utils/clamp_path.py | |
| parent | f8df02ff9eccb740c193c0af9707d5b9cc41dac0 (diff) | |
| parent | 72a0a7384fb61daa2cc5ce4082cf1ff222831710 (diff) | |
Merge pull request #2346 from inkstitch/lexelby/fill-clamp-and-smooth
auto-fill clamp and smooth
Diffstat (limited to 'lib/utils/clamp_path.py')
| -rw-r--r-- | lib/utils/clamp_path.py | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/utils/clamp_path.py b/lib/utils/clamp_path.py index e5ef78d8..f9b8991a 100644 --- a/lib/utils/clamp_path.py +++ b/lib/utils/clamp_path.py @@ -1,6 +1,6 @@ from shapely.geometry import LineString, Point as ShapelyPoint, MultiPolygon from shapely.prepared import prep -from .geometry import Point, ensure_multi_line_string +from .geometry import Point, ensure_geometry_collection def path_to_segments(path): @@ -66,23 +66,34 @@ def find_border(polygon, point): def clamp_path_to_polygon(path, polygon): """Constrain a path to a Polygon. + The path is expected to have at least some part inside the Polygon. + Description: https://gis.stackexchange.com/questions/428848/clamp-linestring-to-polygon """ - path = LineString(path) + start = path[0] + end = path[-1] # This splits the path at the points where it intersects with the polygon # border and returns the pieces in the same order as the original path. - split_path = ensure_multi_line_string(path.difference(polygon.boundary)) + split_path = ensure_geometry_collection(LineString(path).difference(polygon.boundary)) + + if len(split_path.geoms) == 1: + # The path never intersects with the polygon, so it's entirely inside. + return path + + # Add the start and end points to avoid losing part of the path if the + # start or end coincides with the polygon boundary + split_path = [ShapelyPoint(start), *split_path.geoms, ShapelyPoint(end)] - # contains() checks can fail without this. + # contains() checks can fail without the buffer. buffered_polygon = prep(polygon.buffer(1e-9)) last_segment_inside = None was_inside = False result = [] - for segment in split_path.geoms: + for segment in split_path: if buffered_polygon.contains(segment): if not was_inside: if last_segment_inside is not None: |
