Инструменты пользователя

Инструменты сайта


// Готовим растровую карту для навигатора Garmin GPSMap 62s

UPD 2013-11-16: обновил список программ, добавил информацию об автоматической обрезке рамок, добавил информацию о создании многослойного JNX. Убрал текст помеченный как удалённый. За остальными подробностями - в историю изменения страницы. Вики всё же :)

Задача: сделать растровую карту для навигатора Garmin GPSMap 62s.

Инструменты:

  • GDAL 1.8.0. С версии 1.10.0 научился конвертировать привязки OZI Explorer в виде .map + растр (.png, .gif и т.п.) в geotiff, рекоменду обновляться.
  • map2jnx 1.7.8. В последних версиях QLandkarteGT идёт в комплекте + уже с моими патчами для задания различного scale-factor для разных слоёв. Скачёк версии с 0.2.4 до 1.7 (или даже 1.6) случился как раз из-за включения в состав QLandkarteGT.
    • QLandkarteGT задепрекейчена в пользу новой программы от автора - QMapShack
    • Соответственно map2jnx теперь можно разжиться тут
  • QLandKarteGT или QMapShack - нужны для просмотра.
  • NEW: geocrop
  • NEW: ozi2map, опционально, если у вас GDAL младше 1.10.x и есть куча растров привязанных в OZI Explorer (.gif, .png, .jpg и т.д.)

Исходные карты в формате OZFX3 (Ozi Explorer) с готовой привязкой. Если нет привязанных карт, можно почитать тут как это сделать самому. Теперь можно брать любые озиковские привязки (кроме OZFX2 и новых шифрованных OZFX3), но только если у вас версия gdal больше 1.10.0, иначе можно воспользоваться утилитой ozi2map.

Конвертируем карту из OZFX3 в GeoTIFF

Для простых привязок OZI Explorer почти всё аналогично. Про использование ozi2map я писать не буду в виду простоты оной, а так же её неактуальности.

Про это я уже упомянул в своей прошлой заметке, теперь немного развернём, в частности, как исправить что бы проекция стала корректной для всех остальных программ. Буду приводить на примере конкретных имен файлов.

  1. Конвертируем карту в GeoTIFF:
    gdal_translate -of GTiff 200k--n57-21_ozf.map 200k--n57-21_ozf.tiff
  2. Карты внутри OZFX3 зачастую имеют индексированную палитру, поэтому сделаем из них RGB, что бы потом добиться прозрачности ненужных областей:
    pct2rgb.py 200k--n57-21_ozf.tiff 200k--n57-21_ozf-rgb.tiff
  3. Теперь исправим систему координат в нужную (датум Пулково 1942, элепсоид Красовского, проекция Гаусса-Крюгера (разновидность поперечно-цилиндрической проекции (Transverse Mercator)) для нужной зоны), при преобразовании укажем какой цвет использовать в результирующем изображении как nodata:
    gdalwarp -t_srs "EPSG:28427" -dstnodata "255" 200k--n57-21_ozf-rgb.tiff 200k--n57-21_ozf-rgb-fixed.tiff

    Дам немного пояснений: параметр EPSG, точнее номер, смотрится в базе EPSG, например тут или тут, для простоты же можно принять, что последние две цифры в номере и есть номер зоны листа, т.е. «EPSG:284##», где вместо «##» подставляется номер зоны, который, если нужно, дополняется лидирующим нулём (т.е. не «2», а «02»). Значение EPSG можно полностью заменить описанием проекции, как её считать, можно посмотреть в вышеприведённой статье про привязке генштабовских карт, или брать из тех же базах EPSG1). Отмечу только, что номер зоны так же легко узнаётся из номенклатурного листа, просто из номера вычитается 30, т.е. в нашем случае лист «n57», значит номер зоны:

    = 57 - 30 = 27

    Кроме того номер зоны легко узнаётся из километровой сетки: у полгого значения в километрах отбрасывается три последние цифты и остаётся номер зоны (на листе линии нумеруются двухзначным числом, но в левом верхнем углу, обычно, стоит небольшими цифрами что-то вроде 274, т.е. полное значение будет 27444, если на вертикальной линии стоит подпись 44, а номер зоны отсюда - 27). И всё-таки вынесу формулы расчёта центрального меридиана и номера зоны по прочим данным:

    lon_0 =* 6 - 3            # центральный меридиан по известной зоне
    Nз    = floor(lon / 6) + 1    # номер зоны по любому значению долготы на листе, floor - взятие целой части от деления
    Nз    = (lon_0 + 3) / 6       # номер зоны по центральному меридиану (частный случай)
    x_0   =* 1000000 + 500000 # мнимый восток (false easting)
  4. А теперь сделаем всё пространство, которое стало после предыдущего преобразования nodata полупрозрачным:
    gdalwarp -srcnodata "255" -dstalpha 200k--n57-21_ozf-rgb-fixed.tiff 200k--n57-21_ozf-rgb-result.tiff
  5. Сразу сохраним (на будущее) геоданные из файла:
    listgeo -no_norm 200k--n57-21_ozf-rgb-result.tiff > 200k--n57-21_ozf-rgb-result.geo

