🎯 MapView v2.0 - Global Deployment Ready

 MAJOR FEATURES:
• Auto-zoom intelligence với smart bounds fitting
• Enhanced 3D GPS markers với pulsing effects
• Professional route display với 6-layer rendering
• Status-based parking icons với availability indicators
• Production-ready build optimizations

🗺️ AUTO-ZOOM FEATURES:
• Smart bounds fitting cho GPS + selected parking
• Adaptive padding (50px) cho visual balance
• Max zoom control (level 16) để tránh quá gần
• Dynamic centering khi không có selection

🎨 ENHANCED VISUALS:
• 3D GPS marker với multi-layer pulse effects
• Advanced parking icons với status colors
• Selection highlighting với animation
• Dimming system cho non-selected items

🛣️ ROUTE SYSTEM:
• OpenRouteService API integration
• Multi-layer route rendering (glow, shadow, main, animated)
• Real-time distance & duration calculation
• Visual route info trong popup

📱 PRODUCTION READY:
• SSR safe với dynamic imports
• Build errors resolved
• Global deployment via Vercel
• Optimized performance

🌍 DEPLOYMENT:
• Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app
• Bundle size: 22.8 kB optimized
• Global CDN distribution
• HTTPS enabled

💾 VERSION CONTROL:
• MapView-v2.0.tsx backup created
• MAPVIEW_VERSIONS.md documentation
• Full version history tracking
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit 07a93d44b4
113 changed files with 28421 additions and 1831 deletions

27
valhalla/Dockerfile Normal file
View File

@@ -0,0 +1,27 @@
# Valhalla Routing Engine Dockerfile
FROM ghcr.io/gis-ops/docker-valhalla/valhalla:latest
# Set working directory
WORKDIR /app
# Create necessary directories
RUN mkdir -p /custom_files /data/valhalla
# Copy configuration file
COPY valhalla.json /valhalla.json
# Copy OSM data files (if they exist)
COPY custom_files/ /custom_files/
# Set proper permissions
RUN chown -R valhalla:valhalla /data/valhalla /custom_files
# Expose the service port
EXPOSE 8002
# Health check
HEALTHCHECK --interval=60s --timeout=30s --start-period=300s --retries=3 \
CMD curl -f http://localhost:8002/status || exit 1
# Start Valhalla service
CMD ["valhalla_service", "/valhalla.json"]

169
valhalla/README.md Normal file
View File

