diff --git a/src/routes/TimeLine.svelte b/src/routes/TimeLine.svelte new file mode 100644 index 0000000..94dddeb --- /dev/null +++ b/src/routes/TimeLine.svelte @@ -0,0 +1,215 @@ + + + +
+
+ + + + + + +
+ {formatTime(currentHour)} +
+
+ + dispatchTimeUpdate()} + class="timeline-slider" + /> + +
+ {#each Array(Math.floor(totalHours / updateInterval) + 1) as _, i} +
{ + currentHour = i * updateInterval; + dispatchTimeUpdate(); + }} + > + {i * updateInterval % 24 === 0 ? `День ${Math.floor(i * updateInterval / 24) + 1}` : ''} +
+ {/each} +
+
+ + \ No newline at end of file diff --git a/src/routes/WindVisualisation.svelte b/src/routes/WindVisualisation.svelte index 6184958..713cde8 100644 --- a/src/routes/WindVisualisation.svelte +++ b/src/routes/WindVisualisation.svelte @@ -20,36 +20,54 @@ // Функция для нормализации данных тепловой карты const prepareHeatData = (windData) => { - if (!windData || !windData.header || !windData.data) { - console.warn("Wind data is missing or incomplete"); - return []; + if (!windData || windData.length < 2) { + console.warn("Invalid wind data structure"); + return []; } - const { lo1, la1, dx, dy, nx, ny } = windData.header; + // Получаем U и V компоненты + const uComponent = windData.find(item => item.header.parameterNumber === 2); + const vComponent = windData.find(item => item.header.parameterNumber === 3); + + if (!uComponent || !vComponent) { + console.warn("Missing wind components"); + return []; + } + + const header = uComponent.header; // Используем header из U компоненты + const { lo1, la1, dx, dy, nx, ny } = header; const heatData = []; let maxSpeed = 0; + // Проверяем совпадение размеров данных + if (uComponent.data.length !== vComponent.data.length) { + console.warn("U and V components have different lengths"); + return []; + } + // Собираем данные и находим максимальную скорость - for (let y = 0; y < ny; y++) { - for (let x = 0; x < nx; x++) { - const u = windData.data[y][x * 2]; - const v = windData.data[y][x * 2 + 1]; - const speed = Math.sqrt(u * u + v * v); + for (let i = 0; i < uComponent.data.length; i++) { + const u = uComponent.data[i]; + const v = vComponent.data[i]; + const speed = Math.sqrt(u * u + v * v); - if (!isNaN(speed)) { - const lat = la1 - y * dy; - const lng = lo1 + x * dx; - heatData.push([lat, lng, speed]); - maxSpeed = Math.max(maxSpeed, speed); - } + if (!isNaN(speed)) { + // Вычисляем координаты для текущей точки + const y = Math.floor(i / nx); + const x = i % nx; + const lat = la1 - y * dy; + const lng = lo1 + x * dx; + + heatData.push([lat, lng, speed]); + maxSpeed = Math.max(maxSpeed, speed); } } - console.log('Prepared heat data: ${heatData.length} points, max speed: ${maxSpeed}'); + console.log(`Prepared heat data: ${heatData.length} points, max speed: ${maxSpeed}`); // Нормализуем значения интенсивности от 0 до 1 if (maxSpeed > 0) { - return heatData.map(([lat, lng, intensity]) => [lat, lng, intensity / maxSpeed]); + return heatData.map(([lat, lng, intensity]) => [lat, lng, intensity / maxSpeed]); } return heatData; @@ -58,27 +76,27 @@ // Создание тепловой карты const createHeatLayer = (data) => { if (!data || data.length === 0) { - console.warn("No valid heat data provided"); - return null; + console.warn("No valid heat data provided"); + return null; } try { - return L.heatLayer(data, { - radius: 15, - blur: 20, - maxZoom: 17, - minOpacity: 0.5, - gradient: { - 0.1: 'blue', - 0.3: 'cyan', - 0.5: 'lime', - 0.7: 'yellow', - 1.0: 'red' - } - }); + return L.heatLayer(data, { + radius: 20, // Увеличьте радиус для глобальной карты + blur: 15, + maxZoom: 10, + minOpacity: 0.7, + gradient: { + 0.1: 'blue', + 0.3: 'cyan', + 0.5: 'lime', + 0.7: 'yellow', + 1.0: 'red' + } + }); } catch (e) { - console.error("Failed to create heat layer:", e); - return null; + console.error("Failed to create heat layer:", e); + return null; } }; @@ -124,7 +142,6 @@ map.removeControl(layerControl); } - const baseLayers = {}; const overlays = {}; if (velocityLayer) { @@ -223,7 +240,7 @@ font-size: 14px; cursor: pointer; } - .wind-heat-legend { + :global(.wind-heat-legend) { padding: 8px 10px; background: rgba(255, 255, 255, 0.9); border-radius: 5px; @@ -233,23 +250,23 @@ font-family: Arial, sans-serif; } - .wind-heat-legend h4 { + :global(.wind-heat-legend h4) { margin: 0 0 5px; font-size: 14px; font-weight: bold; } - .legend-scale { + :global(legend-scale) { display: flex; margin-bottom: 3px; } - .legend-color { + :global(legend-color) { height: 12px; flex-grow: 1; } - .legend-labels { + :global(.legend-labels) { display: flex; justify-content: space-between; font-size: 11px; diff --git a/src/routes/map.svelte b/src/routes/map.svelte index 88fec6d..b039764 100644 --- a/src/routes/map.svelte +++ b/src/routes/map.svelte @@ -29,7 +29,7 @@ onMount(async () => { if (!mapContainer) return; - map = L.map(mapContainer).setView([51.505, -0.09], 13); + map = L.map(mapContainer).setView([30, 0], 2); plotLayerGroup = L.layerGroup().addTo(map); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {