Когда мы готовились к автоматизации работы местных муниципальных служб, мы обратили внимание на использование картографии, которое мы сочли действительно мощным и эффективным инструментом для решения широкого кластера задач. На карте можно отображать актуальную информацию о местоположении объектов, маршруты движения уборочной техники, транспорта, план работы и тепловую карту с проблемными и “здоровыми” участками.
Использование картографии в целом помогает ускорить время реакции и принятия решений по экстренным вопросам, упрощает процесс планирования и прогнозирования, а главное — вся информация доступна в максимально наглядном виде.
В ходе работы с одним из заказчиков перед нами возникла интересная задача — подсчитать количество объектов на карте по категориям.
Найти
Определить самый “зеленый” город в ЦФО по совокупности следующих данных: количество лавочек, урн и парков.
Дано
Картография. В качестве плацдарма мы выбрали OpenStreetMap (далее — OSM) по весьма простой причине — Open Source.
Решение
Существует несколько подходов к решению поставленной задачи. К примеру, мы можем использовать PostgreSQL для осуществление запросов к базе данных OSM и получения необходимых данных, или использовать QGIS — систему для создания, анализа и публикации геопространственной информации. Однако, мы нашли более элегантный и эффективный способ — Overpass API.
Overpass API — мощный инструмент для извлечения данных из базы OSM по запросу пользователя. Он оптимизирован для задач любого масштаба: от получения нескольких элементов из базы до сотен миллионов объектов, которые отбираются согласно запросу в виде XML или Overpass QL — модернизированной версии Overpass XML. Подробнее об Overpass API — здесь.
Будем начинать все с чистого листа: в первую очередь потребуется развернуть OSM на сервере. В качестве операционной системы на нашей машине используется Ubuntu.
Q: Зачем разворачивать свой OSM?
A: Для работы с данными нам потребуется Overpass API, общедоступный сервер которого имеет ограничение на количество запросов в сутки. Именно по этой причине мы развернем свой сервер с блекджеком OSM и Overpass API.
Подробная инструкция по установке OSM лежит здесь.
Следующим шагом мы устанавливаем Overpass API — его последний релиз можно найти тут.
sudo apt-get update sudo apt-get install g++ make expat libexpat1-dev zlib1g-dev apache2 -y wget http://dev.overpass-api.de/releases/osm-3s_ВЕРСИЯ.tar.gz tar -zxvf osm-3s_ВЕРСИЯ.tar.gz cd osm-3s_ВЕРСИЯ ./configure CXXFLAGS="-O2" --prefix=$EXEC_DIR make install cd ../ chmod -R 755 ./overpass
После установки потребуется провести populating — создание базы данных. База данных всего мира нам не нужна, поэтому мы воспользуемся сервисом Geofabrik, который позволяет получить данные по заданным административным регионам.
Достойная альтернатива Geofabrik — BBBike.
Мы загружаем и распаковываем базу данных, загруженную из каталога Europe > Russian Federation > Central Federal District в формате .osm.bz2, по следующей схеме:
ПУТЬ_К_INIT_OSM3S.SH ПУТЬ_К_ФАЙЛУ_BZ2 ПУТЬ_КУДА_РАСПАКОВЫВАТЬ ДИРЕКТОРИЯ_OVERPASS_API
Примечание: в данном случае все действия выполняются в каталоге overpass.
Итак, платформа практически готова — сейчас мы можем сделать свой первый запрос и узнать количество парков в целом по региону.
ПУТЬ_К_OSM3S_QUERY —db-dir = ПУТЬ_К_DB
Наш запрос и ответ выглядят следующим образом:
root@MIP-USER55:~# cd overpass/ root@MIP-USER55:~/overpass# ./osm-3s_v0.7.56.7/bin/osm3s_query --db-dir=db encoding remark: Please enter your query and terminate it with CTRL+D. [out:json][timeout:25]; ( nwr["landuse"="forest"]; ); out count; { ..., "elements": [ { "type": "count", "id": 0, "tags": { "nodes": "23", "ways": "19723", "relations": "4206", "total": "23952" } } ] }
Мы уже близко: осталось только разбить парки по областям и городам. Справиться с этой задачей нам поможет отдельно запущенный и постоянно работающий Dispatcher.
Запускаем API и в директории /etc/apache2/ports.conf добавляем Listen ПОРТ.
echo "ИМЯ_СЕРВЕРА localhost" | sudo tee /etc/apache2/conf-available/ИМЯ_СЕРВЕРА.conf && sudo a2enconf ИМЯ_СЕРВЕРА sudo iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport ПОРТ -j ACCEPT sudo a2enmod cgi sudo a2enmod ext_filter sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/ИМЯ_КОНФИГА_ДЛЯ_СЕРВЕРА.conf
Проверяем конфигурацию. Она должна выглядеть следующим образом.
<VirtualHost *:ПОРТ> ServerAdmin webmaster@localhost ExtFilterDefine gzip mode=output cmd=/bin/gzip DocumentRoot ПУТЬ_К_OVERPASS_API/html ScriptAlias /api/ ПУТЬ_К_OVERPASS_API/cgi-bin/ <Directory "ПУТЬ_К_OVERPASS_API"> AllowOverride None Options Indexes FollowSymLinks Require all granted </Directory> <Directory "ПУТЬ_К_OVERPASS_API/cgi-bin/"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Далее включаем новый хост и отправляем старый отдыхать.
sudo a2ensite КОНФИГ.conf sudo a2dissite 000-default.conf sudo a2dissite ВСЕ_ДРУГИЕ_КОНФИГИ.conf sudo service apache2 reload
Настало время включить первый Dispatcher, который будет обрабатывать наши запросы. Для этого воспользуемся командой.
nohup ПУТЬ_К_OVERPASS_API/bin/dispatcher --osm-base --db-dir=ПУТЬ_К_DB --meta &
Первый признак того, что все пошло по плану — создание файла
osm3s_OVERPASS_API_ВЕРСИЯ_osm_base в директории с базой данных. В файле nohup.out появится сообщение о статусе Dispatcher — dispatcher just started.
Однако, работа на этом не заканчивается: требуется запустить ещё один Dispatcher. Для начала копируем папку rules в директорию с базой данных и раздаем права на появившийся в результате файл osm3s_OVERPASS_API_ВЕРСИЯ_areas.
nohup ПУТЬ_К_OVERPASS_API/bin/dispatcher --areas --db-dir=ПУТЬ_К_DB & chmod 666 "../db/osm3s_OVERPASS_API_ВЕРСИЯ_areas" nohup ПУТЬ_К_OVERPASS_API/bin/rules_loop.sh ПУТЬ_К_DB &
Теперь мы можем сделать запрос по области и подсчитать количество парков в Рязани. И, кстати, это уже работает в адресной строке браузера.
http://localhost:ПОРТ/api/interpreter?data=[output:json][timeout:25]; area[name="Рязань"]->.searchArea; ( nwr["leisure"="park"](area.searchArea); ); out count;
Долгожданный ответ!
"elements": [ { "type": "count", "id": 0, "tags": { "nodes": "0", "ways": "57", "relations": "11", "areas": "0", "total": "68" } } ] }
Итак, теперь мы можем погрузиться в аналитику и вопросы благоустройства: найдем количество парков, лавочек и мусорных баков в 25 крупных городах ЦФО и сравним эти показатели при помощи аналитических инструментов платформы ODANT.
ODANT — цифровая интеграционная платформа отечественной разработки, предназначенная для построения информационных систем различной сложности и распределенности. Подробнее об ODANT — здесь.
Так выглядят наши параметры для поиска урн: в рамках задачи мы не делаем различий между контейнерными площадками, отдельно стоящими урнами и пунктами приема ТБО.
nwr["amenity"="recycling"](area.searchArea); nwr["amenity"="waste_disposal"](area.searchArea); nwr["amenity"="waste_basket"](area.searchArea);
Выходные данные мы экспортировали из ODANT в виде плоской таблицы.
|
Город
|
Урны
|
Население
|
Население/Урны
|
|
Владимир
|
1525
|
356937
|
234
|
|
Красногорск
|
274
|
175554
|
641
|
|
Калуга
|
376
|
332039
|
883
|
|
Тамбов
|
279
|
292140
|
1047
|
|
Москва
|
11473
|
12678079
|
1105
|
|
Коломна
|
111
|
140129
|
1262
|
|
Балашиха
|
378
|
507366
|
1342
|
|
Курск
|
336
|
452976
|
1348
|
|
Рыбинск
|
129
|
184635
|
1431
|
|
Мытищи
|
140
|
235504
|
1682
|
|
Люберцы
|
119
|
205295
|
1725
|
|
Зеленоград
|
140
|
250453
|
1789
|
|
Воронеж
|
544
|
1058261
|
1945
|
|
Тверь
|
225
|
449507
|
1998
|
|
Ярославль
|
273
|
608353
|
2228
|
|
Муром
|
43
|
106984
|
2488
|
|
Подольск
|
114
|
308130
|
2703
|
|
Химки
|
89
|
259550
|
2916
|
|
Кострома
|
72
|
276929
|
3846
|
|
Липецк
|
124
|
509420
|
4108
|
|
Рязань
|
118
|
539290
|
4570
|
|
Королёв
|
49
|
224348
|
4579
|
|
Тула
|
101
|
475161
|
4705
|
|
Электросталь
|
32
|
156026
|
4876
|
В данном рейтинге город Владимир занимает почетную первую строчку: на одно место скопления мусора там приходится всего 234 человека. Используя встроенные инструменты ODANT строим два занятных графика.


