Когда мы готовились к автоматизации работы местных муниципальных служб, мы обратили внимание на использование картографии, которое мы сочли действительно мощным и эффективным инструментом для решения широкого кластера задач. На карте можно отображать актуальную информацию о местоположении объектов, маршруты движения уборочной техники, транспорта, план работы и тепловую карту с проблемными и “здоровыми” участками.
Использование картографии в целом помогает ускорить время реакции и принятия решений по экстренным вопросам, упрощает процесс планирования и прогнозирования, а главное — вся информация доступна в максимально наглядном виде.
В ходе работы с одним из заказчиков перед нами возникла интересная задача — подсчитать количество объектов на карте по категориям.
Найти
Определить самый “зеленый” город в ЦФО по совокупности следующих данных: количество лавочек, урн и парков.
Дано
Картография. В качестве плацдарма мы выбрали 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 — его последний релиз можно найти тут.
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-разработчик, Инфостандарт — Епифанов Даниил.
Редактор, Инфостандарт — Морозов Никита.