Все эти шаги объеденены в маленьком скрипте:

genshtab-ozfx3-to-geotiff.sh
#!/bin/bash
 
 
use()
{
    echo "Use: $0 <OziExplorer MAP file> [Gauss-Kruger Zone]"
}
 
if [ -z "$1" ]; then
    use
    exit
fi
 
inf="$1"
name=`basename "$inf" .map`
 
 
# convert ozfx to geotiff
tmp1=`mktemp`
gdal_translate -of GTiff "$inf" "$tmp1"
 
# convert pallete to RGB
tmp2=`mktemp`
pct2rgb.py "$tmp1" "$tmp2"
 
# Check zone or calculate it
if [ -z "$2" ]; then
    central_meridian=`gdalinfo "$tmp2" | grep "central_meridian" | sed 's|.*PARAMETER\["central_meridian",\([0-9.]\+\)\].*|\1|'`
    zone=`expr $central_meridian / 6 + 1`
else
    zone="$2"
fi
 
if [ -z "$zone" ]; then
    echo "Gauss-Kruger Zone for map don't set and I can't take it from source map. Please point it manually and try again."
    exit
fi
 
# format zone to two digit
zone=`printf "%.2d" $zone`
 
# EPSG data
# See: http://gisgeek.pdx.edu/webmapping/epsg.html
# See: http://nautilus.baruch.sc.edu/resources/mapserver/epsg
EPSG="EPSG:284$zone"
 
# Fix projection and coordinate systems
tmp3=`mktemp`
gdalwarp -t_srs "$EPSG" -dstnodata "255" "$tmp2" "$tmp3"
 
# Make transparency and produce map, also, save geodata to TXT
gdalwarp -srcnodata "255" -dstalpha "$tmp3" "$name.tiff"
listgeo -no_norm "$name.tiff" > "$name.geo"
 
rm -f "$tmp1" "$tmp2" "$tmp3"

Использовать очень просто:

./genshtab-ozfx3-to-geotiff.sh 200k--n57-21_ozf.map

В результате работы в этом же каталоге появятся два новых файла:

  • 200k–n57-21_ozf.tiff - привязанный GeoTIFF
  • 200k–n57-21_ozf.geo - геоданные из карты, для будущих преобразований.

Если же карту привязывали сами в QLandKarteGT, то для полученного в ней результата потребуется выполнить только шиги 4 и 5

Обрезка рамки

Ручная обрезка рамки. Только в ознакомительных целях

Ручная обрезка рамки. Только в ознакомительных целях

UPD 2013-11-16: тест ниже оставлен только для ознакомительных целей. Сразу переходите к разделу «Автоматическая обрезка рамки».

На этом этапе карта привязана, как нужно повернута, полупрозрачность добавлена, геоданные в отдельный файл сохранены. Теперь можно приступать к обрезке рамок.

