RU:Appllied Multipolygons/Theory

From OpenStreetMap Wiki
Jump to: navigation, search

Что такое отношение?

Самая большая опасность правки чужих отношений — что можно ненароком что-нибудь порушить. Это происходит от незнания механики и от забывчивости. По крайней мере первую проблему мы сейчас решим.

Основные объекты OSM — точки и линии. Последние состоят из точек; сами по себе они бесполезны. Соответственно, редактор, загружая линию, загружает все связанные с ней точки. Обратное не всегда верно: можно скачать точку и не знать, что она принадлежит одной или нескольким линиям. После чего можно её удалить, и при попытке загрузки сервер скажет: «Непорядок!» — и заставит улаживать конфликт.

(картинка с линиями и точками)

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

Что у нас ещё находится на нулевом слое? Правильно, теги. Другими словами, отношения — это свойства объектов.

(картинка с отношениями как свойствами)

Отсюда всплывает неочевидность, из-за которой отношения считаются «сложными», и мапперы избегают их использовать. Если отношения по свойствам стоят в одном ряду с тегами, то почему в [продвинутых] редакторах есть список всех отображаемых на карте отношений, но нет списка всех отображаемых на карте тегов? Потому что тегов слишком дофига. Почему же отношений меньше? Потому что их сложнее делать (хотя со временем процесс упрощается), и потому что при большом их количестве с ними сложнее управляться. Потому что нынешняя практика работы с ними идёт от отношения, а не от объекта.

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

(картинка с панелью отношений, в которой их много)

Разорванные связи

В обычном API нельзя сказать: «дай-ка все объекты, на которых поставлен такой-то тег». Нельзя запросить линию без тегов, которые на неё навешены. Однако всё это можно сделать с отношениями. Более того, такие запросы — основной метод работы. Давайте разберём пример.

(картинка)

Запросив линию, мы получили также точки и отношения на ней. То есть, одно отношение: знакомый мультиполигон. На схеме заметно, что в базе к этому отношению приделаны и другие объекты, только они нам не выдались. Почему? Ну, когда вы запрашиваете точку, и на ней стоит тег shop=books, — вам же не выдаются автоматически все остальные точки с этим тегом?

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

(картинка с полным отношением)

Здесь нарисовано упрощённо, на деле членов отношения часто десятки, а то и сотни. Для всех линий, очевидно, грузятся ещё и точки. Дорисовав хорду, приделываем её к линии 3. Разбивая её, редактор копирует отношение во второй кусок:

(разбитая линия, но видна проблема)

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

(подгрузили отношения сегмента)

Внезапно, соседний мультиполигон, в котором теперь дырка. Но нам не выдалось никакого предупреждения, как, например, при удалении точек «вне скачанной области», когда можно ненароком оставить без точки какую-то невидимую линию. Увы, такая вот несправедливость — и единственное, что можно сделать, это не забыть.

Структура

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

 <relation id='550310'>
   <member type='way' ref='31372054' role='from' />
   <member type='node' ref='237694' role='via' />
   <member type='way' ref='54952848' role='to' />
   <tag k='restriction' v='no_left_turn' />
   <tag k='type' v='restriction' />
 </relation>

Есть ли ссылки на это отношение на его членах? Разумеется, нет: база бы была не нормализованной, что повлекло бы сложности при изменении и потенциальную потерю связей. Таким образом, легко узнать всех членов нужного отношения: ссылки на них возвращаются при любом запросе отношения, как точки для линий. Отсюда несложно запросить данные по всем этим членам. Однако обратная процедура — найти отношение, в котором состоит объект — уже сложнее, поэтому на этой операции экономят. Разумеется, во многих редакторах есть способ получить все отношения для выделенных объектов, и при сложном редактировании ей лучше не пренебрегать.

Отношения в отношениях

«Подождите, но если отношения подобны тегам, то отношения из отношений... мой мозг!»

Смотрите. Когда мы ставим на линию тег building, мы как бы говорим: «эта линия — здание». Если мы добавляем линию в отношение с этим тегом, это означает: «эта линия — часть здания». В первом случае мы говорим о принадлежности классу объектов, во втором — определённому объекту. Поэтому отношение внутри другого отношения представляет один объект, который состоит из других — как линия состоит из точек.

То есть, в этом плане отношения — именно третий слой над линиями и точками, собирающий их в одно целое.

«Но... нулевой слой...»

Отношения находятся на третьем слое, но обращаться с ними нужно, как с тегами. Не «линия входит в список членов отношения, которое обозначает дом», а «линия является частью дома». Она может перестать быть его частью, может стать частью озера. Может стать целым озером, то есть, «частью класса озёр». Не сложнее, чем убрать один тег и навесить другой. Вместе с линией или точкой скачиваются теги и отношения. Удалишь с видимых линий отношения — в панели списка отношений будет висеть «призрак». Что странно, потому что при удалении тегов нигде не остаётся следа. Пустые отношения — именно то, что указывает на сложность модели, и таких, поверьте, в базе очень много.

Связи в JOSM

Для поддержки связности нужно будет постоянно пользоваться функциями докачки объектов. Они находятся в трёх местах. Во-первых, в меню «Файл».

Appmulti3-08-parent.gif

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

Appmulti3-09-tags.gif

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

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

Appmulti3-10-relations.gif

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

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

Хотя редактирования границ вообще непросто »