From 8fa1652e622fb6af0e7bc079b2ccc126ce754854 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 30 Aug 2026 13:12:23 +0900 Subject: [PATCH] =?UTF-8?q?feat(B06):=20=EC=84=B8=EC=9B=94=EA=B5=90=20?= =?UTF-8?q?=EC=9B=94=EB=A5=98=20=EC=A0=84=20=EB=85=B8=EB=A9=B4=20=EC=A0=90?= =?UTF-8?q?=EC=84=A0=EC=9D=84=20=EB=82=A0=EA=B0=9C=EB=B2=BD=20=EC=83=81?= =?UTF-8?q?=EB=8B=A8=EA=B9=8C=EC=A7=80=20=EB=8C=80=EA=B0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=87=EB=8A=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 점선(월류가 없었을 때의 계획고)이 노견에서 뚝 끊겨, 구체 밖에서 노면이 어디로 떨어지는지 읽히지 않았다. 양 끝을 그 측 **날개벽 상단**까지 대각으로 내려 잇는다 (2026-08-30 사용자). - `FordSideLayout.wingTop` — 바닥판 바깥 끝(계류측 극점) × 바닥판 상면 + 날개벽 짧은쪽 높이. 날개벽 설치가 없으면 null이고, 그 측은 노견에서 끊는다. - `appendFordSurfaceDropPlan`이 세월교 기하를 받아 한 폴리라인으로 그린다: 좌 날개벽 상단 → 좌 노견 → 우 노견 → 우 날개벽 상단. 자체검증(공용 브라우저 5174 + 워크트리 백엔드 8001, 측점 7+9.7): - tsc --noEmit 통과. - 점선 폴리라인 4점 확인(수정 전 2점). 양 끝이 바닥판 바깥 상단 자리로 나간다. - 날개벽 상단이 원래 계획고보다 21.70px 아래 = 0.890m (y축 1m = 24.375px). 바닥판 상면~원래 계획고 1.89m − 날개 짧은쪽 높이 1.0m = 0.89m와 일치. Co-Authored-By: Claude Opus 5 (1M context) --- B06_Section/B06_Section_UI_Cross_Ford_Geom.ts | 13 ++++++++++ .../B06_Section_UI_Cross_Ford_Pavement.ts | 24 +++++++++++++++---- B06_Section/B06_Section_UI_Cross_View.ts | 2 +- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/B06_Section/B06_Section_UI_Cross_Ford_Geom.ts b/B06_Section/B06_Section_UI_Cross_Ford_Geom.ts index f862cce8..8a166d10 100644 --- a/B06_Section/B06_Section_UI_Cross_Ford_Geom.ts +++ b/B06_Section/B06_Section_UI_Cross_Ford_Geom.ts @@ -72,6 +72,9 @@ export interface FordSideLayout { pipeEnd: OffsetPoint; /** 바닥판 안쪽 변(위·아래) — 두 측벽 사이를 잇는 판이 여기서 시작한다. */ slabInner: [OffsetPoint, OffsetPoint]; + /** 날개벽 상단(바닥판 바깥 끝 × 바닥판 상면 + 짧은쪽 높이). 설치가 없으면 null. + * 월류 전 노면(점선)이 이 점까지 대각으로 내려온다(2026-08-30 사용자). */ + wingTop: OffsetPoint | null; /** 구조물 계류측 끝이 원지반 위일 때의 성토부선(집수정과 같은 체계). */ fillSegments: OutletFillSegment[]; /** 원지반 안으로 박힐 때의 절토선. */ @@ -222,6 +225,16 @@ export function computeFordLayout( slabTopElevation: built.pipeEnd.elevation, pipeEnd: built.pipeEnd, slabInner: [floor.points[0], floor.points[3]], + // 날개벽 상단 — 바닥판 바깥 끝(계류측 극점) 위로 짧은쪽 높이만큼. + wingTop: wing.installed + ? { + offset: floor.points.reduce( + (far, point) => ((point.offset - far) * outward > 0 ? point.offset : far), + floor.points[0].offset, + ), + elevation: built.pipeEnd.elevation + (wing.height_m ?? 0), + } + : null, fillSegments: extras.segments, cutLine: built.basin.cutLine, adjust: { diff --git a/B06_Section/B06_Section_UI_Cross_Ford_Pavement.ts b/B06_Section/B06_Section_UI_Cross_Ford_Pavement.ts index be1e4f48..3802cf50 100644 --- a/B06_Section/B06_Section_UI_Cross_Ford_Pavement.ts +++ b/B06_Section/B06_Section_UI_Cross_Ford_Pavement.ts @@ -14,6 +14,7 @@ * ========================================================================== */ import type { CrossDesign } from "./B06_Section_Api_Fetch"; +import type { OffsetPoint } from "./B06_Section_UI_Cross_Culvert_Types"; const SVG_NS = "http://www.w3.org/2000/svg"; /** 빗금 패턴 id는 문서 안에서 유일해야 한다 — 카드마다 하나씩 번호를 준다. */ @@ -70,24 +71,37 @@ function line(points: string[], className: string): SVGPolylineElement { /** * 세월교로 **내려 앉힌 노면** 위에 "월류가 없었다면" 노면을 점선으로 되그린다 * (2026-08-30 사용자 확정). 계획고는 이미 백엔드가 월류 높이만큼 내려 잡았으므로 - * (`design.surface_drop_m`) 여기서는 그 양만큼 위로 올린 선 한 줄만 얹는다. + * (`design.surface_drop_m`) 여기서는 그 양만큼 위로 올린 선을 얹는다. * 물넘이포장의 「기존 계획고 점선」과 같은 표기라 사용자가 한 규칙으로 읽는다. + * + * 양 끝은 **날개벽 상단까지 대각으로 내려 잇는다**(2026-08-30 사용자) — 월류 전 + * 노면이 구체 밖에서 어디로 떨어지는지가 그 선으로 읽힌다. 날개벽이 없는 측은 + * 노견에서 끊는다. */ export function appendFordSurfaceDropPlan( svg: SVGElement, design: CrossDesign, x: (offset: number) => number, y: (elevation: number) => number, + ford?: { sides: ReadonlyArray<{ outward: number; wingTop: OffsetPoint | null }> } | null, ): void { const drop = design.surface_drop_m ?? 0; if (!(drop > 0) || !design.road_edges) return; const { left, right } = design.road_edges; + // +offset이 좌측이다 — 좌 노견 바깥(날개벽) → 좌 노견 → 우 노견 → 우 노견 바깥 순. + const wingAt = (side: 1 | -1): OffsetPoint | null => + ford?.sides.find((entry) => Math.sign(entry.outward) === side)?.wingTop ?? null; + const points: OffsetPoint[] = [ + { offset: left.offset_m, elevation: left.elevation_m + drop }, + { offset: right.offset_m, elevation: right.elevation_m + drop }, + ]; + const leftWing = wingAt(1); + if (leftWing) points.unshift(leftWing); + const rightWing = wingAt(-1); + if (rightWing) points.push(rightWing); svg.append( line( - [ - `${x(left.offset_m)},${y(left.elevation_m + drop)}`, - `${x(right.offset_m)},${y(right.elevation_m + drop)}`, - ], + points.map((point) => `${x(point.offset)},${y(point.elevation)}`), "b06-chart__ford-deck-plan", ), ); diff --git a/B06_Section/B06_Section_UI_Cross_View.ts b/B06_Section/B06_Section_UI_Cross_View.ts index 580dfb85..36b0188a 100644 --- a/B06_Section/B06_Section_UI_Cross_View.ts +++ b/B06_Section/B06_Section_UI_Cross_View.ts @@ -467,7 +467,7 @@ export function createCrossSectionCard( if (!fordPaved) appendPavementOverlay(plotLayer, section.design, x, toDisplayY); // 세월교 측점 — 계획고는 이미 월류 높이만큼 내려와 있다. "월류가 없었다면" // 노면을 점선으로 남겨 얼마나 내려앉았는지 읽히게 한다(2026-08-30 사용자). - appendFordSurfaceDropPlan(plotLayer, section.design, x, toDisplayY); + appendFordSurfaceDropPlan(plotLayer, section.design, x, toDisplayY, fordLayout); // 독립 기슭막이(구 D군 경로) — 이 측점에 배관/숨김 기슭막이 세트(section.culvert)가 // 붙으면 그쪽(배관 경로)이 그린다. 아직 이관 안 된 정본만 이 옛 경로로 그린다 // (2026-08-28 이관: pipe_points 숨김 세트로 옮기는 중 — 이중 그리기 방지 가드).