opentopomap.cz – топографические карты opentopomap для наших условий

Если вам не трудно, добавьте пожалуйста на стороне веб-сервера заголовок Access-Control-Allow-Origin: *
Браузеры стали довольно капризны и для краткосрочного сохранения тайлов через leaflet и оффлайн плагины требуется такое разрешение. Это немного снизит нагрузку на ваш сервис за счёт меньшего количества обращений. И ещё раз спасибо за такой прекрасный рендер!

UPD: суть проблемы: https://github.com/MazeMap/Leaflet.TileLayer.PouchDBCached#cross-origin-resource-sharing

Добавил.

Есть ли возможность выделить отдельно покрытие дорог?
Например вот здесь: https://opentopomap.ru/#map=18/53.90307/27.29177 вся дорога выделена желтым из чего можно сделать вывод, что это асфальтовая дорога. Однако это не так. Левая часть это гравейка. Это хорошо видно например на карте OpenHikingMap на ресурсе https://gpxstudio.github.io/. И это действительно так, живу я рядом. :slight_smile:

Хоть пока и не спрашивали “зачем”, отвечу: на велике зимой катать.
По асфальту жутко неинтересно и опасно.
По лесным дорогам невозможно.
Зато по гравейкам самое то.
И я испытываю определенные трудности в поиске новых гравеек, где я еще не катался, коих становится все меньше и меньше.

В качестве фильтра для поиска гравеек думаю можно использовать вот такую строку:
“surface=compacted|gravel|raw|winter|unpaved”.

Я думал об этом, но пока не понял, как это можно красиво и функционально сделать.

Правило с жёлтой заливкой работает только для дорог типа unclassified.

Для вашей задачи очень подходит https://overpass-turbo.eu/.

Почему не скопировать уже сделанное на OpenHikingMap?
Если такая карта будет, то ее можно будет использовать в навигаторе. :slight_smile:

За ссылку спасибо. Это то что нужно.
Для ПК это отличное решение.

И теперь стало понятно, что увидев нужное покрытие я свою задачу не решу. Потому как очень много неточностей. Много где нарисован асфальт, которого нету и никогда не было. Или лесные дороги, показываются как дороги с покрытием. :slight_smile:

Если вы имеете ввиду http://maps.refuges.info/ (единственное работающее, что я нашёл по ключевому слову OpenHikingMap), то в её легенде нет поддержки тега surface для дорог (https://wiki.openstreetmap.org/wiki/Hiking/mri#Map_Legend), поэтому я не понял, что у неё можно скопировать.

Судя по вот этой статье: “https://wiki.openstreetmap.org/wiki/Hiking/mri” OpenHikingMap это есть старое название проекта OpenTopoMap.

В OpenHikingMap дороги же раскрашиваются в зависимости от покрытия, значит такая информация каким то образом хранится.

Для оверпаса написал запрос:

[out:json][timeout:25];
// gather results
(
// query part for: ““дорога НЕ асфальт””
way[“highway”=“tertiary”]“surface”=“gravel”;
way[“highway”=“tertiary”]“surface”=“compacted”;
way[“highway”=“tertiary”]“surface”=“unpaved”;
way[“highway”=“tertiary”]!“surface”;
);
// print results
out body;

;
out skel qt;

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

Вдруг кому то еще пригодится.

Это не соответствует действительности.

Почему бы не сделать как на советских топокартах: символ “А” в подписи — асфальт, “Щ” — щебень, “Г” — гравий? И заодно индексы дорог “щитом” оформить.

Потому что, например, в населённых пунктах это будет излишняя, и даже мусорная информация. Там актуальнее названия улиц. Но дороги населённых пунктов и за их пределами при рендеринге не отличить, поскольку эта информация в базе не хранится. Нужен очень ресурсоёмкий препроцессинг, который точно лишит возможности обновлять базу раз в день.
По этой же причине нельзя, например, все асфальтовые дороги залить жёлтым, а грунтовые и гравийные - белым. Тут же пожелтеют все города. Худо-бедно, да и то не всегда, это получается с unclassified, поскольку их сравнительно нечасто используют в российских городах.
Я считаю это недостатком базы openstreetmap. В своё время надо было предусмотреть тег, обозначающий, относится ли дорога к населённому пункту, или же нет. Хотя бы для таких случаев.

Относится ли дорога к населенному пункту несложно определить по вхождению в полигон place=*. Ограничения скорости в навигаторах работают именно по этому принципу и в подавляющем большинстве случаев работают достаточно хорошо.

Одни только операции по объединению смежных полигонов леса и воды, чтобы были красивые границы, по статистике занимают около 40% по загрузке процессора от всех выборок, несмотря на то, что работают только начиная с 14-го зума. Если ещё пытаться тут же определять входжения, то сервером можно будет отлично отапливать помещение, но не рендерить в реальном времени. Кроме того, тут нужно не просто определять признак пересекает/нет, но и вычислять участки пересечения и рисовать их отдельно, поскольку никто не обязует маппера резать дороги по границам населённых пунктов.
Навигатору не надо рендерить большие площади, плюс информация может быть подготовлена заранее при создании графа дорожной сети и т.п.

в навигаторах? а в каких? В Османде и мопсе, например, это не работает.

У вас что-ли в реальном времени все это рендерится? Вообще без препроцессинга и генерализации? O_o

Объединения полигонов - да. Поскольку они делаются только на квадрате выборки. Объединить смежные полигоны по всей базе заранее - это утопия, как по ресурсам (по explain’у там какие-то фантастические величины), так и по эффективности дальнейшего использования, поскольку тогда при выборке даже маленького участка может выбираться огромный объединённый и совсем не нужный полигон.

