B16: локальный OSM в PostGIS — geo_service без интернета
- services/osm_local.py: слой запросов к planet_osm_* (osm2pgsql, SRID 3857): roads/density (ST_Length merc × cos(lat) — проверено на merc/geo=1/cos), forest (честная площадь ST_Intersection), water (полигон/водоток), settlements (village/town/city). Сектор-«пирог» 45° строится в WGS84. - geo_service.get_zone_features: PostGIS-путь, Overpass — fallback (osm_available() по наличию planet_osm_line). - scripts/b16-import.sh: osm2pgsql --slim -C 800, Беларусь 333МБ pbf (Geofabrik, md5 проверен) → 4.5 мин на CT108; PostGIS 3.6 установлен в живой vector-postgres (apt, без смены образа). - Валидация: Минск/Полоцк/Браслав — правдоподобные плотности (7.9/2.9/1.5 км/км²), зоны различаются по направлениям; 32 сектора за 1.9 c (без сети). - Тесты: +8 (osm_local контракт, интеграция, отсутствие Overpass-вызовов), вне БД — skip. Всего 190 passed, 5 skipped. Критерий B16: build_search_zones без внешнего интернета — ВЫПОЛНЕН (единственный Overpass остаётся fallback-веткой при пустых таблицах).
This commit is contained in:
+14
-10
@@ -1,5 +1,9 @@
|
||||
"""
|
||||
Geo service for building search zones and querying OpenStreetMap data via Overpass API.
|
||||
"""Geo service for building search zones and querying OpenStreetMap data.
|
||||
|
||||
B16: данные берутся из ЛОКАЛЬНОГО PostGIS (services/osm_local.py, таблицы
|
||||
planet_osm_* залиты osm2pgsql). Overpass — только fallback, если локальных
|
||||
таблиц нет (osm_available() == False). Никаких внешних вызовов при
|
||||
локальном режиме.
|
||||
"""
|
||||
import asyncio
|
||||
import math
|
||||
@@ -13,6 +17,8 @@ from typing import List, Dict, Optional, Tuple
|
||||
import httpx
|
||||
from pydantic import BaseModel
|
||||
|
||||
from services.osm_local import get_zone_features_postgis, osm_available
|
||||
|
||||
|
||||
class Zone(BaseModel):
|
||||
"""Search zone with geographic features."""
|
||||
@@ -344,17 +350,15 @@ def calculate_forest_coverage(elements: List[Dict], radius_m: int) -> float:
|
||||
|
||||
|
||||
async def get_zone_features(lat: float, lon: float, direction: str, radius_m: int) -> Dict:
|
||||
"""
|
||||
Get geographic features for a zone using Overpass API.
|
||||
|
||||
Args:
|
||||
lat, lon: Center point
|
||||
direction: Sector direction
|
||||
radius_m: Search radius in meters
|
||||
"""Характеристики сектора. B16: локальный PostGIS; Overpass — fallback.
|
||||
|
||||
Returns:
|
||||
Dict with roads_km, water_distance_km, settlement_distance_km, forest_pct
|
||||
Dict with roads_km, road_density, water_distance_km, settlement_distance_km, forest_pct
|
||||
"""
|
||||
if osm_available():
|
||||
return get_zone_features_postgis(lat, lon, direction, radius_m)
|
||||
|
||||
# Fallback: живой Overpass (старое поведение, пока B16-данные не залиты)
|
||||
# Query roads
|
||||
roads_query = f"""
|
||||
[out:json];
|
||||
|
||||
Reference in New Issue
Block a user