|
1 | 1 | import os
|
2 | 2 | from pathlib import Path
|
3 |
| -from typing import Optional, Union |
| 3 | +from typing import Union |
4 | 4 |
|
5 | 5 | import numpy as np
|
| 6 | +from matplotlib.path import Path |
6 | 7 |
|
7 | 8 | from ..datbase import DataInterface, DataListInterface, DataType
|
8 | 9 | from ..mbase import BaseModel, ModelInterface
|
@@ -1706,20 +1707,55 @@ def export_contours(
|
1706 | 1707 | if not isinstance(contours, list):
|
1707 | 1708 | contours = [contours]
|
1708 | 1709 |
|
| 1710 | + # Below we export a geometry (shape) for each |
| 1711 | + # disjoint contour component. Multiple shapes |
| 1712 | + # may correspond to the same contour level. |
1709 | 1713 | geoms = []
|
1710 | 1714 | level = []
|
| 1715 | + |
1711 | 1716 | 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 |
1717 | 1755 |
|
1718 |
| - # convert the dictionary to a recarray |
1719 | 1756 | ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)
|
1720 | 1757 |
|
1721 | 1758 | recarray2shp(ra, geoms, filename, **kwargs)
|
1722 |
| - return |
1723 | 1759 |
|
1724 | 1760 |
|
1725 | 1761 | def export_contourf(
|
@@ -1806,7 +1842,6 @@ def export_contourf(
|
1806 | 1842 | ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)
|
1807 | 1843 |
|
1808 | 1844 | recarray2shp(ra, geoms, filename, **kwargs)
|
1809 |
| - return |
1810 | 1845 |
|
1811 | 1846 |
|
1812 | 1847 | def export_array_contours(
|
|
0 commit comments