Перейдем к следующему элементу — лавочкам.
nwr["amenity"="bench"](area.searchArea);
Получаем следующий результат в виде таблицы.
|
Город
|
Лавочки
|
Население
|
Население/лавочки
|
|
Владимир
|
593
|
356937
|
602
|
|
Тамбов
|
413
|
292140
|
707
|
|
Москва
|
13970
|
12678079
|
908
|
|
Красногорск
|
143
|
175554
|
1228
|
|
Балашиха
|
411
|
507366
|
1234
|
|
Зеленоград
|
185
|
250453
|
1354
|
|
Тверь
|
268
|
449507
|
1677
|
|
Люберцы
|
115
|
205295
|
1785
|
|
Калуга
|
176
|
332039
|
1887
|
|
Курск
|
214
|
452976
|
2117
|
|
Муром
|
42
|
106984
|
2547
|
|
Тула
|
172
|
475161
|
2763
|
|
Коломна
|
49
|
140129
|
2860
|
|
Воронеж
|
272
|
848752
|
3120
|
|
Подольск
|
79
|
308130
|
3900
|
|
Рязань
|
132
|
539290
|
4086
|
|
Кострома
|
61
|
276929
|
4540
|
|
Химки
|
43
|
259550
|
6036
|
|
Рыбинск
|
25
|
184635
|
7385
|
|
Ярославль
|
78
|
608353
|
7799
|
|
Липецк
|
55
|
509420
|
9262
|
|
Электросталь
|
16
|
156026
|
9752
|
|
Королёв
|
23
|
224348
|
9754
|
|
Мытищи
|
17
|
235504
|
13853
|
И снова Владимир оказался самым благоустроенным из всех претендентов: 602 человека на одну скамейку посадить не получится, но в Мытищах за места идет куда более ожесточенная борьба. Однако, всегда можно придумать расписание.
Визуализируем наши результаты.


