feat(B06): 유출부 보호공 삭제·성토부선 전환 + 추가 기슭막이(계단식)
- 보호공(돌붙임) 띠 삭제, 윗면 선만 성토부선(계획선)으로 유지 — 구간별
사면길이·5m 초과 여부 툴팁 표기
- 성토부 5m 이상이면 조정창 +로 추가 기슭막이(배관 없는 동일 형상 벽)
계단식 추가 — 자동 자리는 배관용과 같은 규칙(1:1.2 최소 자리)
- 추가 벽도 ◀/▶/↺ 이동(안쪽 한계 = 앞 구조물), 마지막 벽 - 삭제
- 개수·이동량 세션 보관(b06:extrawall / revetx extra{n} 키)
- 700줄 제한: Extra(성토부선·추가 벽)·Wire(카드 배선) 분리 신설
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,8 +23,8 @@ import {
|
||||
sectionModeLabel,
|
||||
type RockBoundaryControl,
|
||||
} from "./B06_Section_UI_Cross_Design";
|
||||
import { showToast } from "@ui/ui_template_elements";
|
||||
import { appendCulvertOverlay, computeCulvertLayout } from "./B06_Section_UI_Cross_Culvert";
|
||||
import { appendCulvertOverlay } from "./B06_Section_UI_Cross_Culvert";
|
||||
import { computeCardCulvert } from "./B06_Section_UI_Cross_Culvert_Wire";
|
||||
import type { InletStructureChoice } from "./B06_Section_UI_Cross_Culvert";
|
||||
import { buildStructurePanel } from "./B06_Section_UI_Cross_Structure_Panel";
|
||||
import { attachZoomPan, buildZoomControls } from "./B06_Section_UI_Cross_View_Zoom";
|
||||
@@ -181,6 +181,16 @@ export interface InletStructureControl {
|
||||
set: (chainageM: number, value: InletStructureChoice) => void;
|
||||
}
|
||||
|
||||
/** 유출측 추가 기슭막이 개수 제어(2026-08-22 사용자 — 성토부 5m 이상 계단식 추가). */
|
||||
export interface ExtraWallControl {
|
||||
countFor: (section: CrossSection) => number;
|
||||
add: (chainageM: number) => void;
|
||||
/** 마지막 추가 벽 삭제(그 벽의 이동량도 함께 지운다). */
|
||||
removeLast: (chainageM: number) => void;
|
||||
/** 기하가 실제로 세운 개수로 잘라 동기화(성토부가 없어져 못 세운 벽 정리). */
|
||||
syncCount: (chainageM: number, built: number) => void;
|
||||
}
|
||||
|
||||
export function createCrossSectionCard(
|
||||
section: CrossSection,
|
||||
selected: boolean,
|
||||
@@ -203,6 +213,8 @@ export function createCrossSectionCard(
|
||||
revetOffset?: RevetOffsetControl,
|
||||
/** 유입측 구조물 형식 선택(드롭다운 — 2026-08-22). */
|
||||
inletStructure?: InletStructureControl,
|
||||
/** 유출측 추가 기슭막이 개수 제어(2026-08-22). */
|
||||
extraWalls?: ExtraWallControl,
|
||||
): CrossCardElement {
|
||||
// 이 카드의 실효 표시 반폭 — 개별값이 전역 반폭보다 우선한다(2026-08-06).
|
||||
const effectiveHalfWidth = stationWidth?.widthFor(section) ?? crossHalfWidth;
|
||||
@@ -230,6 +242,8 @@ export function createCrossSectionCard(
|
||||
let culvertInletIsBasin = false;
|
||||
/** 드롭다운 선택지 가용성(2026-08-22) — 기하 판정을 조정창에 전달. */
|
||||
let culvertInletOptions = { revetAllowed: true, basinLUAllowed: true };
|
||||
/** 추가 기슭막이 상태(2026-08-22) — 끝 성토부 5m 이상(canAdd)·세워진 개수. */
|
||||
let culvertExtraState = { canAdd: false, count: 0 };
|
||||
/**
|
||||
* 기슭막이를 고른다. 구조물 선택과 절·성토 면적 강조는 **같은 레벨**이라 하나를
|
||||
* 고르면 다른 하나는 풀린다(2026-08-21 사용자). 또 구조물을 고르면 그 **측점 카드도
|
||||
@@ -467,17 +481,14 @@ export function createCrossSectionCard(
|
||||
toDisplayY,
|
||||
toggleArea,
|
||||
);
|
||||
// 배수관 세트 기하를 먼저 계산한다 — 설계선이 기슭막이 밖 성토 경사를 끊는 데 쓴다.
|
||||
const culvertLayout: ReturnType<typeof computeCulvertLayout> = computeCulvertLayout(
|
||||
// 배수관 세트 기하 계산 + 이동량 되받기(토스트) — 분리 파일(Wire, 700줄 제한).
|
||||
const culvertLayout = computeCardCulvert(
|
||||
section,
|
||||
sourceSamples,
|
||||
revetOffset
|
||||
? {
|
||||
inlet: revetOffset.shiftFor(section, "inlet"),
|
||||
outlet: revetOffset.shiftFor(section, "outlet"),
|
||||
}
|
||||
: undefined,
|
||||
inletStructure?.valueFor(section),
|
||||
activeRevet,
|
||||
revetOffset,
|
||||
inletStructure,
|
||||
extraWalls,
|
||||
);
|
||||
// 포장층 → 설계선 → 암 경계선 순으로 겹쳐, 설계선이 포장 박스 위에 오게 한다.
|
||||
appendPavementOverlay(plotLayer, section.design, x, toDisplayY);
|
||||
@@ -499,32 +510,16 @@ export function createCrossSectionCard(
|
||||
toDisplayY,
|
||||
);
|
||||
}
|
||||
// 배수관 측점 세트(배관·기슭막이·보호공) — 기존 도형 위에 추가만 한다(2026-08-19).
|
||||
// 배수관 측점 세트 — 기존 도형 위에 추가만 한다(2026-08-19). 조정창이 쓸
|
||||
// 카드 상태(관 길이·집수정 여부·선택지·추가 벽 상태)를 여기서 받아 둔다.
|
||||
culvertPipeLengthM = culvertLayout?.pipe.lengthM ?? null;
|
||||
culvertInletIsBasin = !!culvertLayout?.basin;
|
||||
if (culvertLayout) culvertInletOptions = culvertLayout.inletOptions;
|
||||
// 요청한 이동량이 한계에 걸려 잘렸으면 그 값으로 되돌려 담는다 — 안 그러면 눌러도
|
||||
// 안 움직이는데 창의 숫자만 계속 커진다(2026-08-21 사용자 지적).
|
||||
// 잘린 순간에는 **왜 안 움직였는지 토스트로 알린다**(2026-08-22 사용자 요청 —
|
||||
// 13+15.7처럼 자동 자리가 이미 안쪽 한계라 ◀가 그대로 먹히지 않는 경우).
|
||||
// 조작 중(그 벽이 선택된 상태)일 때만 띄운다 — 리로드로 복원된 옛 세션 값에는 침묵.
|
||||
if (culvertLayout && revetOffset) {
|
||||
for (const role of ["inlet", "outlet"] as const) {
|
||||
const requested = revetOffset.shiftFor(section, role);
|
||||
const applied = culvertLayout.revetShift[role];
|
||||
if (activeRevet === role && Math.abs(requested - applied) > 0.05) {
|
||||
// 이동량 부호: + = 계류측 바깥. 요청이 적용보다 작으면 안쪽 요청이 잘린 것.
|
||||
showToast(
|
||||
L(
|
||||
requested < applied
|
||||
? "B06_Cross_Revet_Limit_Inward"
|
||||
: "B06_Cross_Revet_Limit_Outward",
|
||||
),
|
||||
"info",
|
||||
);
|
||||
}
|
||||
revetOffset.syncShift(section.chainage_m, role, applied);
|
||||
}
|
||||
if (culvertLayout) {
|
||||
culvertInletOptions = culvertLayout.inletOptions;
|
||||
culvertExtraState = {
|
||||
canAdd: culvertLayout.outletFill.addable,
|
||||
count: culvertLayout.extraWalls.length,
|
||||
};
|
||||
}
|
||||
if (culvertLayout) {
|
||||
setRevetActive = appendCulvertOverlay(
|
||||
@@ -622,9 +617,21 @@ export function createCrossSectionCard(
|
||||
},
|
||||
structureFor: () => inletStructure?.valueFor(section) ?? "auto",
|
||||
setStructure: (value) => inletStructure?.set(section.chainage_m, value),
|
||||
// 집수정은 자리 고정 — 유입이 집수정이면 ◀/▶/↺를 숨긴다.
|
||||
canNudge: (key) => key === "outlet" || !culvertInletIsBasin,
|
||||
// 집수정은 자리 고정 — 유입이 집수정이면 ◀/▶/↺를 숨긴다(추가 벽은 항상 이동).
|
||||
canNudge: (key) => key !== "inlet" || !culvertInletIsBasin,
|
||||
optionsFor: () => culvertInletOptions,
|
||||
extraState: () => culvertExtraState,
|
||||
addExtra: () => extraWalls?.add(section.chainage_m),
|
||||
removeExtra: () => {
|
||||
// 삭제되는 벽이 선택 중이면 선택을 유출 벽으로 옮긴다 — 다시 그려질 때
|
||||
// 없는 키를 강조하려다 조정창이 빈 대상으로 남는 것을 막는다.
|
||||
const last = `extra${culvertExtraState.count - 1}` as RevetKey;
|
||||
if (activeRevet === last) {
|
||||
activeRevet = "outlet";
|
||||
revetOffset?.select(section.chainage_m, "outlet");
|
||||
}
|
||||
extraWalls?.removeLast(section.chainage_m);
|
||||
},
|
||||
});
|
||||
showRevetControl = (visible) => panel.show(visible ? activeRevet : null);
|
||||
showRevetControl(activeRevet !== null);
|
||||
|
||||
Reference in New Issue
Block a user