Initial commit: v1.0
This commit is contained in:
217
app.js
Normal file
217
app.js
Normal file
@@ -0,0 +1,217 @@
|
||||
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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user