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

Относится ли дорога к населенному пункту несложно определить по вхождению в полигон 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, без эвристики где она в городе или в лесу.

Сделал, начиная с 14-го зума.

Также, сделал рендеринг разрушенных зданий с тегами abandoned=yes, ruins=yes, abandoned:building, ruined:building, ruins:building. Рисуются и подписываются с 16-го зума, стиль приближен к Генштабу.

Появились на 18 зуме.

Огромное спасибо, отлично получилось!
Хотел еще заметить, что на building name отображается, но если name поставлен на полигоне amenity (например как это принято для школ) то он не отображается.

Пожалуйста. Вам тоже спасибо за идею.

Я не очень понял, в чём проблема. Если есть тег building на полигоне, то name подписывается, если площадь полигона больше 1000 кв.м. Если проблема в другом, то приведите пожалуйста её пример.

Вот школа https://www.openstreetmap.org/relation/10985709 - названия на opentopomap нет на любых масштабах. Тоже самое - пожарная часть https://www.openstreetmap.org/relation/12267901, детский сад - https://www.openstreetmap.org/relation/11048498 и т.д.
Но вот поликлиника - https://www.openstreetmap.org/way/91887427 или другая школа - https://www.openstreetmap.org/way/137119504 - название есть. То ли дело в мультиполигонах, то ли еще в чем-то, но поведение не совсем ожидаемое.

Если на building нет name, то, соответственно, ничего и не подписывается. Из amenity без building подписываются только больницы, укрытия от дождя, церкви, и, возможно, ещё что-то. Какие amenity из площадных, как вы считаете, нужно ещё подписывать?

На мой взгляд стоит подписывать следующие площадные объекты, если у них есть name
Образование:
amenity kindergarten
amenity college
amenity school
amenity university
amenity library
Медицина:
amenity hospital
amenity clinic
amenity doctors
amenity social_facility
Крупные объекты культуры
amenity arts_centre
amenity community_centre
amenity social_centre
Экстренные службы:
amenity fire_station
amenity police
Разное:
amenity embassy
amenity marketplace
amenity monastery
amenity prison
Ну может быть еще amenity=fuel

Из landuse
landuse cemetery
landuse industrial
landuse construction
landuse religious

Из leisure
leisure nature_reserve
leisure park
leisure stadium
leisure sports_centre
leisure sports_hall
leisure water_park

но это будет уже не топографическая карта

Но сейчас же большинство из этих объектов подписывается, если name стоит на building. И не вызывает вроде как вопросов. Я только за единый подход. Если подписываем название школы проставленное на building, то надо подписывать и площадной объект (что кстати для школ более правильный по вики вариант). Ну или уж тогда не подписывать школы вообще.

О. Супер. Спасибо. Работает. :slight_smile:

Помасштабировал знакомые куски местности… мне кажется можно и с 12го зума делать такую заливку цветом. :slight_smile:

Подход и сейчас единый и логичный - подписываются все buildnig более 1000 квадратов (если меньше, то надписей становится слишком много + не умещаются), у которых есть name, плюс площадные, важные в экстренных ситуациях объекты hospital. Таким образом топокарта не запруживается излишней информацией. А уж что там за buildnig, и почему у него есть или нет name, это дело второе.
По поводу подхода я согласен с literan, но спасибо вам за список, я буду иметь ввиду.

До 14-го зума цвет нужен в большей степени, чтобы хорошо отличать более главные/менее главные дороги, что логично для обзорных масштабов.

Так мое предложение не противоречит. Начиная с 12го масштаба не исключая 13, 14 и т.д

Для моих зимних велозабав например, когда я пытаюсь найти место в радиусе 100-150км от города, где бы найти связку гравейных дорог общей длиной километров 50 с минимум асфальта на связки на субботнюю покатушку, 12-й масштаб гораздо более обзорный.

Вдруг это не противоречит каким то другим “условиям” отображения карт. :slight_smile: