- 高德 GeoJSON 参考流程: `scripts/lib/gaode-junction-reference.js` 与 `scripts/inspect-junction-reference.js` 将 GCJ-02 参考转换为 WGS84, 按 node id/最近距离关联 OSM, 支持普通路口面和 `complex-cluster` 两种匹配。 - 复合路口模板 `complex-junction-v1`: `scripts/lib/complex-junction.js` 用参考 几何校准 core 半径, 生成路口面、进口路面、斑马线、停止线、角部圆角与安全岛; 拓扑/信号/连接全部沿用 OSM/native。 - 车道中心线控制要素避让: `compileLaneCenterlines` 现接收模板已产出的斑马线/停止线, 新增 `trimLaneOutsideControls` 按到路口中心的半径定向裁剪; 标线源几何同步裁剪, 不再 越过斑马线继续画到核心区。拓扑几何不变, connector 集合前后一致。 - 复合路口人行道转角: `buildComplexJunctionGeometry` 沿已定义的路缘生成 2m 宽转角带, 复用圆角曲线, 通过 `islands` 通道并入 `sidewalk_surface`; 自交或坐标非有限时报 `complex-junction-sidewalk-corner-fallback` 并跳过。 - 新增诊断: `complex-junction-configured-radius-ignored`、 `lane-centerline-fully-inside-control`、`complex-junction-sidewalk-corner-fallback`。 - 死码清理: 移除未被调用的 `clusterApproachRing`。 - spec 更新: `.trellis/spec/pipeline/cli-and-stages.md` 复合路口小节补充控制要素 避让顺序、人行道转角契约、Validation 矩阵三行; 索引新增导航。 - 任务产物 `08-19-gaode-junction-reference`: 8 条验收标准全部实测记录, Scope Drift / Verification Log / Known Gaps 三节沉淀本次工作。 Regression: test:native-road / test:road-workbench / test:preflight / test:native-preview-traffic / test:package-contract / test:traffic-signals / test:gaode-junction-reference 全绿; road:check ok=true, errors=[]。
47 lines
2.2 KiB
JavaScript
47 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
"use strict";
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { inspectReference, localReferenceSvg } = require("./lib/gaode-junction-reference");
|
|
|
|
function parseArgs(argv) {
|
|
const result = {};
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
if (!argv[index].startsWith("--")) continue;
|
|
const key = argv[index].slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
result[key] = argv[index + 1] && !argv[index + 1].startsWith("--") ? argv[++index] : "true";
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function required(args, key) {
|
|
if (!args[key]) throw new Error(`--${key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)} is required`);
|
|
return path.resolve(args[key]);
|
|
}
|
|
|
|
function main() {
|
|
const args = parseArgs(process.argv.slice(2));
|
|
const result = inspectReference({
|
|
referenceFile: required(args, "reference"),
|
|
osmFile: required(args, "osm"),
|
|
nativeIntersectionFile: required(args, "nativeIntersection"),
|
|
nativeRoadSurfaceFile: args.nativeRoadSurface ? path.resolve(args.nativeRoadSurface) : null,
|
|
nodeId: args.nodeId,
|
|
clusterId: args.clusterId,
|
|
});
|
|
const output = path.resolve(args.output || `${args.reference.replace(/\.geojson$/i, "")}-wgs84.geojson`);
|
|
const comparison = output.replace(/\.geojson$/i, "-comparison.json");
|
|
fs.mkdirSync(path.dirname(output), { recursive: true });
|
|
fs.writeFileSync(output, `${JSON.stringify(result.converted, null, 2)}\n`);
|
|
fs.writeFileSync(comparison, `${JSON.stringify({ ...result, converted: undefined, matchedFeatures: undefined }, null, 2)}\n`);
|
|
const svg = output.replace(/\.geojson$/i, "-overlay.svg");
|
|
// Draw whatever the comparison actually matched: a per-node junction surface
|
|
// for ordinary junctions, or the whole complex cluster for templated ones.
|
|
const matchingNative = { type: "FeatureCollection", features: result.matchedFeatures || [] };
|
|
fs.writeFileSync(svg, localReferenceSvg({ converted: result.converted, nativeIntersection: matchingNative, center: result.matchedOsmNode.coordinate }));
|
|
console.log(JSON.stringify({ output, comparison, svg, ...result, converted: undefined, matchedFeatures: undefined }, null, 2));
|
|
}
|
|
|
|
if (require.main === module) main();
|