# Mapas

> MapContainer, pins, formas, rotas e utilitários — com as armadilhas de chave, null e thread.

Source: https://crossfly.dev/pt/docs/data-and-services/maps — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Mapas

Mapa nativo embutido com **`MapContainer`** (um `Component`) sobre a interface `Map`. Suporta Google e
OSM como engines.

## ⚠️ Quatro armadilhas que evitam bugs
1. **Configure a chave** (estática) antes de criar o mapa: `MapContainer.googleMapsKey = "...";`.
2. **`map` pode ser `null`** — acesse `mc.map` **só depois** do `onMapLoad` (e trate `null`: Web/TeaVM
   **não suporta** mapa nativo).
3. **Todas as operações de mapa na render (paint) thread** — volte com `onUI(...)` se vier de fundo.
4. A antiga `phone.GoogleMaps` (visualizador externo) **foi removida**.

## Criar e centralizar
```java
MapContainer.googleMapsKey = "SUA_CHAVE";

MapContainer mc = new MapContainer(Map.MapEngine.GOOGLE, 0, () -> {   // onMapLoad
   if (mc.map == null) return;                          // Web/TeaVM: sem mapa nativo
   mc.map.centerOnLocation(new LatLon(-23.55, -46.63), 14);
   mc.map.setMapType(Map.LayerType.NORMAL);
});
tela.add(LAY_FILL, mc);
```
`MapEngine`: `GOOGLE` · `OSM`. `LayerType`: `NORMAL` · `TERRAIN` · `HYBRID` · `SATELLITE`.

## Pins (API fluente)
```java
mc.map.add(new MapPin()
   .position(-23.55, -46.63)
   .title("São Paulo")
   .snippet("Centro")
   .draggable(false)
   .onClick(p -> { Hint.show(p.title, 2000); return true; }));   // true = suprime info window
```

## Formas — `MapShape.Line/Polygon/Circle`
```java
// círculo de 500 m (cores em ARGB 0xAARRGGBB)
MapShape.Circle c = new MapShape.Circle(2, 0xFF2196F3, 0x402196F3);
c.setPolygon(new LatLon(-23.55, -46.63), 500.0);   // centro + raio em metros
mc.map.add(c);
```
`Line(thick, color)` e `Polygon(borderWidth, borderColor, fillColor)` seguem o mesmo padrão.

## Rotas e utilitários
```java
double metros = MapUtils.distanceInMeters(new LatLon(-23.55,-46.63), new LatLon(-22.90,-43.20));
Image thumb = MapUtils.getMapImage(-23.55, -46.63, false, 13, 600, 400);   // imagem estática (null se erro/sem chave)
```
Direções reais (HTTP + **Jackson**) vêm de `DirectionsFetcher` (callback `onRouteReady(List<LatLon>)`),
combinado com `MapRoute(lineShape, pins)` — marshale o resultado com `onUI(...)`. Detalhe no
Capítulo 25.

## Boas práticas
- Chave **antes** de instanciar; acesso a `mc.map` **só** no `onMapLoad`.
- Trate `mc.map == null` (Web) e `getMapImage(...) == null`.
- Operações de mapa na render thread; resultados de rede via `onUI(...)`.

## Erros comuns
- Acessar `mc.map` no construtor (ainda `null`).
- Esquecer `MapContainer.googleMapsKey`.
- Usar `phone.GoogleMaps` (removido).

## Veja também
- [Localização e GPS](/docs/data-and-services/device-location-gps) · [LocationView](/docs/ui/widgets/locationview)
