From a7f6232c012d88bafc7952ec6378690f7655662b Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 3 Sep 2026 10:32:20 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20I=ED=98=95=20=EC=A7=91=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B4=80=20=ED=95=98=EB=8B=A8=EC=9D=84=20=EB=B2=BD?= =?UTF-8?q?=EB=A9=B4=20=EC=95=88=EC=9C=BC=EB=A1=9C=20=EC=A0=9C=ED=95=9C=20?= =?UTF-8?q?=E2=80=94=20=EA=B4=80=EC=9D=B4=20=EB=B2=BD=EC=9D=84=20=EA=B4=80?= =?UTF-8?q?=ED=86=B5=ED=95=98=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 관 하단 자리는 벽 계류측 변과 원지반의 교점인데, 원지반이 벽 상단보다 높은 자리에서는 교점이 벽 상단으로 밀려 관이 벽 위에 얹혔다(측벽과 배관이 만나지 않음). ㄴ·ㄷ형은 관이 바닥판 윗면에서 시작해 벽 안에 물리는 것과 대비된다. 교점을 벽 상단에서 관경+여유(0.5m)만큼 아래로 제한한다. 원지반이 그보다 낮으면 종전대로 교점을 그대로 쓴다. 벽을 키우는 방향은 벽이 1:0.3으로 기울어 base가 계류측으로 밀리며 지반 교점이 함께 올라가 벽이 7.5m까지 자라 폐기했다. 검증 — 공용 브라우저 B06 I형 8개 단면 실측: 관 유입측 끝단과 벽의 세로 겹침 18.1~56.4px(수정 전 0 — 벽 위로 이탈). ㄴ형 대조(13+4.1을 조정창에서 ㄴ형으로 바꿔 확인) 겹침 유지, 확인 후 세션값 원복. pytest 370 passed·17 skipped, typecheck·prettier 통과. Co-Authored-By: Claude Opus 5 (1M context) --- .../B06_Section_UI_Cross_Culvert_Basin.ts | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts b/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts index d789323a..744c21cb 100644 --- a/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts +++ b/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts @@ -174,21 +174,15 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult { }; // I형 벽 자리 = **상단 도로측 꼭짓점이 노견 끝 지점에 닿는다**(2026-08-22 사용자 // 확정). 벽 상단이 도로측으로 1:0.3 물러나므로 하단(base)은 그만큼 계류측 바깥. - const wallBase = anchor.offset + outward * (lean * wallHeight); + const wallBaseAt = (height: number): number => anchor.offset + outward * (lean * height); // I형 벽 하단은 **원지반까지 묻는다**(2026-08-22 사용자 — 지반 아래 부재두께만큼 // 근입 후 배관을 둔다). ㄴ·ㄷ형은 바닥판이 원지반을 대체하므로 현행 유지. - const iWallBottom = - shape === "I" - ? Math.min(anchor.elevation, groundAt(wallBase), groundAt(wallBase + outward * memberT)) - - floorThickness - : defaultBottom; - const parts: BasinLayout["parts"] = [ - { kind: "wall", points: wallOf(wallBase, outward, iWallBottom) }, - ]; - const iWallPoints = parts[0].points; - const iGroundIntersection = (): OffsetPoint => { - const low = iWallPoints[3]; - const high = iWallPoints[2]; + const iBottomAt = (base: number): number => + Math.min(anchor.elevation, groundAt(base), groundAt(base + outward * memberT)) - floorThickness; + /** 벽 계류측 변(하단-전면 → 상단-전면)과 원지반의 교점 — I형 관 하단 자리. */ + const groundOnFace = (points: OffsetPoint[]): OffsetPoint => { + const low = points[3]; + const high = points[2]; let lo = 0; let hi = 1; for (let pass = 0; pass < 32; pass += 1) { @@ -206,6 +200,34 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult { elevation: low.elevation + (high.elevation - low.elevation) * t, }; }; + const wallBase = wallBaseAt(wallHeight); + const iWallBottom = shape === "I" ? iBottomAt(wallBase) : defaultBottom; + const parts: BasinLayout["parts"] = [ + { kind: "wall", points: wallOf(wallBase, outward, iWallBottom) }, + ]; + const iWallPoints = parts[0].points; + /** 벽 계류측 변 위에서 그 표고에 해당하는 점 — 관 하단을 벽면을 따라 내릴 때 쓴다. */ + const pointOnFaceAt = (elevation: number): OffsetPoint => { + const low = iWallPoints[3]; + const high = iWallPoints[2]; + const span = high.elevation - low.elevation; + const t = span > 1e-9 ? Math.min(Math.max((elevation - low.elevation) / span, 0), 1) : 0; + return { + offset: low.offset + (high.offset - low.offset) * t, + elevation: low.elevation + span * t, + }; + }; + /** + * I형 관 하단 자리 = 벽 계류측 변과 원지반의 교점. 다만 **관이 벽을 관통해야** 하므로 + * (ㄴ·ㄷ형은 바닥판 위에서 이미 물린다) 벽 상단에서 관경+여유만큼 아래로 제한한다. + * 원지반이 벽 상단보다 높은 자리에서 제한이 없으면 관이 벽 위로 떠 벽과 만나지 않았다 + * (2026-09-03 사용자 지적: 「측벽과 배관의 형상이 교차하고 있어야 함」). + */ + const iGroundIntersection = (): OffsetPoint => { + const hit = groundOnFace(iWallPoints); + const invertCeiling = anchor.elevation + wallHeight - (diameterM + REVET_FREEBOARD_M); + return hit.elevation <= invertCeiling ? hit : pointOnFaceAt(invertCeiling); + }; // ㄴ형 = I형 + 바닥판. 바닥은 벽 바깥(계류측) 변에 맞대고 그 너머로 뻗는다 // (2026-08-20 확정). 벽이 기울어 있어 안쪽 변도 벽 바깥면 선을 그대로 따른다. const wallOuterAt = (elevation: number): number => {