299 lines
6.8 KiB
Markdown
299 lines
6.8 KiB
Markdown
# Wind Layer Implementation Guide
|
|
|
|
## 🌬️ Overview
|
|
|
|
The project now uses **[@sakitam-gis/maplibre-wind](https://github.com/sakitam-fdd/wind-layer)** for professional wind visualization on MapLibre GL maps.
|
|
|
|
## 📦 Installation
|
|
|
|
```bash
|
|
npm install @sakitam-gis/maplibre-wind --save
|
|
```
|
|
|
|
**Package installed:** ✅ Version included in `package.json`
|
|
|
|
## 🎨 Features Implemented
|
|
|
|
### Wind Particle Animation
|
|
- **5000 particles** flowing with wind direction
|
|
- **Color gradient:** Blue → Green → Yellow → Orange → Red
|
|
- **Smooth animation** with WebGL acceleration
|
|
- **Configurable speed** and fade effects
|
|
|
|
### Heatmap Visualization
|
|
- **Color-coded intensity** display
|
|
- **Opacity control** (70% default)
|
|
- **Display range:** 0-20 m/s
|
|
- **Rainbow color scheme:** Blue → Cyan → Green → Yellow → Red
|
|
|
|
## 🔧 Component Structure
|
|
|
|
### File: `src/lib/components/WindVisualisation.svelte`
|
|
|
|
**Props:**
|
|
- `map` - MapLibre GL map instance
|
|
- `windData` - Wind data in GRIB format (U/V components)
|
|
|
|
**State:**
|
|
- `showHeatmap` - Toggle heatmap layer
|
|
- `showParticles` - Toggle particle animation layer
|
|
|
|
**Functions:**
|
|
- `initializeWindLayers()` - Creates particle and heatmap layers
|
|
- `prepareWindData()` - Transforms GRIB data to wind-layer format
|
|
- Reactive `$effect()` - Toggles layer visibility
|
|
|
|
## 📊 Data Format
|
|
|
|
### Input: GRIB Wind Data (`testVelo.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"header": {
|
|
"parameterNumber": 2, // U-component
|
|
"nx": 360, // Grid columns
|
|
"ny": 181, // Grid rows
|
|
"lo1": 0.0, // Starting longitude
|
|
"la1": 90.0 // Starting latitude
|
|
},
|
|
"data": [/* U-component values */]
|
|
},
|
|
{
|
|
"header": {
|
|
"parameterNumber": 3, // V-component
|
|
...
|
|
},
|
|
"data": [/* V-component values */]
|
|
}
|
|
]
|
|
```
|
|
|
|
### Output: Wind-Layer Format
|
|
|
|
```typescript
|
|
{
|
|
uMin: number, // Min U-component value
|
|
uMax: number, // Max U-component value
|
|
vMin: number, // Min V-component value
|
|
vMax: number, // Max V-component value
|
|
rows: number, // Grid rows (ny)
|
|
cols: number, // Grid columns (nx)
|
|
data: [Array, Array] // [U-component, V-component]
|
|
}
|
|
```
|
|
|
|
## 🎛️ Configuration Options
|
|
|
|
### Particle Layer
|
|
|
|
```javascript
|
|
{
|
|
renderType: 'particles',
|
|
styleSpec: {
|
|
numParticles: 5000, // Number of particles
|
|
fadeOpacity: 0.996, // Trail fade rate (0.9-0.999)
|
|
speedFactor: 0.25, // Animation speed multiplier
|
|
dropRate: 0.003, // Particle regeneration rate
|
|
dropRateBump: 0.01, // Regeneration boost
|
|
colors: [ // Color gradient
|
|
'#3288bd', // Blue
|
|
'#66c2a5', // Green
|
|
'#fee08b', // Yellow
|
|
'#f46d43', // Orange
|
|
'#d53e4f' // Red
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Heatmap Layer
|
|
|
|
```javascript
|
|
{
|
|
renderType: 'colorize',
|
|
styleSpec: {
|
|
opacity: 0.7,
|
|
colors: [
|
|
'#0000ff', // Blue
|
|
'#00ffff', // Cyan
|
|
'#00ff00', // Green
|
|
'#ffff00', // Yellow
|
|
'#ff0000' // Red
|
|
],
|
|
displayRange: [0, 20] // Min/max wind speed (m/s)
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🎮 Usage
|
|
|
|
### UI Controls
|
|
|
|
Located in bottom-left corner of the map:
|
|
|
|
- ☑️ **Тепловая карта** - Toggle heatmap visualization
|
|
- ☑️ **Частицы ветра** - Toggle particle animation (default: ON)
|
|
|
|
### Programmatic Control
|
|
|
|
```typescript
|
|
// In Map.svelte
|
|
<WindVisualization {map} {windData} />
|
|
|
|
// Toggle layers via checkbox binding
|
|
// Layers automatically add/remove from map
|
|
```
|
|
|
|
## 🔄 Data Flow
|
|
|
|
```
|
|
1. testVelo.json (GRIB format)
|
|
↓
|
|
2. Map.svelte loads data
|
|
↓
|
|
3. WindVisualisation component receives:
|
|
- map instance
|
|
- windData
|
|
↓
|
|
4. prepareWindData() transforms to wind-layer format
|
|
↓
|
|
5. WindLayer instances created:
|
|
- Particle layer
|
|
- Heatmap layer
|
|
↓
|
|
6. Layers added to map
|
|
↓
|
|
7. User toggles visibility via checkboxes
|
|
```
|
|
|
|
## 🎯 Key Implementation Details
|
|
|
|
### 1. Svelte 5 Runes
|
|
|
|
Uses modern Svelte 5 syntax:
|
|
- `$props()` for component props
|
|
- `$state()` for reactive state
|
|
- `$effect()` for reactive layer toggling
|
|
|
|
### 2. Map Lifecycle
|
|
|
|
- Waits for map to load before initializing
|
|
- Checks `map.loaded()` status
|
|
- Listens to `'load'` event if not ready
|
|
|
|
### 3. Layer Management
|
|
|
|
- Checks if layer exists before adding
|
|
- Removes layers on component destroy
|
|
- Prevents duplicate layer IDs
|
|
|
|
### 4. Error Handling
|
|
|
|
- Validates wind data structure
|
|
- Catches initialization errors
|
|
- Logs detailed error messages
|
|
- Graceful degradation on failure
|
|
|
|
## 🐛 Debugging
|
|
|
|
### Console Logs
|
|
|
|
```javascript
|
|
// On mount
|
|
"WindVisualization mounted with MapLibre map"
|
|
"Wind data available: [...]"
|
|
|
|
// Data processing
|
|
"Wind data stats - U: [-21.32, 26.80], V: [-21.57, 21.42]"
|
|
|
|
// Success
|
|
"Wind layers initialized successfully"
|
|
|
|
// Errors
|
|
"Missing U or V wind components"
|
|
"Error initializing wind layers: [error]"
|
|
```
|
|
|
|
### Check Layer Status
|
|
|
|
```javascript
|
|
// In browser console
|
|
map.getLayer('wind-particles') // Should return layer object
|
|
map.getLayer('wind-heatmap') // Should return layer object
|
|
```
|
|
|
|
## 📚 Resources
|
|
|
|
- **GitHub:** https://github.com/sakitam-fdd/wind-layer
|
|
- **Examples:** https://sakitam-fdd.github.io/wind-layer/examples/
|
|
- **MapLibre Docs:** https://maplibre.org/maplibre-gl-js/docs/
|
|
|
|
## ⚙️ Advanced Customization
|
|
|
|
### Adjust Particle Count
|
|
|
|
```javascript
|
|
numParticles: 10000 // More particles (slower performance)
|
|
numParticles: 2000 // Fewer particles (better performance)
|
|
```
|
|
|
|
### Change Animation Speed
|
|
|
|
```javascript
|
|
speedFactor: 0.5 // Faster animation
|
|
speedFactor: 0.1 // Slower animation
|
|
```
|
|
|
|
### Custom Color Schemes
|
|
|
|
```javascript
|
|
// Wind speed colors
|
|
colors: ['#000080', '#0000FF', '#FFFF00', '#FF0000', '#800000']
|
|
|
|
// Monochrome
|
|
colors: ['#FFFFFF', '#CCCCCC', '#999999', '#666666', '#000000']
|
|
```
|
|
|
|
### Adjust Display Range
|
|
|
|
```javascript
|
|
displayRange: [0, 30] // For stronger winds
|
|
displayRange: [0, 10] // For lighter winds
|
|
```
|
|
|
|
## 🚀 Future Enhancements
|
|
|
|
Potential additions:
|
|
- Timeline control for temporal wind data
|
|
- Arrow vector visualization
|
|
- Wind speed labels
|
|
- Custom tile sources for real-time data
|
|
- Wind barbs (meteorological standard)
|
|
- Integration with prediction module
|
|
|
|
## ✅ Testing Checklist
|
|
|
|
- [x] Package installed successfully
|
|
- [x] Component imports without errors
|
|
- [x] Wind data loads from testVelo.json
|
|
- [x] Particle animation displays on map
|
|
- [x] Heatmap visualization works
|
|
- [x] Checkboxes toggle layers correctly
|
|
- [x] No console errors on mount/unmount
|
|
- [x] Layers clean up on component destroy
|
|
|
|
## 📝 Notes
|
|
|
|
- Wind data must be in GRIB format with U/V components
|
|
- Particle layer is GPU-accelerated (requires WebGL)
|
|
- Large particle counts may impact performance
|
|
- Data transformation happens client-side
|
|
- Layers are added above base map tiles
|
|
- Z-index managed by MapLibre layer order
|
|
|
|
---
|
|
|
|
**Implementation Date:** December 2025
|
|
**Package Version:** @sakitam-gis/maplibre-wind
|
|
**Status:** ✅ Production Ready
|