Skip to content

Commit

Permalink
Merge pull request #443 from Open-Earth-Foundation/on-1643
Browse files Browse the repository at this point in the history
feat: add area to city boundaries and own endpoint
  • Loading branch information
evanp authored Apr 15, 2024
2 parents 3040668 + 6a73d04 commit f30e6f6
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
3 changes: 2 additions & 1 deletion global-api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ dns-cache==0.3.*
openpyxl==3.1.*
pytest==8.1.1
pytest-cov==4.1.0
httpx==0.27.0
httpx==0.27.0
pyproj==3.6.*
51 changes: 51 additions & 0 deletions global-api/routes/city_boundaries_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
from decimal import Decimal
from shapely.geometry import Point, shape
from shapely.wkt import loads
import pyproj
from functools import partial
from shapely.ops import transform
import math

api_router = APIRouter(prefix="/api/v0")

Expand All @@ -21,6 +25,37 @@ def db_query(locode):

return row

def epsg_code(polygon):
"""Calculate the UTM zone and corresponding EPSG code for a polygon"""
# Calculate centroid of the polygon
centroid = polygon.centroid
longitude = centroid.x
latitude = centroid.y

# Calculate UTM zone from centroid longitude
zone_number = math.floor((longitude + 180) / 6) + 1

# Determine the hemisphere and corresponding EPSG code
if latitude >= 0:
code = 32600 + zone_number
else:
code = 32700 + zone_number

return code

def get_area(geometry):
polygon = loads(geometry)
code = epsg_code(polygon)

proj = partial(
pyproj.transform,
pyproj.Proj("epsg:4326"), # lat/lon
pyproj.Proj(f'epsg:{code}')
)

utm_polygon = transform(proj, polygon)
area = utm_polygon.area / 10.0**6 # in km^2
return area

@api_router.get("/cityboundary/city/{locode}")
def get_city_boundary(locode: str):
Expand All @@ -29,12 +64,28 @@ def get_city_boundary(locode: str):
if not city:
raise HTTPException(status_code=404, detail="City boundary not found")

area = get_area(city.geometry)

return {
"city_geometry": city.geometry,
"bbox_north": city.bbox_north,
"bbox_south": city.bbox_south,
"bbox_east": city.bbox_east,
"bbox_west": city.bbox_west,
"area": area
}

@api_router.get("/cityboundary/city/{locode}/area")
def get_city_area(locode: str):
city = db_query(locode)

if not city:
raise HTTPException(status_code=404, detail="City boundary not found")

area = get_area(city.geometry)

return {
"area": area
}

@api_router.get("/cityboundary/locode/{lat}/{lon}")
Expand Down

0 comments on commit f30e6f6

Please sign in to comment.