diff --git a/B06_Section/B06_Section_UI_Cross_Culvert.ts b/B06_Section/B06_Section_UI_Cross_Culvert.ts index a3070292..6d7defff 100644 --- a/B06_Section/B06_Section_UI_Cross_Culvert.ts +++ b/B06_Section/B06_Section_UI_Cross_Culvert.ts @@ -239,7 +239,10 @@ export function appendCulvertOverlay( fill.setAttribute("y2", String(toDisplayY(basin.fillLine.to.elevation))); fill.setAttribute("class", "b06-chart__design-cross"); const fillTitle = document.createElementNS(SVG_NS, "title"); - fillTitle.textContent = `집수정(${shapeName}) 성토(되메움)선 — 구조물이 원지반 밖으로 나와 5° 경사로 채움`; + fillTitle.textContent = + basin.shape === "I" + ? "집수정(I형) 되메움(성토)선 — 관 하단에서 수평으로 원지반과 연결" + : `집수정(${shapeName}) 성토(되메움)선 — 구조물이 원지반 밖으로 나와 5° 경사로 채움`; fill.append(fillTitle); layer.append(fill); } diff --git a/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts b/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts index 7dd2829e..bab25523 100644 --- a/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts +++ b/B06_Section/B06_Section_UI_Cross_Culvert_Basin.ts @@ -250,3 +250,24 @@ export function inletChoiceAvailability(input: { }); return { revetAllowed, basinLUAllowed: probe.basin.cutLine != null, revetAutoOffset }; } + +/** + * I형 집수정의 **관 하단 수평 되메움(성토)선**(2026-08-22 사용자). 관 유입 하단 + * 꼭짓점이 원지반 위에 뜨면 그 표고 그대로 계류측으로 나가 원지반과 만나는 점까지 + * 잇고, 그 아래를 성토로 본다. 지반 교점 절단 방식은 보고 후 철회. + */ +export function applyBasinPipeFill( + basin: BasinLayout, + corner: OffsetPoint, + outward: number, + groundAt: (offset: number) => number, +): void { + if (basin.shape !== "I" || corner.elevation <= groundAt(corner.offset) + 0.02) return; + for (let run = 0.05; run <= 30; run += 0.05) { + const probe = corner.offset + outward * run; + if (groundAt(probe) >= corner.elevation) { + basin.fillLine = { from: corner, to: { offset: probe, elevation: corner.elevation } }; + return; + } + } +} diff --git a/B06_Section/B06_Section_UI_Cross_Culvert_Geom.ts b/B06_Section/B06_Section_UI_Cross_Culvert_Geom.ts index 4ea3d438..20f17694 100644 --- a/B06_Section/B06_Section_UI_Cross_Culvert_Geom.ts +++ b/B06_Section/B06_Section_UI_Cross_Culvert_Geom.ts @@ -39,6 +39,7 @@ export * from "./B06_Section_UI_Cross_Culvert_Const"; export * from "./B06_Section_UI_Cross_Culvert_Types"; import { + applyBasinPipeFill, BASIN_INNER_WIDTH_M, buildBasin, inletChoiceAvailability, @@ -137,16 +138,12 @@ export function computeCulvertLayout( : ruleReason; // 집수정 형식 기본값 = ㄴ(L)형(2026-08-20 확정) — 선택 시 그 형식. const basinShape: BasinShape = choice === "I" || choice === "L" || choice === "U" ? choice : "L"; - // ㄴ·ㄷ형은 **측면·바닥 사이즈를 유지한 채 통째로 노견 끝점에 일치**시킨다(2026-08-22 - // 사용자 확정 — 노견과 빈 공간을 채운다). 바닥(=관 유입 invert)이 따라 올라가므로 - // 관 물매도 바뀐다. 유출단은 원지반 위 원칙 그대로. I형은 원지반 배관을 유지하고 - // 벽 높이로만 노견에 연결한다(buildWall). + // ㄴ·ㄷ형은 사이즈 유지한 채 통째로 노견 끝점 일치(2026-08-22 확정) — 바닥(=관 + // 유입 invert)이 따라 올라 물매도 바뀐다. I형은 원지반 배관 유지(상세 Basin 참조). if (basinReason && basinShape !== "I") { inlet.elevation = inletInfo.edge.elevation_m - BASIN_INNER_HEIGHT_M; } else if (basinReason) { - // I형 — 관 시작점(내공 1.0m 자리) invert는 **그 x의 원지반 위**에 앉힌다(토피 - // 상한 이내). 종전에는 노견 x의 원지반을 써서 지반이 오르내리는 자리에서 관이 - // 지반에 파묻히거나 떴다(2026-08-22 사용자 ② — 13+15.7 확인). + // I형 — 관 시작점(내공 1.0m 자리) invert = 그 x의 원지반(토피 상한 이내). const startOffset = inlet.offset + inletInfo.outward * BASIN_INNER_WIDTH_M; inlet.elevation = Math.min(groundAt(startOffset), invertCap(inletInfo.edge)); } @@ -475,26 +472,6 @@ export function computeCulvertLayout( }; }; deriveAxis(); - // I형 집수정: 관 유입 끝의 마감면을 **관 하단선이 원지반과 만나는 점**으로 옮긴다 - // (2026-08-22 사용자 — 관 파란선 시작 꼭짓점이 지반 녹색선 위에 있어야 한다). - // invert가 토피 상한에 걸려 지반보다 낮으면 벽 변에서 자른 꼭짓점이 지반과 떠서 - // 어긋나 보였다. 마감면 기울기(벽과 나란)는 유지하고 기준점만 교점으로 바꾼다. - if (basin && basinShape === "I" && endFaces.inlet) { - let prevDiff = pipeStart.elevation - groundAt(pipeStart.offset); - for (let t = 0.02; t <= 3; t += 0.02) { - const px = pipeStart.offset + axis.offset * t; - const pe = pipeStart.elevation + axis.elevation * t; - const diff = pe - groundAt(px); - if (Math.abs(diff) < 0.005 || Math.sign(diff) !== Math.sign(prevDiff)) { - endFaces.inlet = { - base: { offset: px, elevation: pe }, - direction: endFaces.inlet.direction, - }; - break; - } - prevDiff = diff; - } - } const endCorners = (role: "inlet" | "outlet", endPoint: OffsetPoint): PipeEnd => { const fallback: PipeEnd = { bottom: endPoint, @@ -600,6 +577,11 @@ export function computeCulvertLayout( : 0; } + // I형 집수정: 관 하단 꼭짓점이 지반 위에 뜨면 수평 되메움선(Basin 분리 — 700줄). + if (basin) { + applyBasinPipeFill(basin, pipeCorners.inlet.bottom, inletInfo.outward, groundAt); + } + // 보호공(돌붙임) — 유출측. 2026-08-20 사용자 ①·②: // ① 시작 변은 **기슭막이 전면과 같은 경사**(밑면을 벽 전면 방향으로 민다), // 윗면 시작점 = **관 하단 꼭짓점**(관 밑면과 한 점에서 만난다).