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

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

Итак, перед нами стояла задача - получить полигоны зданий, в которых находятся медицинские учреждения - клиники или врачебные кабинеты. В OSM такое обозначается тегами amenity=clinic или doctors (есть и другие значения этого тега, связанные с медициной, но нас интересовали именно эти два).

Для начала создадим два фильтра по этим двум значениям тега и объединим их результат с помощью операции объединения:

Простая выборка объектов по двум возможным значениям тега

Запустим пайплайн и поглядим на результат:

Мы видим, что наши значения тега встречаются как у зданий (синий прямоугольник справа), так и в виде отдельных точек (маркеры). Так работает тегирование в OSM - всякие объекты внутри зданий (магазины или вот клиники), не занимающие все здание целиком, отмечаются точками внутри полигона здания.

Проблема в том, что нам были нужны именно сами полигоны зданий, но с тегами медицинского объекта. Чтобы этого добиться, нам надо:

  • Выделить все здания (это объекты с тегом building)
  • Найти те из них, в которые попадают точки с нужными нам значениями amenity
  • Объединить значения тегов здания и точки внутри

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

Выборка всех зданий

Далее нам надо отобрать только точечные объекты-клиники, так как именно они находятся внутри зданий. Для этого мы будем использовать узел выборки по типу геометрии:

Собрав все объекты с нужным нам amenity, дальше передадим только те, которые заданы точками

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

Подадим на вход объектов здания, на вход геометрий - наши точечные клиники и получим на выходе здания, которые содержат в себе клинику.

Теперь нам осталось перенести теги с точечных клиник на здания, внутри которых они находятся. Для этого у нас есть узел слияния объектов. Этот узел ищет пересекающиеся объекты во входном потоке, объединяет их геометрии и теги, и полученные объекты передает на выход.

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

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

Добавим вывод всех клиник, имеющих полигональную геометрию, сразу на выход с помощью еще одного узла объединения. Итоговый граф выглядит вот так:

Казалось бы, это уже то, что надо:

Где раньше была точка - теперь у нас полигон здания, с проставленным amenity=doctors.

Оданко OpenStreetMap не был бы таким, какой он есть, если бы в нем все было так просто. Расширим нашу область карты, чтобы она захватывала большую часть Васильевского острова, и увидим вот такое:

Оказывается, иногда медицинские amenity ставят не на точку или здание, а на территорию медучреждения целиком. Нам придется еще доработать наш пайплайн, чтобы он смог обработать и такие варианты.

Если раньше мы просто брали полигональные amenity=clinic и подавали на выход, то теперь нам нужно выделить внутри них все здания и тоже перенести теги на здания.

Добавим еще один фильтр по пересечениям, в котором отберем теперь здания, которые содержатся внутри. Переключим режим на "Contains" - нам нужны здания, которые находятся полностью внутри территории клиники (иначе при дефолтной проверке "Intersects" мы можем получить здания, которые касаются ее края, но сами находятся за ее пределами)

Теперь у нас есть полигоны клиник и здания на их территории. Мы не можем просто так их объединить с помощью узла Merge как делали для точечных клиник. Так как при объединении геометрии здания и большей по размеру клиники результатом будет опять большой полигон территории.

Поэтому мы сперва "вырежем" из клиник участки, соответствующие зданиям. Для этого используется узел Intersection. Он модифицирует объекты с первого входа, оставляя только ту часть их геометрии, которая пересекается хотя бы с одним объектом из второго входа.

Разберемся, что тут происходит:

  1. Со входа 1 поступают все здания
  2. От фильтра 2 поступают полигональные клиники (это могут быть как отдельные здания, так и области)
  3. На выходе фильтра 3 мы получаем здания (со входа 1), которые содержатся хотя бы в одной клинике.
  4. Узел 4 принимает на первых вход клиники, на второй здания. Обрезает клиники, оставляя только ту часть их геометрии, которая находится хотя бы под одним зданием.
  5. Узел 5 объединяет работу предыдущих узлов - выход узла 3 (здания) и выход узла 4 (клиники, обрезанные до полигонов зданий).
  6. Узел 6 объединяет пересекающиеся объекты. Геометрия клиник и зданий уже совпадает после обрезки, поэтому меняются (объединяются) только теги. На выходе мы получаем объекты, имеющие геометрию зданий и теги и от зданий, и от клиник.

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

Итоговый граф пайплайна выглядит вот так:

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

А сколько бы такое же заняло у вас в вашем текущем инструменте?