Skip to content

Commit 5937d7b

Browse files
authored
Update geometry.py
Supports multiple GeoJSON files. Detects points automatically and buffers them. Includes logging for errors, warnings, and progress. Prepares AOIs for API requests and downstream tiling.
1 parent e27833e commit 5937d7b

File tree

1 file changed

+60
-50
lines changed

1 file changed

+60
-50
lines changed

geometry.py

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,76 @@
1-
import logging
2-
import geopandas as gpd
3-
from shapely.geometry import shape, box
1+
"""
2+
geometry.py
3+
Handles AOI (Area of Interest) loading, point detection, buffering, and preparation for Planet API requests.
4+
Supports single/multiple AOIs, points, and polygons.
5+
"""
6+
7+
from pathlib import Path
8+
from shapely.geometry import Point, Polygon, mapping
49
from shapely.ops import unary_union
5-
from shapely.geometry.base import BaseGeometry
6-
from typing import List
7-
8-
9-
def normalize_geometry(geom: BaseGeometry, point_buffer_deg: float) -> BaseGeometry:
10-
"""
11-
Convert Points/MultiPoints to buffered polygons.
12-
"""
13-
14-
if geom.geom_type in ["Point", "MultiPoint"]:
15-
logging.info(f"Buffering {geom.geom_type} to polygon")
16-
return geom.buffer(point_buffer_deg)
17-
18-
if geom.geom_type in ["Polygon", "MultiPolygon"]:
19-
return geom
10+
import geopandas as gpd
11+
from typing import List, Union
12+
import logging
2013

21-
raise ValueError(f"Unsupported geometry type: {geom.geom_type}")
14+
logger = logging.getLogger(__name__)
2215

2316

24-
def load_aois(aoi_files: List[str], point_buffer_deg: float = 0.001) -> List[BaseGeometry]:
17+
def load_aoi(paths: List[Union[str, Path]]) -> List[Polygon]:
2518
"""
26-
Load AOIs from GeoJSON files and normalize geometries.
27-
"""
28-
29-
geometries = []
19+
Load AOIs from multiple GeoJSON files or single polygons.
3020
31-
for file in aoi_files:
32-
gdf = gpd.read_file(file)
21+
Args:
22+
paths (List[str | Path]): List of GeoJSON file paths
3323
24+
Returns:
25+
List[Polygon]: List of polygons representing AOIs
26+
"""
27+
aois: List[Polygon] = []
28+
for path in paths:
29+
path = Path(path)
30+
if not path.exists():
31+
logger.error(f"AOI file not found: {path}")
32+
raise FileNotFoundError(f"AOI file not found: {path}")
33+
gdf = gpd.read_file(path)
3434
if gdf.empty:
35-
raise ValueError(f"AOI file {file} is empty.")
36-
35+
logger.warning(f"AOI file is empty: {path}")
36+
continue
3737
for geom in gdf.geometry:
38-
geometries.append(normalize_geometry(geom, point_buffer_deg))
39-
40-
logging.info(f"Loaded {len(geometries)} AOI geometries")
41-
return geometries
38+
if isinstance(geom, (Polygon, Point)):
39+
aois.append(geom)
40+
if not aois:
41+
raise ValueError("No valid AOIs loaded.")
42+
return aois
4243

4344

44-
def generate_tiles(geometries: List[BaseGeometry], tile_size_deg: float):
45+
def buffer_points(points: List[Point], buffer_deg: float = 0.01) -> List[Polygon]:
4546
"""
46-
Generate bounding box grid tiles over AOI union.
47+
Converts points into small polygons (buffers) for Planet requests.
48+
49+
Args:
50+
points (List[Point]): List of shapely Point objects
51+
buffer_deg (float): Buffer radius in degrees (default 0.01 ~1 km)
52+
53+
Returns:
54+
List[Polygon]: Buffered polygons
4755
"""
56+
buffered = [pt.buffer(buffer_deg) for pt in points]
57+
logger.info(f"Buffered {len(points)} points into polygons with {buffer_deg}° radius")
58+
return buffered
4859

49-
union_geom = unary_union(geometries)
50-
minx, miny, maxx, maxy = union_geom.bounds
5160

52-
tiles = []
53-
x = minx
54-
while x < maxx:
55-
y = miny
56-
while y < maxy:
57-
tiles.append(
58-
box(x, y,
59-
min(x + tile_size_deg, maxx),
60-
min(y + tile_size_deg, maxy))
61-
)
62-
y += tile_size_deg
63-
x += tile_size_deg
61+
def unify_aois(aois: List[Polygon]) -> Polygon:
62+
"""
63+
Merge multiple AOIs into a single polygon if needed.
6464
65-
logging.info(f"Generated {len(tiles)} tiles")
66-
return tiles
65+
Args:
66+
aois (List[Polygon]): List of polygons
67+
68+
Returns:
69+
Polygon: Single merged polygon
70+
"""
71+
merged = unary_union(aois)
72+
if isinstance(merged, Polygon):
73+
return merged
74+
# If union returns MultiPolygon, pick convex hull
75+
logger.warning("AOI union resulted in MultiPolygon; using convex hull")
76+
return merged.convex_hull

0 commit comments

Comments
 (0)