Skip to content

Commit 1114c93

Browse files
authored
perf(Gridintersect): optimize intersection methods for shapely 2.0 (#1666)
1 parent 19b3daa commit 1114c93

File tree

4 files changed

+526
-299
lines changed

4 files changed

+526
-299
lines changed

CITATION.cff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ authors:
5151
given-names: Jon Jeffrey
5252
orcid: https://orcid.org/0000-0001-5909-0010
5353
- family-names: Brakenhoff
54-
given-names: Davíd
54+
given-names: Davíd A.
55+
orcid: https://orcid.org/0000-0002-2993-2202
5556
- family-names: Bonelli
5657
given-names: Wesley P.
5758
orcid: https://orcid.org/0000-0002-2665-5078

autotest/test_gridintersect.py

Lines changed: 47 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -120,42 +120,6 @@ def get_rect_vertex_grid(angrot=0.0, xyoffset=0.0):
120120
return tgr
121121

122122

123-
def plot_structured_grid(sgr):
124-
_, ax = plt.subplots(1, 1, figsize=(8, 8))
125-
sgr.plot(ax=ax)
126-
return ax
127-
128-
129-
def plot_vertex_grid(tgr):
130-
_, ax = plt.subplots(1, 1, figsize=(8, 8))
131-
pmv = fplot.PlotMapView(modelgrid=tgr)
132-
pmv.plot_grid(ax=ax)
133-
return ax
134-
135-
136-
def plot_ix_polygon_result(rec, ax):
137-
from descartes import PolygonPatch
138-
139-
for i, ishp in enumerate(rec.ixshapes):
140-
ppi = PolygonPatch(ishp, facecolor=f"C{i % 10}")
141-
ax.add_patch(ppi)
142-
143-
144-
def plot_ix_linestring_result(rec, ax):
145-
for i, ishp in enumerate(rec.ixshapes):
146-
if ishp.type == "MultiLineString":
147-
for part in ishp:
148-
ax.plot(part.xy[0], part.xy[1], ls="-", c=f"C{i % 10}")
149-
else:
150-
ax.plot(ishp.xy[0], ishp.xy[1], ls="-", c=f"C{i % 10}")
151-
152-
153-
def plot_ix_point_result(rec, ax):
154-
x = [ip.x for ip in rec.ixshapes]
155-
y = [ip.y for ip in rec.ixshapes]
156-
ax.scatter(x, y)
157-
158-
159123
# %% test point structured
160124

161125

@@ -597,6 +561,26 @@ def test_rect_grid_linestrings_on_boundaries_return_all_ix_shapely(rtree):
597561
assert len(r) == n_intersections[i]
598562

599563

564+
@requires_pkg("shapely")
565+
@rtree_toggle
566+
def test_rect_grid_linestring_cell_boundary_shapely(rtree):
567+
gr = get_rect_grid()
568+
ix = GridIntersect(gr, method="vertex", rtree=rtree)
569+
ls = LineString(ix._rect_grid_to_geoms_cellids()[0][0].exterior.coords)
570+
r = ix.intersect(ls, return_all_intersections=False)
571+
assert len(r) == 1
572+
573+
574+
@requires_pkg("shapely")
575+
@rtree_toggle
576+
def test_rect_grid_linestring_cell_boundary_return_all_ix_shapely(rtree):
577+
gr = get_rect_grid()
578+
ix = GridIntersect(gr, method="vertex", rtree=rtree)
579+
ls = LineString(ix._rect_grid_to_geoms_cellids()[0][0].exterior.coords)
580+
r = ix.intersect(ls, return_all_intersections=True)
581+
assert len(r) == 3
582+
583+
600584
@requires_pkg("shapely")
601585
@rtree_toggle
602586
def test_tri_grid_linestring_outside(rtree):
@@ -681,7 +665,26 @@ def test_tri_grid_linestrings_on_boundaries_return_all_ix(rtree):
681665
ls = LineString([(x[i], y[i]), (x[i + 1], y[i + 1])])
682666
r = ix.intersect(ls, return_all_intersections=True)
683667
assert len(r) == n_intersections[i]
684-
return
668+
669+
670+
@requires_pkg("shapely")
671+
@rtree_toggle
672+
def test_tri_grid_linestring_cell_boundary_shapely(rtree):
673+
tgr = get_tri_grid()
674+
ix = GridIntersect(tgr, method="vertex", rtree=rtree)
675+
ls = LineString(ix._vtx_grid_to_geoms_cellids()[0][0].exterior.coords)
676+
r = ix.intersect(ls, return_all_intersections=False)
677+
assert len(r) == 1
678+
679+
680+
@requires_pkg("shapely")
681+
@rtree_toggle
682+
def test_tri_grid_linestring_cell_boundary_return_all_ix_shapely(rtree):
683+
tgr = get_tri_grid()
684+
ix = GridIntersect(tgr, method="vertex", rtree=rtree)
685+
ls = LineString(ix._vtx_grid_to_geoms_cellids()[0][0].exterior.coords)
686+
r = ix.intersect(ls, return_all_intersections=True)
687+
assert len(r) == 3
685688

686689

687690
# %% test polygon structured
@@ -1064,7 +1067,7 @@ def test_point_offset_rot_structured_grid():
10641067
p = Point(10.0, 10 + np.sqrt(200.0))
10651068
ix = GridIntersect(sgr, method="structured")
10661069
result = ix.intersect(p)
1067-
# assert len(result) == 1.
1070+
assert len(result) == 1
10681071

10691072

10701073
@requires_pkg("shapely")
@@ -1073,7 +1076,8 @@ def test_linestring_offset_rot_structured_grid():
10731076
ls = LineString([(5, 10.0 + np.sqrt(200.0)), (15, 10.0 + np.sqrt(200.0))])
10741077
ix = GridIntersect(sgr, method="structured")
10751078
result = ix.intersect(ls)
1076-
# assert len(result) == 2.
1079+
# NOTE: in shapely 2.0, this returns a Linestring with length 10^-15 in cell (0, 1)
1080+
assert len(result) == 2 or len(result) == 3
10771081

10781082

10791083
@requires_pkg("shapely")
@@ -1089,7 +1093,7 @@ def test_polygon_offset_rot_structured_grid():
10891093
)
10901094
ix = GridIntersect(sgr, method="structured")
10911095
result = ix.intersect(p)
1092-
# assert len(result) == 3.
1096+
assert len(result) == 3
10931097