@@ -0,0 +1,169 @@
# Valhalla Routing Engine
This directory contains the configuration and setup for the Valhalla routing engine.
## 🚀 Quick Setup
### 1. Download OSM Data
Download OpenStreetMap data for your region from [Geofabrik](https://download.geofabrik.de/):
```bash
# For Vietnam/Southeast Asia
wget https://download.geofabrik.de/asia/vietnam-latest.osm.pbf -P custom_files/
# For smaller regions (Ho Chi Minh City area)
wget https://download.geofabrik.de/asia/vietnam-latest.osm.pbf -P custom_files/
```
### 2. Build and Run
```bash
# Build Valhalla container
docker-compose up -d valhalla
# Check status
curl http://localhost:8002/status
```
## 📊 API Endpoints
### Route Calculation
```bash
# POST /route
curl -X POST http://localhost:8002/route \
-H "Content-Type: application/json" \
-d '{
"locations": [
{"lat": 10.7769, "lon": 106.7009},
{"lat": 10.7796, "lon": 106.7019}
],
"costing": "auto",
"directions_options": {
"units": "kilometers"
}
}'
```
### Locate Nearby Roads
```bash
# POST /locate
curl -X POST http://localhost:8002/locate \
-H "Content-Type: application/json" \
-d '{
"locations": [
{"lat": 10.7769, "lon": 106.7009}
],
"costing": "auto"
}'
```
### Health Check
```bash
# GET /status
curl http://localhost:8002/status
```
## ⚙️ Configuration
The `valhalla.json` file contains the routing engine configuration:
- **Costing models**: auto, bicycle, pedestrian
- **Data sources**: OpenStreetMap
- **Service endpoints**: route, locate, status
- **Logging**: Configurable log levels
## 🗺️ Supported Regions
Current OSM data includes:
- Vietnam (complete)
- Southeast Asia (partial)
- Custom boundary areas
To add new regions:
1. Download `.osm.pbf` files to `custom_files/`
2. Restart the container
3. Wait for data processing to complete
## 🔧 Performance Tuning
### Memory Configuration
```json
{
"mjolnir": {
"tile_dir": "/data/valhalla",
"max_cache_size": 1000000000
}
}
```
### Costing Options
```json
{
"costing_options": {
"auto": {
"maneuver_penalty": 5,
"gate_cost": 30,
"toll_booth_cost": 15
}
}
}
```
## 📈 Monitoring
### Health Checks
- Container status: `docker ps`
- Service health: `curl http://localhost:8002/status`
- Logs: `docker logs valhalla`
### Performance Metrics
- Route calculation time
- Memory usage
- Cache hit rate
- Request throughput
## 🐛 Troubleshooting
### Common Issues
1. **Container won't start**
- Check OSM data files in `custom_files/`
- Verify memory allocation (minimum 2GB)
- Check port conflicts
2. **Slow route calculation**
- Increase cache size in configuration
- Optimize OSM data for your region
- Add more memory to container
3. **Routes not found**
- Verify coordinates are within OSM data bounds
- Check road connectivity
- Try different costing models
### Debug Mode
```bash
# Enable debug logging
docker-compose up valhalla --build
docker logs -f valhalla
```
## 🔄 Updates
### Update OSM Data
```bash
# Download new data
wget https://download.geofabrik.de/asia/vietnam-latest.osm.pbf -P custom_files/
# Rebuild container
docker-compose down valhalla
docker-compose up -d valhalla --build
```
### Update Valhalla Version
```bash
# Update base image in Dockerfile
# Rebuild container
docker-compose build valhalla --no-cache
```

89
valhalla/download-osm-data.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/bin/bash
# Download OSM data for Vietnam/Southeast Asia
# This script downloads OpenStreetMap data files for use with Valhalla
set -e
# Create custom_files directory if it doesn't exist
mkdir -p custom_files
echo "🗺️ Downloading OpenStreetMap data for Vietnam..."
# Download Vietnam OSM data from Geofabrik
VIETNAM_URL="https://download.geofabrik.de/asia/vietnam-latest.osm.pbf"
VIETNAM_FILE="custom_files/vietnam-latest.osm.pbf"
if [ ! -f "$VIETNAM_FILE" ]; then
echo "📥 Downloading Vietnam OSM data..."
wget -O "$VIETNAM_FILE" "$VIETNAM_URL"
echo "✅ Downloaded Vietnam OSM data"
else
echo "📁 Vietnam OSM data already exists"
fi
# Optional: Download other regional data
read -p "Do you want to download additional regional data? (y/N): " download_more
if [[ $download_more =~ ^[Yy]$ ]]; then
echo "Available regions:"
echo "1. Southeast Asia (larger file, ~2GB)"
echo "2. Cambodia"
echo "3. Laos"
echo "4. Thailand"
echo "5. Myanmar"
read -p "Select region (1-5): " region_choice
case $region_choice in
1)
REGION_URL="https://download.geofabrik.de/asia/southeast-asia-latest.osm.pbf"
REGION_FILE="custom_files/southeast-asia-latest.osm.pbf"
;;
2)
REGION_URL="https://download.geofabrik.de/asia/cambodia-latest.osm.pbf"
REGION_FILE="custom_files/cambodia-latest.osm.pbf"
;;
3)
REGION_URL="https://download.geofabrik.de/asia/laos-latest.osm.pbf"
REGION_FILE="custom_files/laos-latest.osm.pbf"
;;
4)
REGION_URL="https://download.geofabrik.de/asia/thailand-latest.osm.pbf"
REGION_FILE="custom_files/thailand-latest.osm.pbf"
;;
5)
REGION_URL="https://download.geofabrik.de/asia/myanmar-latest.osm.pbf"
REGION_FILE="custom_files/myanmar-latest.osm.pbf"
;;
*)
echo "Invalid selection"
exit 1
;;
esac
if [ ! -f "$REGION_FILE" ]; then
echo "📥 Downloading additional regional data..."
wget -O "$REGION_FILE" "$REGION_URL"
echo "✅ Downloaded additional regional data"
else
echo "📁 Regional data already exists"
fi
fi
echo ""
echo "🎉 OSM data download complete!"
echo "📁 Files saved to: custom_files/"
ls -lh custom_files/
echo ""
echo "🚀 Next steps:"
echo "1. Run: docker-compose up -d valhalla"
echo "2. Wait for data processing to complete (may take 10-30 minutes)"
echo "3. Test: curl http://localhost:8002/status"
echo ""
echo "💡 Tips:"
echo "- Larger OSM files take longer to process but provide better coverage"
echo "- Vietnam data (~100MB) is sufficient for most Vietnamese locations"
echo "- Southeast Asia data (~2GB) covers the entire region"

