User:Zverik/Areas ru
Что ж, почти все уже высказали предложения по типу данных area, пора и мне. Комментарии оставляйте на странице обсуждения.
Требования
Области должны заменить три типа данных, используемых ныне в OpenStreetMap:
- замкнутые линии (проблемы: самопересечения, теги могут относиться и к полигону, и к контуру);
- мультиполигоны (проблемы: легко сломать, теги можно вешать на линии и отношения);
- береговая линия, коллекции мультиполигонов (проблемы: до фига линий — сотни тысяч, — и теги можно вешать на всё).
Область
Я предлагаю создать новый тип объекта, area (область):
<area id="..." ...>
<tag k="..." v="..." />
<ring>
<nd ref="1" />
<nd ref="2" />
</ring>
<ring>
<nd ref="3" />
<nd ref="4" />
</ring>
</area>
Как можно заметить, области состоят из контуров. Это позволит хранить мультиполигоны формата Simple Features, с внешними и внутренними контурами. Точки сортируются против часовой стрелки для внешних контуров и по часовой для внутренних, как предписывает модель Simple Features.
Схема похожа на The Future of Areas/Areas on Nodes, но вместо разделения внешних и внутренних контуров мы полагаемся на порядок точек. Это поможет редакторам и рендерерам, потому что:
- имея координаты точек, внешние и внутренние контуры различить элементарно;
- построение полигона Simple Features тривиально;
- частично загруженные области можно правильно отобразить.
Каждая точка должна входить в область не более одного раза. Все контуры замкнуты, поэтому первую точку не нужно повторять в конце списка.
Плюсы
- Замкнутые линии легко преобразуются в области (не считая конфликтов тегов) и не потребуют создания дополнительных объектов.
Минусы
- Область может содержать огромное количество точек, и их все придётся загружать при загрузке объекта.
Ссылки на область
Затем, я предлагаю добавить ссылки на области линиям:
<way id="..." ...>
<tag k="..." v="..." />
<nd ref="5" />
<nd ref="6" />
<arearef id="1000" reverse="false" />
</way>
Ссылок может быть несколько. Направление линий должно быть тем же, что и для точек: против часовой для внешних контуров, по часовой для внутренних. Теги на линиях касаются только самих линий, но не областей.
Плюсы
- Ссылки не увеличивают номер версии области, поэтому возможно править одну и ту же область одновременно.
- Береговые линии и объекты навроде границы Франции легко рисуются (просто сделайте пустую область с тегами, и ссылайтесь на неё).
- Требование направления позволяет редактировать или отрисовать часть области без ошибок.
Минусы
- Нельзя быть уверенным, что скачал все контуры области.
- Одна область для леса или поля может внезапно покрыть всю страну.
- Проверки целостности на стороне сервера могут быть сложны.
- Разворачивать линии потребуется очень осторожно, чтобы не сломать область.
Наглядный пример
<area id="1">
<tag k="landuse" v="residential" />
<!-- два внешних контура: перечисляем точки против часовой -->
<ring>
<nd ref="8" />
<nd ref="9" />
<nd ref="10" />
<nd ref="11" />
</ring>
<ring>
<nd ref="3" />
<nd ref="2" />
<nd ref="4" />
</ring>
</area>
<way>
<nd ref="1" />
...
<nd ref="1" />
<!-- точки в линии расположены по часовой: для представления внешнего контура её нужно развернуть -->
<arearef id="1" reverse="true" />
</way>
<!-- направления следующих трёх линий верны, поэтому просто отметим их частями области -->
<way>
<nd ref="7" />
...
<nd ref="5" />
<arearef id="1" reverse="false" />
</way>
<way>
<nd ref="5" />
...
<nd ref="7" />
<arearef id="1" reverse="false" />
</way>
<way>
<nd ref="6" />
...
<nd ref="6" />
<arearef id="1" reverse="false" />
</way>
Целостность
Понадобятся несколько проверок правильности загружаемых данных, которые не были возможны для мультиполигонов. Конечно, контроль геометрии в нашей базе данных невозможен, но хотя бы проверим на пересечения в точках.
Области на точках
Контуры не должны касаться или самопересекаться: проверить, что идентификаторы точек не дублируются; каждая точка должна участвовать единожды во всех контурах области.
Последовательности линий
Потребуется обрабатывать линии после того, как они все прочитаны; для каждой загруженной линии должна существовать линия (лучше — единственная линия), первая или последня точка которой (лучше — в зависимости от флага reverse) совпадает с концом этой линии, и то же про начало линии. Проверять координаты не нужно.
Линии со ссылкой на область не должны иметь самопересечений, но могут быть замкнуты.
Запрет на касание колец
Линии, формирующие контуры области (и точки этой области) не должны иметь общих точек, не считая первых и последних точек линий. Эта проверка нагрузит базу, так что она не обязательна.
Запрос числа линий
Перед загрузкой области целиком (/area/:id/full) может захотеться проверить количество линий в ней: едва ли кому-то улыбается скачивать всю береговую линию, например. Поэтому нужен запрос "info", который возвращает это число. Как вариант, можно сделать поле «количество ссылок» в базе данных, которое обновлять каждый раз, когда на область добавляется или удаляется ссылка.
Или пусть запрос /full выдаёт ошибку, если линий больше 1000.