Skip to content

Commit

Permalink
feat: addressing of project using Nominatim (#913)
Browse files Browse the repository at this point in the history
* feat: Addressing of project using Nominatim

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* refactor: move repeated location update logic to func

* test: add additional proj
ect location update checks

---------

Co-authored-by: sujanadh <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: spwoodcock <[email protected]>
  • Loading branch information
4 people authored Oct 18, 2023
1 parent 1ae34f6 commit f6fdd40
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
54 changes: 48 additions & 6 deletions src/backend/app/projects/project_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,8 @@ def update_multi_polygon_project_boundary(
result = db.execute(query)
data = result.fetchone()

db_project.outline = data[0]
db_project.centroid = (wkt.loads(data[0])).centroid.wkt
update_project_location_info(db_project, data[0])

db.commit()
db.refresh(db_project)
log.debug("COMPLETE: creating project boundary, based on task boundaries")
Expand Down Expand Up @@ -898,8 +898,7 @@ def remove_z_dimension(coord):
else:
outline = shape(features[0]["geometry"])

db_project.outline = outline.wkt
db_project.centroid = outline.centroid.wkt
update_project_location_info(db_project, outline.wkt)

db.commit()
db.refresh(db_project)
Expand Down Expand Up @@ -1011,8 +1010,7 @@ def update_project_with_zip(
outline_shape = get_outline_from_geojson_file_in_zip(
zip, outline_filename, f"Could not generate Shape from {outline_filename}"
)
db_project.outline = outline_shape.wkt
db_project.centroid = outline_shape.centroid.wkt
update_project_location_info(db_project, outline_shape.wkt)

# get all task outlines from file
project_tasks_feature_collection = get_json_from_zip(
Expand Down Expand Up @@ -1894,6 +1892,7 @@ def convert_to_project_summary(db_project: db_models.DbProject):
None,
)
# default_project_info = project_schemas.ProjectInfo
summary.location_str = db_project.location_str
summary.title = default_project_info.name
summary.description = default_project_info.short_description

Expand Down Expand Up @@ -2669,3 +2668,46 @@ def generate_appuser_files_for_janakpur(
update_background_task_status_in_database(
db, background_task_id, 4
) # 4 is COMPLETED


def get_address_from_lat_lon(latitude, longitude):
"""Get address using Nominatim, using lat,lon."""
base_url = "https://nominatim.openstreetmap.org/reverse"

params = {
"format": "json",
"lat": latitude,
"lon": longitude,
"zoom": 18,
}
headers = {"Accept-Language": "en"} # Set the language to English

response = requests.get(base_url, params=params, headers=headers)
data = response.json()
address = data["address"]["country"]

if response.status_code == 200:
if "city" in data["address"]:
city = data["address"]["city"]
address = f"{city}" + "," + address
return address
else:
return "Address not found."


def update_project_location_info(
db_project: sqlalchemy.orm.declarative_base, project_boundary: str
):
"""Update project boundary, centroid, address.
Args:
db_project(sqlalchemy.orm.declarative_base): The project database record.
project_boundary(str): WKT string geometry.
"""
db_project.outline = project_boundary
centroid = (wkt.loads(project_boundary)).centroid.wkt
db_project.centroid = centroid
geometry = wkt.loads(centroid)
longitude, latitude = geometry.x, geometry.y
address = get_address_from_lat_lon(latitude, longitude)
db_project.location_str = address if address is not None else ""
15 changes: 14 additions & 1 deletion src/backend/tests/test_projects_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from fastapi import FastAPI
from geoalchemy2.elements import WKBElement
from loguru import logger as log
from shapely import Polygon
from shapely import Polygon, wkb
from shapely.geometry import shape

from app.central.central_crud import create_odk_project
from app.db import db_models
Expand Down Expand Up @@ -139,6 +140,18 @@ def test_generate_appuser_files(db, project):
db, project_id, boundary_geojson, 500
)
assert boundary_created is True
# Check updated locations
db_project = project_crud.get_project_by_id(db, project_id)
# Outline
project_outline = db_project.outline.data.tobytes()
file_outline = shape(boundary_geojson)
assert wkb.loads(project_outline).wkt == file_outline.wkt
# Centroid
project_centroid = wkb.loads(db_project.centroid.data.tobytes()).wkt
file_centroid = file_outline.centroid.wkt
assert project_centroid == file_centroid
# Location string
assert db_project.location_str == "Zurich,Switzerland"

# Load data extracts
data_extracts_file = f"{test_data_path}/building_footprint.zip"
Expand Down

0 comments on commit f6fdd40

Please sign in to comment.