10941098

10951099
@requires_pkg("shapely")
@@ -1099,7 +1103,7 @@ def test_point_offset_rot_structured_grid_shapely(rtree):
10991103
p = Point(10.0, 10 + np.sqrt(200.0))
11001104
ix = GridIntersect(sgr, method="vertex", rtree=rtree)
11011105
result = ix.intersect(p)
1102-
# assert len(result) == 1.
1106+
assert len(result) == 1
11031107

11041108

11051109
@requires_pkg("shapely")
@@ -1109,7 +1113,7 @@ def test_linestring_offset_rot_structured_grid_shapely(rtree):
11091113
ls = LineString([(5, 10.0 + np.sqrt(200.0)), (15, 10.0 + np.sqrt(200.0))])
11101114
ix = GridIntersect(sgr, method="vertex", rtree=rtree)
11111115
result = ix.intersect(ls)
1112-
# assert len(result) == 2.
1116+
assert len(result) == 2
11131117

11141118

11151119
@requires_pkg("shapely")
@@ -1126,66 +1130,7 @@ def test_polygon_offset_rot_structured_grid_shapely(rtree):
11261130
)
11271131
ix = GridIntersect(sgr, method="vertex", rtree=rtree)
11281132
result = ix.intersect(p)
1129-
# assert len(result) == 3.
1130-
1131-
1132-
# %% test non strtree shapely intersect
1133-
1134-
1135-
@requires_pkg("shapely")
1136-
def test_all_intersections_shapely_no_strtree():
1137-
"""avoid adding separate tests for rtree=False"""
1138-
# Points
1139-
# regular grid
1140-
test_rect_grid_point_on_inner_boundary_shapely(rtree=False)
1141-
test_rect_grid_point_on_outer_boundary_shapely(rtree=False)
1142-
test_rect_grid_point_outside_shapely(rtree=False)
1143-
test_rect_grid_multipoint_in_one_cell_shapely(rtree=False)
1144-
test_rect_grid_multipoint_in_multiple_cells_shapely(rtree=False)
1145-
# vertex grid
1146-
test_tri_grid_point_on_inner_boundary(rtree=False)
1147-
test_tri_grid_point_on_outer_boundary(rtree=False)
1148-
test_tri_grid_point_outside(rtree=False)
1149-
test_tri_grid_multipoint_in_multiple_cells(rtree=False)
1150-
test_tri_grid_multipoint_in_one_cell(rtree=False)
1151-
1152-
# LineStrings
1153-
# regular grid
1154-
test_rect_grid_linestring_on_inner_boundary_shapely(rtree=False)
1155-
test_rect_grid_linestring_on_outer_boundary_shapely(rtree=False)
1156-
test_rect_grid_linestring_outside_shapely(rtree=False)
1157-
test_rect_grid_linestring_in_2cells_shapely(rtree=False)
1158-
test_rect_grid_linestring_in_and_out_of_cell_shapely(rtree=False)
1159-
test_rect_grid_multilinestring_in_one_cell_shapely(rtree=False)
1160-
# vertex grid
1161-
test_tri_grid_linestring_on_inner_boundary(rtree=False)
1162-
test_tri_grid_linestring_on_outer_boundary(rtree=False)
1163-
test_tri_grid_linestring_outside(rtree=False)
1164-
test_tri_grid_linestring_in_2cells(rtree=False)
1165-
test_tri_grid_multilinestring_in_one_cell(rtree=False)
1166-
1167-
# Polygons
1168-
# regular grid
1169-
test_rect_grid_polygon_on_inner_boundary_shapely(rtree=False)
1170-
test_rect_grid_polygon_on_outer_boundary_shapely(rtree=False)
1171-
test_rect_grid_polygon_outside_shapely(rtree=False)
1172-
test_rect_grid_polygon_in_2cells_shapely(rtree=False)
1173-
test_rect_grid_polygon_with_hole_shapely(rtree=False)
1174-
test_rect_grid_multipolygon_in_one_cell_shapely(rtree=False)
1175-
test_rect_grid_multipolygon_in_multiple_cells_shapely(rtree=False)
1176-
# vertex grid
1177-
test_tri_grid_polygon_on_inner_boundary(rtree=False)
1178-
test_tri_grid_polygon_on_outer_boundary(rtree=False)
1179-
test_tri_grid_polygon_outside(rtree=False)
1180-
test_tri_grid_polygon_in_2cells(rtree=False)
1181-
test_tri_grid_polygon_with_hole(rtree=False)
1182-
test_tri_grid_multipolygon_in_multiple_cells(rtree=False)
1183-
test_tri_grid_multipolygon_in_one_cell(rtree=False)
1184-
1185-
# offset and rotated grids
1186-
test_point_offset_rot_structured_grid_shapely(rtree=False)
1187-
test_linestring_offset_rot_structured_grid_shapely(rtree=False)
1188-
test_polygon_offset_rot_structured_grid_shapely(rtree=False)
1133+
assert len(result) == 3
11891134

11901135

11911136
# %% test rasters
@@ -1298,8 +1243,3 @@ def test_raster_sampling_methods(example_data_path):
12981243
raise AssertionError(
12991244
f"{method} resampling returning incorrect values"
13001245
)
1301-
1302-
1303-
if __name__ == "__main__":
1304-
1305-
test_all_intersections_shapely_no_strtree()

0 commit comments

Comments
 (0)