refactor: consume external road compiler
This commit is contained in:
@@ -4,7 +4,7 @@ const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { spawnSync } = require("child_process");
|
||||
const { readAreaConfig } = require("./lib/area-config");
|
||||
const { compileArea: compileNativeRoads } = require("./compile-native-roads");
|
||||
const { compileArea: compileNativeRoads } = require("./lib/road-compiler-cli");
|
||||
const { resolveStages } = require("./lib/build-stages");
|
||||
const { validateManifest, addIntegrity } = require("./lib/package-contract");
|
||||
const { blenderExecutable: resolveBlenderExecutable } = require("./lib/tool-paths");
|
||||
@@ -226,7 +226,7 @@ function buildBlenderScene(area, roadProvider) {
|
||||
fs.mkdirSync(path.dirname(area.outputs.blend), { recursive: true });
|
||||
fs.mkdirSync(path.dirname(area.outputs.render), { recursive: true });
|
||||
if (roadProvider === "native") {
|
||||
compileNativeRoads(configPath);
|
||||
compileNativeRoads(area);
|
||||
ensureNativeRoadLayers(area);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ const os = require("os");
|
||||
const { execFileSync } = require("child_process");
|
||||
const { JsStreetNetwork } = require("osm2streets-js-node");
|
||||
const { qgisPaths } = require("./lib/tool-paths");
|
||||
const { buildCustomTurnLaneArrows } = require("../packages/road-compiler/src/compile/turn-lane-arrows");
|
||||
const { turnLaneArrows: { buildCustomTurnLaneArrows } } = require("@osm-asset/road-compiler");
|
||||
const { readTrafficSignalFeatures } = require("./lib/traffic-signals");
|
||||
const {
|
||||
SCENE_LAYERS,
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
const path = require("path");
|
||||
const { readAreaConfig } = require("./lib/area-config");
|
||||
const { compileArea, parseArgs } = require("./compile-native-roads");
|
||||
const { checkOutput } = require("../packages/road-compiler/src/check");
|
||||
const { check } = require("@osm-asset/road-compiler");
|
||||
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
|
||||
function checkArea(configPath, options = {}) {
|
||||
if (options.compile) compileArea(configPath);
|
||||
const area = readAreaConfig(configPath, { repoRoot });
|
||||
return checkOutput({ areaId: area.id, outDir: area.outputs.nativeRoadDir });
|
||||
return check.checkOutput({ areaId: area.id, outDir: area.outputs.nativeRoadDir });
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const { readAreaConfig, toRoadCompilerInput } = require("./lib/area-config");
|
||||
const { compileInput } = require("../packages/road-compiler/src/compile/compiler");
|
||||
const { readAreaConfig } = require("./lib/area-config");
|
||||
const { compileArea: compileWithCli } = require("./lib/road-compiler-cli");
|
||||
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
|
||||
@@ -19,15 +19,13 @@ function parseArgs(argv) {
|
||||
|
||||
function compileArea(configPath) {
|
||||
const area = readAreaConfig(configPath, { repoRoot });
|
||||
const compiled = compileInput(toRoadCompilerInput(area));
|
||||
return { ...compiled, area };
|
||||
return { area, marker: compileWithCli(area) };
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = parseArgs(process.argv.slice(2));
|
||||
const configPath = path.resolve(args.config || path.join(repoRoot, "config", "areas", "nantaizi-lake-innovation-valley.json"));
|
||||
const { area, result, comparison } = compileArea(configPath);
|
||||
console.log(`NATIVE_ROAD_COMPILE_DONE ${JSON.stringify({ areaId: area.id, roads: result.model.roads.length, endpoints: result.model.endpoints.length, diagnostics: result.diagnostics.length, output: area.outputs.nativeRoadDir, comparison })}`);
|
||||
compileArea(configPath);
|
||||
}
|
||||
|
||||
if (require.main === module) main();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { inspectReference, localReferenceSvg } = require("../packages/road-compiler/src/reference/gaode");
|
||||
const { gaodeReference: { inspectReference, localReferenceSvg } } = require("@osm-asset/road-compiler");
|
||||
|
||||
function parseArgs(argv) {
|
||||
const result = {};
|
||||
|
||||
47
scripts/lib/road-compiler-cli.js
Normal file
47
scripts/lib/road-compiler-cli.js
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { spawnSync } = require("child_process");
|
||||
const { toRoadCompilerInput } = require("./area-config");
|
||||
|
||||
function compilerCli() {
|
||||
const packageFile = require.resolve("@osm-asset/road-compiler/package.json");
|
||||
const packageRoot = path.dirname(packageFile);
|
||||
const manifest = require(packageFile);
|
||||
return path.join(packageRoot, typeof manifest.bin === "string" ? manifest.bin : manifest.bin["road-compiler"]);
|
||||
}
|
||||
|
||||
function writeInput(area) {
|
||||
const input = toRoadCompilerInput(area);
|
||||
fs.mkdirSync(area.outputs.pipelineDir, { recursive: true });
|
||||
const file = path.join(area.outputs.pipelineDir, "road-compiler.input.json");
|
||||
fs.writeFileSync(file, `${JSON.stringify(input, null, 2)}\n`);
|
||||
return { file, input };
|
||||
}
|
||||
|
||||
function parseCompletionMarker(stdout, input) {
|
||||
const lines = String(stdout).split(/\r?\n/).filter((line) => line.startsWith("NATIVE_ROAD_COMPILE_DONE "));
|
||||
if (lines.length !== 1) throw new Error(`Expected exactly one NATIVE_ROAD_COMPILE_DONE marker, found ${lines.length}`);
|
||||
let marker;
|
||||
try { marker = JSON.parse(lines[0].slice("NATIVE_ROAD_COMPILE_DONE ".length)); }
|
||||
catch (error) { throw new Error(`Invalid NATIVE_ROAD_COMPILE_DONE JSON: ${error.message}`); }
|
||||
if (!marker || typeof marker !== "object") throw new Error("NATIVE_ROAD_COMPILE_DONE payload must be an object");
|
||||
if (marker.areaId !== input.areaId) throw new Error(`NATIVE_ROAD_COMPILE_DONE areaId mismatch: expected ${input.areaId}, got ${marker.areaId}`);
|
||||
if (path.resolve(marker.output || "") !== path.resolve(input.outDir)) throw new Error(`NATIVE_ROAD_COMPILE_DONE output mismatch: expected ${input.outDir}, got ${marker.output}`);
|
||||
return marker;
|
||||
}
|
||||
|
||||
function compileArea(area) {
|
||||
const { file, input } = writeInput(area);
|
||||
const result = spawnSync(process.execPath, [compilerCli(), "--input", file], { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] });
|
||||
if (result.stdout) process.stdout.write(result.stdout);
|
||||
if (result.error) throw result.error;
|
||||
if (result.status !== 0) {
|
||||
const signal = result.signal ? ` signal=${result.signal}` : "";
|
||||
throw new Error(`Native road compiler failed with status=${result.status}${signal}`);
|
||||
}
|
||||
return parseCompletionMarker(result.stdout, input);
|
||||
}
|
||||
|
||||
module.exports = { compileArea, compilerCli, parseCompletionMarker, writeInput };
|
||||
@@ -1,8 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const { parseOsm } = require("../../packages/road-compiler/src/osm");
|
||||
const trafficSignals = require("../../packages/road-compiler/src/traffic-signals");
|
||||
const { osm: { parseOsm }, trafficSignals } = require("@osm-asset/road-compiler");
|
||||
|
||||
function readTrafficSignalFeatures(stopLinePath, intersectionPath, osmPath) {
|
||||
const controls = parseOsm(fs.readFileSync(osmPath, "utf8")).trafficSignalControls;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const { parseOsm } = require("../../packages/road-compiler/src/osm");
|
||||
const {
|
||||
const { osm: { parseOsm }, laneGeometry: {
|
||||
appendCoordinates,
|
||||
haversineMeters,
|
||||
laneCenterline,
|
||||
@@ -10,7 +9,7 @@ const {
|
||||
orientPolyline,
|
||||
polylineLength,
|
||||
polylineMidpoint,
|
||||
} = require("../../packages/road-compiler/src/geometry/lane-geometry");
|
||||
} } = require("@osm-asset/road-compiler");
|
||||
|
||||
const MAX_ROUTES = 5;
|
||||
const MAX_PATH_EDGES = 7;
|
||||
|
||||
@@ -17,7 +17,7 @@ const path = require("path");
|
||||
const os = require("os");
|
||||
const { execFileSync } = require("child_process");
|
||||
const { qgisPaths } = require("./lib/tool-paths");
|
||||
const { parseOsm } = require("../packages/road-compiler/src/osm");
|
||||
const { osm: { parseOsm } } = require("@osm-asset/road-compiler");
|
||||
const {
|
||||
validateTrafficSignalSourceReferences,
|
||||
} = require("./lib/traffic-signals");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { templateFor } = require("../packages/road-compiler/src/compile/turn-lane-arrows");
|
||||
const { turnLaneArrows: { templateFor } } = require("@osm-asset/road-compiler");
|
||||
|
||||
const output = path.resolve(process.argv[2] || path.join("outputs", "turn-lane-arrow-samples.svg"));
|
||||
const DISPLAY_SCALE = 60;
|
||||
|
||||
@@ -5,7 +5,7 @@ const { execFileSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const { readAreaConfig } = require("./lib/area-config");
|
||||
const { parseArgs } = require("./compile-native-roads");
|
||||
const { startWorkbench } = require("../packages/road-compiler/workbench/server");
|
||||
const { startWorkbench } = require("@osm-asset/road-compiler/workbench/server");
|
||||
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
const args = parseArgs(process.argv.slice(2));
|
||||
|
||||
@@ -5,7 +5,7 @@ const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { gcj02ToWgs84, convertGeoJson, inspectReference } = require("../packages/road-compiler/src/reference/gaode");
|
||||
const { gaodeReference: { gcj02ToWgs84, convertGeoJson, inspectReference } } = require("@osm-asset/road-compiler");
|
||||
|
||||
const converted = gcj02ToWgs84([114.12864875054062, 30.460485279762146]);
|
||||
assert.ok(Math.abs(converted[0] - 114.1229659) < 0.00001);
|
||||
|
||||
@@ -5,7 +5,7 @@ const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { compileRoadModel, compileGeometry, validateOverrides } = require("../packages/road-compiler/src/compile/native-road");
|
||||
const { nativeRoad: { compileRoadModel, compileGeometry, validateOverrides } } = require("@osm-asset/road-compiler");
|
||||
const { compileArea } = require("./compile-native-roads");
|
||||
const { checkArea } = require("./check-native-roads");
|
||||
|
||||
@@ -164,7 +164,7 @@ assert.equal(clusterApproaches.filter((feature) => feature.properties.kind === "
|
||||
assert.ok(clusterApproachGeometry.diagnostics.some((item) => item.rule === "complex-junction-insufficient-nodes"));
|
||||
assert.equal(clusterApproachGeometry.intersectionSurface.features.length, 0);
|
||||
|
||||
const fixtureDir = path.join(__dirname, "..", "packages", "road-compiler", "test", "fixtures");
|
||||
const fixtureDir = path.join(path.dirname(require.resolve("@osm-asset/road-compiler/package.json")), "test", "fixtures");
|
||||
const fengshuOsm = fs.readFileSync(path.join(fixtureDir, "fengshu-er-road.osm"), "utf8");
|
||||
const fengshuModel = compileRoadModel(fengshuOsm, empty);
|
||||
const fengshuCluster = {
|
||||
@@ -402,20 +402,22 @@ try {
|
||||
fs.writeFileSync(input, osm);
|
||||
fs.writeFileSync(config, JSON.stringify({ id: "fresh", input, outputRoot }));
|
||||
const compiledArea = compileArea(config);
|
||||
assert.equal(compiledArea.result.areaId, "fresh");
|
||||
assert.equal(compiledArea.marker.areaId, "fresh");
|
||||
assert.ok(fs.existsSync(path.join(outputRoot, "fresh", "native-road", "compiled.json")));
|
||||
const compiled = JSON.parse(fs.readFileSync(path.join(outputRoot, "fresh", "native-road", "compiled.json"), "utf8"));
|
||||
const comparison = JSON.parse(fs.readFileSync(path.join(outputRoot, "fresh", "native-road", "comparison.json"), "utf8"));
|
||||
const centerLineLayer = JSON.parse(fs.readFileSync(path.join(outputRoot, "fresh", "native-road", "layers", "center_lines.geojson"), "utf8"));
|
||||
const edgeLineLayer = JSON.parse(fs.readFileSync(path.join(outputRoot, "fresh", "native-road", "layers", "edge_lines.geojson"), "utf8"));
|
||||
assert.equal(centerLineLayer.type, "FeatureCollection");
|
||||
assert.equal(centerLineLayer.features.length, compiledArea.comparison.nativeCenterLineFeatures);
|
||||
assert.equal(centerLineLayer.features.length, comparison.nativeCenterLineFeatures);
|
||||
assert.equal(edgeLineLayer.features.length, 0);
|
||||
assert.equal(compiledArea.comparison.schema, "native-road-comparison/v2");
|
||||
assert.equal(compiledArea.comparison.nativeRoadCount, compiledArea.result.model.roads.length);
|
||||
assert.equal(compiledArea.comparison.nativePublishedMovementCount, compiledArea.result.movements.filter((movement) => movement.geometryPublished).length);
|
||||
assert.equal(compiledArea.comparison.nativeCrosswalkFeatures, 0);
|
||||
assert.equal(compiledArea.comparison.nativeVehicleStopLineFeatures, 0);
|
||||
assert.equal(compiledArea.comparison.nativeApproachEnvelopeJunctions + compiledArea.comparison.nativeFallbackJunctions, compiledArea.comparison.nativeJunctionSurfaceFeatures);
|
||||
assert.ok(compiledArea.comparison.nativeMaxJunctionExpansionRatio >= 0);
|
||||
assert.equal(comparison.schema, "native-road-comparison/v2");
|
||||
assert.equal(comparison.nativeRoadCount, compiled.model.roads.length);
|
||||
assert.equal(comparison.nativePublishedMovementCount, compiled.movements.filter((movement) => movement.geometryPublished).length);
|
||||
assert.equal(comparison.nativeCrosswalkFeatures, 0);
|
||||
assert.equal(comparison.nativeVehicleStopLineFeatures, 0);
|
||||
assert.equal(comparison.nativeApproachEnvelopeJunctions + comparison.nativeFallbackJunctions, comparison.nativeJunctionSurfaceFeatures);
|
||||
assert.ok(comparison.nativeMaxJunctionExpansionRatio >= 0);
|
||||
assert.equal(checkArea(config).ok, true);
|
||||
} finally {
|
||||
fs.rmSync(freshArea, { recursive: true, force: true });
|
||||
|
||||
@@ -22,8 +22,7 @@ const {
|
||||
uTurnConnector,
|
||||
} = require("./lib/vehicle-route");
|
||||
const { buildTrafficSignals } = require("./lib/traffic-signals");
|
||||
const { haversineMeters, laneCenterline } = require("../packages/road-compiler/src/geometry/lane-geometry");
|
||||
const { parseOsm } = require("../packages/road-compiler/src/osm");
|
||||
const { laneGeometry: { haversineMeters, laneCenterline }, osm: { parseOsm } } = require("@osm-asset/road-compiler");
|
||||
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "preview-assets-"));
|
||||
const osmPath = path.join(tempDir, "fixture.osm");
|
||||
|
||||
16
scripts/test-road-compiler-cli.js
Normal file
16
scripts/test-road-compiler-cli.js
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
const assert = require("assert/strict");
|
||||
const { parseCompletionMarker } = require("./lib/road-compiler-cli");
|
||||
|
||||
const input = { areaId: "fixture", outDir: "/tmp/fixture/native-road" };
|
||||
const marker = `NATIVE_ROAD_COMPILE_DONE ${JSON.stringify({ areaId: input.areaId, output: input.outDir, roads: 1, endpoints: 2, diagnostics: 0 })}`;
|
||||
|
||||
assert.equal(parseCompletionMarker(marker, input).areaId, input.areaId);
|
||||
assert.throws(() => parseCompletionMarker("compiler output", input), /exactly one/);
|
||||
assert.throws(() => parseCompletionMarker(`${marker}\n${marker}`, input), /exactly one/);
|
||||
assert.throws(() => parseCompletionMarker("NATIVE_ROAD_COMPILE_DONE {", input), /Invalid/);
|
||||
assert.throws(() => parseCompletionMarker("NATIVE_ROAD_COMPILE_DONE {\"areaId\":\"other\",\"output\":\"/tmp/fixture/native-road\"}", input), /areaId mismatch/);
|
||||
assert.throws(() => parseCompletionMarker("NATIVE_ROAD_COMPILE_DONE {\"areaId\":\"fixture\",\"output\":\"/tmp/other\"}", input), /output mismatch/);
|
||||
console.log("road compiler CLI tests passed");
|
||||
@@ -5,7 +5,8 @@ const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const client = path.join(__dirname, "..", "packages", "road-compiler", "workbench", "client");
|
||||
const packageRoot = path.dirname(require.resolve("@osm-asset/road-compiler/package.json"));
|
||||
const client = path.join(packageRoot, "workbench", "client");
|
||||
const html = fs.readFileSync(path.join(client, "index.html"), "utf8");
|
||||
assert.match(html, /id="width" type="number" min="1" step="0\.01"/);
|
||||
assert.match(html, /data-layer="sidewalks" type="checkbox" checked> 路缘与步行带/);
|
||||
@@ -81,7 +82,7 @@ assert.match(app, /fromLonLat/);
|
||||
assert.match(app, /armFeatures\.push\(new Feature/);
|
||||
assert.match(app, /headFeatures\.push\(new Feature/);
|
||||
assert.match(app, /faceFeatures\.push\(new Feature/);
|
||||
const server = fs.readFileSync(path.join(__dirname, "..", "packages", "road-compiler", "workbench", "server.js"), "utf8");
|
||||
const server = fs.readFileSync(path.join(packageRoot, "workbench", "server.js"), "utf8");
|
||||
assert.match(server, /\/api\/traffic-signals\/generate/);
|
||||
assert.match(server, /function startWorkbench\(/);
|
||||
assert.match(server, /context\.compileFresh\(\)/, "workbench regeneration must use the host-provided fresh compiler callback");
|
||||
|
||||
@@ -11,8 +11,8 @@ const {
|
||||
buildTrafficSignalsFromFeatures,
|
||||
validateTrafficSignalFeatures,
|
||||
validateTrafficSignalSourceReferences,
|
||||
} = require("../packages/road-compiler/src/traffic-signals");
|
||||
const { SCHEMA, loadOrGenerate } = require("../packages/road-compiler/src/native-traffic-signals");
|
||||
} = require("@osm-asset/road-compiler").trafficSignals;
|
||||
const { SCHEMA, loadOrGenerate } = require("@osm-asset/road-compiler").nativeTrafficSignals;
|
||||
|
||||
function rectangle(lon, lat, dx = 0.00003, dy = 0.000006) {
|
||||
return { type: "Feature", geometry: { type: "Polygon", coordinates: [[
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"use strict";
|
||||
|
||||
const assert = require("assert");
|
||||
const { arrowRingsAt, buildCustomTurnLaneArrows, loadManifest, normalizeManeuver, supportedAssets, templateFor } = require("../packages/road-compiler/src/compile/turn-lane-arrows");
|
||||
const { turnLaneArrows: { arrowRingsAt, buildCustomTurnLaneArrows, loadManifest, normalizeManeuver, supportedAssets, templateFor } } = require("@osm-asset/road-compiler");
|
||||
|
||||
function node(id, lon, lat) { return { id, lon, lat, tags: {} }; }
|
||||
function way(id, refs, tags) { return { id, refs, tags }; }
|
||||
|
||||
@@ -5,7 +5,7 @@ const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
const { gcj02ToWgs84: referenceGcj02ToWgs84 } = require("../packages/road-compiler/src/reference/gaode");
|
||||
const { gaodeReference: { gcj02ToWgs84: referenceGcj02ToWgs84 } } = require("@osm-asset/road-compiler");
|
||||
|
||||
const source = fs.readFileSync(path.join(__dirname, "lib", "v2x-cesium-overlay.js"), "utf8");
|
||||
const context = {
|
||||
|
||||
Reference in New Issue
Block a user