Перейдем к самой интересной части: подсчет площади парков. Для решения этой задачи мы можем использовать несколько методов, но самым оупенсорсным и замечательным мы находим библиотеку Leaflet. В самом запросе потребуется заменить out count на out geom, что в результате даст нам координаты областей.
Leaflet — библиотека с открытым исходным кодом, написанная на JavaScript, предназначенная для отображения карт на веб-сайтах. Поддерживает большинство мобильных и стационарных платформ из числа тех, что поддерживают HTML5 и CSS3. Leaflet позволяет разработчику, не знакомому с ГИС, легко отображать растровые карты, состоящие из маленьких фрагментов — тайлов, с, возможно, дополнительными слоями, накладываемыми поверх основного. Подробнее о Leaflet — здесь.
Создадим полигон.
const polygon = L.polygon(КООРДИНАТЫ).addTo(map); const area = L.GeometryUtil.geodesicArea(polygon.getLatLngs());
Теперь в area лежит площадь региона в м2. Извлекаем данные для выбранных нами городов и получаем следующую таблицу.
|
Город
|
Общая площадь парков (km2)
|
Площадь города (km2)
|
Процент пространства, занимаемого парками
|
Кол-во парков
|
|
Зеленоград
|
4.13
|
37.199
|
0.111
|
26
|
|
Калуга
|
12.60
|
168.8
|
0.075
|
140
|
|
Москва
|
121.75
|
2561.5
|
0.048
|
1469
|
|
Люберцы
|
0.60
|
12.87
|
0.047
|
28
|
|
Владимир
|
4.62
|
137.14
|
0.034
|
104
|
|
Химки
|
3.55
|
109.8
|
0.032
|
27
|
|
Подольск
|
1.29
|
40.39
|
0.032
|
53
|
|
Балашиха
|
1.78
|
62.8
|
0.028
|
55
|
|
Тамбов
|
2.71
|
96.58
|
0.028
|
140
|
|
Тула
|
4.09
|
145.8
|
0.028
|
102
|
|
Кострома
|
3.95
|
144.5
|
0.027
|
50
|
|
Красногорск
|
0.69
|
25.65
|
0.027
|
21
|
|
Рязань
|
4.32
|
224.163
|
0.019
|
96
|
|
Ярославль
|
3.68
|
205.8
|
0.018
|
176
|
|
Королёв
|
0.97
|
55.47
|
0.017
|
30
|
|
Курск
|
3.31
|
208.2
|
0.016
|
862
|
|
Коломна
|
1.03
|
65.1
|
0.016
|
21
|
|
Мытищи
|
0.53
|
34.59
|
0.015
|
30
|
|
Воронеж
|
8.25
|
596.51
|
0.014
|
414
|
|
Липецк
|
4.44
|
330.15
|
0.013
|
78
|
|
Тверь
|
1.38
|
152.22
|
0.009
|
129
|
|
Муром
|
0.33
|
43.78
|
0.008
|
11
|
|
Рыбинск
|
0.65
|
101.42
|
0.006
|
62
|
|
Электросталь
|
0.25
|
51.45
|
0.005
|
52
|
По данным OSM Зеленоград полностью оправдывает свое название — 11% площади города занято зелеными массивами. Получим отношение количества жителей к количеству парков.
|
Город
|
Общая площадь парков (м2)
|
Кол-во м2 парков на 1 жителя
|
Количество жителей на 1 парк
|
|
Калуга
|
12,600,000
|
37.95
|
2372
|
|
Зеленоград
|
4,130,000
|
16.49
|
9633
|
|
Кострома
|
3,950,000
|
14.26
|
5539
|
|
Химки
|
3,550,000
|
13.68
|
9613
|
|
Владимир
|
4,620,000
|
12.94
|
3432
|
|
Воронеж
|
8,250,000
|
9.72
|
2050
|
|
Москва
|
121,750,000
|
9.60
|
8630
|
|
Тамбов
|
2,710,000
|
9.28
|
2087
|
|
Липецк
|
4,440,000
|
8.72
|
6531
|
|
Тула
|
4,090,000
|
8.61
|
4658
|
|
Рязань
|
4,320,000
|
8.01
|
5618
|
|
Коломна
|
1,030,000
|
7.35
|
6673
|
|
Курск
|
3,310,000
|
7.31
|
525
|
|
Ярославль
|
3,680,000
|
6.05
|
3457
|
|
Королёв
|
970,000
|
4.32
|
7478
|
|
Подольск
|
1,290,000
|
4.19
|
5814
|
|
Красногорск
|
690,000
|
3.93
|
8360
|
|
Рыбинск
|
650,000
|
3.52
|
2978
|
|
Балашиха
|
1,780,000
|
3.51
|
9225
|
|
Муром
|
330,000
|
3.08
|
9726
|
|
Тверь
|
1,380,000
|
3.07
|
3485
|
|
Люберцы
|
600,000
|
2.92
|
7332
|
|
Мытищи
|
530,000
|
2.25
|
7850
|
|
Электросталь
|
250,000
|
1.60
|
3001
|
Представим данные в виде графиков.


