Каждый, кто самостоятельно создаёт карты в Польском формате с помощью картографического редактора GPSMapEdit, периодически
сталкивается с вопросом распределения объектов по уровням детализации. Действительно, обычно карта создаётся на самом подробном уровне
детализации, а затем нужные объекты распределяются по уровням детализации. Существует несколько вариантов такого распределения, но все они не
очень удобны, особенно когда речь идёт о картах, содержащих большое количество различных объектов. Кроме этого, всегда хочется иметь возможность
гибко управлять таким распределением, не повторяя всё с самого начала.
Именно о таком способе реализации автоматического формирования уровней детализации и распределения по ним объектов пойдёт речь в данной статье.
В этом нам поможет многофункциональный конвертер mp2mp, созданный замечательным программистом Денисом Першиным (dyp).
В последствии он был доработан Юрием
Головешкиным (Hjugo). Именно этот конвертер
используется при работе с картами в проекте "Нарисуй карту".
В данной статье будут рассмотрены
все его основные возможности, которых вполне
достаточные для решения поставленных нами
задач.
Скачать конвертер и сопутствующие файлы можно со страницы Загрузки. В архиве, помимо конвертера, содержится рабочий
пример в виде карты, содержащей несколько объектов.
При описании всего процесса я буду использовать модульную структуру. То есть будет ставиться задача и описываться её решение. Как обычно, пойдём
от простого к сложному. На самом деле ничего сложного не будет. Может быть потребуется поверхностное представление о любом языке программирования
начиная от Basic. Но и тем, кто совершенно не представляет что такое команды и синтаксис программирования, не стоит волноваться потому что я буду подробно описываться
все шаги.
Общая схема конвертирования.
В целом весь процесс выглядит следующим образом.
Конвертер просматривает все папки, соответствующие определённым правилам. В этих папках находятся исходные карты в Польском формате с одним уровнем детализации. Это исходники. Они остаются неизменными. Далее анализируется файл, содержащий заголовок будущей карты и определяющий количество уровней детализации конечной карты и её общие настройки. Для каждого исходника может быть свой файл заголовка. Для определения правил распределения объектов по уровням детализации используется специальный конфигурационный файл. Именно он определяет вид будущей карты. В процессе работы конвертера в отдельной папке получается полностью готовый файл в
Польском формате, имеющий имя этой папки. Если папок с исходниками было несколько, то, соответственно, будет несколько файлов с именами этих папок. Если в конечной папке до этого уже был файл в именем нового файла, то старый файл без запроса заменяется новым.
Теперь рассмотрим весь процесс подробно. Практически все приведённые в данной статье параметры и имена файлов настраиваемые. Так что вы всегда сможете изменить их так, так вам будет удобнее.
Файлы запуска.
Так как сам конвертер mp2mp не имеет GUI и управляется из командной строки, то, для упрощения работы сделаны управляющие BAT-файлы, которые значительно упростят общую работу с конвертером. Таких файлов два. В нашем случае - go.bat и convert.bat. Сначала рассмотрим что содержит файл
go.bat. Именно его нужно запускать для начала
конвертирования. В нём всего одна строка:
for /d %%i in (?.*) do convert.bat %%i
Не вдаваясь в подробности, расшифрую только те фрагменты, которые можно произвольно изменять. Это маска для поиска папок с определённым именем. В нашем случае - "(?.*)". И команда запуска второго BAT-файла - "do convert.bat".
В маске для поиска папок с исходниками применяются стандартные виды запроса:
? - поиск любого одиночного символа. Например, (?-??) найдёт все папки типа N-37, K-14, Я-Ты;
* - поиск любой последовательности символов.
Так же может использоваться явное указание имени папки - (Taganrog).
В данном примере мной использована маска для нахождения папок с именем "г.Название города". Кириллицу в командах конвертер не понимает, но имена папок и файлов, написанные кириллицей, она воспринимает нормально.
Следующий файл в нашем случае "convert.bat". Это он запускается из строки "do convert.bat". Так что его имя тоже можно менять, не забыв изменить его имя в go.bat.
Посмотрим что в нём интересного:
cd %1
..\mp2mp.exe -h ..\%1\header.txt -m %1 ..\allocation.cfg ..\target\%1.mp
cd ..
Как видно из команд, именно здесь идёт формирование команды для запуска конвертера mp2mp. Так же кратко рассмотрим что здесь можно изменять и зачем.
..\%1\header.txt - путь к заголовку карты. Имя и путь можно менять. В данном случае каждая карта может иметь свой заголовок и, соответственно, количество уровней детализации и настройки целевой карты. Если, например, мы захотим иметь общие настройки заголовка для всех карт, то нам стоит изменить путь на "..\header.txt" и положить один этот файл вместе с конвертером mp2mp.
..\allocation.cfg - это тот самый конфигурационный файл, который будет делать основную часть работы. Как видно, так же можно сделать отдельным для каждой карты.
..\target\%1.mp - имя папки (в нашем случае - "target"), куда будут помещаться конечные карты.
В этим всё.
Заголовок карты.
Заголовок карты содержится в файле "convert.bat" и является совершенно стандартным для Польского формата. Вот типичный пример:
Не буду расписывать что всё это означает. Для тех, кто не знает, настоятельно рекомендую прочитать отдельную
статью про структуру и составляющие карт в Польском формате.
Отмечу лишь один момент. Если написать имя карты так - "Name=$", то её название будет соответствовать имени папки с исходниками для данной карты. Это очень удобно, когда файл заголовка используется для множества карт.
Распределение объектов.
Теперь наступает момент, ради которого и писалась данная статья. Именно в этой части мы будем ставить задачи и описывать методы их решения. Как было сказано ранее, наш конфигурационный файл называется "allocation.cfg". Это обычный текстовый файл, содержащий необходимые указания. Именно эти указания обрабатывает конвертер mp2mp. C помощью этого конфига мы и будем создавать нашу конечную карту. Сразу скажу, что занятие это очень увлекательное. И к тому же экономит кучу времени. Но прежде чем им пользоваться, нужно сначала его сделать. Начнём.
После каждой строки после символов "//" я буду писать комментарий. Кстати, рекомендую
использовать этот приём и в реальной работе. Комментарий будет только к тем
участка кода, которые ранее не расшифровывались. Ниже могут быть некоторые пояснения.
1. Определим начальные параметры.
file "source.mp" { // Определяем имя исходного файла
export=false;
// Запрещаем перенос объектов без условия
}
// Заканчиваем действие команды "file"
Примечание: Как видно, все исходные карты, лежащие в обрабатываемых папках, в данном случае должны иметь имя "source.mp".
Все команды обработки сделуют в пределах
действия этой команды, как показано ниже.
2. Перенести все объекты типа "0x2" в конечную карту.
file "source.mp" {
export=false;
case type=0x2 {
// Условие: Если тип объекта "0x2" то...
export=true;
// ... то объект переносится в конечную карту.
}
}
Примечание: Легко заметить, что такая конструкция
опасна своей неоднозначностью, потому что объекты типа "0x2" есть как среди полигонов, так и среди линий. Каждая команда "case" начинает своё действие с символа "{" и заканчивает "}". Очень внимательно за этим следите.
3. Перенести в конечную карту только линии типа "0x2".
file "source.mp" {
export=false;
case type=0x2 {
case kind=line { // Условие: Только для линий.
export=true;
}
}
}
Примечание: Допускается использовать только значения - polygon, line, point.
4. При переносе объекта присвоить ему имя.
file "source.mp" {
export=false;
case type=0x2f01 {
case kind=point {
label="АЗС";
// Присвоение имени "АЗС" точкам типа "0x2f01"
export=true;
}
}
}
Примечание: При этом стирается текущее имя объектов.
5. При переносе объекта присвоить ему имя только в том случае, когда его нет.
file "source.mp" {
export=false;
case type=0x2 {
case kind=line {
case label="" {
// Условие: Если поле имени объекта не пустое.
label="АЗС";
// Присвоение имени "АЗС" точкам типа
"0x2f01"
export=true;
}
}
}
}
Примечание: Допускается только два значения - Равно (=) или Не равно (!=).
6. При переносе объекта добавить к имени объекта произвольный текст.
file "source.mp" {
export=false;
case type=0x0a {
case kind=line {
label+=" зимник";
// К названию дороги добавляется текст " зимник".
export=true;
}
}
}
7. Изменить тип объекта на другой.
file "source.mp" {
export=false;
case type=0x52 {
case kind=polygon {
type=0x82;
// Тип "0x52" изменяется на "0x82"
export=true;
}
}
}
8. Задать верхнее значение уровня детализации, до которого будет виден объект.
file "source.mp" {
export=false;
case type=0x52 {
case kind=polygon {
type=0x82;
layer_max=1;
// Объект будет виден на первом и втором уровнях детализации.
export=true;
}
}
}
Примечание: По умолчанию все объекты переносятся только на первый уровень
детализации.
9. Задать нижнее значение уровня детализации, до которого будут виден объекты.
file "source.mp" {
export=false;
case type=0x52 {
case kind=polygon {
type=0x82;
layer_min=1;
// Объект будет виден только на втором уровне детализации.
export=true;
}
}
}
10. Задать диапазон видимости объектов в уровнях детализации.
file "source.mp" {
export=false;
case type=0x52 {
case kind=polygon {
type=0x82;
layer_min=1; // Объект будет виден только на втором
...
layer_max=2;
// ... и третьем уровнях детализации.
export=true;
}
}
}
11. Преобразовать полигоны в линии.
file "source.mp" {
export=false;
case type=0x2 {
case kind=polygon {
kind=line;
// Объект преобразуется в линию.
type=0x45;
export=true;
}
}
}
Примечание: Допускается преобразовывать полигоны в линии и точки. При этом точка ставится в центре полигона. Преобразование линии в
полигон и точку тоже возможно. В одной секции "file" дважды обработку для одного типа делать нельзя. В этом случае нужно создавать ещё одну такую же секцию.
12. Распределить полигоны по уровням
детализации в зависимости от их площади..
file "source.mp" {
export=false;
case type=0x40 {
case kind=polygon {
case area <= 1000 { // Если
площадь полигона меньше или равна 1000,
layer_max=1;
// ... то объект виден до второго уровня
детализации включительно.
}
case area > 1000 { // Если
площадь полигона больше 1000,
layer_max=2;
// ... то объект виден до третьего уровня
детализации включительно.
}
export=true;
}
}
}
Примечание: Значение "area"
берётся из автоматически рассчитываемого
атрибута "; RAREA=" расположенного в
комментарии к объектам.
13. Обработка [Restrict].
Новая версия mp2mp теперь
позволяет иметь в картах данные о дорожном
графе. Всё, кроме секций ограничения
поворотов [Restrict], обрабатывается
по умолчанию. Для включения в конечные
карты этих секций ограничений поворотов
необходимо добавить следующие команды:
file "source.mp" {
export=false;
case type=0x52 {
case kind=line {
export=true;
}
}
case kind=Restriction {
export=true;
}
Примечание: Все остальные атрибуты,
связанные с дорожным графом, переносятся
автоматически. При любом количестве
уровней детализации конечной карты, данные
о дорожном графе располагаются только на
первом (самом подробном) уровне детализации.
Чтобы избежать проблем, связанных с
генерализацией при конвертировании,
значения уровня детализации для исходной
карты и первого уровня детализации в
конечной карте, должны быть идентичными.
14. Обработка данных секций [Countries],
[Regions], [Cities], [ZipCodes].
Наконец-то преодолено
последнее ограничение на использование
конвертера mp2mp. Теперь им можно
обрабатывать карты со всеми применяемыми
атрибутами. Передача данных о секциях
данных для поиска производится точно так же,
как и данные об ограничениях поворотов:
case kind=Countries {
export=true;
}
case kind=Regions {
export=true;
}
case kind=Cities {
export=true;
}
case kind=ZipCodes {
export=true;
}
Примечание: В данном случае существует
два очень важных условия:
1. Если в конфигурационном
файле прописаны на обработку несколько
файлов, то данные о поиске должны быть
только в одном из них.
2. Файл с данными о поиске
должен обрабатываться первым.
15. Применение произвольных
дополнительных атрибутов.
При сборке карт с помощью
конвертера mp2mp есть возможность учитывать
некоторые дополнительные, произвольно
задаваемые, атрибуты. Такие атрибуты должны
быть расположены в полях комментария. Метод сборки
карты с применением дополнительных
атрибутов, раскрывает практически
безграничные возможности её автору, так как
в данном случае становится возможно делать
собственные классификаторы произвольного
количества объектов и их характеристик, и
учитывать эти данные при формировании
конечной карты.
Приведу пример. Необходимо распределить
все высотные дома до второго уровня детализации,
пятиэтажки до первого, а все здания с
количеством этажей менее пяти, оставить на
нулевом уровне. Если использовать один и тот же
тип (0x6c - Жилое здание) для всех таких
объектов, то сделать такой анализ можно
только по присутствию дополнительного
элемента описания. Таким элементом может стать,
например, атрибут "HouseHeight", а
параметрами: High - для высотных зданий, Medium -
для пятиэтажек. Для малоэтажных домов, в
данном случае, параметр нужен не будет. Записываются эти
данные для каждого объекта в поле
комментария в таком виде: для высоток - ;
HouseHeight=High, для пятиэтажек - ; HouseHeight=Medium.
Количество атрибутов к одному объекту не ограничено.
Код обработки в данном случае может иметь
такой вид:
file "source.mp" {
export=false;
case type=0x6с {
case kind=polygon {
case attr "HouseHeight"="Hight" {
layer_max=2;
}
case attr "HouseHeight"="Medium"
{
layer_max=1;
}
export=true;
}
}
}
Примечание: Возможность
присвоения параметров дополнительным
атрибутам так же поддерживается. Есть
несколько дополнительных атрибутов,
которые обрабатываются автоматически. К
таким атрибутам относятся:
1. StreetName - присваивает значение
основному атрибуту названия улицы (StreetDesc);
2. House - присваивает значение
основному атрибуту номера дома (HouseNumber).
16. Удаление атрибутов.
Необходимость удалить
некоторые атрибуты возникает достаточно
редко. Обычно в этом случае берётся
подходящий текстовый редактор и путём
поиска/замены удаляется всё ненужное.
Однако если это всё таки нужно, то конвертер
mp2mp может сделать это автоматически.
Просто нужно в конфигураторе
записать следующее:
file "source.mp" {
export=false;
case type=0x6с {
case kind=polygon {
label="";
// Удалить имя объекта и сам атрибут Label.
export=true;
}
}
}
Ограничения.
Все основные данные Польского
формата в настоящее время нормально
обрабатываются конвертером. Если
конвертер вдруг отказывается работать, то
нужно посмотреть на формируемое им
сообщение об ошибке. Там будет указана
строка исходника карты или конфигуратора,
которая вызвала данную ошибку. Удобнее всего это
делать в FAR.
Заключение.
В данной статье рассмотрены
все возможности конвертера mp2mp. Они
позволят Вам очень гибко управлять конечным видом своей карты. При этом всегда есть возможность оперативно что-либо изменить. Очень легко делать тематические карты. Время, затраченное на создание конфигурационного файла с лихвой окупается впоследствии.
Возможно в дальнейшем появятся ещё несколько очень интересных функций, которые позволят делать более качественную генерализацию при формировании конечной карты.
Если это произойдёт, то я обязательно опишу
эти возможности в данной статье.
Графическая
оболочка к конвертеру.
Силами
Ильи Воронкова
(ipr@tdutn.com.ua)
был создан вариант графической
оболочки к конвертеру mp2mp. Пока это только
бета версия, но она содержит всё
необходимое для создания очень сложных
конфигураторов. Скачать эту оболочку можно
со страницы "Скачать".
Благодарности:
Денису
Першину (dyp).
Юрию Головешкину (Hjugo).
Илье
Воронкову.
Игорю Брежневу
(IgorA100).
Дата: 16.04.2006г. Дополнение: Распределение объектов п.12,
Ограничения.
Дата: 23.04.2006г. Заменён
конвертер mp2mp.
Дата: 01.09.2006г. Дополнение: Команды для
обработки атрибутов дорожного графа.
Заменён конвертер mp2mp.
Дата: 08.09.2006г. Дополнение: Применение
произвольных дополнительных атрибутов.
Дата: 22.09.2006г. Дополнение: Удаление
атрибутов.
Дата: 20.02.2007г. Дополнение: Команды для обработки
секций поиска. Заменён конвертер mp2mp.
Дата: 24.04.2007г. Дополнение: Добавлен раздел о
графической оболочке для конвертера mp2mp.
Дата: 29.08.2007г. Дополнение: Добавлена
поддержка Numbers, типа Background, RouteParamExt и
RouteParams, блока Districts и атрибута DistrictName. Заменён конвертер mp2mp.
Дата: 24.12.2008г. Дополнение: Добавлена
поддержка атрибутов "Zip", "HLevel",
возможна конструкция attr "type"=type, имена атрибутов сравниваются без учета регистра.
Заменён конвертер mp2mp.