Files
worldmonitor/docs/map-engine.mdx
Elie Habib 1f38dea225 docs: restructure documentation into focused, navigable pages (#1465)
* docs: restructure documentation into focused, navigable pages (#docs-reorg)

Break the 4096-line documentation.mdx monolith into 13 focused pages
organized by feature area. Reorganize Mintlify navigation from 5 generic
groups into 7 feature-based groups. Move Orbital Surveillance from
Infrastructure to Map Layers where it belongs.

- Extract: signal-intelligence, features, overview, hotspots, CII,
  geographic-convergence, strategic-risk, infrastructure-cascade,
  military-tracking, maritime-intelligence, natural-disasters,
  contributing, getting-started
- Append to: architecture.mdx (9 sections), ai-intelligence.mdx (3 sections)
- Fix legacy .md links in map-engine.mdx, maps-and-geocoding.mdx
- Slim documentation.mdx to an 80-line index/hub page
- Eliminate duplicate content that caused repeated headings

* fix(docs): remove duplicate H1 headings from all Mintlify pages

Mintlify auto-renders the frontmatter `title` as an H1, so having
`# Title` in the body creates a doubled heading on every page.
Remove the redundant H1 (and repeated description lines) from all
31 .mdx files.
2026-03-12 06:44:35 +04:00

80 lines
9.0 KiB
Plaintext
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.
---
title: "Map Engine"
description: "3D globe and flat map rendering, textures, shaders, clustering, and mobile touch gestures in World Monitor."
---
### Dual Map Engine — 3D Globe + Flat Map
Two rendering engines are available, switchable at runtime via Settings or the `VITE_MAP_INTERACTION_MODE` environment variable (`globe` or `flat`). The preference is persisted in localStorage.
**3D Globe (globe.gl + Three.js)** — a photorealistic 3D Earth with full pitch and rotation:
- **Earth textures** — topographic-bathymetric day surface (`earth-topo-bathy.jpg`), specular water map for ocean reflections, and a starfield night-sky background
- **Atmosphere shader** — a Fresnel limb-glow effect simulates atmospheric scattering at the globe's edge
- **Auto-rotation** — the globe slowly rotates when idle, pausing on any user interaction and resuming after 60 seconds of inactivity
- **HTML marker layer** — all 28+ data categories (conflicts, intel hotspots, AIS vessels, flights, protests, fires, etc.) render as HTML elements pinned to geographic coordinates on the globe surface
- **Geopolitical polygon overlays** — the Korean DMZ and other boundary polygons render directly on the globe under the conflicts layer
- **Debounced marker flush** — rapid data updates are coalesced via `debounceFlushMarkers()` to prevent Three.js scene graph crashes during high-frequency data refresh
- **Configurable render quality** — a Settings dropdown offers five pixel-ratio presets: Auto (matches device DPR, capped at 2×), Eco (1×), Sharp (1.5×), 4K (2×), and Insane (3×). The setting updates the Three.js renderer live without page reload. Desktop (Tauri) builds cap the default at 1.25× to avoid software-rendering fallback on machines without discrete GPUs
- **Desktop-optimized defaults** — Tauri desktop builds request the high-performance GPU (`powerPreference: 'high-performance'`), disable the logarithmic depth buffer (saves shader overhead), and turn off auto-rotation and camera damping to eliminate continuous render loop wakeups when idle — addressing reports of 1 fps performance on some machines
- **Background pause** — when the desktop app window loses focus or the globe panel is hidden, the WebGL render loop pauses entirely, stopping the Three.js animation loop and canceling auto-rotate. Data updates received while paused are queued and flushed in a single batch when the globe returns to view, eliminating background GPU load on laptops
- **Beta indicator** — a pulsing cyan "BETA" badge appears when the globe is active, signaling the feature is newer than the flat map
### Map Tile Providers
The flat map supports multiple tile providers, selectable at runtime via **Settings → Map Tile Provider**. The selection persists in localStorage.
| Provider | Description | Cost | Default |
|----------|-------------|------|---------|
| **OpenFreeMap** | Free community-hosted OpenStreetMap tiles. Dark and Positron styles. No API key required. | Free | Yes (when `VITE_PMTILES_URL` is unset) |
| **CARTO** | CARTO's Dark Matter and Voyager GL styles. No API key required. | Free tier | No |
| **PMTiles (self-hosted)** | Self-hosted vector tiles via the [PMTiles](https://protomaps.com/docs/pmtiles) format. Tiles are served as a single `.pmtiles` archive file over HTTP Range requests — the browser only downloads tiles for the current viewport (~50-200KB per pan/zoom), not the entire file. Requires `VITE_PMTILES_URL` environment variable. | Self-hosted | Yes (when `VITE_PMTILES_URL` is set) |
| **Auto** | Tries PMTiles first, falls back to OpenFreeMap on error (2+ tile load failures or 10s timeout). Only available when `VITE_PMTILES_URL` is set. | Self-hosted | No |
**OSS-friendly defaults**: When `VITE_PMTILES_URL` is not set (the default), only OpenFreeMap and CARTO appear in Settings. PMTiles and Auto options are hidden. This ensures community installations work out of the box with zero configuration and no external tile hosting costs.
**Self-hosting PMTiles**: To use your own tiles:
1. Download a PMTiles planet file from [Protomaps builds](https://maps.protomaps.com/builds/) or generate a regional extract with [`go-pmtiles extract`](https://github.com/protomaps/go-pmtiles)
2. Upload to any HTTP server that supports Range requests (Cloudflare R2, S3, or a static file server)
3. Set `VITE_PMTILES_URL=https://your-server.example/planet.pmtiles` in `.env.local`
4. The PMTiles and Auto options will appear in Settings
### Map Themes
Each tile provider offers different visual themes, selectable via **Settings → Map Theme**. The theme selection is **per-provider** — switching providers remembers each provider's last-used theme. Map theme is fully independent of the app theme (Auto/Dark/Light); the app theme only affects UI chrome, while the map theme controls basemap appearance.
| Provider | Available Themes | Default |
|----------|-----------------|---------|
| **PMTiles** | Black (deepest dark), Dark, Grayscale, Light, White | Black |
| **OpenFreeMap** | Dark, Positron (light) | Dark |
| **CARTO** | Dark Matter, Voyager (light), Positron (light) | Dark Matter |
**Sprite mapping**: PMTiles themes `black`, `dark`, and `grayscale` use the `dark` Protomaps sprite sheet; `light` and `white` use the `light` sprite sheet.
**Overlay paint adaptation**: Country highlight/hover paint colors automatically adapt to the selected map theme (not the app theme), using lower opacity on light themes for visibility.
**Fallback behavior**: When using PMTiles or Auto mode, if tile loading fails (CORS errors, server downtime, 403s), the map automatically falls back to OpenFreeMap after detecting 2+ errors within 10 seconds. The fallback respects the current map theme's light/dark nature — a light PMTiles theme falls back to OpenFreeMap Positron, not Dark. A console warning is logged when fallback activates.
**Flat Map (deck.gl + MapLibre GL JS)** — a WebGL-accelerated 2D map with smooth 60fps rendering and thousands of concurrent markers:
- **Layer types** — `GeoJsonLayer`, `ScatterplotLayer`, `PathLayer`, `IconLayer`, `TextLayer`, `PolygonLayer`, `ArcLayer`, `HeatmapLayer` composited in a single render pass
- **Smart clustering** — Supercluster groups markers at low zoom, expands on zoom in. Cluster thresholds adapt to zoom level
- **Progressive disclosure** — detail layers (bases, nuclear, datacenters) appear only when zoomed in; zoom-adaptive opacity fades markers from 0.2 at world view to 1.0 at street level
- **Label deconfliction** — overlapping labels (e.g., multiple BREAKING badges) are automatically suppressed by priority, highest-severity first
- **Day/night overlay** — a terminator line divides the map into sunlit and dark hemispheres based on the current UTC time
**Shared across both engines:**
- **45 data layers** — conflicts, military bases, nuclear facilities, undersea cables, pipelines, satellite fire detection, protests, natural disasters, datacenters, displacement flows, climate anomalies, cyber threat IOCs, GPS/GNSS jamming zones, Iran attacks, CII country risk heatmap, day/night terminator, geopolitical boundaries (Korean DMZ), stock exchanges, financial centers, central banks, commodity hubs, Gulf investments, trade routes, airport delays, sanctions regimes, and more. All layer definitions are maintained in a single shared catalog (`map-layer-definitions.ts`) consumed by both renderers — adding a new layer is a single-file operation. Layers are variant-specific: full (29 geopolitical + military + infrastructure), tech (12 startup/cloud/cyber), finance (15 exchange/banking/trade), and happy (5 positive-events/conservation)
- **8 regional presets** — Global, Americas, Europe, MENA, Asia, Africa, Oceania, Latin America
- **Time filtering** — 1h, 6h, 24h, 48h, 7d event windows
- **URL state sharing** — map center, zoom, active layers, and time range are encoded in the URL for shareable views (`?view=mena&zoom=4&layers=conflicts,bases`)
- **Mobile touch gestures** — single-finger pan with inertial velocity animation (0.92 decay factor, computed from 4-entry circular touch history), two-finger pinch-to-zoom with center-point preservation, and bottom-sheet popups with drag-to-dismiss. An 8px movement threshold prevents accidental interaction during taps
- **Timezone-based region detection** — on first load, the map centers on the user's approximate region derived from `Intl.DateTimeFormat().resolvedOptions().timeZone` — no network dependency, no geolocation prompt. On mobile, the browser's Geolocation API is queried (5-second timeout) and the map auto-centers on the user's precise GPS coordinates at zoom level 6. If the URL already contains shared coordinates, the shared view takes precedence and geolocation is skipped
- **Cmd+K map navigation** — the command palette supports `Map:` prefixed commands to fly to any country or region on either engine
### Static Map Assets & Geocoding
Country boundaries, boundary overrides, and the geocoding service are documented in [Maps & Geocoding](/maps-and-geocoding). All large static files are served from R2 CDN via `maps.worldmonitor.app`.