# Arma raster tiles Servidor estático de tiles raster XYZ para os mapas de Arma 3 fornecidos como KML/KMZ `GroundOverlay`. Todas as fontes compõem uma camada mundial única: não existe identificador de mapa na URL. ## Arquitetura `tile-builder` lê `source/` recursivamente, extrai KMZs somente em diretórios temporários, lê cada `GroundOverlay`, localiza a imagem local indicada por `Icon/href` e a reprojeta para Web Mercator (EPSG:3857). Para `LatLonBox` com `rotation`, os quatro cantos são girados no sentido anti-horário em torno do centro antes do warp GDAL; o raster final recebe alfa para conservar transparência e recortar as bordas rotacionadas. Cada overlay gera tiles temporários por `gdal2tiles --xyz`. O builder os compõe com alfa em uma única pirâmide. Uma área menor tem prioridade e é desenhada por cima; se as áreas forem iguais, vence primeiro o caminho relativo em ordem alfabética e depois o índice do `GroundOverlay`. A área é calculada a partir do polígono rotacionado em EPSG:3857. O resultado físico é: ```text tiles/{z}/{x}/{y}.png tiles/metadata.json ``` O Nginx aceita exclusivamente a rota pública abaixo e faz a tradução interna. Não publique nem use a ordem de armazenamento diretamente. ```text https://arma_tiles.valmo.dev/tiles/{x}/{y}/{z} https://arma_tiles.valmo.dev/tiles/18342/12417/15 ``` Mesmo sem `.png` na URL, a resposta é `Content-Type: image/png`. Tiles ausentes, inclusive áreas sem cobertura, respondem `404`. ## Entradas Coloque `.kmz` e `.kml` em `source/`, inclusive em subpastas. Um KMZ deve conter um KML (o builder prefere `doc.kml`) e a imagem local referenciada pelo KML. KMLs soltos podem referenciar imagens dentro da mesma árvore de `source/`. Os arquivos de entrada nunca são modificados ou removidos. Erros por arquivo são registrados em `tiles/metadata.json` e não bloqueiam as demais fontes. Links HTTP(S), caminhos absolutos e `gx:LatLonQuad` não fazem parte desta primeira versão; use `LatLonBox` e imagens locais. ## Zoom e configuração O máximo automático de cada overlay é calculado a partir da maior resolução reprojetada em metros por pixel. O builder escolhe o maior zoom cuja resolução de tile ainda não é mais detalhada que a fonte, evitando ampliação de pixels. O mínimo automático é `clamp(maxzoom - 7, 6, 10)`, oferecendo alguns níveis de contexto sem criar uma pirâmide mundial vazia. Cada fonte para no próprio máximo: acima dele não haverá tile direto dessa fonte. Se nenhuma outra fonte cobrir a coordenada, a resposta será `404`. `config/maps.json` permite overrides globais e por caminho relativo a `source/`: ```json { "global": { "minzoom": null, "maxzoom": null }, "sources": { "Altis.kmz": { "minzoom": 8, "maxzoom": 16 }, "subpasta/exemplo.kml": { "maxzoom": 14 } } } ``` Use inteiro entre 0 e 22 ou `null`. A precedência é fonte, global, cálculo automático. Um `maxzoom` explícito acima do máximo automático é permitido e ficará marcado em `metadata.json`, pois solicita ampliação conscientemente. ## Geração local Dependências locais: Python 3, Pillow, GDAL com `gdal_translate`, `gdalwarp`, `gdalinfo` e `gdal2tiles.py`. ```bash ./scripts/build-tiles.sh ./scripts/build-tiles.sh --source-filter Altis.kmz ``` O cache em `cache/` usa SHA-256 da fonte. Entradas inalteradas reutilizam os GeoTIFFs reprojetados. Para garantir a composição e a prioridade corretas, a v1 recompõe a pirâmide final inteira em staging a cada build; apenas a reprojeção das fontes inalteradas é reutilizada. O diretório final é publicado somente após a geração de `metadata.json`. ## Docker Compose e Coolify Para desenvolvimento local: ```bash docker compose up --build ``` O Nginx ficará disponível em `http://localhost:8080`. O Compose executa primeiro o builder e monta o volume de tiles como somente leitura no Nginx. No Coolify, mantenha as entradas fora do Git e crie uma pasta/volume persistente no host. Defina `ARMA_TILES_SOURCE_DIR` para esse caminho; ele será montado como `/app/source` somente leitura. O volume nomeado `arma_tiles_data` preserva tiles e cache entre deploys. Configure o domínio `arma_tiles.valmo.dev` e TLS no proxy do Coolify, apontando para a porta 80 do serviço `tiles`. Para limitar paralelismo do GDAL, configure `GDAL2TILES_PROCESSES` (o padrão é `1`). As respostas de tile têm cache público de um dia e `stale-while-revalidate` de sete dias, além de ETag. ## Validação ```bash python3 tests/test_build_tiles.py ./scripts/smoke-test.sh ``` O teste de fumaça processa `Altis.kmz`, verifica `tiles/metadata.json` e um PNG, sobe o Nginx, consulta uma tile pela ordem pública `{x}/{y}/{z}` e confirma `200` com `image/png`; também confirma `404` para `/tiles/0/0/0`. ## Limitações conhecidas - Não há watcher: após adicionar ou alterar uma entrada, execute o builder ou faça um novo deploy. - A composição final ainda é uma reconstrução global; a estrutura de cache permite uma futura invalidação apenas dos tiles afetados. - Esta versão não baixa imagens externas, não suporta `gx:LatLonQuad`, não trata overlays que cruzam o antimeridiano e não inclui DEM, hillshade, vetores, MBTiles, frontend, autenticação ou banco de dados.