@mytec: iter1.6 ready for testing
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import re
|
||||
import httpx
|
||||
import asyncio
|
||||
from typing import List, Optional
|
||||
@@ -34,6 +35,33 @@ class BuildingsService:
|
||||
self._memory_cache: dict[str, List[Building]] = {}
|
||||
self._max_cache_size = 50 # bbox regions
|
||||
|
||||
@staticmethod
|
||||
def _safe_int(value) -> Optional[int]:
|
||||
"""Safely parse int from OSM tag (handles '1а', '2-3', '5+', etc.)"""
|
||||
if not value:
|
||||
return None
|
||||
try:
|
||||
return int(value)
|
||||
except (ValueError, TypeError):
|
||||
match = re.search(r'\d+', str(value))
|
||||
if match:
|
||||
return int(match.group())
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _safe_float(value) -> Optional[float]:
|
||||
"""Safely parse float from OSM tag (handles '10 m', '~12', '10m')"""
|
||||
if not value:
|
||||
return None
|
||||
try:
|
||||
cleaned = str(value).lower().replace('m', '').replace('~', '').strip()
|
||||
return float(cleaned)
|
||||
except (ValueError, TypeError):
|
||||
match = re.search(r'[\d.]+', str(value))
|
||||
if match:
|
||||
return float(match.group())
|
||||
return None
|
||||
|
||||
def _bbox_key(self, min_lat: float, min_lon: float, max_lat: float, max_lon: float) -> str:
|
||||
"""Generate cache key for bbox"""
|
||||
# Round to 0.01 degree (~1km) grid for cache efficiency
|
||||
@@ -157,7 +185,7 @@ class BuildingsService:
|
||||
id=element["id"],
|
||||
geometry=geometry,
|
||||
height=height,
|
||||
levels=int(tags.get("building:levels", 0)) or None,
|
||||
levels=self._safe_int(tags.get("building:levels")),
|
||||
building_type=tags.get("building"),
|
||||
material=material_str,
|
||||
tags=tags
|
||||
@@ -169,22 +197,15 @@ class BuildingsService:
|
||||
"""Estimate building height from OSM tags"""
|
||||
# Explicit height tag
|
||||
if "height" in tags:
|
||||
try:
|
||||
h = tags["height"]
|
||||
# Handle "10 m" or "10m" format
|
||||
if isinstance(h, str):
|
||||
h = h.replace("m", "").replace(" ", "")
|
||||
return float(h)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
h = self._safe_float(tags["height"])
|
||||
if h is not None and h > 0:
|
||||
return h
|
||||
|
||||
# Calculate from levels
|
||||
if "building:levels" in tags:
|
||||
try:
|
||||
levels = int(tags["building:levels"])
|
||||
levels = self._safe_int(tags["building:levels"])
|
||||
if levels is not None and levels > 0:
|
||||
return levels * self.DEFAULT_LEVEL_HEIGHT
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
# Default based on building type
|
||||
building_type = tags.get("building", "yes")
|
||||
|
||||
Reference in New Issue
Block a user