Hello!
I used cesium-terrain-builder to generate .terrain
tiles from a .geotiff
. Now I want to use them in offline CesiumJS, but I’m not sure how to properly connect them.
I’m running a local Python (Flask) server to serve the files:
from flask import Flask, send_from_directory
import os
app = Flask(
name
, static_folder=“.”, static_url_path=“”)
@app.route(“/”)
def root():
return app.send_static_file(“index.html”)
@app.route(“/tiles/
<int:z
>/
<int:x
>/
<int:y
>.jpeg”)
def tiles(z, x, y):
return send_from_directory(“tiles/{}/{}”.format(z, x), f"{y}.jpeg")
if
name
== “
main
”:
app.run(host=“0.0.0.0”, port=8003, debug=False, use_reloader=False)
The question is: how exactly do I load these .terrain tiles in CesiumJS offline?Most tutorials I find are for online services (Cesium Ion, AGI), but I can’t find a clear example for serving local terrain tiles.
I guess I should use CesiumTerrainProvider
or something similar, but I don’t know the correct way to point it to my tiles so that CesiumJS can render them.
Any help or example code would be greatly appreciated
What does your index.html serve?
This is my offline CesiumJS map. I’m just learning it, sorry if there are any silly mistakes.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<title>Cesium Offline</title>
<script src="Cesium/Cesium.js"></script>
<link href="Cesium/Widgets/widgets.css" rel="stylesheet" />
<style>
html, body, #cesiumContainer { width:100%; height:100%; margin:0; padding:0; overflow:hidden; }
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Координаты запуска карты
const ALMATY_LON = 76.980671, ALMATY_LAT = 43.353934;
const ORIGIN = window.location.origin;
const TILE_ROOT = ORIGIN + "/tiles"; // http://localhost:8003/tiles
function makeProvider(opts) {
const yToken = opts.useTMS ? "{reverseY}" : "{y}";
const url = `${TILE_ROOT}/{z}/{x}/${yToken}.jpeg`;
return new Cesium.UrlTemplateImageryProvider({
url,
tilingScheme: opts.useGeographic
? new Cesium.GeographicTilingScheme()
: new Cesium.WebMercatorTilingScheme(),
minimumLevel: opts.minZ,
maximumLevel: opts.maxZ,
tileWidth: opts.tileSize,
tileHeight: opts.tileSize
});
}
function flyKazakhstan(heightMeters) {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(ALMATY_LON, ALMATY_LAT, heightMeters ?? 1000) // высота камеры
});
}
// VIEWER - основная часть Cesium (карта, сцена, камера и т.д.)
const viewer = new Cesium.Viewer("cesiumContainer", {
baseLayerPicker: false,
geocoder: false,
timeline: false,
animation: false,
requestRenderMode: false,
navigationHelpButton: false,
fullscreenButton: false
});
viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString('#00151C'); // цвет не програженных областей
viewer._cesiumWidget._creditContainer.style.display = "none"; // скрыть логотип Cesium
// Физуальная кастомизация карты
//viewer.scene.globe.enableLighting = true; // освещение по времени суток
viewer.clock.shouldAnimate = true; // анимация времени
//viewer.scene.globe.depthTestAgainstTerrain = true; // скрытие объектов за рельефом
viewer.scene.skyAtmosphere.show = true; //Атмосфера и небо
viewer.scene.skyBox.show = true; // Атмосфера и небо (по умолчанию true)
viewer.scene.fog.enabled = true; // Туман
viewer.scene.fog.density = 0.001; // Туман (плотность (меньше — прозрачнее))
viewer.scene.fog.minimumBrightness = 0.03; // Туман (минимальная яркость для предотвращения полного затемнения)
viewer.scene.sun = new Cesium.Sun(); // Солнце
viewer.scene.moon = new Cesium.Moon(); // Луна
viewer.scene.highDynamicRange = true; // HDR
//viewer.scene.postProcessStages.bloom.enabled = true; // Свечение (bloom)
//viewer.scene.postProcessStages.bloom.uniforms.bloomIntensity = 1.0; // Интенсивность свечения
// Загружаем границы Казахстана из локального geojson
//Cesium.GeoJsonDataSource.load("/borders/kazakhstan.geojson", { // Границы Казхастана
Cesium.GeoJsonDataSource.load("/borders/world.json", { // Границы мира во круг Казахстана
stroke: Cesium.Color.YELLOW, // цвет линии границы
fill: Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.05), // заливка (прозрачная)
strokeWidth: 0,
clampToGround: true
}).then(function(dataSource) {
viewer.dataSources.add(dataSource);
});
const prov = makeProvider({ useTMS: false, useGeographic: false, minZ: 1, maxZ: 17, tileSize: 256 });
viewer.imageryLayers.removeAll();
viewer.imageryLayers.addImageryProvider(prov);
// Перемещения по прописанным координатам (Алматы)
flyKazakhstan(1000);
// Подсказки консоли
console.log("Страница origin:", ORIGIN);
console.log("Тайлы берём с:", TILE_ROOT);
console.log("Важно: страница и тайлы должны быть с ОДНОГО origin (тот же хост и порт).");
</script>
<script src="/models/TANK.js"></script> <!-- 3D модель -->
</body>
</html>
I really appreciate your help. Would you mind sharing a sample code snippet to make things clearer?