Приветствую всех!
Хочу рассказать вам о моей утилите на C# —
https://github.com/chubrik/OsmDataKitОна была создана во время работы над проектами
https://toponim.by/ и
https://toponym.org/Основное назначение утилиты в том, чтобы из базы OSM-PBF делать выборки объектов по спискам ID или по фильтрам, а в ответ получать не плоский набор данных, а полные древовидные структуры со всеми вложенными объектами.
Простой пример из жизни.
Мне нужно отрисовать идеальный контур границы Беларуси на сайте. Для этого нужно получить все точечные «ноды» с их координатами. Нам известен ID границы в OSM:
https://www.openstreetmap.org/relation/59065 Но в базе граница страны представлена сложным образом. Это объект «отношение», состоящий из множества «путей» и других «отношений», которые в свою очередь состоят из таких же сущностей и т. д. В сумме мы имеем 7-кратную вложенность объектов, описывающих границу Беларуси. Моя утилита позволяет одним простым запросом получить сразу всю полную объектную модель. Достаточно «натравить» её на единственный ID. Выглядит это так:
var border = OsmService.LoadCompleteObjects(
pathToPbf, new GeoRequest(null, null, 59065));
Более сложный пример из жизни.
Нужно получить все населённые пункты. Запрос может быть долгий, поэтому я могу его прокешировать в файл, чтобы в дальнейшем легко отлаживать проектный код без повторных ожиданий:
var populated = OsmService.LoadCompleteObjects(
pathToPbf,
cacheName: "populated",
i => ((i.Tags.ContainsKey("place") &&
!i.Tags.Contains("place", "locality")) ||
i.Tags.ContainsKey("old_place") ||
i.Tags.ContainsKey("abandoned:place") ||
i.Tags.Contains("landuse", "residential")) &&
GeoHelper.TitleRu(i) != null);
Существует официальная утилита OsmSharp —
https://github.com/OsmSharp/core и неё режим CompleteStream, у которого заявлен похожий функционал. Но есть непреодолимые проблемы, делающие использование официальной утилиты невозможным:
• Даже при работе с одной страной запросто забьётся вся ваша оперативка. А если нужен весь мир?
• Малейшее нарушение целостности базы — крэш, и вы ничего не получите. А мелкие нарушения целостности неизбежно присутствуют.
• Построение запроса очень сложное, нужно продумать и отфильтровать все элементы, которые ПОТЕНЦИАЛЬНО могут оказаться в результирующем объекте. Любая ваша ошибка — крэш.
Преимущества моей утилиты:
• Экономия оперативки. Даже если вы работаете с целыми континентами, это не проблема.
• Устойчивость к нарушению целостности базы. Если у гео-объекта потерялась «нода», вы всё равно получите полноценные данные, с которыми можно работать.
• Высокоуровневые запросы. Утилита сама разбирается, как ей достать все необходимые части того, что вы просите.
• Возможность кеширования запросов. Достаточно придумать запросу какое-то имя.