fix(계산묶음): 349-0j 노선 초안 미리보기 누가토량 = [저장] 정본 — cross 단계 미교차 넓힘(서버 짝 그대로)

- 대조(검증_sub2 · 2번째 꺾임점 서쪽 20 m · 서버 [저장] 체인을 실제로 돌리고 체인 스스로 되살림 — 최신 노선 · 관 · 파일 그대로 확인):
  미리보기 -11,378.5 ㎥ = 서버 이월 직후(보정 전) -11,391.3 ㎥(측점 · 계획고 · 면적 측점마다 같음) · 정본 -21,249.3 ㎥
  · 갈린 몫 = [확정] 보정 — 미교차 넓힘(표본 20 m → 지표면 끝) -9,531 ㎥ · 관 구조물 면적 -334 ㎥(넓힌 뒤 기준 1,971 ㎥) · 그 밖 +7 ㎥
- logic/B06_Section_Cross_Stage: createCrossStage({ grid }) — 비탈이 표본 끝에서 원지반과 안 만나면 열린 쪽만 +5 m 씩 격자에서 다시 떠 셈(extendUnclosed ↔ 서버 extend_unclosed 짝 · 격자 없으면 안 넓힘)
- logic/B05_Profile_Pipeline_Detail: 초안 상세 설계 = cross 단계 결과 사본(구조물 면적 얹기가 단계 기억을 안 고침)
- 넓힘 + 서버 구조물 면적이면 검증_sub2 초안 정본과 12.5 ㎥ 차이(측점 끝 EP 0.1 ㎡)
- 시험 test_349_0j_draft_vs_saved 8(가짜 · 검증_sub7 — 넓힌 끝 · 면적 · 누가토량 = 서버 엔진 + extend_unclosed · 검증_sub7 넓힘 17곳 -16,639.8 → -30,757.9 = 서버 · 단계 합 65 ms)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
This commit is contained in:
2026-10-16 15:42:14 +09:00
co-authored by Claude Opus 5.5
parent 81aa1d5c49
commit 23bb885610
4 changed files with 469 additions and 2 deletions
+21 -1
View File
@@ -4,6 +4,8 @@
* 측점 열쇠마다 횡단 설계(`CrossOutput.byKey`).
*
* · 계산 = `computeCrossDesign`(파이썬 `B06_Section_Engine_Design.py` 짝 · Cross_Refresh 와 같은 엔진).
* · 미교차 넓힘 = 비탈이 표본 끝에서 원지반과 안 만나면 열린 쪽만 +5 m 씩 지형 격자에서 다시 떠 셈
* (`extendUnclosed` ↔ 서버 [저장] `B06_Section_Engine_SampleExtend.extend_unclosed` · 349-0j) — 격자가 없으면 안 넓힘.
* · 국부 연산 = 측점 열쇠마다 입력 지문(지반 표본 · 계획고 · 횡단 입력 · 확폭 · 표준값) — 같으면 앞 결과 그대로.
* · 바뀐 범위(`ctx.range`) 밖이고 앞 출력(`ctx.prev`)에 있고 계획고가 그대로면 셈 없이 재사용 — 노선 초안의
* 첫 계획선은 바뀐 구간 앞 꼭짓점까지 움직이므로 범위만 보면 낡은 설계가 남음(349-0f).
@@ -21,6 +23,8 @@ import type {
} from "../../A00_Common/design/logic/design_pipeline_types";
import { planElevationAt } from "../../B05_Profile/logic/B05_Profile_UI_Profile_Alignment";
import { groundSamples } from "./B06_Section_Station_Swap";
import { extendUnclosed } from "../../B05_Profile/logic/B05_Profile_Sections_Ground";
import type { DtmGrid } from "@util/common_util_surface_sampler";
export { groundSamples };
@@ -67,10 +71,15 @@ const sameSpot = (kept: CrossStationResult, station: PipelineStation, elevation:
Number((kept.detail as { design_elevation_m?: number } | null)?.design_elevation_m) - elevation,
) <= 1e-4;
/** 단계가 받는 것 — 설계 지형 격자(ground 단계와 같은 `groundStageDeps(projectId).grid`). */
export interface CrossStageDeps {
grid?: () => { grid: DtmGrid } | null;
}
/**
* `cross` 단계 만들기 — 측점 지문 기억은 이 단계 함수가 사는 동안. `counts()` = 마지막 계산의 다시 셈 · 재사용 수.
*/
export function createCrossStage() {
export function createCrossStage(deps: CrossStageDeps = {}) {
const memo = new Map<string, { fingerprint: string; result: CrossStationResult }>();
let last = { computed: 0, reused: 0 };
@@ -102,6 +111,17 @@ export function createCrossStage() {
let design;
try {
design = computeCrossDesign(samples, elevation, options);
const grid = design.slope_unclosed ? deps.grid?.()?.grid : null;
const wide =
grid &&
extendUnclosed(
samples,
[station.x, station.y],
station.left,
(next) => computeCrossDesign(next as typeof samples, elevation, options),
grid,
);
if (wide) design = computeCrossDesign(wide.samples as typeof samples, elevation, options);
} catch {
continue; // 표본 부족 측점은 건너뜀(Cross_Refresh · 서버 엔진과 같은 태도)
}