Архив рубрики: карта

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

Мы посовещались и я решил, что выход в лес будет всё-таки в воскресенье — так будет лучше по ряду причин. Девятнадцатого марта часов в двенадцать буду на месте — и до вечера. Если не поленюсь — прибегу и в субботу часа на полтора (с 12:00 до 13:30) налегке, чтоб встретить тех, кто не увидел это объявление.

А в воскресенье — всё по-серьёзному, с мясом, гитарой и чаем. Самовар брать? 🙂

Карта

Место традиционное, рыжие указатели будут. Надеюсь, что шарики тоже не забуду.

Пять раз по восемь звёздочек

  1. КДПВ:
    40 звёздочек
  2. Традиции важнее суеверий, поэтому буду ждать гостей. Место традиционное, время — тоже: суббота после дня рождения, то есть 18 марта, часов после двенадцати. Буратиновка уже давно настоялась — ревизия выявила значительные запасы прошлых лет. Для разнообразия сделана и марганцовка смородиновка. Хотя я, наверное, буду за рулём. Для рулевых-беременных-кормящих-непьющих — чай и сок, если не поленюсь, то возьму самовар. Месяц назад на том же месте мы варили два глинтвейна — красный обычный и белый безалкогольный — можно повторить.
    Карта
  3. Вишлист придумывать лень — его вообще не существует :-). Всяким туристским, велосипедным, автомобильным, музыкальным и компьютерным штуковинам буду рад. Подаркам для юных туристят и их родителей — тоже. Придёте сами по себе — тоже хорошо.

Пробую ориентироваться по Maps.me

Поставил на телефон Maps.me — для сравнения. Теперь у меня на одном телефоне аж пять карт: кроме Мэпс.ми это OsmAnd (как и Мэпс.ми, на OpenStreetMap, хотя им можно и спутниковые снимки смотреть, и всякие веб-карты), 2GIS (потому что в городе он круче, чем OSM), Яндекс.Навигатор (ради просмотра пробок и прокладки маршрута c ними) и Google Maps (потому что он уже есть — телефон-то ведроидный). Сравниваю, в общем-то, с ОсмАндом — у них хотя бы общая картографическая основа.

Первое ощущение: Мэпс.ми проще и шустрее. Но карта у них какая-то неконтрастная и серая да и, похоже, её внешний вид никак не регулируется.

Карты maps.me на смартфоне CAT B15

Кроме того, подробные карты появляются слишком поздно: на масштабах 1:500000 (в 1 см 5 км) и крупнее. Для Европы или Юго-Восточной Азии это, может быть, и хорошо, но для Урала образуется зазор: начиная с масштаба 1:2000000 (в 1 см 20 км) детализация встроенной грубой карты уже мала: в таком масштабе легко можно сдвинуть карту на такое место, где не будет ни одного отображающегося на карте города, и приходится либо карту приближать, в надежде случайно попасть в нужное место, либо отодвигать, чтобы понять, где вообще ты находишься. Получается, авторам приложения надо сдвинуть границу переключения карт: либо для всех регионов разом, либо с учётом плотности имеющихся картографических данных.

Следующий этап — тестирование навигации: в Мэпс.ми есть два варианта прокладки маршрута: для автомобиля и для пешехода. Плюс — голосовые подсказки. Попробую проверить в ближайшие дни.

Karta ne po-russki

Недавно появилась задача — перевести карту студенческого городка на английский. Или хотя бы транслитерировать её, избавившись от кириллицы. Карта состоит из двух групп слоёв, в одной из них содержатся слои с маркерами, задаными яваскриптовым кодом — перевести их не составит труда, а вот растровый слой, подложку, поверх которой отображаются маркеры, перевести чуть сложнее — об этом сегодняшняя история.

Для того, чтоб иметь контроль над внешним видом подложки, не зависеть от размещающих тайлы (квадратные растровые фрагменты карт) сторонних сервисов, и не платить им денег в конце концов, тайлы генерируются из геоданных OpenStreetMap самостоятельно. OpenStreetMap для любого объекта может содержать множество имён — это и то, что хранится с ключом name — имя вообще, и int_name — международное имя, и куча имён с ключами вида name:ru, name:en, name:что_попало. Если делать тайлы с помощью TileMill, а свой стиль создавать на основе OSM Bright, то доступно только одно имя — name, однако в настройках сопоставления для imposm можно выбрать нужный язык — по умолчанию эта строка в файле imposm-mapping.py закомментирована:

