Как нарисовать высотный график по GPX файлу

Материал из Туристский клуб НГУ
Перейти к: навигация, поиск
Пример высотного профиля маршрута


Сейчас многие группы берут на маршрут GPS-навигатор. По мере прохождения маршрута на навигаторе отмечается множество точек, и по возвращении в город нужно обрабатывать эту информацию. В частности, при написании отчёта встаёт вопрос, как нарисовать красивый высотный график с минимальными затратами. Хочется, чтобы на графике были отмечены важные точки, подписаны перевалы и ночёвки, и при этом не было лишней информации. И самое главное — чтобы не нужно было рисовать график вручную. Автор перепробовал несколько программ и веб-сервисов для построения графиков, но так и не получил удовлетворительного результата. В результате появилась программа, которая будет описана ниже. Программа была написана для личного использования, однако, возможно, пригодится и кому-нибудь ещё. Автор готов принять пожелания по улучшению программы, однако, желающим (и умеющим) не возбраняется делать это самим.

GPX Viewer

Сперва был написан небольшой скрипт, но затем он разросся до полноценной (более-менее) программы с графическим интерфейсом. В программе реализованы все функции скрипта, а также некоторые дополнительные возможности. В частности, можно построить высотный график по маршрутным точкам или трекам, добавить к точкам маркеры и подписи, посмотреть некоторую статистику по маршруту (километраж, набор/сброс высоты и т.д.). GPX Viewer имеет версии под Windows и основные дистрибутивы Linux, возможна также сборка из исходников.

Подробнее можно узнать здесь.

Главное окно с меню
Окно с графиком
Статистика по маршруту

О скрипте

Скрипт доступен для загрузки по ссылке.

Скрипт написан на языке Python, соответственно, для его использования нужен интерпретатор этого языка. В операционной системе GNU/Linux это не должно вызывать проблем (нужно только убедиться, что присутствуют модули matplotlib и matplotlib-tk). Пользователям же иных систем, таких как Windows, придётся установить его отдельно. Проще всего сделать это, воспользовавшись одной из сборок SciPy, например, Anaconda или Enthought Canopy. В случае установки стандартного Python нужно установить также модули setuptools, python-dateutil, pyparsing, six, numpy и matplotlib.

Скрипт рассчитан на привычный автору рабочий процесс: на привалах отмечаются маршрутные точки, затем полученные с навигатора файлы объединяются в один файл в формате GPX (именно такой используется, по крайней мере, современными навигаторами Garmin). Предполагается, что в файле записаны отдельные точки, а не треки, и эти точки имеют осмысленные названия (которые будут соответствовать подписям). Для преобразования файлов с маршрутными точками между разными форматами можно воспользоваться утилитой gpsbabel, которая имеет и веб-интерфейс.

Далее в качестве примера будет использоваться следующий GPX файл (лишние данные удалены):

свернуть/развернуть
<?xml version="1.0" encoding="UTF-8"?>
<gpx
  version="1.1"
  creator="GPSBabel - http://www.gpsbabel.org"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<time>2014-08-22T10:43:57Z</time>
<bounds minlat="39.634969000" minlon="72.305292000" maxlat="40.543309000" maxlon="72.800615000"/>
</metadata>
<wpt lat="39.892218000" lon="72.393594000">
  <ele>4309.083984</ele>
  <time>2014-08-07T11:55:26Z</time>
  <name>СТОЯНКА 7</name>
</wpt>
<wpt lat="39.886667000" lon="72.400451000">
  <ele>4473.322754</ele>
  <time>2014-08-08T02:27:09Z</time>
  <name>8-1</name>
</wpt>
<wpt lat="39.885458000" lon="72.402422000">
  <ele>4616.407715</ele>
  <time>2014-08-08T03:05:11Z</time>
  <name>8-2</name>
</wpt>
<wpt lat="39.885126000" lon="72.402978000">
  <ele>4667.305176</ele>
  <time>2014-08-08T04:26:22Z</time>
  <name>пер. СПАРТАКИАДЫ</name>
</wpt>
<wpt lat="39.884908000" lon="72.402787000">
  <ele>4656.387207</ele>
  <time>2014-08-08T06:07:27Z</time>
  <name>8-4</name>
</wpt>
<wpt lat="39.883345000" lon="72.407718000">
  <ele>4494.261719</ele>
  <time>2014-08-08T06:32:10Z</time>
  <name>ОБЕД 8</name>
</wpt>
<wpt lat="39.876370000" lon="72.427292000">
  <ele>4388.644043</ele>
  <time>2014-08-08T08:41:58Z</time>
  <name>8-6</name>
