Skip to content

Commit dda40e6

Browse files
committed
update export_contours (can't rely on a path for each disjoint component)
1 parent e2aab50 commit dda40e6

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

autotest/test_export.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
from flopy.utils.crs import get_authority_crs
5252
from flopy.utils.geometry import Polygon
5353

54-
5554
HAS_PYPROJ = has_pkg("pyproj", strict=True)
5655
if HAS_PYPROJ:
5756
import pyproj
@@ -717,14 +716,14 @@ def test_export_contours(function_tmpdir, example_data_path):
717716
with Reader(filename) as r:
718717
shapes = r.shapes()
719718
# expect 65 with standard mpl contours (structured grids), 86 with tricontours
720-
# assert len(shapes) >= 65
719+
assert len(shapes) >= 65
721720

722721
# debugging
723-
for s in shapes:
724-
x = [i[0] for i in s.points[:]]
725-
y = [i[1] for i in s.points[:]]
726-
plt.plot(x, y)
727-
plt.show()
722+
# for s in shapes:
723+
# x = [i[0] for i in s.points[:]]
724+
# y = [i[1] for i in s.points[:]]
725+
# plt.plot(x, y)
726+
# plt.show()
728727

729728

730729
@pytest.mark.mf6

flopy/export/utils.py

+44-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import os
22
from pathlib import Path
3-
from typing import Optional, Union
3+
from typing import Union
44

55
import numpy as np
6+
from matplotlib.path import Path
67

78
from ..datbase import DataInterface, DataListInterface, DataType
89
from ..mbase import BaseModel, ModelInterface
@@ -1706,20 +1707,55 @@ def export_contours(
17061707
if not isinstance(contours, list):
17071708
contours = [contours]
17081709

1710+
# Below we export a geometry (shape) for each
1711+
# disjoint contour component. Multiple shapes
1712+
# may correspond to the same contour level.
17091713
geoms = []
17101714
level = []
1715+
17111716
for ctr in contours:
1712-
levels = ctr.levels
1713-
for i, c in enumerate(ctr.collections):
1714-
paths = c.get_paths()
1715-
geoms += [LineString(p.vertices) for p in paths]
1716-
level += list(np.ones(len(paths)) * levels[i])
1717+
# ContourSet.collections was deprecated with
1718+
# matplotlib 3.8, ContourSet is a collection
1719+
# of Paths now. Each Path corresponds to one
1720+
# contour level, and may contain one or more
1721+
# (possibly disconnected) components.
1722+
1723+
paths = ctr.get_paths()
1724+
for pi, path in enumerate(paths):
1725+
# skip empty paths
1726+
if path.vertices.shape[0] == 0:
1727+
continue
1728+
1729+
# Each Path may contain multiple components
1730+
# so we unpack them as separate geometries.
1731+
comps = []
1732+
segs = []
1733+
for seg in path.iter_segments():
1734+
pts, code = seg
1735+
if code == Path.MOVETO:
1736+
if len(segs) > 0:
1737+
comps.append(LineString(segs))
1738+
segs = []
1739+
segs.append(pts)
1740+
elif code == Path.LINETO:
1741+
segs.append(pts)
1742+
elif code == Path.CLOSEPOLY:
1743+
segs.append(pts)
1744+
segs.append(segs[0]) # add closing segment
1745+
comps.append(LineString(segs))
1746+
segs = []
1747+
if len(segs) > 0:
1748+
comps.append(LineString(segs))
1749+
if len(segs) == 1:
1750+
raise RuntimeError(
1751+
f"Encountered component with only 1 vertex. This should not have happened, contact developers."
1752+
)
1753+
level += list(np.ones(len(comps)) * ctr.levels[pi])
1754+
geoms += comps
17171755

1718-
# convert the dictionary to a recarray
17191756
ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)
17201757

17211758
recarray2shp(ra, geoms, filename, **kwargs)
1722-
return
17231759

17241760

17251761
def export_contourf(
@@ -1806,7 +1842,6 @@ def export_contourf(
18061842
ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)
18071843

18081844
recarray2shp(ra, geoms, filename, **kwargs)
1809-
return
18101845

18111846

18121847
def export_array_contours(

0 commit comments

Comments
 (0)