Надо полагать, что 90% дорог вне НП и отрабатываться должна в момент. А уж дорог выходящих из НП и которые надо порезать, можно посчитать по пальца.

Нагрузку можно прикинуть на практике. Возьмём прямоугольную область, например, на северо-западе Московской области и посмотрим, сколько времени нужно на обработку запросов по поиску участков дорог внутри полигонов place=* и вне их, и сравним с операцией, по которой уже есть общая статистика загрузки, применив её к той же площади.

Фильтрацию возьмём простейшую, на каждом этапе не будем обрабатывать только highway=track.
Сначала выберем все дороги, не проходящие через place=*, а также типа highway=track.

explain (analyze) select planet_osm_line.way from planet_osm_line, planet_osm_polygon where planet_osm_polygon.place is not null
 and planet_osm_polygon.way && st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 56.080593, 37.224936 55.694698)',4326)),
 4326), 3857) and planet_osm_line.highway is not null and planet_osm_line.way &&
 st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 56.080593, 37.224936 55.694698)',4326)), 4326), 3857) and ( not
 st_intersects(planet_osm_line.way, planet_osm_polygon.way) or planet_osm_line.highway = 'track');
[skip]
 Planning Time: 7.783 ms
 Execution Time: 9868.915 ms
(20 строк)

Потом выберем все части дорог внутри полигонов place=*.

opentopomap=# explain (analyze) select st_intersection(planet_osm_line.way, planet_osm_polygon.way) from planet_osm_line, planet_osm_polygon
 where planet_osm_polygon.place is not null and planet_osm_polygon.way && st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133
 56.080593, 37.224936 55.694698)',4326)), 4326), 3857) and planet_osm_line.highway != 'track' and planet_osm_line.way &&
 st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 56.080593, 37.224936 55.694698)',4326)), 4326), 3857) and
 st_intersects(planet_osm_line.way, planet_osm_polygon.way);
[skip]
 Planning Time: 5.914 ms
 Execution Time: 8477.381 ms
(17 строк)

И в конце выберем отрезки дорог, “торчащие” из населённых пунктов:

opentopomap=# explain (analyze) select st_difference(planet_osm_line.way, planet_osm_polygon.way) from planet_osm_line, planet_osm_polygon
 where planet_osm_polygon.place is not null and planet_osm_polygon.way && st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 
56.080593, 37.224936 55.694698)',4326)), 4326), 3857) and planet_osm_line.highway != 'track' and planet_osm_line.way && 
st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 56.080593, 37.224936 55.694698)',4326)), 4326), 3857) and
 st_intersects(planet_osm_line.way, planet_osm_polygon.way);
[skip]
Planning Time: 8.060 ms
 Execution Time: 8801.962 ms
(17 строк)

И теперь сравним это, например, одной из операций объединения полигонов леса на той же области:

opentopomap=# explain (analyze) select ST_Union("way") as "way","natural",landuse,leaf_type from (SELECT "way","natural",landuse,leaf_type FROM
 planet_osm_polygon WHERE "natural" = 'wood' or landuse IN ('wood', 'forest')) AS landuse where way && 
st_transform(ST_SetSRID(box2d(ST_GeomFromText('LINESTRING(36.464133 56.080593, 37.224936 55.694698)',4326)), 4326), 3857) group by 
"natural",leaf_type,landuse;
[skip]
 Planning Time: 0.464 ms
 Execution Time: 12697.379 ms
(14 строк)

Про последнюю операцию по статистике известно, что она занимает около 11% процессорного времени от всех других операций.
Операции выборки дорог в сумме заняли чуть больше 27 секунд, сшивка полигонов - около 13. То есть первые операции длились более чем в два раза дольше одной из самых ресурсоёмких операций при рендеринге, при том, что была применена только простейшая фильтрация.
Но полигоны сшивать необходимо, так как иначе в лесу появляются артефакты, дезориентирующие пользователя, чего не скажешь о дорогах.

Но, изучив подробнее ситуацию с дорогами, я понял, что можно доработать существующую цветовую схему маркировки дорог без ущерба для общего дизайна карты и лёгкости её прочтения, при том, что будет более полно учитываться тип покрытия и не будет сильно загружаться база. Для этого для дорог типа tertiary и secondary нужно сделать заливку цветом в зависимости от типа покрытия, как это уже сделано для дорог типа unclassified, но с небольшим отличием - если вообще нет тега surface, то оптимистично заливать дорогу жёлтым, а не белым. Тогда за пределами населённых пунктов, если все теги проставлены правильно, можно будет точно сказать, что “жёлтые дороги” - с твёрдым покрытием, “белые” - нет. Твёрдым считается покрытие, когда surface = ‘paved’ , ‘asphalt’, ‘concrete’ , ‘paving_stones’, ‘sett’, ‘cobblestone’, ‘metal’.
Через некоторое время я добавлю эту схему.

Внимательно прочитал ваш научный спор.
Ничего не понял. :slight_smile:
Но хочу возразить. :slight_smile:
Вот здесь “http://brouter.de/brouter-web/#map=15/53.9017/27.2913/cyclosm&profile=shortest” так же видны “гравейки”.

Работает быстро. (Только надо карту “cyclosm” вручную включить в настройках, ее нет по умолчанию)

Кстати opentopomap там тоже есть и даже по умолчанию в списке карт. :slight_smile:

Так там просто показывается внесённый surface, без эвристики где она в городе или в лесу.