From ea19ed0d8fd1e18d95236ef09863734efa16edf0 Mon Sep 17 00:00:00 2001 From: viktot14-ai Date: Wed, 9 Sep 2026 19:40:20 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B4=D0=B8=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BE=20=D0=B2=D0=BE=D0=B4=D1=8B/?= =?UTF-8?q?=D0=9D=D0=9F=20=E2=80=94=20real=20=3D=20merc=C3=97cos=20+=20?= =?UTF-8?q?=D0=BC=D0=B5=D1=82=D1=80=D1=8B=E2=86=92=D0=BA=D0=BC=20(=D0=B1?= =?UTF-8?q?=D1=8B=D0=BB=D0=BE=20850=20=C2=AB=D0=BA=D0=BC=C2=BB=20=D0=B4?= =?UTF-8?q?=D0=BE=20=D0=BE=D0=B7=D0=B5=D1=80=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Два бага в одной строке: водные дистанции делились на cos (вместо умножения, как дороги) и отдавались как км без /1000. Результат — 850.671 «км» до озера в Браславе (реально 271 м). Верифицировано против geography: merc×cos = 271.0 м ≈ geo 271.5 м (дельта 0.1%). Теперь Браслав SE: water 0.271 км, settle 0.119 км. 197 passed. --- scripts/b16-water-scale.sql | 10 ++++++++++ services/osm_local.py | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 scripts/b16-water-scale.sql diff --git a/scripts/b16-water-scale.sql b/scripts/b16-water-scale.sql new file mode 100644 index 0000000..1ee23aa --- /dev/null +++ b/scripts/b16-water-scale.sql @@ -0,0 +1,10 @@ +-- Верификация масштаба дистанций: mercator vs geography (Браслав) +WITH s AS ( + SELECT ST_Transform(ST_SetSRID(ST_MakePoint(27.03, 55.64), 4326), 3857) AS c_m, + ST_SetSRID(ST_MakePoint(27.03, 55.64), 4326) AS c_g +) +SELECT + (SELECT MIN(ST_Distance(p.way, c_m)) FROM planet_osm_polygon p, s + WHERE (p."natural"='water' OR p.landuse='reservoir') AND p.way && ST_Expand(s.c_m, 30000)) AS merc_m, + (SELECT MIN(ST_Distance(ST_Transform(p.way, 4326)::geography, c_g::geography)) FROM planet_osm_polygon p, s + WHERE (p."natural"='water' OR p.landuse='reservoir') AND p.way && ST_Expand(s.c_m, 30000)) AS geo_m; \ No newline at end of file diff --git a/services/osm_local.py b/services/osm_local.py index e6a90c9..0c992e6 100644 --- a/services/osm_local.py +++ b/services/osm_local.py @@ -100,19 +100,19 @@ def get_zone_features_postgis(lat: float, lon: float, direction: str, radius_m: AND p.way && s.sector ), water_near AS ( - SELECT MIN(ST_Distance(p.way, s.center_m)) / :scale AS meters + SELECT MIN(ST_Distance(p.way, s.center_m)) AS meters FROM planet_osm_polygon p, s WHERE (p."natural" = 'water' OR p.landuse = 'reservoir') - AND p.way && ST_Transform(ST_SetSRID(ST_GeomFromText(:sector_wkt), 4326), 3857) + AND p.way && s.sector ), waterway_near AS ( - SELECT MIN(ST_Distance(l.way, s.center_m)) / :scale AS meters + SELECT MIN(ST_Distance(l.way, s.center_m)) AS meters FROM planet_osm_line l, s WHERE l.waterway IN ('river','stream','canal','ditch','drain') AND l.way && s.sector ), settle_near AS ( - SELECT MIN(ST_Distance(p.way, s.center_m)) / :scale AS meters + SELECT MIN(ST_Distance(p.way, s.center_m)) AS meters FROM planet_osm_point p, s WHERE p.place IN ('village','town','city') AND p.way && s.sector @@ -137,10 +137,11 @@ def get_zone_features_postgis(lat: float, lon: float, direction: str, radius_m: # real = mercator * cos(lat) (проверено: merc/geo = 1/cos(lat) точно). roads_km = float(row[0] or 0) / 1000.0 * scale forest_m2 = float(row[1] or 0) * (scale * scale) # mercator-м² → реальные м² - # Расстояния (row[2..4]) уже поделены на scale в SQL → вернулись в метры - water_poly_m = row[2] - waterway_m = row[3] - settle_m = row[4] + # Дистанции: mercator-метры → реальные метры (та же поправка, что у дорог: + # раньше деление на cos здесь ДВОИЛО раздувание — 850 «км» до озера в Браславе). + water_poly_m = float(row[2]) * scale if row[2] is not None else None + waterway_m = float(row[3]) * scale if row[3] is not None else None + settle_m = float(row[4]) * scale if row[4] is not None else None search_area_km2 = math.pi * (radius_m / 1000.0) ** 2 road_density = roads_km / search_area_km2 if search_area_km2 > 0 else 0.0 @@ -153,7 +154,7 @@ def get_zone_features_postgis(lat: float, lon: float, direction: str, radius_m: if forest_m2 > 0 and search_area_km2 > 0: forest_pct = round(min(1.0, (forest_m2 / 1e6) / search_area_km2), 3) - water_candidates = [float(m) for m in (water_poly_m, waterway_m) if m is not None] + water_candidates = [float(m) / 1000.0 for m in (water_poly_m, waterway_m) if m is not None] water_distance_km = round(min(water_candidates), 3) if water_candidates else None settlement_distance_km = round(float(settle_m) / 1000.0, 3) if settle_m is not None else None