89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
"""
|
|
Swiss Parcel (Liegenschaften) Connector
|
|
|
|
Fetches parcel data from geodienste.ch OGC API Features (Amtliche Vermessung).
|
|
Covers all of Switzerland. Returns GeoJSON in WGS84.
|
|
|
|
Uses: geodienste.ch OGC API - RESF collection (Liegenschaften)
|
|
No config override needed - this is the single working solution.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Dict, Any
|
|
|
|
import requests
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# geodienste.ch OGC API - RESF = Liegenschaften (parcels), all Switzerland
|
|
# API returns WGS84 directly when bbox-crs=EPSG:2056 is used
|
|
_OGC_API_BASE = "https://www.geodienste.ch/db/av_0/deu/ogcapi/collections/RESF/items"
|
|
_MAX_ITEMS = 2000
|
|
_TIMEOUT = 30
|
|
|
|
|
|
class ZhWfsParcelsConnector:
|
|
"""
|
|
Connector for Swiss parcel (Liegenschaften) data via geodienste.ch OGC API.
|
|
Returns GeoJSON FeatureCollection in WGS84.
|
|
"""
|
|
|
|
def __init__(self, timeout: int = _TIMEOUT):
|
|
self.timeout = timeout
|
|
logger.info("ZhWfsParcelsConnector initialized (geodienste.ch OGC API)")
|
|
|
|
def get_parcels_by_bbox(self, bbox: str) -> Dict[str, Any]:
|
|
"""
|
|
Fetch parcels within bounding box.
|
|
Returns GeoJSON FeatureCollection in WGS84 (EPSG:4326).
|
|
|
|
Args:
|
|
bbox: Bounding box as "minx,miny,maxx,maxy" in LV95 (EPSG:2056)
|
|
|
|
Returns:
|
|
GeoJSON FeatureCollection with geometries in WGS84
|
|
"""
|
|
try:
|
|
parts = [p.strip() for p in bbox.split(",")]
|
|
if len(parts) != 4:
|
|
raise ValueError(f"Invalid bbox: expected minx,miny,maxx,maxy, got {bbox}")
|
|
minx, miny, maxx, maxy = (float(p) for p in parts)
|
|
|
|
params = {
|
|
"f": "json",
|
|
"limit": _MAX_ITEMS,
|
|
"bbox": f"{minx},{miny},{maxx},{maxy}",
|
|
"bbox-crs": "http://www.opengis.net/def/crs/EPSG/0/2056",
|
|
}
|
|
|
|
logger.debug(f"Requesting parcels: bbox={bbox}")
|
|
resp = requests.get(_OGC_API_BASE, params=params, timeout=self.timeout)
|
|
|
|
if resp.status_code != 200:
|
|
logger.error(f"Parcel API failed: status={resp.status_code}, body={resp.text[:500]}")
|
|
return {"type": "FeatureCollection", "features": []}
|
|
|
|
data = resp.json()
|
|
|
|
# OGC API returns FeatureCollection in WGS84 directly
|
|
features = data.get("features", [])
|
|
if not features:
|
|
return {"type": "FeatureCollection", "features": []}
|
|
|
|
# Pass through - geodienste returns WGS84 GeoJSON
|
|
result = {
|
|
"type": "FeatureCollection",
|
|
"features": features,
|
|
}
|
|
logger.info(f"Returned {len(features)} parcels in WGS84")
|
|
return result
|
|
|
|
except ValueError as e:
|
|
logger.warning(f"Invalid bbox: {e}")
|
|
raise
|
|
except requests.RequestException as e:
|
|
logger.error(f"Parcel API request error: {e}")
|
|
return {"type": "FeatureCollection", "features": []}
|
|
except Exception as e:
|
|
logger.error(f"Error fetching parcels: {e}", exc_info=True)
|
|
return {"type": "FeatureCollection", "features": []}
|