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", {