mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-08-26 17:31:37 +00:00
Fix lat-aware buffer + count WKB parse failures
- query_buffered_line: replace the static _DEG_PER_M with _buffer_degrees_for_meters(), which scales longitude degrees by cos(lat) and uses the larger lat/lon equivalent; buffer at the polyline avg latitude. Early-return [] for empty coords. - _load_table: count WKB parse failures and logger.warning once per table when > 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d9fe84660d
commit
adfc110520
1 changed files with 17 additions and 4 deletions
|
|
@ -7,6 +7,7 @@ indicating which roads/trails are open or closed to specific vehicle modes.
|
||||||
MVUM is motor-vehicle specific — foot mode should skip this layer entirely.
|
MVUM is motor-vehicle specific — foot mode should skip this layer entirely.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
@ -33,9 +34,14 @@ def navi_db_path() -> Path:
|
||||||
|
|
||||||
logger = logging.getLogger("navi_offroute.mvum_spatial")
|
logger = logging.getLogger("navi_offroute.mvum_spatial")
|
||||||
|
|
||||||
# Rough degrees-per-metre for small buffers (latitude scale; good enough for the
|
def _buffer_degrees_for_meters(meters: float, lat: float) -> float:
|
||||||
# coarse candidate filter at Layer 0).
|
"""Approximate buffer radius in degrees for a metre tolerance at a given latitude.
|
||||||
_DEG_PER_M = 1.0 / 111320.0
|
Longitude degrees shrink with cos(lat); use the larger of the lat/lon equivalents so
|
||||||
|
the bbox-coarse buffer stays conservative."""
|
||||||
|
cos_lat = max(math.cos(math.radians(lat)), 0.01)
|
||||||
|
lat_deg = meters / 111320.0
|
||||||
|
lon_deg = meters / (111320.0 * cos_lat)
|
||||||
|
return max(lat_deg, lon_deg)
|
||||||
|
|
||||||
|
|
||||||
class MVUMSpatialIndex:
|
class MVUMSpatialIndex:
|
||||||
|
|
@ -74,6 +80,7 @@ class MVUMSpatialIndex:
|
||||||
|
|
||||||
def _load_table(self, table, kind):
|
def _load_table(self, table, kind):
|
||||||
count = 0
|
count = 0
|
||||||
|
parse_errors = 0
|
||||||
conn = sqlite3.connect(f"file:{self.db_path}?mode=ro", uri=True)
|
conn = sqlite3.connect(f"file:{self.db_path}?mode=ro", uri=True)
|
||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
try:
|
try:
|
||||||
|
|
@ -83,6 +90,7 @@ class MVUMSpatialIndex:
|
||||||
try:
|
try:
|
||||||
geom = wkb.loads(bytes(row["shape"]))
|
geom = wkb.loads(bytes(row["shape"]))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
parse_errors += 1
|
||||||
continue
|
continue
|
||||||
if geom.is_empty:
|
if geom.is_empty:
|
||||||
continue
|
continue
|
||||||
|
|
@ -101,6 +109,8 @@ class MVUMSpatialIndex:
|
||||||
count += 1
|
count += 1
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
if parse_errors > 0:
|
||||||
|
logger.warning("%s: %d rows had unparseable WKB shape blobs", table, parse_errors)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -127,9 +137,12 @@ class MVUMSpatialIndex:
|
||||||
MVUM features which merely cross the route are rejected, keeping only those
|
MVUM features which merely cross the route are rejected, keeping only those
|
||||||
that run alongside it.
|
that run alongside it.
|
||||||
"""
|
"""
|
||||||
|
if not coords:
|
||||||
|
return []
|
||||||
pts = [(lon, lat) for (lat, lon) in coords]
|
pts = [(lon, lat) for (lat, lon) in coords]
|
||||||
geom = LineString(pts) if len(pts) >= 2 else Point(pts[0])
|
geom = LineString(pts) if len(pts) >= 2 else Point(pts[0])
|
||||||
return self._query_geom(geom.buffer(tolerance_m * _DEG_PER_M))
|
avg_lat = sum(lat for (lat, lon) in coords) / len(coords)
|
||||||
|
return self._query_geom(geom.buffer(_buffer_degrees_for_meters(tolerance_m, avg_lat)))
|
||||||
|
|
||||||
|
|
||||||
def parse_date_range(date_str: str) -> List[Tuple[int, int, int, int]]:
|
def parse_date_range(date_str: str) -> List[Tuple[int, int, int, int]]:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue