|
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
nigig-map / test (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
Complete overlay rendering system ported from Makepad upstream: ## New Features - **Route Overlay Rendering**: Route polyline with casing (9px) and fill (5.5px) - Traveled portion dimming (alpha 0.30) for navigation progress - Additive glow effect (route_glow) for visual enhancement - Destination dot at route end - Screen-space rendering with viewport clipping - **Drop Markers**: Professional pin-shaped markers with: - Soft ground shadow (ellipse) - Triangular tail + circular head pin shape - White pip in center - 16px tap detection radius for interaction - Custom color support per marker - **Position Puck**: Current location indicator with: - Accuracy circle (scales with zoom, 10-28% alpha) - Heading wedge (20px tip, shows direction) - White ring + blue dot (9px/6.2px) - Automatic viewport clipping (60px margin) ## Implementation Details - **OverlayCamera**: Screen-space transformation system - norm_to_screen() converts normalized coords to screen pixels - Supports rotation and 2.5D tilt (for future phases) - Meters-per-pixel calculation for accuracy circle scaling - **Integration**: Seamlessly integrated into NigigMapView - Added draw_overlay: DrawVector field to widget - Added overlay_state: MapOverlayState field - Rendering happens after tile passes, before status text - Zero overhead when no overlays are active (is_empty() check) - **Helper Functions**: - draw_route(): Multi-pass route rendering with travel dimming - draw_marker(): Pin-shaped marker with shadow and highlight - draw_puck(): Location indicator with accuracy and heading - marker_at(): Hit testing for tap interaction - **Viewport Enhancement**: Added meters_per_pixel() method - Calculates real-world scale for accuracy circle sizing - Accounts for latitude-based distortion - Used by position puck for realistic accuracy visualization ## Technical Architecture - Immediate-mode rendering using DrawVector - Per-frame geometry rebuild (route scale: few hundred points) - Viewport clipping with margin (24px for routes, 30px for markers) - Decimation for performance (1.5px threshold on zoom-out) - Additive blending for glow effects (no HDR required) ## Files Changed - crates/apps/map/src/overlay.rs (NEW, 379 lines) - crates/apps/map/src/lib.rs (module registration) - crates/apps/map/src/view.rs (widget integration, 15 lines added) - crates/apps/map/src/viewport.rs (meters_per_pixel method, 18 lines) ## API Usage ## Performance - Zero cost when no overlays (early return on is_empty()) - Efficient viewport clipping reduces overdraw - Route decimation prevents excessive geometry at low zoom - All rendering uses GPU-accelerated DrawVector ## Compatibility - Backward compatible: existing map functionality unchanged - Overlay state persists across frames (no per-frame allocation) - Integrates with existing theme system (route colors from theme) - Supports future 2.5D camera and heading-up rotation ## Testing Recommendations 1. Verify routes render with casing/fill at all zoom levels 2. Test traveled portion dimming updates correctly 3. Verify markers appear at correct screen positions 4. Test position puck accuracy circle scales with zoom 5. Verify heading wedge rotates correctly 6. Test viewport clipping at screen edges Refs: Phase 2 from MAKEPAD_DEV_BRANCH_GAP_ANALYSIS.md Built on: Phase 1 (POI icon system, commit ae23d36) |
||
|---|---|---|
| .. | ||
| benches | ||
| certs | ||
| fuzz | ||
| src | ||
| tests | ||
| API.md | ||
| Cargo.toml | ||
| README.md | ||
| USER_GUIDE.md | ||
Nigig Map
A high-performance, offline-capable map rendering widget for Makepad applications.
Overview
Nigig Map is a vector tile renderer designed for Makepad applications. It supports both offline (MBTiles) and online (Overpass API) map data sources, with comprehensive label placement, style customization, and smooth pan/zoom interactions.
Features
- Offline Maps: Load and render MBTiles files for offline map display
- Online Maps: Fetch and render map data from Overpass API
- Vector Tiles: Render vector tiles with fill, stroke, and label layers
- Label Placement: Intelligent label placement with collision detection
- Style Customization: Comprehensive style system with zoom-dependent styles
- Smooth Interactions: Smooth pan, zoom, and pinch gestures
- Performance Optimized: Optimized for 60 FPS rendering with efficient caching
Architecture
The map renderer follows a modular architecture with clear separation of concerns:
view.rs (1115 lines) - Main widget, orchestrates rendering
├── viewport.rs (538 lines) - Viewport state and transformations
├── cache.rs (786 lines) - Tile caching with LRU eviction
├── scheduler.rs (849 lines) - Tile loading scheduler
├── render_graph.rs - Render graph execution
├── tessellation.rs (597 lines) - Geometry tessellation
├── mvt_parser.rs (711 lines) - MVT tile parsing
├── overpass_parser.rs (282 lines) - Overpass API parsing
├── style.rs (496 lines) - Style compilation
├── label.rs (1098 lines) - Label extraction
├── label_state.rs (487 lines) - Label placement
├── sprite.rs (433 lines) - Sprite rendering
├── tile.rs (303 lines) - Tile types
├── tile_decode.rs (361 lines) - Tile decoding
└── tile_disk.rs (204 lines) - Disk cache
Usage
Basic Usage
use makepad_widgets::*;
use nigig_map::MapView;
live_design!{
use mod.prelude.widgets.*;
MyApp = {{App}} {
ui: <Window> {
map_view = <MapView> {
center_lon: 36.8219, // Nairobi
center_lat: -1.2921,
zoom: 14.0,
min_zoom: 10.0,
max_zoom: 18.0,
use_local_mbtiles: true,
local_mbtiles_path: "kenya-shortbread-1.0.mbtiles",
}
}
}
}
Offline Maps (MBTiles)
map_view = <MapView> {
use_local_mbtiles: true,
local_mbtiles_path: "kenya-shortbread-1.0.mbtiles",
use_network: false,
}
Online Maps (Overpass API)
map_view = <MapView> {
use_local_mbtiles: false,
use_network: true,
}
Style Customization
map_view = <MapView> {
style_light: MapThemeStyle {
background: #xeaf0f5,
label: #x1f2937,
MapFillRule { group: "building", color: #xd7dee7 },
MapFillRule { group: "water", color: #xbfe7fb },
MapRoadRule {
kind: "motorway",
sort_rank: 700,
casing_color: #xc1782f,
casing_width: 6.2,
center_color: #xffc266,
center_width: 4.2,
},
},
}
Programmatic Control
// Load style from JSON
map_view.load_style_json(style_json)?;
// Enable/disable render passes
map_view.enable_pass(PassType::Label);
map_view.disable_pass(PassType::POI);
// Set zoom range for a pass
map_view.set_pass_zoom_range(PassType::Label, 14.0, 20.0);
// Access render graph
let graph = map_view.render_graph();
API Reference
MapView
The main map widget.
Properties
center_lon: f64- Center longitude (default: 4.9041)center_lat: f64- Center latitude (default: 52.3676)zoom: f64- Zoom level (default: 14.0)min_zoom: f64- Minimum zoom level (default: 11.0)max_zoom: f64- Maximum zoom level (default: 17.0)dark_theme: bool- Use dark theme (default: false)use_network: bool- Enable network requests (default: true)use_local_mbtiles: bool- Use local MBTiles (default: true)local_mbtiles_path: String- Path to MBTiles filelocal_tile_cache_dir: String- Path to tile cache directorystyle_light: MapThemeStyle- Light theme stylestyle_dark: MapThemeStyle- Dark theme style
Methods
load_style_json(json_str: &str) -> Result<(), String>- Load style from JSONrecompile_style_for_zoom(zoom: f64)- Recompile style for zoom levelrender_graph() -> &RenderGraph- Get render graph referenceenable_pass(pass_type: PassType)- Enable render passdisable_pass(pass_type: PassType)- Disable render passset_pass_zoom_range(pass_type: PassType, min_zoom: f64, max_zoom: f64)- Set zoom range for pass
MapThemeStyle
Style configuration for map rendering.
Properties
background: Vec4f- Background colorlabel: Vec4f- Label colorstatus_text: Vec4f- Status text colorfill_rules: Vec<MapFillRule>- Fill rulesroad_rules: Vec<MapRoadRule>- Road ruleswaterway_rules: Vec<MapWaterwayRule>- Waterway rulesrail_rules: Vec<MapRailRule>- Rail rules
MapFillRule
Fill rule for polygon features.
Properties
group: String- Feature group (e.g., "building", "water")value: String- Feature value (e.g., "residential", "yes")color: Vec4f- Fill color
MapRoadRule
Road rendering rule.
Properties
kind: String- Road kind (e.g., "motorway", "primary")sort_rank: i32- Sort rank (higher = drawn on top)casing_color: Vec4f- Casing colorcasing_width: f32- Casing widthcasing_shape_id: f32- Casing shape IDcenter_color: Vec4f- Center colorcenter_width: f32- Center widthcenter_shape_id: f32- Center shape ID
PassType
Render pass types.
PassType::Fill- Fill pass (polygons)PassType::Stroke- Stroke pass (lines)PassType::Label- Label pass (text)PassType::POI- POI pass (points of interest)
Performance
The map renderer is optimized for 60 FPS rendering:
- Efficient Caching: LRU cache with configurable size (default: 640 tiles)
- Async Loading: Tiles loaded asynchronously in background threads
- Deferred Eviction: Tile eviction deferred to prevent use-after-free
- Optimized Tessellation: Efficient geometry tessellation with signed area calculation
- Label Placement: Intelligent label placement with collision detection
Testing
The map crate has comprehensive test coverage (80%+):
# Run all tests
cargo test -p nigig-map
# Run specific module tests
cargo test -p nigig-map mvt_parser
cargo test -p nigig-map tessellation
cargo test -p nigig-map style
cargo test -p nigig-map overpass_parser
cargo test -p nigig-map asset_loader
Dependencies
makepad-widgets- Makepad widget frameworkmakepad-mbtile-reader- MBTiles file readermakepad-fast-inflate- Fast decompression
License
This project is licensed under the MIT License.
Contributing
Contributions are welcome! Please read the CONTRIBUTING.md for guidelines.
Authors
- Nigig Team
Acknowledgments
- Map data from OpenStreetMap contributors
- MBTiles format from MapBox
- Makepad framework for widget system