feat: add cesium traffic signal countdowns

This commit is contained in:
2026-08-06 16:43:08 +08:00
parent 9fbc218e10
commit 043766b84e
22 changed files with 1022 additions and 170 deletions

View File

@@ -182,6 +182,7 @@ function buildIntermediates(area) {
"--config",
derivedConfigPath,
], "intermediates");
writeTrafficSignals(area);
fs.rmSync(stageManifestPath(area, "reimport"), { force: true });
const finished = Date.now();
writeStageManifest(area, {
@@ -199,6 +200,7 @@ function buildIntermediates(area) {
derivedConfig: fileRecord(derivedConfigPath),
geojsonDir: fileRecord(area.outputs.geojsonDir),
...sceneGeojsonRecords(area),
trafficSignals: fileRecord(area.outputs.trafficSignals),
gpkg: fileRecord(area.outputs.gpkg),
qgisProject: fileRecord(area.outputs.qgisProject),
qgisPreview: optionalFileRecord(area.outputs.qgisPreview),
@@ -221,6 +223,7 @@ function reimportGpkg(area) {
"--config",
derivedConfigPath,
], "reimport");
writeTrafficSignals(area);
fs.rmSync(stageManifestPath(area, "intermediates"), { force: true });
const finished = Date.now();
writeStageManifest(area, {
@@ -238,6 +241,7 @@ function reimportGpkg(area) {
outputs: {
geojsonDir: fileRecord(area.outputs.geojsonDir),
...sceneGeojsonRecords(area),
trafficSignals: fileRecord(area.outputs.trafficSignals),
},
summary: {
geojson: geojsonFeatureCounts(area),
@@ -249,6 +253,7 @@ function reimportGpkg(area) {
function buildBlenderScene(area) {
ensureFile(blenderExecutable(area), "Blender executable");
ensureFile(path.join(repoRoot, "blender", "generate_scene.py"), "Blender scene generator");
ensureFile(area.outputs.trafficSignals, "Traffic signal anchors");
fs.mkdirSync(path.dirname(area.outputs.blend), { recursive: true });
fs.mkdirSync(path.dirname(area.outputs.render), { recursive: true });
@@ -290,6 +295,7 @@ function buildBlenderScene(area) {
osm: fileRecord(area.input),
geojsonDir: fileRecord(area.outputs.geojsonDir),
...sceneGeojsonRecords(area),
trafficSignals: fileRecord(area.outputs.trafficSignals),
},
outputs: {
blend: fileRecord(area.outputs.blend),
@@ -324,9 +330,18 @@ function exportCesium(area) {
area.outputs.blend,
"--glb",
area.outputs.glb,
"--dynamic-glb",
area.outputs.trafficSignalsDynamicGlb,
"--countdown-0-glb",
area.outputs.trafficSignalsCountdown0Glb,
"--countdown-1-glb",
area.outputs.trafficSignalsCountdown1Glb,
"--metadata",
area.outputs.metadata,
], "cesium");
ensureFile(area.outputs.trafficSignalsDynamicGlb, "Dynamic traffic signal GLB");
ensureFile(area.outputs.trafficSignalsCountdown0Glb, "Traffic countdown group 0 GLB");
ensureFile(area.outputs.trafficSignalsCountdown1Glb, "Traffic countdown group 1 GLB");
const semanticAssets = semanticAssetRecords(area);
writeCesiumPreview(area);
const finished = Date.now();
@@ -344,6 +359,7 @@ function exportCesium(area) {
outputs: {
glb: fileRecord(area.outputs.glb),
metadata: fileRecord(area.outputs.metadata),
trafficSignalsDynamicGlb: fileRecord(area.outputs.trafficSignalsDynamicGlb),
semanticAssets,
},
summary: {
@@ -466,19 +482,19 @@ function runCommand(command, commandArgs, stage) {
function writeCesiumPreview(area) {
ensureFile(area.outputs.glb, "Cesium GLB");
ensureFile(area.outputs.metadata, "Cesium metadata");
ensureFile(area.outputs.trafficSignals, "Traffic signal anchors");
const htmlPath = area.outputs.cesiumPreview;
const started = Date.now();
const startedAt = new Date(started).toISOString();
fs.mkdirSync(path.dirname(htmlPath), { recursive: true });
writeVehicleRoute(area);
writeTrafficSignals(area);
const vehicleModelNames = writeVehicleModel(area);
writeCesiumPreviewSupportFiles(path.dirname(htmlPath));
const glbName = path.basename(area.outputs.glb);
const metadataName = path.basename(area.outputs.metadata);
const routeName = path.basename(area.outputs.vehicleRoute);
const vehicleModelName = path.basename(area.outputs.vehicleModel);
fs.writeFileSync(htmlPath, cesiumPreviewHtml(glbName, metadataName, routeName, vehicleModelName, area.id, vehicleModelNames, path.basename(area.outputs.trafficSignals)));
fs.writeFileSync(htmlPath, cesiumPreviewHtml(glbName, metadataName, routeName, vehicleModelName, area.id, vehicleModelNames, previewRelativePath(area.outputs.areaDir, area.outputs.trafficSignals)));
console.log(`Cesium preview: ${htmlPath}`);
const finished = Date.now();
writeStageManifest(area, {
@@ -516,6 +532,10 @@ function writeTrafficSignals(area) {
console.log(`Traffic signals: ${signals.signals.length} anchors in ${area.outputs.trafficSignals}`);
}
function previewRelativePath(fromDir, target) {
return path.relative(fromDir, target).split(path.sep).join("/");
}
function writeVehicleRoute(area) {
const route = buildPreviewVehicleRoute(area.input);
fs.mkdirSync(path.dirname(area.outputs.vehicleRoute), { recursive: true });