- 391-1 측점 맴돔 · 고름 = 한 함수(drawStationNormal) · 좌우 20 m 고정 하늘색 · 짧은 12 px 선 · 절성토 색 지움 · 구조물 마름모 그대로 - 391-2 고른 곡선 = 굵은 호 + 교각점→BC · EC 접선 + BC · MC · EC 세 점(새 파일 RouteEdit_Curve_Pick · MC = curveMidVertex) · 곡선 없는 교각점 = 같은 크기 삼각형 - 391-3 잠금 = 황금(#ca8a04 · 어두움 #facc15) · 굵기 4 + 흰 테 - 시험 test_391_routeedit_plan_draw 새로 · test_381_3 맴돔 배선 고쳐 씀 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
118 lines
3.7 KiB
JavaScript
118 lines
3.7 KiB
JavaScript
/* 391 B05 평면 그림 단위검증 헬퍼 — 측점 법선(`_Hover.drawStationNormal`) · 고른 곡선 밝힘 ·
|
|
* 삼각형(`_Curve_Pick`) · MC 점(`logic/_Curve.curveMidVertex`)을 트랜스파일해 가짜 캔버스로 돌린다.
|
|
*/
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
const B05 = path.join(__dirname, "..", "..", "B05_Profile");
|
|
|
|
const STUBS = { "./B05_Profile_UI_RouteEdit_Input": { pickHover: () => null } };
|
|
const cache = new Map();
|
|
function loadTs(full) {
|
|
if (cache.has(full)) return cache.get(full);
|
|
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
|
}).outputText;
|
|
const box = { exports: {} };
|
|
cache.set(full, box.exports);
|
|
const localRequire = (request) => {
|
|
if (STUBS[request]) return STUBS[request];
|
|
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
|
|
return require(request);
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
|
|
cache.set(full, box.exports);
|
|
return box.exports;
|
|
}
|
|
|
|
/** 그린 것만 적는 가짜 캔버스 — 선 = moveTo/lineTo 점 · 점 = arc 가운데 · 획 색. */
|
|
function fakeContext() {
|
|
const log = { lines: [], dots: [], strokes: [] };
|
|
let path = [];
|
|
const ctx = {
|
|
save() {},
|
|
restore() {},
|
|
setLineDash() {},
|
|
beginPath: () => (path = []),
|
|
moveTo: (x, y) => path.push([x, y]),
|
|
lineTo: (x, y) => path.push([x, y]),
|
|
closePath() {},
|
|
arc: (x, y, r) => log.dots.push([x, y, r]),
|
|
stroke: () => {
|
|
log.strokes.push(ctx.strokeStyle);
|
|
if (path.length) log.lines.push({ color: ctx.strokeStyle, width: ctx.lineWidth, path });
|
|
},
|
|
fill() {},
|
|
};
|
|
return { ctx, log, path: () => path };
|
|
}
|
|
|
|
const round = (v) => Math.round(v * 1000) / 1000;
|
|
const hover = loadTs(path.join(B05, "B05_Profile_UI_RouteEdit_Hover.ts"));
|
|
const pick = loadTs(path.join(B05, "B05_Profile_UI_RouteEdit_Curve_Pick.ts"));
|
|
const curve = loadTs(path.join(B05, "logic", "B05_Profile_UI_RouteEdit_Curve.ts"));
|
|
const style = { getPropertyValue: () => "" };
|
|
const out = {};
|
|
|
|
// 측점 법선 — 동서 노선 50 m 자리 · 화면 = 2 px/m
|
|
const scene = { toScreen: ([x, y]) => [x * 2, y * 2] };
|
|
const normal = fakeContext();
|
|
hover.drawStationNormal(
|
|
normal.ctx,
|
|
scene,
|
|
[
|
|
[0, 0],
|
|
[100, 0],
|
|
],
|
|
50,
|
|
);
|
|
out.normal = normal.log.lines.map((l) => ({
|
|
color: l.color,
|
|
path: l.path.map((p) => p.map(round)),
|
|
}));
|
|
|
|
// 직각 곡선 R 10 — 교각점 (0,0) · BC (-10,0) · EC (0,10)
|
|
const right = {
|
|
apex: [0, 0],
|
|
radius_m: 10,
|
|
tangent_m: 10,
|
|
inner_angle_deg: 90,
|
|
start: [-10, 0],
|
|
end: [0, 10],
|
|
node_first: 1,
|
|
node_last: 1,
|
|
violations: [],
|
|
};
|
|
out.mid = curve.curveMidVertex(right).map(round);
|
|
|
|
const unit = { toScreen: ([x, y]) => [x, y] };
|
|
const picked = fakeContext();
|
|
pick.drawPickedCurve(
|
|
picked.ctx,
|
|
{ ...unit, picked: 1, curveInfo: [right], curveOn: [true, true, true] },
|
|
style,
|
|
);
|
|
out.picked = {
|
|
dots: picked.log.dots.map(([x, y]) => [round(x), round(y)]),
|
|
tangent: picked.log.lines[0].path,
|
|
arcWidths: picked.log.lines.slice(1).map((l) => l.width),
|
|
};
|
|
const off = fakeContext();
|
|
pick.drawPickedCurve(
|
|
off.ctx,
|
|
{ ...unit, picked: 1, curveInfo: [right], curveOn: [true, false, true] },
|
|
style,
|
|
);
|
|
const none = fakeContext();
|
|
pick.drawPickedCurve(
|
|
none.ctx,
|
|
{ ...unit, picked: -1, curveInfo: [right], curveOn: [true, true, true] },
|
|
style,
|
|
);
|
|
out.offDrawn = off.log.strokes.length + none.log.strokes.length;
|
|
|
|
const tri = fakeContext();
|
|
pick.traceNodeTriangle(tri.ctx, 100, 100, 6);
|
|
out.triangle = tri.path().map((p) => p.map(round));
|
|
console.log(JSON.stringify(out));
|