Vector Operations#
Converting between mesh fields and vector geometry.
polygonize dissolves faces sharing a value into one (possibly multi-part) geometry — the mesh
analogue of the raster to_feature_collection — and is meant for fields with few distinct values,
including string label fields. burn is the inverse direction: it stamps a value onto every face a
geometry touches, sizing its output from both the value and the fill so a fractional value is not
truncated by an integer fill. sample_line reads a field along a line.
pyramids.netcdf.ugrid.vector_ops
#
Pure mesh <-> vector operations for UGRID 2D meshes.
Standalone, side-effect-free functions that bridge a :class:~pyramids.netcdf.ugrid.mesh.Mesh2d
(plus a per-face value array and/or shapely / geopandas geometry) and ordinary vector geometry.
None of them mutate their inputs, and none import :mod:pyramids.netcdf.ugrid.dataset, so they can
be driven directly or wrapped by thin UgridDataset facades:
- :func:
polygonize— dissolve adjacent faces that share an (approximately) equal value into merged polygons, one row per value group (the mesh analogue of rasterto_feature_collection). - :func:
sample_line— extract a transect: the face values crossed by a shapelyLineString, ordered along the line, with the along-line distance of each crossed face. - :func:
burn— rasterize vector geometry (points / lines / polygons) onto the faces, returning a per-face array set to a value wherever a face is touched / covered by the geometry.
All three reuse the lazily-built :class:~pyramids.netcdf.ugrid.spatial.MeshSpatialIndex
(face_strtree / face_polygons) rather than constructing a second spatial index.
polygonize(mesh, values, *, decimals=None, crs=None)
#
Dissolve adjacent faces sharing an (approximately) equal value into merged polygons.
Groups the mesh faces by their per-face value and unions each group's face polygons into one
(possibly multi-part) geometry — the mesh analogue of the raster to_feature_collection. The
result has exactly one row per distinct value. Faces whose value is NaN are dropped.
This is intended for fields with few distinct values (e.g. a classified / label field).
Float values are compared by exact equality unless decimals is given, which rounds the
values before grouping so near-equal floats dissolve together. decimals applies to a
numeric field only; on a label field there is nothing to round, so it is ignored rather than
raising.
A face is dropped when it carries no value. For a numeric field that means anything
non-finite -- +inf and -inf as well as NaN; for a label field, None or a NaN
hiding in an object array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
Mesh2d
|
The mesh whose faces are polygonized. |
required |
values
|
ArrayLike
|
Per-face value array of length |
required |
decimals
|
int | None
|
If given, round the values to this many decimals before grouping (approximate
equality). |
None
|
crs
|
Any
|
CRS to attach to the output (anything geopandas accepts, e.g. an EPSG int or WKT). Defaults to the mesh's own CRS when it carries one. |
None
|
Returns:
| Type | Description |
|---|---|
GeoDataFrame
|
geopandas.GeoDataFrame: Columns |
GeoDataFrame
|
group, sorted by value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/pyramids/netcdf/ugrid/vector_ops.py
sample_line(mesh, values, line)
#
Sample face values along a line (a transect / cross-section).
Finds the faces whose polygons intersect line (via the mesh STRtree), orders them along the
line by the along-line distance of each crossing's midpoint, and returns the ordered face values
with those distances.
This is sampling, not exact segment clipping: each part of the line-face intersection
contributes one sample, at that part's midpoint. A line that leaves a face and re-enters it
crosses it twice and is therefore sampled twice -- so a face can appear more than once and
face_indices is not unique, which matters to a caller using it as a join key. Parts of
the line that fall off the mesh simply produce no samples (there is no face to sample there).
The element axis of values is the last axis, so a leading time / layer axis is preserved
in the returned values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
Mesh2d
|
The mesh to sample. |
required |
values
|
ArrayLike
|
Per-face values with the face axis last (shape |
required |
line
|
Any
|
A shapely |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
NDArray
|
|
NDArray
|
|
|
NDArray
|
|
|
tuple[NDArray, NDArray, NDArray]
|
indices in the same order). |
|
tuple[NDArray, NDArray, NDArray]
|
the number of distinct faces the line touches and |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the last axis of |
Source code in src/pyramids/netcdf/ugrid/vector_ops.py
burn(mesh, geometry, value, *, fill=np.nan, all_touched=True)
#
Burn vector geometry onto the mesh faces (rasterize-style).
Returns a per-face array set to value wherever a face is touched / covered by geometry
and to fill everywhere else — the inverse of :func:polygonize. Faces are selected with the
mesh STRtree and shapely predicates, so points, lines and polygons are all supported without a
cell-tree dependency (this is boolean coverage, never area-weighted overlap).
Selection rules
- Points / lines (zero-area geometry): every face the geometry intersects.
- Polygons with
all_touched=True: every face the polygon intersects (any overlap or boundary touch). - Polygons with
all_touched=False: only faces whose centroid lies inside the polygon.
The rule is chosen from the whole geometry's area, not part by part, which matters for a
mixed collection. A line on its own burns every face it crosses; put that same line in a
collection beside a polygon and the collection has an area, so all_touched=False applies
centroid-containment to all of it -- and a line contains a centroid only if one lies exactly
on it. Pass all_touched=True, or burn the parts separately, to have a mixed geometry's
zero-area parts select the faces they cross.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
Mesh2d
|
The mesh to burn onto. |
required |
geometry
|
Any
|
A shapely geometry, a pyramids |
required |
value
|
float
|
The value assigned to burned faces. |
required |
fill
|
float
|
The value for faces not touched by the geometry (default |
nan
|
all_touched
|
bool
|
Polygon selection mode (see above). Ignored for zero-area geometry. |
True
|
Returns:
| Type | Description |
|---|---|
NDArray
|
numpy.ndarray: A |