feat(preview): add traffic signal visualization

This commit is contained in:
2026-08-05 18:09:37 +08:00
parent c8ca009d13
commit 8b3a1d79d9
12 changed files with 438 additions and 7 deletions

View File

@@ -9,6 +9,7 @@ const { cesiumPreviewHtml } = require("./lib/area-preview");
const { makeVehicleGltf } = require("./lib/vehicle-model");
const { VEHICLE_IDS, REVERSED_MODEL_IDS, writePreviewVehicleLibrary } = require("./lib/vehicle-library");
const { allowedTurns, buildVehicleRoute, classifyConnection } = require("./lib/vehicle-route");
const { buildTrafficSignals } = require("./lib/traffic-signals");
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "preview-assets-"));
const osmPath = path.join(tempDir, "fixture.osm");
@@ -113,15 +114,41 @@ const html = cesiumPreviewHtml(
"vehicle.gltf",
"north<&>\u2028valley",
["car-a.gltf", "truck-a.gltf"],
"traffic-signals.json",
);
assert.match(html, /<title>north&lt;&amp;&gt;\u2028valley Cesium Preview<\/title>/);
assert.match(html, /Loading scene&lt;&amp;&gt;\.glb/);
assert.match(html, /"areaId":"north\\u003c\\u0026\\u003e\\u2028valley"/);
assert.match(html, /"glbName":"scene\\u003c\\u0026\\u003e\.glb"/);
assert.match(html, /"vehicleModelNames":\["car-a\.gltf","truck-a\.gltf"\]/);
assert.match(html, /"trafficSignalsName":"traffic-signals\.json"/);
assert.match(html, /id="toggleSignals"/);
assert.match(html, /id="viewMode"/);
assert.match(html, /data-view-mode="inspect"/);
assert.match(html, /id="semanticToggles" class="control-subgroup hidden"/);
const signals = buildTrafficSignals(
{ type: "FeatureCollection", features: [
rectangle(120.0000, 30.0000, 0.00003, 0.000006),
rectangle(120.0002, 30.0000, 0.00003, 0.000006),
] },
{ type: "FeatureCollection", features: [
{ type: "Feature", geometry: { type: "Polygon", coordinates: [[
[119.9998, 29.9998], [120.0004, 29.9998], [120.0004, 30.0003], [119.9998, 30.0003], [119.9998, 29.9998],
]] } },
] },
);
assert.equal(signals.version, 1);
assert.equal(signals.signals.length, 2);
assert.deepEqual(signals.signals.map((signal) => signal.phaseGroup), [0, 1]);
assert.ok(signals.signals.every((signal) => Number.isFinite(signal.headingDegrees)));
fs.rmSync(tempDir, { recursive: true, force: true });
console.log("Preview asset tests passed.");
function rectangle(lon, lat, halfWidth, halfHeight) {
return { type: "Feature", geometry: { type: "Polygon", coordinates: [[
[lon - halfWidth, lat - halfHeight], [lon + halfWidth, lat - halfHeight],
[lon + halfWidth, lat + halfHeight], [lon - halfWidth, lat + halfHeight], [lon - halfWidth, lat - halfHeight],
]] } };
}