diff --git a/B05_Profile/B05_Profile_UI_Profile_MinCover.ts b/B05_Profile/B05_Profile_UI_Profile_MinCover.ts index 09037e96..1eba6dd9 100644 --- a/B05_Profile/B05_Profile_UI_Profile_MinCover.ts +++ b/B05_Profile/B05_Profile_UI_Profile_MinCover.ts @@ -10,7 +10,8 @@ * 산식(사용자 확정 예시 그대로): * 배수관 Ø1000 → 지반고 + 1.0(관경) + 0.5(토피) = +1.5 * BOX암거 2.0×2.0 → 지반고 + 2.0(구체 높이) + 0.5(토피) = +2.5 - * 물넘이·세월교 → 지반고 + 월류 높이(좌측 패널이 설계유량으로 산출한 `ford_height_m`) + * 세월교 Ø1000 → 지반고 + 1.0(관경) + 0.5(토피) + 0.5(물넘이 몫) = +2.0 + * 물넘이포장 → 도로에 그대로 앉히는 시설이라 요구 여유 없음 * 토피 0.5m는 B06 배수관 엔진의 `MIN_PIPE_COVER_M`과 같은 값이다(교차 확인). * * **정본 산식은 백엔드** `common_util_drainage_pipes.facility_clearance_m`이다 — @@ -33,7 +34,8 @@ export const MIN_COVER_M = 0.5; /** 시설 제원이 비었을 때 쓰는 기본값 — 화면 기본 선택과 맞춘다. */ const DEFAULT_PIPE_DIAMETER_MM = 1000; const DEFAULT_BOX_HEIGHT_M = 2; -const DEFAULT_FORD_HEIGHT_M = 0.3; +/** 세월교 추가 여유(m) — 배관 다발 위에 물넘이가 얹힌다(2026-08-23 사용자 확정). */ +const FORD_BRIDGE_EXTRA_M = 0.5; export interface MinCoverPoint { chainage_m: number; @@ -64,20 +66,17 @@ export function minCoverPoints(pipes: MinCoverPipe[]): MinCoverPoint[] { clearance_m: heightM + MIN_COVER_M, label: `BOX암거 H${heightM.toFixed(1)}`, }); - } else if (facility === "ford_pavement" || facility === "ford_bridge") { - // 월류 구조 — 토피가 아니라 월류 높이만큼 노면이 올라간다(좌측 패널 산출값). - const heightM = numberOf(options.ford_height_m, DEFAULT_FORD_HEIGHT_M); - result.push({ - chainage_m: pipe.chainage_m, - clearance_m: heightM, - label: `${facility === "ford_bridge" ? "세월교" : "물넘이포장"} 월류 ${heightM.toFixed(2)}m`, - }); + } else if (facility === "ford_pavement") { + // 물넘이포장은 도로 위에 그대로 만든다 — 들어 올릴 이유가 없다. + continue; } else { + // 세월교는 배관 다발이라 배수관과 같은 산식 + 물넘이 몫 0.5m. const diameterM = numberOf(options.pipe_diameter_mm, DEFAULT_PIPE_DIAMETER_MM) / 1000; + const extra = facility === "ford_bridge" ? FORD_BRIDGE_EXTRA_M : 0; result.push({ chainage_m: pipe.chainage_m, - clearance_m: diameterM + MIN_COVER_M, - label: `배수관 Ø${Math.round(diameterM * 1000)}`, + clearance_m: diameterM + MIN_COVER_M + extra, + label: `${facility === "ford_bridge" ? "세월교" : "배수관"} Ø${Math.round(diameterM * 1000)}`, }); } } diff --git a/common_util/common_util_drainage_pipes.py b/common_util/common_util_drainage_pipes.py index e83f882c..5c37f738 100644 --- a/common_util/common_util_drainage_pipes.py +++ b/common_util/common_util_drainage_pipes.py @@ -273,12 +273,15 @@ def save_detail_basins(stored_path: str, features: list[dict[str, Any]]) -> Path # 두면 시설이 들어갈 자리가 없다 — 시설 제원만큼 계획고를 들어 올려야 한다. # 배수관 Ø1000 → 지반고 + 1.0(관경) + 0.5(토피) = +1.5 # BOX암거 2×2 → 지반고 + 2.0(구체 높이) + 0.5(토피) = +2.5 -# 물넘이·세월교 → 지반고 + 월류 높이(좌측 패널이 설계유량으로 산출한 값) -# 토피 0.5m는 B06 배수관 엔진(`MIN_PIPE_COVER_M`)과 같은 값이다. +# 세월교 Ø1000 → 지반고 + 1.0(관경) + 0.5(토피) + 0.5(물넘이 몫) = +2.0 +# 물넘이포장 → 도로에 그대로 앉히는 시설이라 요구 여유 없음 (2026-08-23 사용자) +# 세월교는 배관을 여러 개 묶어 다리 형태로 만든 것이라 배수관과 같은 산식을 쓰되, +# 그 위에 물넘이가 얹히므로 0.5m를 더 얹는다. 토피 0.5m는 B06 배수관 +# 엔진(`MIN_PIPE_COVER_M`)과 같은 값이다. MIN_PIPE_COVER_M = 0.5 +FORD_BRIDGE_EXTRA_M = 0.5 DEFAULT_PIPE_DIAMETER_MM = 1000.0 DEFAULT_BOX_HEIGHT_M = 2.0 -DEFAULT_FORD_HEIGHT_M = 0.3 def _positive(value: Any, fallback: float) -> float: @@ -294,11 +297,12 @@ def facility_clearance_m(facility: str, options: dict[str, Any] | None) -> float values = options or {} if facility == PIPE_FACILITY_BOX: return _positive(values.get("body_height_m"), DEFAULT_BOX_HEIGHT_M) + MIN_PIPE_COVER_M - if facility in (PIPE_FACILITY_FORD_PAVEMENT, PIPE_FACILITY_FORD_BRIDGE): - # 월류 구조라 토피가 아니라 월류 높이만큼 노면이 올라간다. - return _positive(values.get("ford_height_m"), DEFAULT_FORD_HEIGHT_M) + if facility == PIPE_FACILITY_FORD_PAVEMENT: + # 물넘이포장은 도로 위에 그대로 만든다 — 들어 올릴 이유가 없다. + return 0.0 diameter_m = _positive(values.get("pipe_diameter_mm"), DEFAULT_PIPE_DIAMETER_MM) / 1000.0 - return diameter_m + MIN_PIPE_COVER_M + extra = FORD_BRIDGE_EXTRA_M if facility == PIPE_FACILITY_FORD_BRIDGE else 0.0 + return diameter_m + MIN_PIPE_COVER_M + extra def pipe_anchor_clearances(points: list[PipePoint]) -> list[tuple[float, float]]: