cleanup geometry cache and improve cut_polgon_with_line speed again

This commit is contained in:
Laura Klünder 2017-11-18 19:59:05 +01:00
parent b63ab7d4e4
commit 31886d829d

View file

@ -1,5 +1,6 @@
import math import math
from collections import deque, namedtuple from collections import deque, namedtuple
from contextlib import suppress
from itertools import chain from itertools import chain
from typing import List, Sequence, Union from typing import List, Sequence, Union
@ -9,7 +10,6 @@ from matplotlib.patches import PathPatch
from matplotlib.path import Path from matplotlib.path import Path
from shapely import speedups from shapely import speedups
from shapely.geometry import GeometryCollection, LinearRing, LineString, MultiLineString, MultiPolygon, Point, Polygon from shapely.geometry import GeometryCollection, LinearRing, LineString, MultiLineString, MultiPolygon, Point, Polygon
from shapely.geometry.polygon import orient
if speedups.available: if speedups.available:
speedups.enable() speedups.enable()
@ -134,8 +134,13 @@ def cut_line_with_point(line: LineString, point: Point):
def cut_polygon_with_line(polygon: Union[Polygon, MultiPolygon], line: LineString, debug=False) -> Sequence[Polygon]: def cut_polygon_with_line(polygon: Union[Polygon, MultiPolygon], line: LineString, debug=False) -> Sequence[Polygon]:
orig_polygon = polygon orig_polygon = polygon
polygons = (orient(polygon) for polygon in assert_multipolygon(polygon)) polygons: List[List[LinearRing]] = []
polygons: List[List[LinearRing]] = [[polygon.exterior, *polygon.interiors] for polygon in polygons] for polygon in assert_multipolygon(polygon):
rings = getattr(polygon, 'c3nav_cache', None)
if not rings:
rings = [polygon.exterior, *polygon.interiors]
polygon.c3nav_cache = rings
polygons.append(rings)
# find intersection points between the line and polygon rings # find intersection points between the line and polygon rings
points = deque() points = deque()
@ -263,8 +268,14 @@ def cut_polygon_with_line(polygon: Union[Polygon, MultiPolygon], line: LineStrin
for item in points) for item in points)
last = cutpoint(current.point, new_i, 0) last = cutpoint(current.point, new_i, 0)
return tuple(Polygon(polygon[0], tuple(ring for ring in polygon[1:] if ring is not None))
for polygon in polygons) result = deque()
for polygon in polygons:
polygon = [ring for ring in polygon if ring is not None]
new_polygon = Polygon(polygon[0], tuple(polygon[1:]))
new_polygon.c3nav_cache = polygon
result.append(new_polygon)
return tuple(result)
def clean_cut_polygon(polygon: Polygon) -> Polygon: def clean_cut_polygon(polygon: Polygon) -> Polygon:
@ -272,6 +283,9 @@ def clean_cut_polygon(polygon: Polygon) -> Polygon:
interiors.extend(cut_ring(polygon.exterior)) interiors.extend(cut_ring(polygon.exterior))
exteriors = [(i, ring) for (i, ring) in enumerate(interiors) if ring.is_ccw] exteriors = [(i, ring) for (i, ring) in enumerate(interiors) if ring.is_ccw]
with suppress(AttributeError):
delattr(polygon, 'c3nav_cache')
if len(exteriors) != 1: if len(exteriors) != 1:
raise ValueError('Invalid cut polygon!') raise ValueError('Invalid cut polygon!')
exterior = interiors[exteriors[0][0]] exterior = interiors[exteriors[0][0]]