auto-sync: 2026-05-09 20:30:01

This commit is contained in:
Stream
2026-05-09 20:30:07 +03:00
parent c26e4e21f0
commit d0ec715210

View File

@@ -0,0 +1,130 @@
# BRD: Рельеф (Terrain Layer)
## Цель
Пользователь видит рельеф местности на карте — цветами (все зумы) и тенями (зум 10+). Это позволяет на мелком зуме искать интересные холмистые/горные зоны, а на крупном — детально планировать маршрут по оврагам и склонам.
## Пользовательский сценарий
1. Открывает карту на зуме 6 (весь ЦФО)
2. Видит зелёные равнины, жёлтые холмы, коричневые горы
3. Находит интересную гористую зону
4. Зумит туда
5. На зуме 12+ добавляются тени — овраги и склоны становятся объёмными
6. Строит маршрут по интересному рельефу
## UI
### Кнопка в toolbar
- Иконка: 🏔️ (или `mountain` из Lucide)
- Позиция: после кнопки слоёв, перед линейкой
- Состояние: inactive (серая) / active (белая, подсвечена)
### Попап при нажатии
```
┌─────────────┐
│ 🏔️ Рельеф │
├─────────────┤
│ ☑️ Цветной │ ← всегда доступен
│ рельеф │
│ │
│ ☐ Теневой │ ← disabled на зуме < 10
│ рельеф │ (grayed out с подписью
│ │ "Доступно при приближении")
└─────────────┘
```
- Чекбоксы независимые
- Состояние сохраняется в localStorage
- Попап закрывается по тапу вне его или повторному тапу на кнопку
## Слои на карте (MapLibre)
### Цветной рельеф (hypsometric)
- **Z-Index:** между `background` и основными слоями (дороги, POI)
- **Opacity:** 0.4-0.5 (настраиваемо)
- **Zoom:** 5-15 (все зумы)
- **Source:** `terrain-hypso` → растровые тайлы `/terrain/hypso/{z}/{x}/{y}.png`
### Теневой рельеф (hillshade)
- **Z-Index:** поверх цветного, под дорогами
- **Opacity:** 0.3-0.4
- **Zoom:** 10-15 (minzoom 10)
- **Source:** `terrain-hillshade``/terrain/hillshade/{z}/{x}/{y}.png`
- **Visibility:** none при зуме < 10 (MapLibre `minzoom` + toggle)
## Данные
### Источник
SRTM 1 Arc-Second Global (~30м разрешение)
- Формат: `.hgt` файлы
- Лицензия: Public Domain (NASA)
- Покрытие: 60°N - 56°S
### Регион
ЦФО + Чувашия (первый этап)
- ~30-40 тайлов .hgt (1°×1°)
- ~100 MB сырых данных
### Генерация тайлов
#### Цветной рельеф
- GDAL: `gdaldem color-relief` с кастомной ramp
- Цвета:
- 0-50м: #2d5016 (тёмно-зелёный)
- 50-150м: #5a8a3a (зелёный)
- 150-300м: #a8c66c (светло-зелёный)
- 300-500м: #d4b85a (жёлтый)
- 500-800м: #c49420 (оранжево-жёлтый)
- 800-1200м: #8b5a2b (коричневый)
- 1200-2000м: #6b4423 (тёмно-коричневый)
- 2000м+: #ffffff (белый, снежные вершины)
- Растеризация в тайлы: `gdal2tiles.py` или rio-tiler
- Формат: PNG с прозрачностью (или без, opacity в MapLibre)
- Зумы: 5-15
- Размер тайла: 256×256
- Итоговый объём: ~50-100 MB (оценочно)
#### Теневой рельеф
- GDAL: `gdaldem hillshade` (-az 315 -alt 45)
- Grayscale PNG
- Зумы: 10-15
- Итоговый объём: ~20-40 MB
### Хранение
- Сервер: `/home/slin/enduro-trails/data/terrain/`
- `hypso/{z}/{x}/{y}.png`
- `hillshade/{z}/{x}/{y}.png`
- Nginx: location `/enduro/terrain/` → alias `/home/slin/enduro-trails/data/terrain/`
- Кэширование: `expires 1y` (тайлы не меняются)
## Интеграция с существующим кодом
### Backend (FastAPI)
- Новый endpoint не нужен — nginx отдаёт статику
- При необходимости: `/terrain/{layer}/{z}/{x}/{y}.png` → FileResponse
### Frontend (MapLibre)
- Добавить `raster` sources в стиль карты
- Добавить `raster` layers с `paint: { 'raster-opacity': ... }`
- Toolbar: кнопка + попап компонент
- localStorage ключ: `terrain_layers`
### Стили
- Тёмная тема: ramp адаптирован под тёмную подложку
- Светлая тема: ramp адаптирован под светлую (после F-18)
## Приоритет
P1 — блокер для фазы 6 (SRTM профиль высот, фича «Горка»)
## Критерии приёмки
- [ ] На зуме 6 виден цветной рельеф всего ЦФО
- [ ] Москва — зелёная, Смоленская возвышенность — жёлтая, Урал на востоке — коричневый
- [ ] На зуме 12+ теневой рельеф показывает овраги и склоны
- [ ] Тoggle работает: можно цветной без теневого, теневой без цветного, оба, ни одного
- [ ] Состояние сохраняется после перезагрузки
- [ ] Мобильный: попап не перекрывает кнопки, закрывается по тапу вне
- [ ] Десктоп: попап позиционируется относительно кнопки
## Зависимости
- SRTM данные (скачать)
- GDAL в контейнере/на сервере (или отдельный скрипт генерации)
- Место на диске: ~150 MB тайлов