From d857d3d48a8c26274b88dfe7a8ee883c74250412 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 26 Aug 2026 19:58:05 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EC=9D=B8=EC=A0=91=20=EC=B8=A1?= =?UTF-8?q?=EC=A0=90=EC=97=90=20=EB=82=A8=EB=8D=98=20=EC=A7=91=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=8A=B8=EB=A6=BC=EC=9D=84=20=EC=A7=80=EC=9B=8C=20?= =?UTF-8?q?=EC=84=B1=ED=86=A0=EC=84=A0=EC=9D=84=20=EC=82=B4=EB=A6=B0?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit trimLinkedLayout이 링크(인접) 측점 카드에서 구조물 도형만 지우고, 그 구조물이 만든 설계선 트림(designTrim)과 성토부선은 스프레드로 통과시켰다. 집수정은 조작량이 0이면 대체 사면선(minSlope/maxSlope)도 없어서, 구조물은 안 그려지는데 설계선만 노견 밖에서 끊겼다 — 4측점(80.0m, 관 84.3m)·14측점(280.0m, 관 275.71m) 성토선 삭제. - keepTrimSides(): 살아남지 못한 쪽의 트림을 ∓Infinity로 되돌리고 그쪽 Elevation·Slope를 뺀다. 양쪽 다 없으면 designTrim = null. - 집수정은 링크 측점에 서지 않으므로 유입 쪽 트림은 언제나 지운다. - 연장 밖 유출 벽의 outletFill, 집수정에 딸린 basinFill도 함께 비운다. - 유입이 min·max 어느 쪽인지는 관 양 끝 offset 대소로 가른다. 3D 무영향: trimLinkedLayout은 export되지 않고 유일한 호출자 computeCardCulvert는 B06 Cross_View만 import한다. B05 코리도는 computeCulvertLayout을 직접 부르며 소유 측점에서만 돈다. Co-Authored-By: Claude Opus 5 (1M context) --- .../B06_Section_UI_Cross_Culvert_Wire.ts | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/B06_Section/B06_Section_UI_Cross_Culvert_Wire.ts b/B06_Section/B06_Section_UI_Cross_Culvert_Wire.ts index 7f54b88b..35d1b2bb 100644 --- a/B06_Section/B06_Section_UI_Cross_Culvert_Wire.ts +++ b/B06_Section/B06_Section_UI_Cross_Culvert_Wire.ts @@ -7,7 +7,7 @@ import type { CrossSection, SectionSample } from "./B06_Section_Api_Fetch"; import { computeCulvertLayout } from "./B06_Section_UI_Cross_Culvert"; import type { CulvertLayout, InletStructureChoice, RevetKey } from "./B06_Section_UI_Cross_Culvert"; -import type { BasinAdjust } from "./B06_Section_UI_Cross_Culvert_Types"; +import type { BasinAdjust, CulvertDesignTrim } from "./B06_Section_UI_Cross_Culvert_Types"; import { basinSpanOfSpec, materialLabel, @@ -201,10 +201,36 @@ function spanCovers(span: StructureSpan, deltaM: number): boolean { return deltaM < 0 ? -deltaM <= span.beforeM + 1e-9 : deltaM <= span.afterM + 1e-9; } +/** + * 지운 구조물이 남긴 **설계선 트림**을 쪽별로 되돌린다(2026-08-26 사용자 지적 — + * 4·14 측점 성토선 삭제). 구조물은 안 그리는데 트림만 남으면 그 측점 설계선이 + * 노견 밖에서 통째로 끊긴다 — 집수정은 대체 사면선(`minSlope`/`maxSlope`)도 조작량이 + * 0이면 없어서 아무것도 안 남는다. `-/+Infinity` = 트림 없음(기하가 쓰는 초기값). + */ +function keepTrimSides( + trim: CulvertDesignTrim | null, + keepMin: boolean, + keepMax: boolean, +): CulvertDesignTrim | null { + if (!trim || (!keepMin && !keepMax)) return null; + if (keepMin && keepMax) return trim; + return { + minOffset: keepMin ? trim.minOffset : Number.NEGATIVE_INFINITY, + maxOffset: keepMax ? trim.maxOffset : Number.POSITIVE_INFINITY, + ...(keepMin && trim.minElevation != null ? { minElevation: trim.minElevation } : {}), + ...(keepMax && trim.maxElevation != null ? { maxElevation: trim.maxElevation } : {}), + ...(keepMin && trim.minSlope ? { minSlope: trim.minSlope } : {}), + ...(keepMax && trim.maxSlope ? { maxSlope: trim.maxSlope } : {}), + }; +} + /** * 링크 카드에서 **연장이 여기까지 오지 않는 요소**를 지운다(요소별 판정). * 유입·유출 기슭막이는 각자 길이·전/후를 갖고, 집수정은 자기 연장(기본 2m·1/1) * 만큼만 이어진다. 관은 한 측점 전용이라 그리기 단계에서 숨긴다(`hidePipe`). + * + * 도형뿐 아니라 그 구조물이 만든 **설계선 트림·성토부선까지 함께** 지운다 — 도형만 + * 지우면 없는 구조물이 설계선을 끊는다(2026-08-26). */ function trimLinkedLayout(layout: CulvertLayout, link: CulvertLink): CulvertLayout { const spec = layout.culvert; @@ -212,16 +238,29 @@ function trimLinkedLayout(layout: CulvertLayout, link: CulvertLink): CulvertLayo spec[side]?.structure === "집수정" ? basinSpanOfSpec(spec[side]) : revetSpanOfSpec(spec[side]); const inletIn = spanCovers(spanOf("inlet"), link.deltaM); const outletIn = spanCovers(spanOf("outlet"), link.deltaM); + // 집수정은 링크 측점에 서지 않으므로(아래 `basin: null`) 그 트림은 언제나 지운다. + const keepInlet = inletIn && !layout.basin; + // 좌표 규약 +offset = 좌측, outward=+1(좌) = trimMax — 유입이 어느 쪽 트림인지는 + // 관 양 끝 offset 대소로 가른다(관은 노선을 가로지르므로 좌우가 갈린다). + const inletIsMax = layout.pipe.inlet.offset > layout.pipe.outlet.offset; + const empty = { segments: [], addable: false }; return { ...layout, walls: layout.walls.filter((wall) => (wall.role === "inlet" ? inletIn : outletIn)), // 다단(성토부)은 유출 벽에 딸린다. extraWalls: outletIn ? layout.extraWalls : [], + outletFill: outletIn ? layout.outletFill : empty, // 집수정은 **소유 측점 횡단도 하나에만** 선다(2026-08-24 사용자 확정) — 기슭막이와 - // 달리 옆 측점으로 이어지는 구조물이 아니다. 계류측 다단도 집수정에 딸린 것이라 - // 함께 뺀다. 3D에서는 소유 측점 하나가 자기 길이(기본 2m)만큼 스윕한다. + // 달리 옆 측점으로 이어지는 구조물이 아니다. 계류측 다단·성토부선도 집수정에 딸린 + // 것이라 함께 뺀다. 3D에서는 소유 측점 하나가 자기 길이(기본 2m)만큼 스윕한다. basinExtras: [], + basinFill: empty, basin: null, + designTrim: keepTrimSides( + layout.designTrim, + inletIsMax ? outletIn : keepInlet, + inletIsMax ? keepInlet : outletIn, + ), }; }