Статьи

QGIS, городские кварталы и костыли

ГИС Урбанистика Туториалы
Время прочтения: 5 минут
Источник: https://pikabu.ru/story/programmistyi_poymut_3318185
“Костыль — в программировании, быстрое «уродливое» решение проблемы, иначе требующей долгосрочного и ресурсоемкого исправления.” (с) Википедия

Возможно вы пропустили

Пару месяцев назад в двух статьях мы рассказали о том, как считают города и попробовали посчитать плотность застройки в QGIS. В примере туториала для расчета использовались готовые кварталы, но если вдруг таких данных нет, что скорее правило, чем исключение, то есть собственный уникальный костыльный способ построения городских кварталов в QGIS, которым мы были готовы поделиться за эмодзи единорога 🦄 в нашем телеграм-канале. Таких набралось аж 4 по состоянию на 28 мая 2023 года, поэтому выполняем обещание.

Строим городские кварталы в QGIS

Для того, чтобы построить наши кварталы, нужен QGIS с установленным плагином QuickOSM.
Шаг 1. Скачиваем данные через QuickOSM..
Нам потребуются следующие ключи: landuse, natural, highway и boundary. Качаем сразу всё, чтобы ничего не потерять, в результате у вас получится следующий джентльменский набор слоёв:
Шаг 2. Граница города – основа для кварталов.
Для начала найдем интересующую нас границу города, именно из неё мы будет вырезать лишнее, чтобы получить наши кварталы.
Выделяем в полигональном "boundary" нужное через поиск в любой колонке, в которой есть слово “name”. Следим, чтобы не выбралась созвучная область или район, и сохраняем границу в отдельный слой в метрической системе координат (я использую WGS 84 / UTM zone 38N).
Чтобы не потеряться в видах административных границ, можете прочитать больше про это на OSM Wiki.
Шаг 3. Исключаем лишнее.
Для этого шага нам потребуется 2 скачанных нами полигональных слоя: landuse и natural. Сначала полностью вырезаем из нашего слоя с границами города слой natural, используя функцию Разница. Не забываем перед этим пересохранить слой natural в той же проекции, что и слой с границей.
Окно инструмента "Разница" в QGIS
Сохраняем результат – пока еще далеко от кварталов, но дело пошло
Со слоем landuse всё сложнее, ведь он может содержать не только лишние для нас фермы, леса, луга и прочее, но и территории под жилое и коммерческое использование, чего мы не хотим потерять. Поэтому через запрос выберем лишнее, сохраним в проекцию, как у слоя с границами, и опять проведем операцию Разница.
Вот код для выделения нужных объектов, используем функцию “выделение объектов, удовлетворяющих условию” (ctrl + f3):
 "landuse" = 'vineyard' OR "landuse" = 'reservoir' OR "landuse" = 'orchard' OR 
 "landuse" = 'quarry' OR "landuse" = 'meadow' OR "landuse" = 'landfill' OR 
 "landuse" = 'industrial' OR "landuse" = 'forest' OR "landuse" = 'farmyard' OR 
 "landuse" = 'farmland' OR "landuse" = 'basin' OR "landuse" = 'aquaculture' 
Сохраняем выделенное в отдельный слой и используем разницу:
Шаг 4. Кварталы.
Самый большой, ответственный и финальный шаг выделения кварталов можно разделить на следующие элементы:
  1. Отсеивание лишнего.
  2. Расчет ширины улицы.
  3. Построение буферов.
  4. Разница.
  5. Разбить составную геометрию.