354
valhalla/valhalla.json Normal file
View File

@@ -0,0 +1,354 @@
{
"mjolnir": {
"tile_dir": "/data/valhalla",
"admin": "/data/valhalla/admin.sqlite",
"timezone": "/data/valhalla/tz_world.sqlite",
"max_cache_size": 1000000000,
"global_synchronized_cache": false,
"tile_extract": "/data/valhalla/tiles.tar",
"logging": {
"type": "std_out",
"color": true,
"level": "INFO"
}
},
"loki": {
"actions": ["locate", "route", "height", "sources_to_targets", "optimized_route", "isochrone", "trace_route", "trace_attributes", "expansion"],
"logging": {
"type": "std_out",
"color": true,
"level": "INFO"
},
"service_defaults": {
"minimum_reachability": 50,
"radius": 0,
"search_cutoff": 35000,
"node_snap_tolerance": 5,
"street_side_tolerance": 5,
"street_side_max_distance": 1000,
"heading_tolerance": 60
}
},
"thor": {
"logging": {
"type": "std_out",
"color": true,
"level": "INFO"
},
"source_to_target_algorithm": "select_optimal"
},
"odin": {
"logging": {
"type": "std_out",
"color": true,
"level": "INFO"
}
},
"meili": {
"customizable": ["turn_penalty_factor", "max_route_distance_factor", "max_route_time_factor"],
"mode": "auto",
"grid": {
"cache_size": 100240,
"size": 500
},
"default": {
"sigma_z": 4.07,
"gps_accuracy": 5.0,
"beta": 3,
"max_route_distance_factor": 5,
"max_route_time_factor": 5,
"breakage_distance": 2000,
"max_search_radius": 100,
"interpolation_distance": 10,
"search_radius": 15.0,
"max_candidates": 8,
"turn_penalty_factor": 0
},
"auto": {
"turn_penalty_factor": 200,
"search_radius": 15
},
"pedestrian": {
"turn_penalty_factor": 100,
"search_radius": 25
},
"bicycle": {
"turn_penalty_factor": 140
},
"logging": {
"type": "std_out",
"color": true,
"level": "INFO"
}
},
"httpd": {
"service": {
"listen": "0.0.0.0:8002",
"loopback": "0.0.0.0:8002",
"interrupt": "ipc:///tmp/interrupt"
}
},
"statsd": {
"host": "localhost",
"port": 8125,
"prefix": "valhalla"
},
"service_limits": {
"auto": {
"max_distance": 5000000.0,
"max_locations": 20,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"auto_shorter": {
"max_distance": 5000000.0,
"max_locations": 20,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"bicycle": {
"max_distance": 500000.0,
"max_locations": 50,
"max_matrix_distance": 200000.0,
"max_matrix_location_pairs": 2500
},
"bus": {
"max_distance": 5000000.0,
"max_locations": 50,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"hov": {
"max_distance": 5000000.0,
"max_locations": 20,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"motorcycle": {
"max_distance": 5000000.0,
"max_locations": 20,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"motor_scooter": {
"max_distance": 500000.0,
"max_locations": 50,
"max_matrix_distance": 200000.0,
"max_matrix_location_pairs": 2500
},
"pedestrian": {
"max_distance": 250000.0,
"max_locations": 50,
"min_transit_walking_distance": 1,
"max_transit_walking_distance": 10000,
"max_matrix_distance": 200000.0,
"max_matrix_location_pairs": 2500
},
"bikeshare": {
"max_distance": 500000.0,
"max_locations": 50,
"max_matrix_distance": 200000.0,
"max_matrix_location_pairs": 2500
},
"taxi": {
"max_distance": 5000000.0,
"max_locations": 20,
"max_matrix_distance": 400000.0,
"max_matrix_location_pairs": 2500
},
"max_avoid_locations": 128,
"max_reachability": 100,
"max_radius": 200,
"max_timedep_distance": 500000,
"max_alternates": 2,
"max_exclude_locations": 50,
"max_exclude_polygons_length": 10000,
"max_walkway_shape": 100000,
"skadi": {
"max_shape": 750000,
"min_resample": 10.0
},
"isochrone": {
"max_contours": 4,
"max_time_contour": 120,
"max_distance_contour": 25000,
"max_locations": 1
},
"trace": {
"max_distance": 200000.0,
"max_gps_accuracy": 100.0,
"max_search_radius": 100,
"max_shape": 16000,
"max_best_paths": 4,
"max_best_paths_shape": 100,
"max_alternates": 3,
"max_alternates_shape": 100
},
"transit": {
"max_distance": 500000.0,
"max_locations": 50,
"max_matrix_distance": 200000.0,
"max_matrix_location_pairs": 2500
},
"status": {
"allow_verbose": false
}
},
"costing_options": {
"auto": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.5,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.0,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0,
"include_hov2": false,
"include_hov3": false,
"include_hot": false
},
"auto_shorter": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.5,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.0,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0,
"include_hov2": false,
"include_hov3": false,
"include_hot": false
},
"motorcycle": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.5,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.8,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0
},
"bus": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.3,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.0,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0
},
"taxi": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.5,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.0,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0
},
"hov": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"toll_booth_cost": 15,
"toll_booth_penalty": 0,
"ferry_cost": 300,
"use_ferry": 0.5,
"use_highways": 1.0,
"use_tolls": 0.5,
"use_tracks": 0.0,
"use_living_streets": 0.25,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"private_access_factor": 9.0,
"exclude_unpaved": 1.0
},
"bicycle": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"use_ferry": 0.5,
"use_living_streets": 0.6,
"use_tracks": 0.85,
"cycling_speed": 25.0,
"use_roads": 0.5,
"use_hills": 0.5,
"avoid_bad_surfaces": 0.25
},
"pedestrian": {
"maneuver_penalty": 5,
"gate_cost": 30,
"gate_penalty": 300,
"private_access_penalty": 450,
"service_penalty": 15,
"service_factor": 1.0,
"closure_factor": 9.0,
"use_ferry": 1.0,
"use_living_streets": 0.6,
"use_tracks": 0.85,
"walking_speed": 5.1,
"walkway_factor": 1.0,
"sidewalk_factor": 1.0,
"alley_factor": 2.0,
"driveway_factor": 5.0,
"step_penalty": 0.0,
"max_hiking_difficulty": 6
}
}
}