Сделали расширение, которое вытаскивает координаты из НСПД, конвертирует EPSG:3857 → WGS84 и открывает точку в Яндекс/2ГИС/Google одним кликом. Под капотом — калибровка проекции и перехват SPA-навигации.

Работаем с НСПД ежедневно. Наш типичный сценарий:

  1. Нашли объект в кадастре

  2. Нужно посмотреть его на Яндекс.Картах (спутник, панорамы)

  3. Копируем координаты из URL — x=4366832.14&y=6748857.58

  4. Открываем конвертер EPSG:3857 → WGS84

  5. Копируем результат, вставляем в поиск карт

  6. Повторить 20-30 раз за день

Ежедневная боль: координаты в НСПД — Web Mercator (метры), а все привычные карты ждут градусы. Ручной конвертинг отнимает 10-15 секунд на каждый переход.

Сделали браузерное расширение для Chrome/Firefox, которое:

  • Парсит URL НСПД на лету

  • Конвертирует EPSG:3857 → WGS84 прямо в браузере

  • Показывает панель с готовыми ссылками на 5 сервисов

  • Обновляется при навигации по карте без перезагрузки

Техническая часть

Проекция: почему чистая математика не работает

Стандартная формула Web Mercator → WGS84 выглядит следующим образом:

const SEMI_MAJOR_AXIS = 6378137.0;

function webMercatorToWgs84(x, y) {
  const lon = (x / SEMI_MAJOR_AXIS) * 180 / Math.PI;
  const latRad = 2 * Math.atan(Math.exp(y / SEMI_MAJOR_AXIS)) - Math.PI/2;
  return {
    lat: latRad * 180 / Math.PI,
    lon
  };
}

Но проблема заключается в том, что НСПД использует слегка модифицированную проекцию. Чистая математика даёт погрешность 10-15 метров, а это критично.

Делаем калибровку:

// Берём объект с известными координатами
const CALIBRATION = {
  wgs84: { lat: 51.715703, lon: 39.227681 },      // Реальная точка
  nspd:  { x: 4366832.143757161, y: 6748857.580453986 }  // Что показывает НСПД
};

// Вычисляем поправочный коэффициент
const CAL_IDEAL_Y = Math.log(
  Math.tan(Math.PI/4 + (CALIBRATION.wgs84.lat * Math.PI/180)/2)
) * SEMI_MAJOR_AXIS;

const Y_SCALE_FACTOR = CAL_IDEAL_Y / CALIBRATION.nspd.y;

// Применяем в конвертации
function webMercatorToWgs84(x, y) {
  const lon = (x / SEMI_MAJOR_AXIS) * 180 / Math.PI;
  const yCorrected = y * Y_SCALE_FACTOR;  // ← ключевая строка
  const latRad = 2 * Math.atan(Math.exp(yCorrected / SEMI_MAJOR_AXIS)) - Math.PI/2;
  
  return {
    lat: latRad * 180 / Math.PI,
    lon
  };
}

В результате погрешность сводится к сантиметрам.

Расширение создаёт плавающую панель через Shadow DOM — стили изолированы, конфликтов с CSS НСПД нет:

const container = document.createElement('div');
container.id = 'nspd-extension-panel';

const shadow = container.attachShadow({ mode: 'open' });
shadow.innerHTML = `
  <style>
    /* Изолированные стили */
    :host { position: fixed; top: 80px; right: 20px; z-index: 9999; }
    .panel { background: white; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
    /* ... */
  </style>
  <div class="panel">
    <div class="coords">WGS84: ${lat}, ${lon}</div>
    <a href="https://yandex.ru/maps/?pt=${lon},${lat}" target="_blank">Яндекс</a>
    <a href="https://2gis.ru/geo/${lon},${lat}" target="_blank">2ГИС</a>
    <!-- ещё сервисы -->
  </div>
`;

В результате имеем панель с ссылками на Яндекс, 2ГИС, Google Maps, Google Earth, OSM. Работает при навигации без перезагрузки.


Полная статья с кодом и установкой: Расширение для НСПД — от идеи до релиза