fix(427 공용 측점): 꼭짓점 세움 셈을 공용 파일 밖 B05 logic 새 파일로 — 공용이 B05 종단 선형을 안 끎 · 410 시험 오류 3 풂 (427-2)
- common_util_structure_station `followMovedNodes` = 옮김 · 지움 · 세울 측점(`seat`)만 돌려줌 - 새 B05_Profile/logic/B05_Profile_Grade_Seat.ts `seatBornNodes` = 파이썬 `_seat_born_nodes` 짝 - design_profile_base 가 둘을 차례로 부름 · 272-1 · 427-1 도우미 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
@@ -28,12 +28,6 @@
|
||||
* ========================================================================== */
|
||||
|
||||
import { cardTitle, catalogRow, shapeNeeds } from "./common_util_structure_catalog";
|
||||
import {
|
||||
buildCurves,
|
||||
evaluateAt,
|
||||
type AlignmentBase,
|
||||
type AlignmentNode,
|
||||
} from "../B05_Profile/logic/B05_Profile_UI_Profile_Alignment";
|
||||
|
||||
const EPS = 1e-6;
|
||||
|
||||
@@ -345,19 +339,19 @@ export function oneStationList<S extends ListedStation, P extends { chainage_m:
|
||||
}
|
||||
|
||||
/**
|
||||
* 사라진 구조물 측점(`gone`)의 계획선 꼭짓점을 새 측점(`born`)으로 옮기거나 지우고 새로 세운다 — 서버
|
||||
* `_follow_moved_stations` · `_seat_born_nodes`(B05_Profile_Router_Confirm.py) 짝: 0.006m 안 반올림 차이 ·
|
||||
* 옛 소수 측점의 정수 m 맞춤 자리(272)면 높이 그대로 옮김. 옮긴 관 · 구조물(427) — 짝 못 찾은 옛 측점과
|
||||
* 새 측점이 같은 수면 차례대로 짝 · 높이 고친 꼭짓점(`edited` = 저장 `station_offsets` 키)은 높이째 ·
|
||||
* 나머지 새 측점은 자동 계획선 규칙(원지반 지남 · 다른 꼭짓점 그대로)으로 세움 · 짝 없는 옛 꼭짓점은 지움.
|
||||
* 거울 시험 = `resources/tester/test_427_1_follow_seat.py`.
|
||||
* 사라진 구조물 측점(`gone`)의 계획선 꼭짓점을 새 측점(`born`)으로 옮기거나 지우고, 새로 세울 측점을 고른다 —
|
||||
* 서버 `_follow_moved_stations`(B05_Profile_Router_Confirm.py) 짝: 0.006m 안 반올림 차이 · 옛 소수 측점의
|
||||
* 정수 m 맞춤 자리(272)면 높이 그대로 옮김. 옮긴 관 · 구조물(427) — 짝 못 찾은 옛 측점과 새 측점이 같은
|
||||
* 수면 차례대로 짝 · 높이 고친 꼭짓점(`edited` = 저장 `station_offsets` 키)은 높이째 · 나머지 새 측점은
|
||||
* `seat`(세움은 부르는 쪽이 `seatBornNodes` · B05_Profile/logic/B05_Profile_Grade_Seat.ts) · 짝 없는 옛
|
||||
* 꼭짓점은 지움. 거울 시험 = `resources/tester/test_427_1_follow_seat.py`.
|
||||
*/
|
||||
export function followMovedNodes(
|
||||
base: Pick<AlignmentBase, "basePvi" | "chainage" | "ground" | "policy">,
|
||||
export function followMovedNodes<N extends { chainage_m: number }>(
|
||||
nodes: ReadonlyArray<N>,
|
||||
gone: ReadonlyArray<number>,
|
||||
born: ReadonlyArray<number>,
|
||||
edited: ReadonlyArray<string> = [],
|
||||
): AlignmentNode[] {
|
||||
): { nodes: N[]; seat: number[] } {
|
||||
const target = (old: number): number | null => {
|
||||
const near = born.find((value) => Math.abs(value - old) < 0.006);
|
||||
if (near !== undefined) return near;
|
||||
@@ -379,56 +373,11 @@ export function followMovedNodes(
|
||||
if (!edited.some((key) => Math.abs(Number(key) - old) < 0.006)) seat.push(left[index]);
|
||||
});
|
||||
}
|
||||
const kept = base.basePvi.flatMap((node) => {
|
||||
const kept = nodes.flatMap((node) => {
|
||||
const old = gone.find((value) => Math.abs(value - node.chainage_m) < 0.006);
|
||||
if (old === undefined) return [node];
|
||||
const to = moves.get(old) ?? null;
|
||||
return to === null || seat.includes(to) ? [] : [{ ...node, chainage_m: to }];
|
||||
});
|
||||
return seatBornNodes(base, kept, seat);
|
||||
}
|
||||
|
||||
/** 새 측점에 원지반을 지나는 꼭짓점(서버 `_seat_born_nodes` 짝 · `pass_through` 규칙 · 다른 꼭짓점 그대로). */
|
||||
function seatBornNodes(
|
||||
base: Pick<AlignmentBase, "chainage" | "ground" | "policy">,
|
||||
nodes: AlignmentNode[],
|
||||
born: ReadonlyArray<number>,
|
||||
): AlignmentNode[] {
|
||||
if (!nodes.length || base.chainage.length < 2) return nodes;
|
||||
const first = nodes[0].chainage_m;
|
||||
const last = nodes[nodes.length - 1].chainage_m;
|
||||
const fresh = born.filter(
|
||||
(value) =>
|
||||
first < value &&
|
||||
value < last &&
|
||||
nodes.every((node) => Math.abs(value - node.chainage_m) >= 0.006),
|
||||
);
|
||||
if (!fresh.length) return nodes;
|
||||
const rows = [
|
||||
...nodes.map((node) => ({
|
||||
s: node.chainage_m,
|
||||
z: node.elevation_m,
|
||||
node: node as AlignmentNode | null,
|
||||
})),
|
||||
...fresh.map((s) => ({ s, z: evaluateAt(base.chainage, base.ground, [], s), node: null })),
|
||||
].sort((a, b) => a.s - b.s);
|
||||
const baseS = rows.map((row) => row.s);
|
||||
const target = rows.map((row) => row.z);
|
||||
let baseZ = [...target];
|
||||
for (let round = 0; round < 20; round += 1) {
|
||||
const pvi = baseS.map((s, index) => ({ chainage_m: s, elevation_m: baseZ[index] }));
|
||||
const curves = buildCurves(pvi, base.policy, {}, []);
|
||||
const error = rows.map((row, index) =>
|
||||
row.node ? 0 : target[index] - evaluateAt(baseS, baseZ, curves, baseS[index]),
|
||||
);
|
||||
if (Math.max(...error.map(Math.abs)) < 1e-6) break;
|
||||
baseZ = baseZ.map((z, index) => z + error[index]);
|
||||
}
|
||||
return rows.map(
|
||||
(row, index) =>
|
||||
row.node ?? {
|
||||
chainage_m: Number(row.s.toFixed(6)),
|
||||
elevation_m: Number(baseZ[index].toFixed(6)),
|
||||
},
|
||||
);
|
||||
return { nodes: kept, seat };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user