И в финале — рейтинг городов, подсчитанный по занимаемым местам.
|
Город
|
Рейтинг
|
Место
|
|
Владимир
|
12
|
1
|
|
Калуга
|
15
|
2
|
|
Москва
|
18
|
3
|
|
Зеленоград
|
21
|
4
|
|
Тамбов
|
23
|
5
|
|
Красногорск
|
35
|
6
|
|
Балашиха
|
39
|
7
|
|
Люберцы
|
45
|
8
|
|
Химки
|
46
|
9
|
|
Курск
|
47
|
10
|
|
Коломна
|
48
|
11
|
|
Кострома
|
50
|
12
|
|
Воронеж
|
52
|
13
|
|
Подольск
|
55
|
14
|
|
Тула
|
55
|
15
|
|
Рязань
|
61
|
16
|
|
Тверь
|
63
|
17
|
|
Ярославль
|
63
|
18
|
|
Муром
|
69
|
19
|
|
Рыбинск
|
69
|
20
|
|
Липецк
|
70
|
21
|
|
Королёв
|
75
|
22
|
|
Мытищи
|
75
|
23
|
|
Электросталь
|
94
|
24
|
Эпилог и выводы
Решением судейской коллегии в составе OpenStreetMap, Overpass API и ODANT,
г. Владимир занимает почетное первое место и получает титул “Самый зеленый в ЦФО”.
Стоит отметить следующий факт: наше исследование базировалось исключительно на данных, отраженных в OSM. Естественно, в Мытищах есть еще пара сотен скамеек, да и в Туле куда больше мест для скопления отходов. Наши результаты можно рассматривать с другой стороны, к примеру, для оценки динамики внесения объектов городской инфраструктуры в базу данных OSM. Однако, в среднем люди “одинаково медленно” вносят данные в OSM, поэтому мы можем считать, что данные сравнительно достоверны и заслуживают внимания.
Нам удалось решить поставленную задачу и найти эффективный способ работы с объектами на картах OSM: им оказалась комбинация Overpass API и Leaflet. С помощью данного набора инструментов мы можем делать запросы к БД OSM и получать данные о количестве объектов, вычислять площади областей. Для представления данных и аналитики мы собрали web-решение на базе ODANT, которое удовлетворило все наши потребности.
Существует большое количество отраслей производства, бизнеса и хозяйства, которым могло бы помочь данное решение. Если есть идеи или обратная связь — было бы очень приятно обсудить. Мы потратили на задачу 28 чистых часов, возможно, у вас получится быстрее.
Ведущий Frontend-разработчик, Инфостандарт — Епифанов Даниил.
Редактор, Инфостандарт — Морозов Никита.
ссылка на оригинал статьи https://habr.com/ru/post/520524/
Добавить комментарий