set_default_name_type(LocalizedName(['name:en', 'int_name', 'name']))

Запускаем импорт, английские имена попадают в базу… Однако английских имён мало, сильно меньше, чем объектов с именами, записанными кириллицей.

Выхода из этой ситуации два — правильный и быстрый.
Правильный заключается в аккуратном переводе имён в OSM — слишком долго, да и неохота руками ковыряться.
Быстрый способ — не трогать OSM, а имена транслитерировать локально, в своём экземпляре базы данных. Так и поступим: создадим функцию транслитерации (прообраз подсмотрел на sql.ru) и выполним кучу UPDATE, вызывающих эту функцию. Мне, как перловому программисту, больше был симпатичен вариант с написанием перловой функции внутри PostgreSQL, но сразу такой вариант у меня не заработал, а разбираться было лень.

Итак, скармливаем постгресу такой код:

CREATE OR REPLACE FUNCTION ru_translit(p_string character varying)
  RETURNS character varying AS
$BODY$
-- Transliteration of Cyrillic letters
select
replace(
  replace(
    replace(
      replace(
        replace(
          replace(
            replace(
              replace(
                replace(
                  replace(
                    replace(
                      replace(
                        replace(
                          replace(
                            replace(
                              replace(
                                replace(
                                  replace(
                                    replace(
                                      replace(
                                        replace(
                                          replace(
                                            replace(
                                              replace(
                                                translate(
                                                  $1, 
                                                  'АБВГДЕЗИЙКЛМНОПРСТУФЫЭабвгдезийклмнопрстуфыэ',
                                                  'ABVGDEZIYKLMNOPRSTUFYEabvgdeziyklmnoprstufye'
                                                ),
                                              'ё', 'yo'),
                                            'ж', 'zh'),
                                          'х', 'kh'),
                                        'ц', 'ts'),
                                      'ч', 'ch'),
                                    'ш', 'sh'),
                                  'щ', 'shch'),
                                'ъ', ''),
                              'ь', ''),
                            'э', 'e'),
                          'ю', 'yu'),
                        'я', 'ya'),
                      'Ё', 'Yo'),
                    'Ж', 'Zh'),
                  'Х', 'Kh'),
                'Ц', 'Ts'),
              'Ч', 'Ch'),
            'Ш', 'Sh'),
          'Щ', 'Shch'),
        'Ъ', ''),
      'Ь', ''),
    'Э', 'E'),
  'Ю', 'Yu'),
'Я', 'Ya');
$BODY$
  LANGUAGE sql IMMUTABLE
  COST 100;

UPDATE osm_admin            SET name=ru_translit(name);
UPDATE osm_aeroways         SET name=ru_translit(name);
UPDATE osm_amenities        SET name=ru_translit(name);
UPDATE osm_barrierpoints    SET name=ru_translit(name);
UPDATE osm_barrierways      SET name=ru_translit(name);
UPDATE osm_buildings        SET name=ru_translit(name);
UPDATE osm_landusages       SET name=ru_translit(name);
UPDATE osm_landusages_gen0  SET name=ru_translit(name);
UPDATE osm_landusages_gen1  SET name=ru_translit(name);
UPDATE osm_mainroads        SET name=ru_translit(name);
UPDATE osm_mainroads_gen0   SET name=ru_translit(name);
UPDATE osm_mainroads_gen1   SET name=ru_translit(name);
UPDATE osm_minorroads       SET name=ru_translit(name);
UPDATE osm_motorways        SET name=ru_translit(name);
UPDATE osm_motorways_gen0   SET name=ru_translit(name);
UPDATE osm_motorways_gen1   SET name=ru_translit(name);
UPDATE osm_places           SET name=ru_translit(name);
UPDATE osm_railways         SET name=ru_translit(name);
UPDATE osm_railways_gen0    SET name=ru_translit(name);
UPDATE osm_railways_gen1    SET name=ru_translit(name);
UPDATE osm_transport_points SET name=ru_translit(name);
UPDATE osm_waterareas       SET name=ru_translit(name);
UPDATE osm_waterareas_gen0  SET name=ru_translit(name);
UPDATE osm_waterareas_gen1  SET name=ru_translit(name);
UPDATE osm_waterways        SET name=ru_translit(name);

