From ea55ad1c73f197e6babd79097e0412eb35adab12 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 23 Aug 2026 14:19:57 +0900 Subject: [PATCH] =?UTF-8?q?fix(B05):=20=EC=84=B8=EC=9B=94=EA=B5=90=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=20=EC=97=AC=EC=9C=A0=20=3D=20=EB=B0=B0?= =?UTF-8?q?=EC=88=98=EA=B4=80=20=EC=82=B0=EC=8B=9D=20+=20=EB=AC=BC?= =?UTF-8?q?=EB=84=98=EC=9D=B4=20=EB=AA=AB,=20=EB=AC=BC=EB=84=98=EC=9D=B4?= =?UTF-8?q?=ED=8F=AC=EC=9E=A5=EC=9D=80=20=EC=97=AC=EC=9C=A0=20=EC=97=86?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세월교는 배관을 여러 개 묶어 다리 형태로 만든 것이라 배수관과 같은 산식을 쓰되, 그 위에 물넘이가 얹히므로 0.5m를 더 얹는다(2026-08-23 사용자 확정). 물넘이포장은 도로 위에 그대로 만드는 시설이라 들어 올릴 이유가 없다. - 세월교 Ø1000 → 1.0 + 0.5(토피) + 0.5(물넘이) = 2.0 - 물넘이포장 → 0.0 - 앞서 쓰던 월류 높이(ford_height_m) 기준은 폐기 검증: 계획선 재생성 실측 — 세월교 지점 계획고-지반고 2.00 일치 (배수관 1.50/1.30, BOX 2.50도 유지). pytest 6/6, tsc 통과 Co-Authored-By: Claude Opus 5 (1M context) --- .../B05_Profile_UI_Profile_MinCover.ts | 23 +++++++++---------- common_util/common_util_drainage_pipes.py | 18 +++++++++------ 2 files changed, 22 insertions(+), 19 deletions(-) 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]]: