fix(B06): 세월교 측벽을 수직으로 세운다

증상(사용자): 세월교 횡단도 측벽이 기울어 있고 바닥판 모서리도 깎여 있다.
확인 결과 세로(수직)로 그려져야 한다.

원인: 세월교 측벽은 ㄴ형 집수정 부재를 재사용한다(2026-08-25). 그래서 집수정
규칙인 전면 1:0.3 기움과 거기서 파생된 바닥판 taper(0.3 × 두께)가 딸려 왔다.
세월교 근거가 아니라 부재를 빌려 오며 따라온 값이다.

근거: 지식DB·교본 원문에 세월교 단면 기울기 수치는 없다. 교본 그림 3-18
세월교 설치 종단도의 구체가 수직 벽이고, 사용자가 그렇게 확정했다.

고침: buildBasin에 leanRatio 인자를 두고(기본 0.3) 세월교만 0을 넘긴다.
집수정 호출부는 인자를 안 넘기므로 동작이 그대로다. 벽 상단 도로측 꼭짓점
(설계선 트림 경계)은 노견 끝 그대로라 트림·접근선 규칙도 불변이고, 바닥
길이는 날개벽 투영 연장 + 벽 두께로 유지된다. 3D는 같은 폴리곤을 스윕하므로
자동 반영된다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-29 13:22:50 +09:00
co-authored by Claude Opus 5
parent 2cad971f6a
commit 11abd303e7
2 changed files with 22 additions and 8 deletions
@@ -88,6 +88,12 @@ export interface BasinBuildInput {
memberThicknessM?: number;
/** 바닥판 두께(m). 기본 = 벽 두께. 세월교는 교본 물받이 최소 0.3m를 쓴다. */
floorThicknessM?: number;
/**
* 벽 기움(1:n의 n). 기본 = 집수정 규칙 0.3. **세월교는 0**(수직) — 기움은 집수정
* 부재를 재사용하며 딸려 온 값이고, 교본 그림 3-18 세월교 단면은 수직 벽이다
* (2026-08-30 사용자 확정: 집수정은 그대로 두고 세월교만 세운다).
*/
leanRatio?: number;
}
/** 집수정 구성 결과 — 본체가 트림·관 끝단면·관 시작점에 나눠 꽂는다. */
@@ -127,6 +133,8 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
cutSlopeRatio,
adjust,
} = input;
/** 이 부재의 기움 — 집수정 0.3, 세월교 0(수직). */
const lean = input.leanRatio ?? REVET_LEAN_RATIO;
const movedAnchor = {
offset: baseAnchor.offset + outward * (adjust.lateralM + adjust.slopeM),
elevation: baseAnchor.elevation - adjust.slopeM / 1.2,
@@ -147,7 +155,7 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
dir: number,
bottomElevation = defaultBottom,
): OffsetPoint[] => {
const topShift = -dir * REVET_LEAN_RATIO * wallHeight;
const topShift = -dir * lean * wallHeight;
const spanZ = wallHeight + floorThickness;
const xAt = (elevation: number): number =>
baseOffset + topShift * ((elevation - defaultBottom) / spanZ);
@@ -166,7 +174,7 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
};
// I형 벽 자리 = **상단 도로측 꼭짓점이 노견 끝 지점에 닿는다**(2026-08-22 사용자
// 확정). 벽 상단이 도로측으로 1:0.3 물러나므로 하단(base)은 그만큼 계류측 바깥.
const wallBase = anchor.offset + outward * (REVET_LEAN_RATIO * wallHeight);
const wallBase = anchor.offset + outward * (lean * wallHeight);
// I형 벽 하단은 **원지반까지 묻는다**(2026-08-22 사용자 — 지반 아래 부재두께만큼
// 근입 후 배관을 둔다). ㄴ·ㄷ형은 바닥판이 원지반을 대체하므로 현행 유지.
const iWallBottom =
@@ -203,12 +211,12 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
const wallOuterAt = (elevation: number): number => {
const bottom = anchor.elevation - floorThickness;
const t = (elevation - bottom) / (wallHeight + floorThickness);
return wallBase + outward * memberT - outward * REVET_LEAN_RATIO * wallHeight * t;
return wallBase + outward * memberT - outward * lean * wallHeight * t;
};
const floorTopInner = wallOuterAt(anchor.elevation);
const floorBottomInner = wallOuterAt(anchor.elevation - floorThickness);
const floorOuter = floorTopInner + outward * (adjust.innerWidthM + memberT);
const floorTaper = REVET_LEAN_RATIO * floorThickness;
const floorTaper = lean * floorThickness;
if (shape !== "I") {
parts.push({
kind: "floor",
@@ -240,7 +248,7 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
const refTop =
shape === "U"
? {
offset: mirroredWallBase + outward * REVET_LEAN_RATIO * wallHeight,
offset: mirroredWallBase + outward * lean * wallHeight,
elevation: anchor.elevation + wallHeight,
}
: { offset: floorOuter, elevation: anchor.elevation };
@@ -289,7 +297,7 @@ export function buildBasin(input: BasinBuildInput): BasinBuildResult {
: { offset: floorTopInner, elevation: anchor.elevation },
fillStart,
fillBottomElevation: anchor.elevation - floorThickness,
trimOffset: wallBase - outward * REVET_LEAN_RATIO * wallHeight,
trimOffset: wallBase - outward * lean * wallHeight,
trimElevation: anchor.elevation + wallHeight,
};
}
@@ -4,8 +4,10 @@
* 백엔드 `section.ford` 제원을 좌표로 옮긴다(치수 결정 금지).
*
* 구성(2026-08-25 사용자 확정):
* · 양측 **측벽** = ㄴ형 집수정을 그대로 재사용한다(`buildBasin`) — 전면 1:0.3
* 기움·좌우·상하(대각) 이동·계류측 성토부선이 집수정과 같은 규칙으로 따라온다.
* · 양측 **측벽** = ㄴ형 집수정 부재를 재사용한다(`buildBasin`) — 좌우·상하(대각)
* 이동·계류측 성토부선이 집수정과 같은 규칙으로 따라온다. 단 **벽은 수직**이다
* (`leanRatio: 0` — 2026-08-30 사용자 확정, 교본 그림 3-18). 집수정의 1:0.3
* 기움은 세월교 근거가 아니라 부재를 빌려 오며 딸려 온 값이었다.
* · **바닥판** = 두 측벽 사이를 잇는 판 + 각 측 바깥으로 **날개벽 투영**(길이×cos각)
* 만큼 뻗은 판. 집수정 내공 폭 자리에 그 연장량을 넣어 같은 기하로 만든다.
* · **관**은 바닥판 상면(측벽 바깥면)에 안히고, 관 위 ~ 노면 아래는 **성토(노체)** 다.
@@ -187,6 +189,10 @@ export function computeFordLayout(
},
memberThicknessM: ford.wall_thickness_m,
floorThicknessM: ford.slab_thickness_m,
// 세월교 측벽은 **수직**이다(2026-08-30 사용자 확정 — 교본 그림 3-18 세월교
// 단면). 1:0.3 기움은 ㄴ형 집수정 부재를 재사용하며 딸려 온 값이라 여기서 끈다.
// 바닥판 taper(0.3×두께)도 같은 값에서 나오므로 함께 사라져 직사각형이 된다.
leanRatio: 0,
});
const wall = built.basin.parts.find((part) => part.kind === "wall");
const floor = built.basin.parts.find((part) => part.kind === "floor");