Тут небольшое лирическое отступление: все рассмотренные мной инструменты, которые работают напрямую с GeoTIFF не позволяют вырезать произвольные области, а с gdalwarp и его опциями -cutline и -crop_to_cutline я пока так и не понял как работать: всё время получается пустой (полностью прозрачный) результирующий файл. По этой причине, Я решил, что нужно сохранить геоданные в файл, редактировать его в любом растровом редакторе (ГЛАВНОЕ НЕ МЕНЯТЬ РАЗМЕРА В ПИКСЕЛЯХ!!!) и потом копировать в результат сохраненные данные о привязке.

Итак, растровый редактор - GIMP и его инструмент «Лассо» (для произвольного выделения). Выделяем нужную область, раставляя точки в углах (этого, по большей части, достаточно). Когда область выделения будет замкнута, нужно инвертировать выделение (Ctrl+I) и нажать Del. После чего экспортировать картинку в тот же файл, в параметрах экспорта выбрать сжатие LZW и обязательно снять галочку с параметра «Сохранять значения цвета прозрачных точек».

После чего к сохранённому файлу (предполагаю, что перезаписан был тот же файл, что и открывался) добавляем данные привязки:

geotifcp -g 200k--n57-21_ozf.geo 200k--n57-21_ozf.tiff 200k--n57-21_ozf-croped.tiff

Всё, на этом шаге имеем привязанную карту с обрезанными полями.

Автоматическая обрезка рамки

Да, меня достала ручная обрезка и около года назад (на момент обновления статьи), при подготовке картографического материала для предстоящего похода по Кодару я написал маленькую утилиту geocrop, которая, используя номенклатурную информацию о листе карты, производит автоматическое определение нужной области и обрезку лишнего. Про саму программу можно почитать тут: geocrop. Там же примеры использования.

Склейка карт

Вышеприведённые шаги выполняем для нужного количества листов, дальше стоит, по логике, следующая задача: склейка карт.

Интуитивно просится для этой операции программа gdal_merge.py. Вот только в ходе своей работы она перезаписывает прозрачным цветом соседние изображения, как результат - слитые изображения разделены прозрачными полосами, причем, достаточно широкими. И тут приходят на помощь списки рассылок, достаточно добавить параметр «-n 0» и всё становится на свои места :) в результате команда для объединения выглядит примерно так:

gdal_merge.py -n 0 -o kamchatka-elizovo-rgb.tiff -co COMPRESS=LZW -co TILED=YES *-croped.tiff

В QLandKarteGT, при сборке атласа все карты тоже отлично сошлись, но с таким атласом можно работать только в самом QLandKarteGT (в можно прямо из него экспортировать в JNX, за подробностями - в документацию).

Всё, на этом шаге мы получаем большой склеенный GeoTIFF.

Генерация JNX

Для использования в моём навигаторе, нужно будет прошить его патченной прошивкой, которая снимает ограничение на использованием формата JNX, ссылки по этой теме накидаю несколько позже, сейчас же считаю, что навигатор готов к перевариванию этого формата карт.

У нас есть большой TIFF с привязкой, теперь его можно преобразовать в формат JNX, для этого потребуется утилита map2jnx, до недавних пор она пряталась в svn проекта QLandkarteGT, не имела официальной странички. Теперь же её версия скаканула с 0.2.4 до 1.7.8 и поставляется вместе с QLandkarteGT. Пользователям современных дистрибутивов и пользователям Windows теперь даже собирать ничего не нужно.

Собрается карта не просто, а очень просто:

map2jnx -n "Kamchatka. Elizovo" -m "Kamchatka. Elizovo" -c "Alexander Drozdov <hatred@inbox.ru>" kamchatka-elizovo-rgb.tiff kamchatka-elizovo.jnx

где:

  • «-n» задаёт имя карты
  • «-m» имя продукта (будет выводится в навигаторе при выборе карты)
  • «-c» данные о копирайте, предлагаю записывать сюда создателя карты, что бы иметь возможность к нему обратиться, вдруг если что.
  • kamchatka-elizovo-rgb.tiff - мой склеенный GeoTIFF
  • kamchatka-elizovo.jnx - результирующий файл. Скачать его можно тут2)

Просмотреть карту на компе можно в программе QLandKarteGT, правда отображается она там малость убого, но для общего представления вполне себе сгодится. В приборе отображается корректно.