1. Отсеиваем лишнее:
Через “выделение объектов, удовлетворяющих условию” выбираем из слоя highway то, что может быть улицами, используя следующий код:
"highway" = 'motorway' or "highway"='motorway_link' or "highway" = 'trunk' or 
"highway" = 'trunk_link' or "highway" = 'primary' or "highway" = 'primary_link' 
or "highway" = 'secondary' or "highway" = 'secondary_link' or 
"highway" = 'tertiary' or "highway" = 'tertiary_link' or 
"highway" = 'unclassified' or "highway" = 'residential' or "highway" = 'living_street'
Не пугаемся, если попал какой мусор, теги улиц в OSM местами заполнены по-разному. Для одного и того же участка улицы разные осмеры (герои без плащей, но это не точно, которые и подготовили для нас данные) могут поставить тег service, другие – residential. Методом проб и ошибок я нашел оптимальный для себя запрос, но от города к городу его содержание может меняться, поэтому не ленитесь прокликивать улицы и изучить значение тегов.
2. Рассчитываем ширину улицы для буфера.
В слое highway OSM нам дает 2 колонки: width и lanes. Это хоть какая-то информация, используемая для определения ширины улицы. Колонка width обычно не заполнена, для Волгограда есть значение для всего 4 объектов, так что можем сразу на неё забить, у нас массовое мероприятие. А вот lanes это полезная вещь и встречается довольно часто.
Создаем колонку с типом данных real через Калькулятор полей и рассчитываем ширину, используя следующий код:
CASE
WHEN "lanes" IS NOT NULL THEN  to_int( "lanes") * 3.5 + 3
ELSE 5
END
Почему у нас такие цифры – объяснение следующее, и тут может быть множество мнений, потому что это попытка найти среднее.
Начнем:
WHEN "lanes" IS NOT NULL THEN to_int( "lanes") * 3.5 + 3 
Этим когдом мы говорим, что там, где в поле “lanes” есть значение, мы его умножаем на 3,5 и прибавляем 3. 3,5 – это средняя ширина стороны в метрах, такая ширины полосы может быть у улицы любого типа по старому-доброму СП Градостроительство. Прибавляю 3 метра на тротуары, деревья и прочие элементы профиля улицы.
ELSE 5 
Указываем 5 метров для всех остальных значений. Так как буфер идет в две стороны, то, получится, не зная значения lanes, наши улицы будут иметь ширину 10 метров, каждая сторона улицы состоит из 3,5 метров проезжей части и 1,5 метров для пешеходов. Использовать данные о тротуарах из OSM я не решился, так как их мало относительно количества улиц.
Принято считать, что для одного пешехода нужен тротуар шириной 75 см, поэтому и получаются цифры 1,5 и 3 метра для пешеходов разных вариантах. Такое, конечно, встречается не везде, но это мой способ приблизиться к среднему, и, возможно, у вас получится лучше, например, со значениями вашего конкретного города.
3. Строим полигоны улиц.
Всё очень просто, используем функцию Буферизация, при открытии функции жмем на стрелочку внизу справа от пункта Интервал (на скрине выделено желтым) и выбираем поле с шириной улицы.
Окно инструмента "Буферизация" в QGIS для создания буфера улиц
После построения буферов от улиц можно увидеть наши долгожданные кварталы, есть они не везде, но уже что-то
4.Разница
Всё очень просто, используем хорошо знакомую функцию Разницы, вырезаем из слоя границ буферы от улиц и получаем один большой мультиполигон, в котором видны наши кварталы.
5.Разбить составную геометрию
Используем функцию с названием, как у этого подпункта и получаем множество кварталов.
Кварталы готовы, останется удалить мусор из слишком больших территорий и слишком маленьких и уже можно вести какой-то анализ
Шаг 5. Очистка от лишнего.
Итого мы получили слой с кучей городских кварталов, но в котором есть еще лишние элементы:
Теперь нужно очистить город от явно лишних элементов, которые не смогли выделиться в кварталы или не являются ими. Предлагаю удалить все объекты. Для этого просто удаляю всё, что меньше 2000 квадратных метров и больше 100 га, чтоб наверняка:
$area < 2000 or $area >1000000
Выделяем и удаляем. В идеале можно покликать по нашим кварталам и немного скорректировать цифры.
Уже похоже на кварталы города
А вот сравнение с красными линиями (на картинке черные линии) – кварталами, которые закреплены юридически, местами результат очень хорош

Выводы

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

Источники:

  • Berghauser Pont, Meta & Haupt, Per. (2021). Spacematrix - Space, Density and Urban Form;
  • Стандарт комплексного развития территорий
  • https://docs.momepy.org/en/stable/user_guide/elements/blocks.html
Материал подготовил Александр Зуев
А еще у нас есть рассылка с лучшими статьями и новостями мира геотехнологий. Собираем все лучшее и отправляем в письме раз в две недели ⭐