В данный момент поддержка векторных карт в mapsoft находится в состоянии разработки. Еще не все сделано, возможны любые изменения.
Тут описан формат, в котором mapsoft2 может хранить наборы объектов: точек, линий, многоугольников и подписей, его преобразование в другие форматы, разные операции с ним. Для настоящей карты нужно иметь разную дополнительную информацию: название, границу, геодезическую привязку, правила рисования объектов, правила связи между объектами и т.п., однако полноценно этот уровень пока не сделан и делать его планируется отдельно. Тут описывается только работа с объектами. Некоторые форматы (например, MP) поддерживают разную дополнительную информацию о карте. Обычно низкоуровневые функции поддерживают чтение и запись этих полей, однако при преобразовании в другой формат это все должно теряться - здесь нас интересуют только объекты.
В mapsoft2 основных форматом является VMAP2. В mapsoft1 основным был текстовый формат VMAP - он до сих пор поддерживается, а с 2020 до 2022 -- база данных с гео-индексацией mapdb.
Для работы с векторыми картами используются программы ms2vmap (преобразование форматов и разные другии операции) и ms2vmapdb (разные операции с базой данных). Программа ms2render используется для рендера векторных карт.
См. vmap2/vmap2obj.h
Объект является типом dMultiLine, многосегментной линией. Используются координаты WGS84.
Объект содержит следующие дополнительные поля:
См. vmap2/vmap2.h
В mapsoft используется одно хранилище объектов VMAP2, которое, однако, может хранить объекты в двух видах: в виде простых STL контейнеров в памяти, или в базе данных BerkleyDB на диске (файл с расширением .vmap2db). Работа с хранилищем в памяти должна быть быстрее (не надо кодировать объекты для помещения в базу данных), однако при работе с базой данных на диске не тратится время на чтение и запись всех объектов.
В любом случае объекты хранятся в ассоциативном массиве с ключом типа uint32_t. Таким образом, у объектов появляется уникальный идентификатор, однако он должен использоваться только при работе с конкретным хранилищем. При преобразовании в другой формат (даже в текстовый формат VMAP2) эта информация теряется.
Параллельно с основным хранилищем строится база данных гео-идексации, которая тоже расположена либо в памяти, либо на диске (файл с расширением .map2gh). Ключ - комбинация из типа объекта (старший байт в начале!) и строки Geohash, значение - id объекта в основной базе. Записи с одинаковыми ключами допустимы. Один объект может присутствовать в нескольких записях (это позволяет записывать объект, пересекающий границу короткого геохеша, в виде двух записей с длинными геохэшами). Используя эту базу, можно быстро получить списов всех типов, или список всех объектов данного типа, или список всех объектов данного типа, находящихся в данном районе.
С точки зрения хранилища объектов никакой разницы между точками, линиями, площадными и текстовыми объектами нет. Различается только тип объекта. В данный момент не слишком хорошо определено, как должен обрабатываться точечный или текстовый объект, содержащий несколько координат. Должна ли использоваться только первая точка или все точки? Должны ли линии в текстовом объекте использоваться для рисования текста вдоль кривого контура?
Объекты не могут быть пустыми (не содержать координат). Такой запрет связан с невозможностью разместить объект в базе гео-индексации.
Объекты VMAP2 могут храниться в простом текстовом формате (файлы с расширением .vmap2). В файле объекты разделены пустой строкой. В начале идет строка с типом объекта, причем первый байт записывается в виде слова (point, line, area, text), а два последних -- в виде десятичного или шестнадцетеричного числа, отделенного двоеточием, например "line:0x211". После этого идет несколько строк вида "<тэг><пробел><значение>. В строковых значениях (name, comm, tags) символы \, \n, \0 заменены на \\, \\n, \\0. Выравнивание преобразовано в строки "SW", "W" и т.п. Координаты записаны в виде пар чисел (долгота и широта), разделенных пробелами. Многосегментные линии записаны в виде нескольких строк с тэгом crds. Как устроены тэги можно посмотреть в vmap2/vmap2obj.h, методы write() и read().
Все объекты в текстовом файле сортируются для удобства хранения в git и наблюдения за изменениями.
Объекты хранятся в BerkleyDB, в файле с расширением .vmap2db (вообще, mapsoft2 использует расширения файла, чтобы определить его формат). Ключ -- число uint32_t, значение -- запакованный объект: в начале записан тип объекта (uint32_t), потом идет последовательность в стиле RIFF: 4-символьный тэг ("crds", "name" и т.п.), 4-байтовое число - длина данных в байтах, данные. Для текстовых данных (название объекта, комментарии и т.п.) используется кодировка UTF8. Как устроены теги, можно посмотреть в vmap2/vmap2obj.h, методы :pack() и unpack().
База данных для гео-индексации - расположенный рядом файл с тем же именем и с расширением .vmap2gh. При отсутствии этого файла он создается заново (это не слишком быстрая операция), поэтому при каких-то проблемах с этим файлом его можно просто удалить.
В данный момент никакого окружения BerkleyDB не создается, каждый файл является независимой базой данных, одновременно работать с базой данный может только одна программа. В будущем при необходимости можно будет делать окружение с блокировками, логами, транзакциями... В базах данных используются только дефолтные функции сравнения ключей, поэтому все утилиты для работы с базами BerkleyDB (db_load/db_dump и т.п.) должны работать.
В данный момент не рекомендуется использовать базу данных для хранения реальных карт: формат еще не устоялся. Кроме того, сам я планирую хранить карты в текстовом формате (например, чтобы было удобно использовать git).
См. vmap2/vmap2types.h и пример файла vmap_data/types.cfg
При преобразовании в другие форматы и при создании новых подписей обычно требуется дополнительная информация о типе объекта. Она хранится в специальном текстовом файле и читается в структуру VMap2type со следующими полями:
type point:0x0F00 + name "триангуляционный знак" + fig_mask "2 1 0 2 0 7 57 -1 20 0.000 1 1 -1 0 0" + fig_pic "pics/trig.fig" + mp_end 1 + label_type 5 type text:5 + name "вершины" + fig_mask "4 0 0 41 -1 18 9 0.0000 4"
Обратите внимание, что размер шрифта в render.cfg - в пикселах (как в libcairo), для "естественной" привязки карты. А в параметре fig_mask - в типографских точках на картинке xfig. И шрифты и их размеры могут быть разными. Рекомендуется подобрать такое значение в fig_mask, чтобы подписи примерно совпадали. Например, если "естественное" разрешение карты 150dpi, то шрифт 10px будет примерно соответствовать размеру шрифта в xfig: 10px / 150px/in * 72pt/in = 4.8pt.
VMAP - текстовый формат хранения векторнных карт, использующийся в mapsoft1. До сих пор все исходники векторных карт хранятся в этом формате, хотя уже давно надо бы их преобразовать. Поддержка формата - в vmap/, преобразование в VMAP2 - в vmap2/vmap2io_vmap.cpp.
Основные отличия: в vmap2 подписи всегда отвязаны от объектов, в vmap была возможность хранить их как в объектах, так и отдельно, причем в реальности все подписи хранились в объектах. Размер подписей указывался в виде числе-добавки к номинальному размеру: -1, +2 и т.п. Это, конечно, очень неудобно, когда подпись отвязана от объекта, а "естественный размер" определяется только на этапе рендера.
Особенности преобразования VMAP в VMAP2:
Особенности преобразования VMAP2 в VMAP:
Описание формата: http://magex.sourceforge.net/doc/cGPSmapper-UsrMan-v02.4.pdf
Текст про поддержку формата в mapsoft2: ifdef(`',`',`https://github.com/slazav/mapsoft2-libs/tree/master/mp#readme')
Особенности преобразования MP в VMAP2:
Особенности преобразования VMAP2 в MP:
Векторный графический формат, который я использую для редактирования карт. В mapsoft2 есть расширение формата для хранения гео-привязки и работы с треками, точками, растровыми и векторныи картами. Самое первое, с чего начался mapsoft в 1998 году -- это простые скрипты на awk, позволяющие взять скачанные из gps-приемника геоданные и записать такой привязанный fig-файл. Потом можно было вручную подложить туда растровую карту, нарисовать еще треки и другим скриптом извлечь их для загрузки в gps.)
При записи в fig файл он всегда должен существовать заранее: оттуда будет взята привязка и объекты, не относящиеся к карте. Создать привязанный fig-файл можно программой ms2geofig. TODO: тут довольно много всего надо бы написать...
В библиотеке mapsoft2 имеется небольшой модуль для чтения формата OSM XML. Объекты типа node читаются в ассоциативный массив id - координаты, кроме того, читаются объекты point (node с непустыми тэгами), way и relation.
Поддерживается преобразование OSM XML в другие векторные форматы с помощью программ ms2vmap, ms2vmapdb. Для этого используется отдельный конфигурационный файл, который задается параметром --osm_conf. Формат файла пока не устоялся, сейчас читаются строчки типа "(point|way) <options&rt; <type1&rt; [<type2&rt;]". Здесь options - json объект, поля которого должны совпасть с тегами объекта, type1 - тип в который преобразуется объект, type2 (задается только для линий) - точечный тип в который преобразуется объект, если он слишком мал. Предельный размер задается командой "set min_size <value&rt;" в метрах и действет на все последующие записи в файле. Значение по умолчанию - 10м.
Пример:
way '{"highway": "unclassified", "tunnel": ""}' line:0x06
way '{"tunnel": "yes"}' line:0x16
point '{"natural": "cave_entrance"}' point:0x6601
Смотрите также файл vmap_data/osm.cfg.
В mapsoft2 есть возможность читать и писать файлы Shape с помощью библиотеки shapelib. Взаимодействие с форматом vmap2 пока не сделано, но, кажется, при необходимости это сделать несложно.
В mapsoft2 есть некоторая поддерсжка формате OCAD, но она пока не доведена до конца и не поддерживает взаимодействие с форматом vmap2.