</wpt>
<wpt lat="39.875821000" lon="72.428038000">
  <ele>4392.935547</ele>
  <time>2014-08-08T09:31:01Z</time>
  <name>СТОЯНКА 8</name>
</wpt>
<wpt lat="39.873537000" lon="72.430549000">
  <ele>4500.077637</ele>
  <time>2014-08-09T02:07:27Z</time>
  <name>пер. ГЕЗАРТ ЛОЖНЫЙ</name>
</wpt>
<wpt lat="39.864556000" lon="72.420609000">
  <ele>4710.522461</ele>
  <time>2014-08-09T03:00:15Z</time>
  <name>9-2</name>
</wpt>
<wpt lat="39.864724000" lon="72.411830000">
  <ele>4938.497070</ele>
  <time>2014-08-09T03:56:38Z</time>
  <name>пик ГЕЗАРТ</name>
</wpt>
<wpt lat="39.873783000" lon="72.430544000">
  <ele>4490.993652</ele>
  <time>2014-08-09T05:07:01Z</time>
  <name>9-4</name>
</wpt>
<wpt lat="39.875929000" lon="72.427978000">
  <ele>4399.828613</ele>
  <time>2014-08-09T05:56:32Z</time>
  <name>ОБЕД 9</name>
</wpt>
<wpt lat="39.885035000" lon="72.445276000">
  <ele>4306.570801</ele>
  <time>2014-08-09T08:03:13Z</time>
  <name>9-6</name>
</wpt>
<wpt lat="39.893827000" lon="72.456177000">
  <ele>4414.516602</ele>
  <time>2014-08-09T08:54:53Z</time>
  <name>СТОЯНКА 9</name>
</wpt>
<wpt lat="39.896574000" lon="72.461154000">
  <ele>4560.119141</ele>
  <time>2014-08-10T02:07:28Z</time>
  <name>10-1</name>
</wpt>
<wpt lat="39.897004000" lon="72.462898000">
  <ele>4655.783203</ele>
  <time>2014-08-10T03:14:08Z</time>
  <name>пер. ВЫСОЦКОГО</name>
</wpt>
<wpt lat="39.898409000" lon="72.470240000">
  <ele>4502.219727</ele>
  <time>2014-08-10T04:28:00Z</time>
  <name>10-3</name>
</wpt>
<wpt lat="39.899101000" lon="72.475340000">
  <ele>4344.653809</ele>
  <time>2014-08-10T06:53:06Z</time>
  <name>ОБЕД 10</name>
</wpt>
<wpt lat="39.901255000" lon="72.487397000">
  <ele>4199.055176</ele>
  <time>2014-08-10T08:46:40Z</time>
  <name>10-5</name>
</wpt>
<wpt lat="39.904449000" lon="72.496047000">
  <ele>4096.484375</ele>
  <time>2014-08-10T09:33:40Z</time>
  <name>10-6</name>
</wpt>
<wpt lat="39.906010000" lon="72.504491000">
  <ele>4000.315674</ele>
  <time>2014-08-10T10:22:06Z</time>
  <name>10-7</name>
</wpt>
<wpt lat="39.904000000" lon="72.517871000">
  <ele>3945.649170</ele>
  <time>2014-08-10T11:08:25Z</time>
  <name>СТОЯНКА 10</name>
</wpt>
</gpx>

Применение скрипта

С помощью скрипта можно выполнять две операции: вывод в файл списка точек с их параметрами в определённом формате и построение высотных профилей. В обоих случаях вызов скрипта с указанием имени GPX файла осуществляется командой

  • В Linux
./gpxparser.py -i waypoints.gpx
  • В Windows
python.exe gpxparser.py -i waypoints.gpx

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

--skippoints SKIPPOINTS [SKIPPOINTS ...]

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

./gpxparser.py -i waypoints.gpx --skippoints Гостиница .*База.* Улица

Вывод списка точек

В этом случае нужно указать имя файла, куда будет записан список точек в формате CSV с разделением столбцов табуляцией, а также формат вывода. Делается это так:

./gpxparser.py -i waypoints.gpx -o waypoints.csv --outformat num name alt

В результате мы получим файл такого содержания (столбцы выровнены для удобства чтения):