Если мы добавляли номера домов на карту — транслитерируем и их заодно:

UPDATE osm_buildings SET "addr:housenumber"=ru_translit("addr:housenumber");

После чего можно запускать отрисовку своих тайлов — кириллицы там уже не будет.

Карта без кириллицы

Интерактивная карта Ильменки

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

Карта

Карта — OpenStreetMap, стиль отображения — свой собственный на основе OSM Bright, отрисованный с помощью TileMill, иконки — The Map Icons Collection. Библиотека для отображения — Leaflet c плагинами Leaflet-hash и Leaflet.fullscreen.

Схема с ёлками, если кому-то всё-таки нужна, спрятана под ссылкой, чуть ниже карты. Кроме того, при клике на кнопку с ромбами можно включить наложение этой схемы на карту.

В Сыктывкар и в Мурманск

Недавно Тёма Лебедев писал о том, что гугл отслеживает положение владельцев андроидофонов (тоже мне, удивил — это давно известно), затем тов. Ведмедь написал про то же самое.

Решил я посмотреть, что ж гугл узнал о моих шатаниях, глянул на карту — а там вончо:

Карта

Гугл с какого-то перепугу решил, что меня заносило в Сыктывкар и в Мурманск. Врёт.

Рельеф — в единых цветах

Когда я пробовал рисовать позиционную физическую карту, не сильно парился о точности соответствия цветов тем, что используются на остальных картах — тыкать пипеткой в соседние карты не хотелось. Приблизительно попал — и ладно, потом подправлю. Однако товарищи вики-географы не дремлют, шлют ссылки на правильные палитры. Хорошо, попробуем исправить.

Итак, список высот и соответствующих им цветов такой:

-10   167 223 210
0     172 208 165
100   168 198 143
200   189 204 150
300   209 215 171
400   225 228 181
500   239 235 192
750   232 225 182
1000  222 214 163
1500  211 202 157
2000  202 185 130
2500  195 167 107
3000  185 152  90
3500  170 135  83
4000  172 154 124
5000  186 174 154
6000  202 195 184
7000  224 222 216
8000  245 244 242
9000  245 244 242

Пересчитывать руками для того, чтоб использовать в Маперитиве — не наш метод. Наш метод — автоматизировать:

#!/usr/bin/perl

while (<>) {
    chomp;
    my @data = split;
    printf '%s:#%02x%02x%02x;',
        @data;
}

Ну или можно вообще однострочник написать:

perl -nla -F'\s+' -e 'printf "%s:#%02x%02x%02x;", @F' ramp-colors-above-water.txt

Осталось добавить получившиеся цвета к команде маперитива, рисующей рельеф:

generate-hypsometric ramps=-10:#a7dfd2;0:#acd0a5;100:#a8c68f;200:#bdcc96;300:#d1d7ab;400:#e1e4b5;500:#efebc0;750:#e8e1b6;1000:#ded6a3;1500:#d3ca9d;2000:#cab982;2500:#c3a76b;3000:#b9985a;3500:#aa8753;4000:#ac9a7c;5000:#baae9a;6000:#cac3b8;7000:#e0ded8;8000:#f5f4f2;9000:#f5f4f2

Эти цвета не такие насыщенные как те, что получились сначала. Южный Урал в этой палитре получается таким:

Рельеф Южного Урала

Карта с рельефом

Пару лет назад я пробовал рисовать карты из данных OpenStreetMap при помощи Maperitive — и даже что-то говорил об этом в докладе на UWDC-2013. Что понравилось ещё тогда — возможность «из коробки» отображать рельеф: Маперитив умеет сам ходить в сеть за открытыми данными о рельефе (SRTM) и потом строить из них контуры горизонтали и рисовать отмывку.

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

