summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/stitches/contour_fill.py15
-rw-r--r--lib/utils/geometry.py34
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):