import * as Cesium from "cesium"; Cesium.Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjcxNWZiYy1mZjFiLTQzNGEtYmEwNy1hMmU0ZDg4NWI2ZGUiLCJpZCI6Mzc3NjU2LCJpYXQiOjE3NjgyMTk2NzJ9.D5DL5zrDi4yK6OPgq-ypC4hM5hfqYKODvppgakc7y3g"; const creditContainer = document.createElement('div'); creditContainer.style.display = 'none'; const viewer = new Cesium.Viewer("cesiumContainer", { timeline: false, animation: false, sceneModePicker: false, baseLayerPicker: false, geocoder: false, homeButton: false, navigationHelpButton: false, terrainProvider: await Cesium.createWorldTerrainAsync(), creditContainer: creditContainer, contextOptions: { webgl: { preserveDrawingBuffer: true } } }); try { const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(2275207); viewer.scene.primitives.add(tileset); } catch (error) { console.log(error); } /* =================== Настройка отображения =================== */ const outputWidth = 512; const outputHeight = 512; viewer.scene.canvas.style.width = outputWidth + 'px'; viewer.scene.canvas.style.height = outputHeight + 'px'; viewer.container.style.width = outputWidth + 'px'; viewer.container.style.height = outputHeight + 'px'; viewer.resize(); // важно: обновляет внутренние размеры рендерера /* =================== Вспомагательные функции =================== */ function dmsToDecimal(dms) { // Пример входа: "48°18'20\"N" или "16°24'41\"E" const regex = /(\d+)°(\d+)'(\d+)"?([NSEW])/i; const match = dms.match(regex); if (!match) { throw new Error("Неверный формат координат: " + dms); } const degrees = parseInt(match[1], 10); const minutes = parseInt(match[2], 10); const seconds = parseInt(match[3], 10); const direction = match[4].toUpperCase(); let decimal = degrees + minutes / 60 + seconds / 3600; // Южная и Западная широты — отрицательные if (direction === "S" || direction === "W") { decimal = -decimal; } return decimal; } function metersToLat(m) { return m / METERS_PER_DEG_LAT; } function metersToLon(m, latDeg) { return m / (METERS_PER_DEG_LAT * Math.cos(Cesium.Math.toRadians(latDeg))); } function saveImage(filename) { const canvas = viewer.scene.canvas; const image = canvas.toDataURL("image/png"); const link = document.createElement("a"); link.href = image; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); } function downloadFile(filename, content, mime = "text/plain") { const blob = new Blob([content], { type: mime }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } /* =================== Константы и переменные =================== */ const METERS_PER_DEG_LAT = 111_320; // ---- Параметры сетки ---- const GRID = 2; const TILE_M = 50; const CAMERA_HEIGHT = 450; // ---- Координаты ---- const latDMS = "45°25'3\"N"; const lonDMS = "9°04'15\"E"; //45°25'35"N 9°04'15"E const half = (GRID - 1) * TILE_M / 2; const CENTER_LAT = dmsToDecimal(latDMS); const CENTER_LON = dmsToDecimal(lonDMS); const startLat = CENTER_LAT + metersToLat(half); const startLon = CENTER_LON - metersToLon(half, CENTER_LAT); let row = 0; let col = 0; let index = 0; const offset = 0.0005; /* =================== Главный цикл сбора =================== */ var flag = false; function captureNextTile() { if (flag == false) { setTimeout(() => { flag = true; }, 5000) } const lat = startLat - metersToLat(row * TILE_M); const lon = startLon + metersToLon(col * TILE_M, lat); downloadFile( `tile_${index}_sat.json`, JSON.stringify({ lat: lat, lon: lon }, null, 2), "application/json" ); // ---------- Спутник ---------- viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(lon, lat, CAMERA_HEIGHT), orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-90), roll: 0 } }); viewer.scene.requestRender(); setTimeout(() => { saveImage(`tile_${index}_sat.png`); // ---------- Дрон ---------- viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(lon, lat - offset, CAMERA_HEIGHT), orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-60), roll: 0 } }); viewer.scene.requestRender(); setTimeout(() => { saveImage(`tile_${index}_drone.png`); // ---- След. ячейка ---- col++; if (col >= GRID) { col = 0; row++; } index++; captureNextTile(); }, 2500); // Задержка дрон-рендера }, 2500); // Задержка спутник-рендера } /* =================== Запуск =================== */ viewer.scene.postRender.addEventListener(function once() { viewer.scene.postRender.removeEventListener(once); setTimeout(() => { captureNextTile(); }, 9000); });