У меня не получилось сразу в Маперитиве получить карту такого вида как мне надо: реки текли поверх водохранилищ и водоёмы никак не хотели с административными границами сочетаться. Потратив немного времени на чтение документации и безуспешные эксперименты, пошёл другим путём: сделать пару отдельных карт — с границами и водами — да и собрал их воедино в Inkscape. Маперитив умеет экспортировать карты в SVG. Вот уменьшенный фрагмент того, что вышло:

Север Нязепетровского района

Шаблон с картой лучше делать не по инструкции — там образец неправильный. Лучше взять за образец какой-нибудь существующий шаблон и слегка его поменять: надо изменить координаты границ карты, её названия и имена используемых файлов. Если речь идёт об изготовлении карты актуального состояния существующей местности (то есть, мы рисуем не историческую карту и не карту вымышленного мира), то имеет смысл нарисовать несколько карт одной и той же области, хотя бы две: физическую и политическую/административную — википедия позволяет выбрать нужную карту из шаблона как вручную, так и автоматически: например, в географических статьях (о реках, озёрах, горах) автоматически отображается физическая карта, если она есть.

Пример статьи с этой картой — Шемаха (приток Уфы). В статье Шемаха (Челябинская область) используется тот же самый шаблон, но карта там уже другая — административная.

Двадцать шестой троллейбус вернётся на Первое озеро

С понедельника, 13 октября, сообщает Челябинск.ру меняется трасса движения троллейбусного маршрута № 26 — он снова будет ходить из Первоозёрного через центр города, улицы Братьев Кашириных и Чичерина к северо-западной конечной, на углу Комсомольского проспекта и Молдавской.

[map]55.19372,61.30144 55.187,61.2862 55.1735,61.30474 55.17879,61.31654 55.17875,61.3583 55.1709,61.35813 55.17093,61.37053 55.16757,61.38062 55.15975,61.38117 55.16124,61.43374 55.16017,61.4513 55.17022,61.4531 55.18117,61.44602 55.18387,61.45868 55.19298,61.4664 55.19056,61.47552[/map]

На марсрутах.ру уже опубликовано свежее расписание.

Трамвайная схема — можно и в TileMill

В марте я рисовал для википедии челябинскую трамвайную схему при помощи TileMill, однако как выделить трамвайные пути самим тайлмиллом, я не знал. Пришлось тогда экспортировать схему в SVG и затем редактировать полученный SVG-файл в Inkscape, вручную выделяя нужные рельсы и меняя им внешний вид.

На самом деле в том, чтоб TileMill нарисовал трамвайные пути, нет особо хитрой магии. Более того, даже не надо, пугаясь питона, ковырять imposm-mapping.py — трамвайные пути можно выделить при помощи CartoCSS, потому что для железных дорог сохраняется их тип:

SELECT DISTINCT type FROM osm_railways;
type
--------------
preserved
narrow_gauge
light_rail
subway
tram
rail

Стиль трамвайных путей можно задать в файле roads.mss. В OSM Bright все доро́ги: и железные, и обычные — слиты в один слой. Правила рисования дорог весьма витиеваты, поэтому, чтоб не тратить на эксперименты лишние усилия, мы не будем пытаться переопределить стиль трамвайных путей — вместо этого добавим новое правило, рисующее широкие красные линии поверх трамвайных путей, не трогая более ничего. Правило это надо поместить после правил, описывающих слой #roads_high:

#roads_high::tram_highlight [type='tram'] {
  line-width: 5;
  line-color: @tram_line;
  line-comp-op: darken;
}

Результат:

Схема трамвайных путей

Для того, чтоб убедиться в работоспособности метода, этого вполне достаточно.

Бросается в глаза отсутствие подсветки на мостах — связано это с тем, что слой #bridge находится выше, чем #roads_high. Возможный способ решения — завести свой слой железных дорог (а для этого надо уже́ лезть в imposm-mapping.py, но теперь это не страшно), поместить его выше слоя с мостами и написать для железнодорожного слоя свои стилевые правила.