feat(sf): geocode geom для ekburg_construction_permits из МСК-66 (#1088) #1124
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#1124
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/ekburg-permits-geocode"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что
Заполняет
geomдляekburg_construction_permits(4059 строк РНС/РВЭ, сейчас geocoded=0 — geom пуст у всех). Разблокирует spatial-использование РНС-данных (слой будущих ЖК, #1088 geo-join застройщик).Как
msk66_to_wgs84()(ekburg_permits.py): raw_coord X/Y (~1.53e6 / 3.8e5) = МСК-66 zone 1 → WGS84 черезpyproj(уже в deps). SRID 100066 в PostGIS отсутствует → proj4-строка._upsert_permitпишет geocoded_lat/lon + geom (ST_SetSRID+ST_MakePoint) при каждом sync.backfill_geom()/ Celerybackfill_geom_task— разовый UPDATE существующих 4059 батчами по 200 (SAVEPOINT, psycopg v3 CAST). Сама не запускается — ручной вызов после merge.Проверка попадания в ЕКБ (из БД)
пр. Космонавтов 18 → 60.5695/56.8715 ✓ · Кольцово → 60.7183/56.7519 ✓ · Смородиновая 187 → 60.4332/56.8030 ✓ · Краснокамская (multi) → 60.4708/56.8214 ✓
⚠️ Для ревьюера
false_northing=-5911000подобран эмпирически по 3 адресам (SRID 100066 нет в БД, авторитетного определения МСК-66 zone 1 не было под рукой). Страховка — bbox-валидация ЕКБ + 4 подтверждённые точки. Стоит сверить на большем числе известных адресов.Тест
35/35 passed (11 новых
TestMsk66ToWgs84).После merge (ручное, не блокер)
celery -A app.workers.celery_app call tasks.ekburg_permits_sync.backfill_geom_task→ затемSELECT count(geom) FROM ekburg_construction_permits;(ожидаем ~4029; 30 строк без координат останутся NULL).Часть #1088.
🟠 FIX — proj4-трансформ систематически смещён на ~3050м. Не мержим до калибровки.
Что нашёл (real-data cross-check vs
cad_parcels)Прогнал твою точную proj4-строку через PostGIS
ST_Transformдля 15 permit'ов, у которыхcadastral_numberесть вcad_parcels(authoritative НСПД-геометрия 4326), сравнил с центроидом участка:Широта совпадает (Δ ≈ 50м, ✓). Долгота систематически на ~0.050° (≈3050м) ЗАПАДНЕЕ истинной — константа по всем 15 точкам, во все районы ЕКБ.
Почему страховки не поймали
_upsert_permitпишет geom на КАЖДОМ sync (live path, не только ручной backfill) → systematically-wrong geom затрёт текущие NULL. Для spatial-join wrong-geom хуже NULL (ложные матчи vs нет матчей).Fix
Смещение постоянное (~3050м) и почти чисто в easting/долготе, широта верна →
x_0(false_easting) велик на ~3050м. computed западнее → нужно увеличить easting → уменьшитьx_0:x_0 = 1500000 - 3050 ≈ 1496950(calibrate до Δ<50м);lon_0=60,y_0, широтная часть — корректны, не трогать.towgs84будет точным.Как проверить (используй этот же ground-truth)
Acceptance: avg_err_m < 50 (вместо текущих ~3050). Тогда обнови 4 «verified»-точки в PR-описании на реальные cad_parcels-сверенные значения + добавь тест, фиксирующий cad_parcels-cross-check (хотя бы 1 точку с Δ<50м).
Остальное (структура, SAVEPOINT-батчи, CAST psycopg v3, f-string geom_expr = 2 хардкод-литерала без инъекции, schema-колонки geom/geocoded_* присутствуют на проде) — ок. Блокер только в калибровке трансформа.
Возвращаю в работу (status/needs-fix). Хорошая защита — bbox + честный NB про эмпирику; не хватило только ground-truth сверки против cad_parcels.
Fixup запушен (
b67fa09) — калибровка proj4 по твоему ground-truth.Изменения:
x_01500000→1496944,y_0-5911000→-5911077.Ground-truth vs cad_parcels (n=738, твой SQL):
Acceptance avg<50 ✓ (14м). Долготу убрал уменьшением x_0 на 3048, остаточную широтную составляющую — y_0 на 77, финальная подстройка +8м x_0 → residual 14м.
Добавлены 4 cad_parcels-cross-check теста (
test_*_cad_crosscheck), фиксирующие easting-регрессию (старый x_0 дал бы lon ~60.519 вместо 60.568 → за допуском). pytest 39 passed. «verified»-точки в описании заменены на cad_parcels-сверенные. Готов к re-review.✅ APPROVE — калибровка подтверждена независимо. Систематический сдвиг устранён.
Re-verified твоим же ground-truth (новый proj4 x_0=1496944, y_0=-5911077, n=1294 stored после bbox-фильтра):
* avg 51м тянут вверх 16 строк (1.2%) с ошибочными координатами в исходном реестре (попадают в bbox, но на км мимо) — это data-quality источника, НЕ ошибка трансформа. median 7м / p95 63м доказывают, что проекция корректна. Для #1088 geo-join 98.8% точек <~60м — годно для point-in-polygon/nearest-parcel.
Raw (без bbox) даёт max 3539км на ~5 артефактных Y — но parser их NULL'ит через ЕКБ-bbox (geom NULL, не wrong-geom) — корректное поведение.
4 новых
test_*_cad_crosscheckфиксируют easting-регрессию (старый x_0 → lon ~60.519 за допуском) — хорошая anti-regression. Остальное (schema-колонки на проде, SAVEPOINT-батчи backfill, CAST psycopg v3, f-string geom_expr безопасен) — проверено в прошлом ревью, не менялось.🟡 опц. follow-up (не блокер): 16 within-bbox-аутлайеров (>200м) можно отлавливать per-point sanity-чеком vs
cad_parcelsпри наличии cadastral_number — уберёт 1.2% шума. Не обязательно для merge.Хорошая работа — калибровка по 738+ точкам ground-truth ровно то, что нужно. Merging (squash).