Skip to content

Commit eec817b

Browse files
committed
Add docs about converting between shapely and cf
1 parent 9d2c87f commit eec817b

File tree

2 files changed

+95
-3
lines changed

2 files changed

+95
-3
lines changed

cf_xarray/geometry.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ def shapely_to_cf(geometries: xr.DataArray | Sequence, grid_mapping: str | None
9494
A dataset with shapely geometry objects translated into CF-compliant variables :
9595
- 'x', 'y' : the node coordinates
9696
- 'crd_x', 'crd_y' : the feature coordinates (might have different names if `grid_mapping` is available).
97-
- 'node_count' : The number of nodes per feature. Absent if all instances are Points.
97+
- 'node_count' : The number of nodes per feature. Always present for Lines and Polygons. For Points: only present if there are multipart geometries.
98+
- 'part_node_count' : The number of nodes per individual geometry. Only for Lines with multipart geometries and for Polygons with multipart geometries or holes.
99+
- 'interior_ring' : Integer boolean indicating whether rings are interior or exterior. Only for Polygons with holes.
98100
- 'geometry_container' : Empty variable with attributes describing the geometry type.
99-
- Other variables are not implemented as only Points are currently understood.
100101
101102
References
102103
----------

doc/geometry.md

+92-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,98 @@
1+
---
2+
jupytext:
3+
text_representation:
4+
format_name: myst
5+
kernelspec:
6+
display_name: Python 3
7+
name: python3
8+
---
9+
110
```{eval-rst}
211
.. currentmodule:: xarray
312
```
413

514
# Geometries
615

7-
See {py:func}`cf_xarray.shapely_to_cf`, {py:func}`cf_xarray.cf_to_shapely`
16+
See
17+
18+
1. {py:func}`cf_xarray.shapely_to_cf`
19+
1. {py:func}`cf_xarray.cf_to_shapely`
20+
21+
In order to support vectors as well as arrays `cf_xarray` can convert between shapely objects
22+
and CF-compliant representations of those geometries.
23+
24+
Let's start by creating an xarray object containing some shapely geometries. This example uses
25+
a `xr.DataArray` but these functions also work with a `xr.Dataset` where one of the data variables
26+
contains an array of shapes.
27+
28+
```{code-cell}
29+
import cf_xarray as cfxr
30+
import xarray as xr
31+
32+
from shapely.geometry import MultiPoint, Point
33+
34+
da = xr.DataArray(
35+
[
36+
MultiPoint([(1.0, 2.0), (2.0, 3.0)]),
37+
Point(3.0, 4.0),
38+
Point(4.0, 5.0),
39+
Point(3.0, 4.0),
40+
],
41+
dims=("index",),
42+
name="geometry"
43+
)
44+
```
45+
46+
```{warning}
47+
`cf_xarray` does not support handle multiple types of shapes (Point, Line, Polygon) in one
48+
`xr.DataArray`, but multipart geometries are supported and can be mixed with single-part
49+
geometries of the same type.
50+
```
51+
52+
Now we can take that `xr.DataArray` containing shapely geometries and convert it to cf:
53+
54+
```{code-cell}
55+
ds_cf = cfxr.shapely_to_cf(da)
56+
ds_cf
57+
```
58+
59+
This function returns a `xr.Dataset` containing the CF fields needed to reconstruct the
60+
geometries. In particular there are:
61+
62+
- 'x', 'y' : the node coordinates
63+
- 'crd_x', 'crd_y' : the feature coordinates (might have different names if `grid_mapping` is available).
64+
- 'node_count' : The number of nodes per feature. Always present for Lines and Polygons. For
65+
Points: only present if there are multipart geometries.
66+
- part_node_count : The number of nodes per individual geometry. Only for Lines with multipart
67+
geometries and for Polygons with multipart geometries or holes.
68+
- interior_ring : Integer boolean indicating whether ring is interior or exterior. Only for
69+
Polygons with holes.
70+
- 'geometry_container' : Empty variable with attributes describing the geometry type.
71+
72+
Here are the attributes on `geometry_container`. This pattern mimics the convention of
73+
specifying spatial reference information in the attrs of the empty array `spatial_ref`.
74+
75+
```{code-cell}
76+
ds_cf.geometry_container.attrs
77+
```
78+
79+
```{note}
80+
Z axis is not yet supported for any shapes.
81+
```
82+
83+
This `xr.Dataset` can be converted back into a `xr.DataArray` of shapely geometries:
84+
85+
```{code-cell}
86+
cfxr.cf_to_shapely(ds_cf)
87+
```
88+
89+
This conversion adds coordinates that aren't in the `xr.DataArray` that we started with.
90+
By default these are called `crd_x` and `crd_y` unless `grid_mapping` is specified.
91+
92+
## Gotchas
93+
94+
For MultiPolygons with holes the CF notation is slightly ambiguous on which hole is associated
95+
with which polygon. This is problematic because shapely stores holes within the polygon
96+
object that they are associated with. `cf_xarray` assumes that the the shapes are interleaved
97+
such that the holes (interior rings) are associated with the exteriors (exterior rings) that
98+
immediately precede them.

0 commit comments

Comments
 (0)