| from __future__ import annotations |
|
|
| from typing import Any |
|
|
| from .evidence import make_evidence |
| from .http_client import get_json |
| from .models import EvidenceItem |
|
|
| NOMINATIM_REVERSE_URL = "https://nominatim.openstreetmap.org/reverse" |
|
|
|
|
| def reverse_geocode_site(lat: float, lon: float) -> tuple[dict[str, Any], list[EvidenceItem]]: |
| """Return an OSM-derived address identity for the site anchor. |
| |
| This is intentionally treated as contextual identity, not official address |
| verification. Nominatim public usage is kept to one generate-time reverse |
| lookup instead of interactive autocomplete. |
| """ |
| try: |
| payload = get_json( |
| NOMINATIM_REVERSE_URL, |
| { |
| "format": "jsonv2", |
| "lat": lat, |
| "lon": lon, |
| "addressdetails": 1, |
| "zoom": 18, |
| }, |
| timeout=18, |
| ) |
| address = payload.get("address") or {} |
| identity = { |
| "display_name": payload.get("display_name"), |
| "road": address.get("road") or address.get("pedestrian") or address.get("path"), |
| "neighbourhood": address.get("neighbourhood") |
| or address.get("suburb") |
| or address.get("quarter"), |
| "city": address.get("city") or address.get("town") or address.get("village"), |
| "district": address.get("county") or address.get("state_district"), |
| "state": address.get("state"), |
| "postcode": address.get("postcode"), |
| "country": address.get("country"), |
| "lat": lat, |
| "lon": lon, |
| } |
| evidence = [ |
| make_evidence( |
| category="Site identity", |
| finding="Approximate address and administrative context were reverse-geocoded from the site anchor.", |
| source_name="OpenStreetMap Nominatim", |
| source_url="https://nominatim.org/release-docs/latest/api/Reverse/", |
| source_type="open geocoding service", |
| resolution_or_scope="single reverse-geocoding request at site anchor/centroid", |
| confidence="medium" if identity.get("display_name") else "low", |
| limitation="OSM-derived address context may be incomplete, approximate, or outdated. It is not legal address verification.", |
| design_implication="Use this to label the site and organize studio research by street, city, state, and country.", |
| verification_needed="Confirm final address and administrative names from project brief, faculty, client, or local records.", |
| output_label="public_data", |
| ) |
| ] |
| return identity, evidence |
| except Exception as exc: |
| return { |
| "display_name": None, |
| "lat": lat, |
| "lon": lon, |
| "error": f"{type(exc).__name__}: {exc}", |
| }, [ |
| make_evidence( |
| category="Site identity", |
| finding="Reverse-geocoded address could not be retrieved.", |
| source_name="OpenStreetMap Nominatim", |
| source_url="https://nominatim.org/release-docs/latest/api/Reverse/", |
| source_type="open geocoding service", |
| resolution_or_scope="not available", |
| confidence="low", |
| limitation=f"Reverse geocoder failed: {type(exc).__name__}.", |
| design_implication="Do not infer street/city/state labels from missing geocoding data.", |
| verification_needed="Enter address details manually from the project brief or site documents.", |
| output_label="site_visit_required", |
| ) |
| ] |
|
|