Что бы карта увиделать в приборе, надо её забросить в каталог /Garmin/BirdsEye во внутренней памяти или на флешке.

Многослойный JNX

Выше мы сделали однослойный JNX, который будет смотреться хорошо (будет читабельным) только при каком-то одном увеличении. Весь же цимус JNX кроется в его многослойности, возможности для каждого режима увеличения прибора выбирать какой-то свой слой.

Логично, что для панорамного обзора лучше использовать карду 1:1 000 000, и делать масштам карты больше, по мере увеличения.

map2jnx это позволяет. Но в первых версиях была проблема: коэффициенты увеличения выбирались автоматически по формуле, по сути, взятой с потолка. После некоторого количества проб и ошибок, подобрать алгоритм вычисления коэффициента увеличения в зависимости от номенклатурного масштаба листа не получилось. Поэтому был сделан ход конём: добавилась опция командной строки, через которую можно задать коэффициенты увеличения JNX через запятую, каждый из которых будет использован для соотвествующей входной карты.

Итак, какие входные данные нам нужны? А нужно повторить все шаги до раздела (включительно) «Склейка карт» для карт разных масштабов, к примеру:

  • 1:1 000 000
  • 1:500 000
  • 1:200 000
  • 1:100 000
  • 1:50 000

При наличии автоматической резалки границ карт, это не должно занять много времени (только время на обработку карт).

Количество слоёв JNX ограничено 5, поэтому, возможно, придётся чем-то жертвовать.

Далее нужно выдать примерно такую команду:

map2jnx -p 1 -c 'Alexander Drozdov <hatred@inbox.ru>' -m Kodar -n 'Kodar 1M, 500k, 200k, 100k, 50k' -z 25 -x 78125,20834,7813,3125,1303 1M/merge/kodar-1M-pct.tif 500k/merge/kodar-500k-pct.tif 200k/merge/kodar-200k-pct.tif 100k/merge/kodar-100k-pct.tif 50k/merge/kodar-50k-pct.tif kodar-1M-50k.jnx

Она нам создаст многослойный kodar-1M-50k.jnx3) из набора склееных карт для разных масштабов. Интересна опция -x и цифры - это, собственно, и есть коэффициенты масштаба, выведены эмпирическим путём, хорошо подходят для прибора Garmin GPSMAP 62s. Более подробно в справке к map2jnx:

  -x Override levels scale. Default: autodetect

...

Scale levels must be pass in same order as level files pointed.
Empty and zero values equal to autodetect. We can point only needed
levels, like:
  -x 45356,,,75; -x ,,,,75
Calculated levels table can be found:
  English: http://whiter.brinkster.net/en/JNX.shtml
  Russian: http://whiter.brinkster.net/JNX.shtml
Most common values for different map scales:
  JNX scale              Map scale
  -------------          ---------
  78125-31250            1:1 000 000
  20834-7813             1:500 000
  7813-3125              1:200 000
  3125-2084              1:100 000
  2084-782               1:50 000
  782-32                 1:25 000
  32-21                  1:10 000
  21-14                  1:5000, 1:2000

Остальные опции описаны выше.

Выводы и результаты

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

Кроме того, чувствуется необходимость в фронт-энде к этим утилитам для более комфортного проведения операций обрезки и склейки карт.

UPD 2013-11-16: больше 2х лет прошло с момента публикации статьи, графических утилит так и не появилось, но появились инструменты для автоматического кропа и, как следствие, для практически полного скриптинга процесса конвертации и получения готового рузультата. Теперь, при наличии хороших источников привязанных карт, подготовка пятислойного JNX практически для любого района занимает не больше 1 часа времени на достаточно слабом нетбуке EeePC.

1)
Например тут: http://spatialreference.org/ref/epsg/284##/proj4/, где вместо ## ставим номер зоны - получаем параметры системы координат в виде набора параметров для proj4
2)
на 2013-11-16 ссылка битая, если кому срочно нужно: пишите на почту или в комментарии
3)
если кому нужно - тоже могу поделиться

Комментарии

Старые комментарии

[…] Готовим растровую карту для навигатора Garmin GPSMap 62s […]