Добавим туда папку `backend`. Загрузим [отсюда](https://github.com/gtitov/flask-maplibre-map/raw/refs/heads/main/backend/cities_index.sqlite) и положим туда базу данных. И создадим в этой папке файл с нашим бэкендом `app.py`.
Добавим туда папку `backend`. Загрузим [отсюда](https://github.com/gtitov/flask-maplibre-map/raw/refs/heads/main/backend/cities_index.sqlite) базу данных и положим в созданную папку `backend`. Cоздадим в этой папке файл с нашим бэкендом `app.py`.
Данные можно поделить на кусочки и передавать пользователю только *нужные кусочки* с *нужной детальностью*. Данные можно поделить на кусочки по-разному. Пространственные данные ожидаемо удобно делить на географические кусочки — тайлы. *Нужные кусочки* -- те, что попадают на экран. *Нужная детальность* -- та, что соответствует текущему масштабу карты.
Данные можно поделить на кусочки и передавать пользователю только *нужные кусочки* с *нужной детальностью*. Данные можно поделить на кусочки по-разному. Пространственные данные ожидаемо удобно делить на географические кусочки — тайлы. *Нужные кусочки* -- те, что попадают на экран. *Нужная детальность* -- та, что соответствует текущему масштабу карты.
Стандартная система тайлов делит планету на квадраты X/Y для каждого уровня зума Z. Каждый тайл имеет индекс Z/X/Y. По этому индексу и выполняются запросы тайлов, то есть формируется API сервиса векторных тайлов. Когда запрос выполняется, вызывается серверная функция, формирующая тайл, или возвращается заранее рассчитанный (кэшированный) тайл.
Стандартная система тайлов делит планету на квадраты X/Y для каждого уровня зума Z. Каждый тайл имеет индекс Z/X/Y. По этому индексу и выполняются запросы тайлов. Так формируется API сервиса векторных тайлов. Когда запрос выполняется, вызывается серверная функция, формирующая тайл, или возвращается заранее рассчитанный (кэшированный) тайл.
Познакомимся к возможностями практического применения тайлов. Для этого загрузим наборы пространственных данных в базу пространственных данных. Подключим к ней сервер векторных тайлов. Получим векторные тайлы на клиентской стороне веб-приложения средствами картографической библиотеки.
Познакомимся c возможностями практического применения тайлов. Для этого загрузим наборы пространственных данных в базу пространственных данных. Подключим к ней сервер векторных тайлов. Получим векторные тайлы на клиентской стороне веб-приложения средствами картографической библиотеки.
Дистрибутив для сервера баз данных можно загрузим [здесь](https://www.postgresql.org/download/). При установке следует обратить внимание на порт, который будет занимать сервер баз данных, и пароль для пользователя `postgres`.
Дистрибутив для сервера баз данных загрузим [здесь](https://www.postgresql.org/download/). При установке следует обратить внимание на порт, который будет занимать сервер баз данных, и пароль для пользователя `postgres`.
> Сервер баз данных запускается локально. Доступ к локальному серверу баз данных осуществляется по заданному при установке порту -- обычно 5432. Если установщик предлагает другой порт, возможно, что у вас уже установлен сервер баз данных, который этот порт занимает.
> Сервер баз данных запускается локально. Доступ к локальному серверу баз данных осуществляется по заданному при установке порту -- обычно 5432. Если установщик предлагает другой порт, возможно, что у вас уже установлен сервер баз данных, который этот порт занимает.
После установки сервера баз данных Postgres можно установить расширение для работы с пространственными данными PostGIS. Дистрибутив доступен [тут](https://postgis.net/documentation/getting_started/#installing-postgis).
После установки сервера баз данных Postgres можно установить расширение для работы с пространственными данными PostGIS. Дистрибутив доступен [тут](https://postgis.net/documentation/getting_started/#installing-postgis).
> Наблюдаются проблемы с установкой PostGIS на Windows через StackBuilder. Рабочим вариантом является самостоятельная загрузка дистрибутива PostGIS [отсюда](https://download.osgeo.org/postgis/windows/). Найдите папку с версией Postgres, которую установили. Например, для Postgres 17 нужна папка `pg17/`, в папке находится дистрибутив `pg17/postgis-bundle-pg17x64-setup-3.5.0-2.exe`.
> На Windows наблюдаются проблемы с установкой PostGIS через StackBuilder. Рабочим вариантом является самостоятельная загрузка дистрибутива PostGIS [отсюда](https://download.osgeo.org/postgis/windows/). Найдите папку с версией Postgres, которую установили. Например, для Postgres 17 нужна папка `pg17/`, в папке находится дистрибутив `pg17/postgis-bundle-pg17x64-setup-3.5.0-2.exe`.
#### Создание базы данных
#### Создание базы данных
Вместе с сервером базы данных устанавливается графический интерфейс для работы с базами данных PgAdmin 4.
Вместе с сервером базы данных устанавливается графический интерфейс для работы с базами данных PgAdmin 4.

> При необходимости, его можно установить [отдельно](https://www.pgadmin.org/download/).
> При необходимости, его можно установить [отдельно](https://www.pgadmin.org/download/).
Через этот интерфейс мы создадим базу данных на нашем локальном сервере.
Через этот интерфейс мы создадим базу данных на нашем локальном сервере.
И добавим к созданной базе расширение PostGIS.

Назовём базу данных `oikonyms`. Остальные параметры оставим по умолчанию.

И добавим к созданной базе расширение `PostGIS`.


База пространственных данных создана. Пора её наполнить!
Сделаем это через [QGIS](https://www.qgis.org/download/).
Сделаем это через [QGIS](https://www.qgis.org/download/).

Добавим слои на карту.
Добавим слои на карту.

Выполним подключение к базе данных.
Выполним подключение к базе данных.
Перенесём слои с карты в базу данных.

Назовём подключение `oikonyms-database`. Наша база размещена на локальном сервере `localhost`, занимает порт `5432`, а называется `oikonyms`. Используем базовую аутентификацию (Authentication - Basic), где укажем логин и пароль.

Увидим нашу базу данных в списке подключений. Словом `public` обозначена схема базы данных, которую мы будем заполнять. Она создаётся для базы данных по умолчанию.

Перенесём слои с карты в базу данных. Это можно сделать прямо из списка слоёв.

Для проверки можно перенести наборы данных, загруженные в базу, на карту и посмотреть, как они выглядят.
### Векторные тайлы
### Векторные тайлы
Подготовим векторные тайлы на основе данных, загруженных в базу.
Мы не будем обращаться к базе данных напрямую. Мы добавим прослойку, которая будет формировать векторные тайлы на основе загруженных в базу данных.
#### Сервер векторных тайлов
#### Сервер векторных тайлов
Для подготовки векторных тайлов используем сервер векторных тайлов Martin. Загрузим это приложение [отсюда](https://github.com/maplibre/martin/releases/tag/v0.14.2).
Для подготовки векторных тайлов используем сервер векторных тайлов Martin. Загрузим это приложение [отсюда](https://github.com/maplibre/martin/releases/tag/v0.14.2).
Распакуем архив и запустим сервер векторных тайлов, указав подключение к локальной базе данных, куда мы загрузили ойконимы.
Распакуем архив и запустим сервер векторных тайлов, указав подключение к локальной базе данных, куда мы загрузили ойконимы. Чтобы это сделать, надо запустить терминал в папке, где распакован исполняемый файл Martin, например, `martin.exe`. И выполнить команду, которая в общем виде будет выглядеть так.
```sh
martin postgresql://postgres:password@localhost:5432/oikonyms
```
А в Windows приобетёт такой вид.

После успешного выполнения увидим это.

На последней строчке увидим, что каталог слоёв доступен по адресу `http://0.0.0.0:3000/catalog`, то есть по IP адресам компьютера. Мы воспользуемся нашим любимым `localhost` (другие обычно и недоступны).
Перейдём по адресу `localhost:3000/catalog`, чтобы увидеть доступные наборы векторных тайлов. Их должно быть два по количеству пространственных таблиц в базе данных.
Перейдём по адресу `localhost:3000/catalog`, чтобы увидеть доступные наборы векторных тайлов. Их должно быть два по количеству пространственных таблиц в базе данных.
Остаётся принять эти векторные тайлы на карте. Заготовку для карты формируем как обычно.
Остаётся принять эти векторные тайлы на карте. Заготовку для карты формируем как обычно.
Добавляем источник пространственных данных и картографический слой. При добавлении источника пространственных данных указываем тип `vector`, а не `geojson`, как в прошлых картах. При добавлении слоя указываем `source-layer` -- векторный тайл может содержать несколько слоёв. В нашем случае слой только один, посмотреть мы на него можем в TileJSON описании `localhost:3000/grid`, где идентификаторы слоёв указываются в обязательном списке `vector_layers`.
Добавляем источник пространственных данных и картографический слой. При добавлении источника пространственных данных указываем тип `vector`, а не `geojson`, как в прошлых картах.
При добавлении слоя указываем `source-layer` -- векторный тайл может содержать несколько слоёв. В нашем случае слой только один, посмотреть мы на него можем в TileJSON описании `localhost:3000/grid`, где идентификаторы слоёв указываются в обязательном списке `vector_layers`.

```js title=main.js {2, 8}
```js title=main.js {2, 8}
map.addSource("grid", {
map.addSource("grid", {
@ -107,7 +156,9 @@ map.addLayer({
})
})
```
```
При добавлении источника мы можем указать не только `url` TileJSON описания, но и `tiles` -- список адресов, по которому можно выполнять запросы к тайлам. Если мы указываем `url`, MapLibre самостоятельно находит этот список в TileJSON описании.
При добавлении источника вместо `url` TileJSON-файла мы можем указать `tiles` -- список адресов, по которому можно выполнять запросы к тайлам. Если мы указываем `url`, MapLibre самостоятельно находит этот список в TileJSON описании.

```js title=main.js {3}
```js title=main.js {3}
map.addSource("oikonyms", {
map.addSource("oikonyms", {
@ -125,8 +176,12 @@ map.addLayer({
### Веб-карта
### Веб-карта
Подключили источники данных. Теперь пора заняться визуализацией.
#### Оформление слоёв
#### Оформление слоёв
Слой с сеткой шестиугольников раскрасим интерполяцией цвета по полю численности населения в ячейке.
```js title=main.js
```js title=main.js
map.addLayer({
map.addLayer({
id: "grid-layer",
id: "grid-layer",
@ -135,22 +190,18 @@ map.addLayer({
type: "fill",
type: "fill",
paint: {
paint: {
"fill-color": [
"fill-color": [
"interpolate",
"interpolate", ["linear"],
["linear"],
['to-number', ["get", "sum_pop"]],
['to-number', ["get", "sum_pop"]],
0,
0, "#440154",
"#440154",
100, "#39568c",
100,
1000, '#1f968b',
"#39568c",
10000, '#fde725'
1000,
'#1f968b',
10000,
'#fde725'
]
]
}
}
})
})
```
```
Слой с точками населённых пунктов покажем пунсонами с обводкой.
```js title=main.js
```js title=main.js
map.addLayer({
map.addLayer({
@ -170,6 +221,10 @@ map.addLayer({
#### Подсветка при наведении
#### Подсветка при наведении
Мы уже видели изменение курсора при наведении на объект. Ещё одним вариантом является подсветка объекта при наведении курсора. Воспользуемся одним из способов реализации обводки.
Назначим поле `id` из свойств слоя идентификатором объектов слоя.
```diff title=main.js
```diff title=main.js
map.addSource("grid", {
map.addSource("grid", {
type: "vector",
type: "vector",
@ -178,11 +233,15 @@ map.addSource("grid", {
})
})
```
```
Присвоим объектам слоя состояние `hover`, которое будет становиться для объекта`true`, когда курсор попадает на объект, и `false`, когда курсор переходит на другой объект или покидает слой.
Действием при клике на ячейку сетки будет подлёт к точке клика на 10 уровень зума. Чтобы подчеркнуть интерактивность слоя, к обводке добавим и изменение курсора.