1	СТОЯНКА 7		4309
2	8-1			4473
3	8-2			4616
4	пер. СПАРТАКИАДЫ		4667
5	8-4			4656
6	ОБЕД 8			4494
7	8-6			4389
8	СТОЯНКА 8		4393
9	пер. ГЕЗАРТ ЛОЖНЫЙ	4500
10	9-2			4711
11	пик ГЕЗАРТ		4938
12	9-4			4491
13	ОБЕД 9			4400
14	9-6			4307
15	СТОЯНКА 9		4415
16	10-1			4560
17	пер. ВЫСОЦКОГО		4656
18	10-3			4502
19	ОБЕД 10			4345
20	10-5			4199
21	10-6			4096
22	10-7			4000
23	СТОЯНКА 10		3946

Затем этот файл можно открыть в редакторе таблиц и вычислять интересующие параметры. Формат вывода в файл задаётся словами из списка:

  • num — порядковый номер
  • name — название
  • lat — широта
  • lon — долгота
  • alt — высота
  • dist — пройденное расстояние с горным коэффициентом 1,2
  • time — дата и время
  • timedelta — время с начала маршрута

Построение высотного профиля

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

./gpxparser.py -i waypoints.gpx -p profile.png
./gpxparser.py -i waypoints.gpx -s

Поддерживаются форматы PNG, PDF, PS, EPS, SVG и некоторые другие.

Настроить внешний вид графика можно с помощью опций, описанных ниже.

--includenames INCLUDENAMES [INCLUDENAMES ...]
--excludenames EXCLUDENAMES [EXCLUDENAMES ...]
Первые две опции управляют тем, какие точки будут иметь подписи на графике. Можно указать какие подписи включить, или, наоборот, какие исключить. Также поддерживаются регулярные выражения. Например, для включения только подписей стоянок и обедов можно указать
--includenames СТОЯНКА ОБЕД
А для исключения всех промежуточных точек
--excludenames .*-.*
--profilewidth PROFILEWIDTH
--profilecolor PROFILECOLOR
--fillcolor FILLCOLOR
Данные опции меняют толщину и цвет профиля, а также цвет заливки. Цвета можно задавать по имени или сокращению (green, r), по коду в шестнадцатеричном формате ('#FF0055'), либо в формате RGBA ('1,0,0', '0,1,0,0.3'). Например, для того, чтобы нарисовать профиль толщины 1.5 синим цветом с красной полупрозрачной заливкой, нужно указать
--profilewidth=1.5 --profilecolor=b --fillcolor=1,0,0,0.5
--specialmarkers SPECIALMARKERS [SPECIALMARKERS ...]
--markersformat MARKERSFORMAT [MARKERSFORMAT ...]
Следующие две опции позволяют отметить некоторые точки специальными маркерами. Вид маркеров задаётся по правилам, описанным здесь. Например, для того, чтобы отметить стоянки красным кругом, обеды — зелёным, а перевалы — синим ромбом, нужно указать
--specialmarkers СТОЯНКА ОБЕД пер --markersformat ro go bD
--splitlines SPLITLINES [SPLITLINES ...]
--splitformat SPLITFORMAT [SPLITFORMAT ...]
Аналогичные опции для рисования разделительных линий. Например, для разделения графика по ходовым дням красной пунктирной линией нужно указать
--splitlines СТОЯНКА --splitformat r--
--labelposition LABEL XPOS YPOS
Эта опция позволяет вручную задать положение подписей к некоторым точкам, если они перекрываются. К примеру, для смещения подписей к седьмой и десятой стоянкам можно указать
--labelposition СТОЯНКА.7 10 70 --labelposition СТОЯНКА.10 -10 10
--xaxis {dist,time}
Для того, чтобы откладывать по оси абсцисс не расстояние, а время, нужно задать
--xaxis time
--minalt MINALT
--maxalt MAXALT
Эти опции позволяют явно задать минимальную и максимальную высоту по оси ординат, если вариант по умолчанию не подходит.
--figsize FIGSIZE
Данная опция позволяет задать размер рисунка при сохранении в файл (по умолчанию используется 1280x1024).

Чтение опций из файла

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

--minalt         3800
--excludenames   .*-.*
--profilecolor   0,0,1,0.5
--fillcolor      1,0,0,0.3
--specialmarkers СТОЯНКА ОБЕД пер пик
--markersformat  ro go bD b^
--splitlines     СТОЯНКА
--splitformat    r-- 
--labelposition  СТОЯНКА.7 10 -70
--labelposition  СТОЯНКА.10 -10 10
--labelposition  пик 20 -40

Тогда мы получим график, показанный в начале статьи, выполнив команду

./gpxparser.py -i waypoints.gpx @format -s


Сальников Сергей

См. также

Как нарисовать высотный график при помощи gnuplot