@@ -295,7 +295,7 @@ def cf_to_points(ds: xr.Dataset):
295
295
return xr .DataArray (geoms , dims = node_count .dims , coords = node_count .coords )
296
296
297
297
298
- def grid_bounds_to_polygons (ds : xr .Dataset ) -> xr .DataArray :
298
+ def grid_to_polygons (ds : xr .Dataset ) -> xr .DataArray :
299
299
"""
300
300
Converts a regular 2D lat/lon grid to a 2D array of shapely polygons.
301
301
@@ -313,7 +313,7 @@ def grid_bounds_to_polygons(ds: xr.Dataset) -> xr.DataArray:
313
313
DataArray
314
314
DataArray with shapely polygon per grid cell.
315
315
"""
316
- from shapely import Polygon
316
+ import shapely
317
317
318
318
grid = ds .cf [["latitude" , "longitude" ]].load ().reset_coords ()
319
319
bounds = ds .cf .bounds
@@ -327,30 +327,24 @@ def grid_bounds_to_polygons(ds: xr.Dataset) -> xr.DataArray:
327
327
328
328
bounds_dim = grid .cf .get_bounds_dim_name ("latitude" )
329
329
points = points .transpose (..., bounds_dim )
330
- assert points .sizes [bounds_dim ] == 2
331
-
332
330
lonbnd = points [lon_bounds ].data
333
331
latbnd = points [lat_bounds ].data
334
332
335
- # geopandas needs this
336
- expanded_lon = lonbnd [..., [0 , 0 , 1 , 1 ]]
337
- mask = expanded_lon [..., 0 ] >= 180
338
- expanded_lon [mask , :] = expanded_lon [mask , :] - 360
339
-
340
- # these magic numbers are OK :
341
- # - 4 corners to a polygon, and
342
- # - 2 from stacking lat, lon along the last axis
343
- # flatten here to make iteration easier. It would be nice to avoid that.
344
- # potentially with just np.vectorize. The polygon creation is the real slow bit.
345
- # Shapely's MultiPolygon also iterates over a list in Python...
346
- blocked = np .stack ([expanded_lon , latbnd [..., [0 , 1 , 1 , 0 ]]], axis = - 1 ).reshape (
347
- - 1 , 4 , 2
348
- )
349
- polyarray = np .array (
350
- [Polygon (blocked [i , ...]) for i in range (blocked .shape [0 ])], dtype = "O"
351
- )
352
- newshape = latbnd .shape [:- 1 ]
353
- polyarray = polyarray .reshape (newshape )
333
+ if points .sizes [bounds_dim ] == 2 :
334
+ # geopandas needs this
335
+ lonbnd = lonbnd [..., [0 , 0 , 1 , 1 ]]
336
+ mask = lonbnd [..., 0 ] >= 180
337
+ lonbnd [mask , :] = lonbnd [mask , :] - 360
338
+ latbnd = latbnd [..., [0 , 1 , 1 , 0 ]]
339
+
340
+ elif points .sizes [bounds_dim ] == 4 :
341
+ raise NotImplementedError
342
+ else :
343
+ raise ValueError (
344
+ f"The size of the detected bounds or vertex dimension { bounds_dim } is not 2 or 4."
345
+ )
346
+
347
+ polyarray = shapely .polygons (shapely .linearrings (lonbnd , latbnd ))
354
348
boxes = points [lon_bounds ][..., 0 ].copy (data = polyarray )
355
349
356
350
return boxes
0 commit comments