Files
wiki/tasks/enduro-trails/BRD_TERRAIN.md
2026-05-09 20:30:07 +03:00

131 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 тайлов