Files
Aislo/resources/tester/helper_323_9_twin_cards_3d.cjs
T
eomsangdonandClaude Opus 5.5 09a064da37 refactor(472-3 B05 코리도): 코리도 계산 8 파일 logic 이동 · 검사 도구 헛잡음 걷음
- B05 Corridor Build · Envelope · Station · Station_Structure · Structures · _Box · _Chute · _Path
  → B05_Profile/logic/B05_Profile_Corridor_*.ts (본문 그대로 · import 경로만)
- Structures 재수출 줄 걷음(700 줄 한도) · Envelope 는 Structures_Hash 를 바로 부름
- helper_472_3_graph = 줄 머리 import · export 만 셈(주석 속 낱말 안 셈)
- test_472_3 SESSION_PULLS 헛잡음 6 줄 · GEOMETRY_PULLS B05 8 줄 걷음
  (남은 ui_template_locale 10 = Route_Carry_Patch → common_util_svg 진짜 끌림)
- 옮긴 파일을 읽는 시험 · 헬퍼 경로 새 자리로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:08:29 +09:00

78 lines
3.4 KiB
JavaScript

/* PLAN 323-9 ④-② — 같은 시설을 그리는 카드 둘(같은 m · 노선 끝 EP 꼴 소수 차 0.01 m)이면 3D 관 · 세월교 · BOX 몸체는 한 번.
* 화면 TS(`buildCorridorStructures`)를 그 자리에서 트랜스파일해 Node 로 돌림(로더 = helper_135_3 과 같음).
* 입력 = 73-4 픽스처(세월교 173.087 · BOX 352.14) · 결과 = 표준출력 JSON. 짝 = test_323_9_twin_cards_3d.py.
*/
const fs = require("fs");
const path = require("path");
const ROOT = path.join(__dirname, "..", "..");
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const STUBS = {
"@ui/ui_template_toast": { showToast: () => undefined },
three: require(path.join(ROOT, "config", "node_modules", "three")),
};
const resolve = (base) =>
[base, `${base}.ts`, path.join(base, "index.ts")].find(
(p) => fs.existsSync(p) && fs.statSync(p).isFile(),
) ?? `${base}.ts`;
const { loadTs } = makeLoader({
root: ROOT,
interop: true,
requireFor: (full) => (request) => {
if (STUBS[request]) return STUBS[request];
const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" };
for (const [prefix, dir] of Object.entries(alias))
if (request.startsWith(prefix))
return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length))));
return loadTs(resolve(path.join(path.dirname(full), request)));
},
});
const { buildCorridorStructures } = loadTs(
path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Corridor_Structures.ts"),
);
const fixture = JSON.parse(
fs.readFileSync(path.join(__dirname, "fixtures", "b06_73_4_body_guard_sections.json"), "utf8"),
);
const clone = (v) => JSON.parse(JSON.stringify(v));
const at = (c) => clone(fixture.cross_sections.find((s) => Math.abs(s.chainage_m - c) < 0.6));
/** 직선 노선 — 가장 가까운 측점 프레임에서 앞쪽으로 편다. */
const frameAtOf = (sections) => (atM) => {
const s = sections.reduce((b, x) =>
Math.abs(x.chainage_m - atM) < Math.abs(b.chainage_m - atM) ? x : b,
);
const [lx, ly] = s.frame.left_xy;
const along = atM - s.chainage_m;
return {
cx: s.center_x - ly * along,
cy: s.center_y + lx * along,
leftX: lx,
leftY: ly,
designZ: s.design?.design_elevation_m ?? null,
};
};
/** 부재 차림표 — 종류 · 열쇠 · 측점(같은 몸체를 두 번 세우면 같은 줄이 둘). */
const kinds = (sections) =>
buildCorridorStructures(sections, frameAtOf(sections))
.map((s) => `${s.kind}:${s.key ?? ""}:${s.chainage_m.toFixed(2)}`)
.sort();
const pick = loadTs(
path.join(ROOT, "B05_Profile", "logic", "B05_Profile_UI_Corridor_Structures_Pick.ts"),
);
const own = pick.ownsBody;
/** 노선 끝 꼴 — 같은 시설을 그리는 카드가 소수 차(EP 1078 · 1078.010813)로 하나 더. */
const ep = (one) => Object.assign(clone(one), { chainage_m: one.chainage_m + 0.010813 });
const out = {};
for (const c of [173.087, 352.14]) {
const one = at(c);
const twin = kinds([one, clone(one)]);
const epTwin = kinds([one, ep(one)]);
const epFirst = kinds([ep(one), one]); // 차례가 바뀌어도 시설 자리에 가까운 카드 하나
pick.ownsBody = () => true; // 고치기 전(카드마다 몸체) — 기준이 변경을 재는지
const before = kinds([one, clone(one)]);
const epBefore = kinds([one, ep(one)]);
pick.ownsBody = own;
out[c] = { one: kinds([one]), twin, before, epTwin, epFirst, epBefore };
}
process.stdout.write(JSON.stringify(out));