[Заметка] Конвертирование SVG-координат в GPS-координаты

Дмитрий Филатов
Понадобилось мне как-то нанести план дачного посёлка с номерами домов на карту. Геодезисты дали топосъёмку. Ну, как топосъёмку... Просто сетку участков, выгруженную в графический файл *.bmp - вот такую примерно:
Эту сетку мне и требовалось наложить на карту. Задача показалась мне интересной, а решение - нетривиальным, поэтому решил опубликовать небольшую заметку о том, как я это делал.

1. Нам потребуется программа Inkscape. Открываем в ней исходную сетку в *.bmp и, используя её как подложку, обрисовываем при помощи инструмента "Кривые Безье" (Shift+F6). Важный момент: при импорте исходного изображения в Inkscape лучше использовать способ импорта "Встроить". Каждый участок (полигон) обрисовывается как самостоятельный объект, причём получившийся контур должен быть замкнутым (последнюю точку соединяем с первой). Включите прилипание (быстрая клавиша %). Если показать это на абстрактных фигурах, выглядит примерно так:

В конце должно получиться что-то такое - исходная сетка, обрисованная в векторе:

2. Теперь удаляем подложку. Просто щёлкаем в редакторе Inkscape на подложку, выделяя её, и удаляем клавишей Del. Результат - векторная сетка:

3. Сохраняем векторную сетку в SVG-файл. Можно открыть его в текстовом редакторе (я использую Notepad++) и убедиться, что каждый обрисованный объект представлен элементом типа path, вроде такого:
<path d="m26.880088 77.396587-4.830146-5.262719-.288368-2.234817-12.543959 7.641705 5.623155 11.030044z"/>
Обратите внимание: по-сути, у нас уже есть координаты всех объектов на плане, просто они в системе отсчёта SVG. Нам осталось только конвертировать их в географические координаты. А для этого требуются две опорные точки, для которых точно известно соотношение SVG- и GPS-координат. Я решил получить координаты центров двух участков и сопоставить их с географическими координатами центров этих участков.

4. Скачиваем и устанавливаем плагин "Centroid" для Inkscape: https://github.com/thedatachef/inkscape-centroid. Просто закиньте файлы centroid.inx и centroid.py в папку %AppData%\inkscape\extensions (если быть точным, то в папку, указанную в "Параметрах" Inkscape: меню Правка - Параметры - Системные - Пользовательские расширения).

5. Выбираем два объекта на нашей сетке, расположенные как можно дальше друг от друга. Выделяем первый объект, идём в меню Расширения - Создание из контура - Центроид. Применяем плагин. Получаем точку в центре объекта.

Если мы теперь сохраним SVG-файл и откроем его с помощью текстового редактора, то увидим новый элемент circle, примерно такой:
<circle r="1" fill="red" cy="130.481306584" cx="67.4109488025" />
Здесь нас интересуют координаты центра круга - cx и cy. По факту, это координаты центра участка в системе SVG. Повторяем со вторым объектом.

6. Получив таким образом и записав где-нибудь координаты центров двух противоположных участков, мы должны удалить красные кружочки из исходного SVG, чтобы они нам не мешались.

7. Далее, нужно вычислить географические координаты центров участков. Проще всего это сделать при помощи кадастровой карты, если эти участки на неё нанесены. Я использовал эту карту. Если там в строке поиска ввести кадастровый номер участка, отобразится табличка с информацией о нём, и в ней можно найти географические координаты центра участка (на вкладке "Подробно"). Вообще же, главное - найти объект, для которого точно известны координаты. Мне было проще работать с центрами участков, но в качестве таких точек можно использовать любые объекты, вроде углов участков (координаты которых можно измерить на месте обычным смартфоном с GPS) или фонарных столбов, сотовых вышек и т.д., в зависимости от масштаба плана.

8. Теперь добавим в SVG-файл информацию о сопоставленных координатах. Открываем SVG-файл с сеткой и внутрь тега <svg> вставляем такой код:
<MetaInfo xmlns="http://www.prognoz.ru"><Geo>
<GeoItem X="-595.30" Y="-142.88" Latitude="37.375593" Longitude="-121.977795"/>
<GeoItem X="1388.66" Y=" 622.34" Latitude="37.369930" Longitude="-121.959404"/>
</Geo></MetaInfo>
Здесь X и Y - это те самые координаты центра участка, которые мы получили с помощью плагина "Centroid" (cx = X, cy = Y), а Latitude и Longitude - реальные широта и долгота центра.

9. Все подготовительные работы завершены. Осталось только конвертировать координаты из одной системы в другую. В этом нам поможет инструмент svg2geojson. Для его установки потребуется node.js. Открываем командную строку, запускаем команду svg2geojson file.svg - и файл GeoJSON с координатной сеткой готов. Ну, а для создания, собственно, карты, можно использовать множество инструментов, работающих с GeoJSON. Я применил Leaflet, наложив сетку на карту OpenStreetMap. Получилось примерно так:
2020-01-01