diff options
| -rw-r--r-- | lib/stitches/contour_fill.py | 15 | ||||
| -rw-r--r-- | lib/utils/geometry.py | 34 |
2 files changed, 32 insertions, 17 deletions
diff --git a/lib/stitches/contour_fill.py b/lib/stitches/contour_fill.py index 993fa104..e19e1aad 100644 --- a/lib/stitches/contour_fill.py +++ b/lib/stitches/contour_fill.py @@ -4,6 +4,7 @@ from itertools import chain import networkx as nx import numpy as np import trimesh +from shapely import offset_curve from shapely.geometry import (GeometryCollection, LineString, MultiPolygon, Point, Polygon) from shapely.geometry.polygon import orient @@ -14,7 +15,7 @@ from ..stitch_plan import Stitch from ..utils import DotDict from ..utils.clamp_path import clamp_path_to_polygon from ..utils.geometry import (cut, ensure_geometry_collection, - ensure_multi_polygon, reverse_line_string, + ensure_multi_line_string, reverse_line_string, roll_linear_ring) from ..utils.smoothing import smooth_path from ..utils.threading import check_stop_flag @@ -49,10 +50,10 @@ nearest_neighbor_tuple = namedtuple( def _offset_linear_ring(ring, offset, resolution, join_style, mitre_limit): - result = Polygon(ring).buffer(-offset, resolution, cap_style=2, join_style=join_style, mitre_limit=mitre_limit, single_sided=True) - result = ensure_multi_polygon(result) - rings = GeometryCollection([poly.exterior for poly in result.geoms]) - rings = rings.simplify(0.01, False) + ring = Polygon(ring) + result = offset_curve(ring, -offset, resolution, join_style=join_style, mitre_limit=mitre_limit) + result = ensure_multi_line_string(result) + rings = result.simplify(0.01, False) return _take_only_valid_linear_rings(rings) @@ -200,11 +201,11 @@ def _match_polygons_and_holes(outer, inners): def _convert_polygon_to_nodes(tree, polygon, parent_polygon, child_holes): - polygon = orient(polygon, -1) - if polygon.area < 0.1: return None, None + polygon = orient(polygon, -1) + valid_rings = _take_only_valid_linear_rings(polygon.exterior) try: diff --git a/lib/utils/geometry.py b/lib/utils/geometry.py index 7434ae27..6ef0d439 100644 --- a/lib/utils/geometry.py +++ b/lib/utils/geometry.py @@ -7,7 +7,7 @@ import math import typing import numpy -from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, MultiPoint, GeometryCollection +from shapely.geometry import LineString, LinearRing, MultiLineString, MultiPolygon, MultiPoint, GeometryCollection from shapely.geometry import Point as ShapelyPoint @@ -103,12 +103,19 @@ def reverse_line_string(line_string): def ensure_multi_line_string(thing): - """Given either a MultiLineString or a single LineString, return a MultiLineString""" - - if isinstance(thing, LineString): - return MultiLineString([thing]) - else: + """Given either a MultiLineString, a single LineString or GeometryCollection, return a MultiLineString""" + if thing.is_empty: return thing + if thing.geom_type == "LineString": + return MultiLineString([thing]) + if thing.geom_type == "GeometryCollection": + multilinestring = [] + for line in thing.geoms: + if line.geom_type == "LineString": + multilinestring.append(line) + if multilinestring: + return MultiLineString(multilinestring) + return thing def ensure_geometry_collection(thing): @@ -124,11 +131,18 @@ def ensure_geometry_collection(thing): def ensure_multi_polygon(thing): """Given either a MultiPolygon or a single Polygon, return a MultiPolygon""" - - if isinstance(thing, Polygon): - return MultiPolygon([thing]) - else: + if thing.is_empty: return thing + if thing.geom_type == "Polygon": + return MultiPolygon([thing]) + if thing.geom_type == "GeometryCollection": + multipolygon = [] + for polygon in thing.geoms: + if polygon.geom_type == "Polygon": + multipolygon.append(polygon) + if multipolygon: + return MultiPolygon(multipolygon) + return thing def cut_path(points, length): |
