fix(B06): 폼 높이·형태가 실제로 벽을 제어하게 한다
원인 추적 결과 두 겹이었다. ① 배관 벽 높이는 spec.revet_height_m을 쓰지 않는다 — revetWallSpec이 관경 기준 하한과 조정값(adjust.h)만 본다. 폼 값을 스펙에만 넣어 그림이 안 바뀌었다. 이제 폼의 높이·형태를 조정창과 같은 채널(revetOffset.update)로 보낸다. ② 형태마다 높이 한계가 있다(돌쌓기(메) 2.0m). 한계를 넘겨 입력하면 그림은 그대로인데 폼 숫자만 커져 '제어가 안 된다'로 보였다. 기하가 적용한 값을 폼에 되돌리고 한계를 토스트로 알린다. 폼 기본 높이도 스펙이 아니라 지금 그려진 순수 높이(조정창 표시값)를 쓴다.
This commit is contained in:
@@ -43,6 +43,7 @@ import { computeMassHaul, massHaulPayload } from "@util/common_util_mass_haul";
|
||||
import { computeHaulPlan } from "@util/common_util_mass_haul_balance";
|
||||
import { balloonOffsetsPayload } from "@util/common_util_mass_haul_balance_view";
|
||||
import { staleDesignChainages } from "./B06_Section_UI_Section_Common";
|
||||
import { revetWallSpec } from "./B06_Section_UI_Cross_Culvert_Const";
|
||||
import { createStandardPanel, type StandardPanelController } from "./B06_Section_UI_Standard_Panel";
|
||||
import {
|
||||
createB06StructuresPanel,
|
||||
@@ -138,6 +139,18 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
const structuresPanel = createB06StructuresPanel({
|
||||
projectId,
|
||||
detail: () => sectionDetail,
|
||||
// 폼 기본 높이 = 지금 도면에 그려진 순수 높이(조정창이 보여주던 값과 같은 계산).
|
||||
wallHeight: (chainageM, role) => {
|
||||
const owner = sectionDetail?.cross_sections.find(
|
||||
(section) => Math.abs(section.chainage_m - chainageM) < 0.51,
|
||||
);
|
||||
const culvert = owner?.culvert;
|
||||
if (!owner || !culvert) return null;
|
||||
const spec = role === "outlet" ? culvert.outlet : culvert.inlet;
|
||||
const adjust = stationControls.revetOffset.adjustFor(owner, role);
|
||||
return revetWallSpec(spec, adjust, culvert.hidden_pipe === true, culvert.diameter_m)
|
||||
.pureHeight;
|
||||
},
|
||||
stationInterval: () => stationInterval ?? 20,
|
||||
focusChainage: focusStationAt,
|
||||
queuePipeOptions: (chainageM, patch) => stationControls.queueCulvertOptions(chainageM, patch),
|
||||
@@ -183,19 +196,39 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
put(side, "revet_after_m", num(`${prefix}_revet_after_m`));
|
||||
put(side, "structure", patch[`${prefix}_type`]);
|
||||
}
|
||||
// 폼이 높이·형태를 정하면 그 벽의 **조정값**(revet_adjust.h·m)은 비운다 —
|
||||
// 조정값이 남아 있으면 그림이 폼 값을 따라오지 않는다(2026-08-29 사용자 보고).
|
||||
// 배관 벽의 **높이·형태는 스펙이 아니라 조정값**(revet_adjust.h·m)이 정한다
|
||||
// — `revetWallSpec`이 배관에서는 spec.revet_height_m을 쓰지 않기 때문이다.
|
||||
// 폼에서 고친 값을 조정창과 같은 채널로 보내야 도면이 따라온다(2026-08-29 사용자).
|
||||
for (const [role, prefix] of [
|
||||
["inlet", "inlet"],
|
||||
["outlet", "outlet"],
|
||||
] as const) {
|
||||
const patchHeight = patch[`${prefix}_revet_height_m`] !== undefined;
|
||||
const patchForm = patch[`${prefix}_revet_form`] !== undefined;
|
||||
if (!patchHeight && !patchForm) continue;
|
||||
const height = num(`${prefix}_revet_height_m`);
|
||||
const form = patch[`${prefix}_revet_form`];
|
||||
if (height === undefined && typeof form !== "string") continue;
|
||||
stationControls.revetOffset.update(owner.chainage_m, role, {
|
||||
...(patchHeight ? { h: null } : {}),
|
||||
...(patchForm ? { m: null } : {}),
|
||||
...(height !== undefined ? { h: height } : {}),
|
||||
...(typeof form === "string" ? { m: form } : {}),
|
||||
});
|
||||
// 형태마다 높이 한계가 있다(돌쌓기(메) 2.0m 등). 기하가 잘라 낸 실제 높이를
|
||||
// 폼에 되돌린다 — 숫자만 커지고 그림은 그대로인 상태를 남기지 않는다.
|
||||
if (height === undefined) continue;
|
||||
const applied = revetWallSpec(
|
||||
role === "outlet" ? culvert.outlet : culvert.inlet,
|
||||
stationControls.revetOffset.adjustFor(owner, role),
|
||||
culvert.hidden_pipe === true,
|
||||
culvert.diameter_m,
|
||||
).pureHeight;
|
||||
if (Math.abs(applied - height) > 0.05) {
|
||||
structuresPanel.overrideOptions(owner.chainage_m, {
|
||||
[`${prefix}_revet_height_m`]: Number(applied.toFixed(1)),
|
||||
});
|
||||
showToast(
|
||||
`${prefix === "outlet" ? "유출" : "유입"} 기슭막이 높이는 형태 한계로 ` +
|
||||
`${applied.toFixed(1)}m까지만 적용됩니다.`,
|
||||
"error",
|
||||
);
|
||||
}
|
||||
}
|
||||
put(culvert.inlet, "basin_length_m", num("inlet_basin_length_m"));
|
||||
put(culvert.inlet, "basin_before_m", num("inlet_basin_before_m"));
|
||||
|
||||
@@ -38,6 +38,9 @@ export interface B06StructuresPanelDeps {
|
||||
/** 횡단 캐시 — 폼 기본값을 조정창과 **같은 원천**(culvert 스펙)에서 읽는다
|
||||
* (2026-08-29 사용자: 예전 조정창이 보여주던 값이 기본값이다). */
|
||||
detail?: () => SectionDetailResponse | null;
|
||||
/** 지금 그려진 벽 높이(m) — 배관 벽은 스펙이 아니라 기하가 정하므로 폼 기본
|
||||
* 높이도 이 값을 쓴다(조정창 표시값과 같다). */
|
||||
wallHeight?: (chainageM: number, role: "inlet" | "outlet") => number | null;
|
||||
/** 측점 간격(m) — 측점번호+잔여거리 환산용. */
|
||||
stationInterval: () => number;
|
||||
/** 목록·폼에서 고른 시설의 측점 카드를 선택·스크롤한다. */
|
||||
@@ -62,6 +65,9 @@ export interface B06StructuresPanel {
|
||||
load: () => Promise<void>;
|
||||
/** 횡단도에서 고른 벽·구체의 시설을 폼에 올린다(null = 해제). */
|
||||
showPipeAt: (chainageM: number | null) => void;
|
||||
/** 기하가 한계로 자른 실제 값을 폼에 되돌린다 — 입력 숫자만 커지고 그림은 그대로인
|
||||
* 상태를 막는다(2026-08-29 사용자: 재질 높이 한계에 걸린 값). */
|
||||
overrideOptions: (chainageM: number, patch: Record<string, string | number>) => void;
|
||||
/** 고른 횡단도(측점)에 있는 구조물을 폼에 올린다 — 계곡 통과 시설이 먼저고,
|
||||
* 없으면 그 측점을 덮는 구조물 정본 항목. 둘 다 없으면 해제(2026-08-29). */
|
||||
showAtChainage: (chainageM: number | null) => void;
|
||||
@@ -94,6 +100,7 @@ function withSpecDefaults(
|
||||
options: Record<string, string | number> | undefined,
|
||||
detail: SectionDetailResponse | null,
|
||||
chainageM: number,
|
||||
wallHeight?: (chainageM: number, role: "inlet" | "outlet") => number | null,
|
||||
): Record<string, string | number> | undefined {
|
||||
const owner = detail?.cross_sections.find(
|
||||
(section) => Math.abs(section.chainage_m - chainageM) < PIPE_MATCH_M,
|
||||
@@ -112,7 +119,8 @@ function withSpecDefaults(
|
||||
] as const) {
|
||||
put(`${prefix}_type`, side.structure);
|
||||
put(`${prefix}_revet_form`, side.revet_form);
|
||||
put(`${prefix}_revet_height_m`, side.revet_height_m);
|
||||
// 높이는 기하가 정한 실제 값이 기준이다 — 못 구하면 스펙 값으로 물러난다.
|
||||
put(`${prefix}_revet_height_m`, wallHeight?.(chainageM, prefix) ?? side.revet_height_m);
|
||||
put(`${prefix}_revet_length_m`, side.revet_length_m);
|
||||
put(`${prefix}_revet_before_m`, side.revet_before_m);
|
||||
put(`${prefix}_revet_after_m`, side.revet_after_m);
|
||||
@@ -218,7 +226,7 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
end_m: pipe.end_m,
|
||||
source: pipe.source,
|
||||
// 폼 기본값 = 조정창이 쓰던 값(횡단 스펙). 저장된 옵션이 있으면 그쪽이 이긴다.
|
||||
options: withSpecDefaults(pipe.options, detail, pipe.chainage_m),
|
||||
options: withSpecDefaults(pipe.options, detail, pipe.chainage_m, deps.wallHeight),
|
||||
design_flow_m3s: null,
|
||||
}));
|
||||
section.setPipeFacilities(pipeFacilities);
|
||||
@@ -236,7 +244,12 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < PIPE_MATCH_M,
|
||||
);
|
||||
if (!hit) return;
|
||||
hit.options = withSpecDefaults(hit.options, deps.detail?.() ?? null, hit.chainage_m);
|
||||
hit.options = withSpecDefaults(
|
||||
hit.options,
|
||||
deps.detail?.() ?? null,
|
||||
hit.chainage_m,
|
||||
deps.wallHeight,
|
||||
);
|
||||
section.setPipeFacilities(pipeFacilities);
|
||||
}
|
||||
|
||||
@@ -249,6 +262,16 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
setInletStructure: (value) => section.facility.setInletStructure(value),
|
||||
onInletStructureChange: (handler) => section.facility.onInletStructureChange(handler),
|
||||
},
|
||||
overrideOptions: (chainageM, patch) => {
|
||||
const hit = pipeFacilities.find(
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < PIPE_MATCH_M,
|
||||
);
|
||||
if (!hit) return;
|
||||
hit.options = { ...(hit.options ?? {}), ...patch };
|
||||
section.setPipeFacilities(pipeFacilities);
|
||||
// 폼을 그 값으로 다시 세운다 — 조정창이 한계를 알려 주던 것과 같은 자리다.
|
||||
section.selectPipeByChainage(hit.chainage_m);
|
||||
},
|
||||
showPipeAt: (chainageM) => {
|
||||
currentChainageM = chainageM;
|
||||
if (chainageM !== null) refreshSpecDefaults(chainageM);
|
||||
|
||||
Reference in New Issue
Block a user