/* 391 B05 평면 그림 단위검증 헬퍼 — 측점 법선(`_Hover.drawStationNormal`) · 고른 곡선 밝힘 · * 삼각형(`_Curve_Pick`) · MC 점(`logic/_Curve.curveMidVertex`)을 트랜스파일해 가짜 캔버스로 돌린다. */ const fs = require("fs"); const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const B05 = path.join(__dirname, "..", "..", "B05_Profile"); const STUBS = { "./B05_Profile_UI_RouteEdit_Input": { pickHover: () => null } }; const { loadTs } = makeLoader({ root: path.join(__dirname, "..", ".."), requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); }, }); /** 그린 것만 적는 가짜 캔버스 — 선 = 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));