- 관 유입·유출 흙막이 · 추가 흙막이 · 사면안정 흙막이 · 옹벽 모두 공용 buildRevetWallGeometry - 외곽 기울기 형태 무관(outlineLeanOf) — 형태는 안 무늬만 - 형태별 높이 한도(메 2.0 · 찰 3.0 · 콘크리트 5.0) 자르기 · 경고 삭제 — 입력 높이 그대로 - 추가 흙막이 원지반 맞춤 늘이기 삭제(돌쌓기(메) 원지반 따라 연장 흠) - 벽 윗면 노면 위 금지 — 넘으면 노면에서 멈춤 - 다단 묶음 _Cross_Culvert_Tiers 로 분리(Geom 700줄 이하) - 시험 test_b06_wall_shape_unified 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYJJRCfHfdCGNhmXTjQKV7
129 lines
5.9 KiB
TypeScript
129 lines
5.9 KiB
TypeScript
/* =============================================================================
|
||
* B06_Section_UI_Cross_Culvert_Tiers.ts
|
||
* 배수관 세트 기하(`_Cross_Culvert_Geom`)에서 떼어 낸 **벽 자리 도우미 + 다단 흙막이** 층.
|
||
* 다단 벽은 `buildExtrasAt`(공용 `buildRevetWallGeometry`)이 세우고, 여기서는 유출측과
|
||
* 집수정 계류측 두 채널의 입력을 짜고 면적용(미확정 단 제외) 결과를 함께 돌려준다.
|
||
* ========================================================================== */
|
||
|
||
import type { CrossSection } from "./B06_Section_Api_Fetch";
|
||
import { REVET_EMBED_DEPTH_M, REVET_TRAP_TOP_M } from "./B06_Section_UI_Cross_Culvert_Const";
|
||
import type { OutletExtrasResult } from "./B06_Section_UI_Cross_Culvert_Extra";
|
||
import { buildExtrasAt } from "./B06_Section_UI_Cross_Culvert_Extra";
|
||
import { fillWallBaseWidth } from "./B06_Section_UI_Cross_Culvert_Solve";
|
||
import type { OffsetPoint, WallAdjust, WallLayout } from "./B06_Section_UI_Cross_Culvert_Types";
|
||
import { outlineLeanOf } from "./B06_Section_UI_Cross_Lean";
|
||
|
||
// d의 0점 = **성토선 길이 0 지점**(벽 상단 = 노견 — 2026-08-23 사용자 확정).
|
||
// 그 자리(하단선 중점)는 이음선 상단점이 노견 끝에 오는 offset이고, 기본 자리는
|
||
// 성토선을 타고 경사길이 4m 내려간 지점(PIPE_WALL_DEFAULT_RUN_M)이다.
|
||
export const slopeZeroAnchor = (
|
||
edge: { offset_m: number },
|
||
outward: number,
|
||
wallHeight: number,
|
||
lean: number,
|
||
): number => edge.offset_m + outward * (fillWallBaseWidth(wallHeight, lean) / 2 - REVET_TRAP_TOP_M);
|
||
|
||
/** 유출 관 하단 끝점 목표 = 벽 바닥 기준 0.5m 상단(기준선)과 **전면 경사선의
|
||
* 교차점**(2026-08-22 사용자 ① — 성토부선 시작 규칙과 같은 자리). */
|
||
export const outletPipeEnd = (wall: WallLayout): OffsetPoint => {
|
||
// 기준 = 바닥 +0.5(= 관 invert 자리 — 2026-08-23부터 바닥은 invert−0.5 고정).
|
||
const reference = wall.bottomBack.elevation + REVET_EMBED_DEPTH_M;
|
||
return {
|
||
offset:
|
||
wall.points[2].offset + wall.outward * wall.lean * (wall.topJoint.elevation - reference),
|
||
elevation: reference,
|
||
};
|
||
};
|
||
|
||
// 다단 기슭막이의 성토부선까지 트림에 넣는다 — 넣지 않으면 단을 올려도 폐회로가 그대로라
|
||
// **물량이 안 바뀐다**(2026-09-07 사용자 확정). 화면이 그리는 선(`outletFill.segments`)과
|
||
// 같은 선을 면적도 보게 맞춘다 — 그리지 않는 `cut` 갈래(벽이 원지반에 묻힌 자리)는 뺀다.
|
||
export const drawnFillPoints = (result: OutletExtrasResult): OffsetPoint[] =>
|
||
result.segments.filter((segment) => segment.kind !== "cut").flatMap((segment) => segment.points);
|
||
|
||
interface SideInfo {
|
||
outward: number;
|
||
limit: number;
|
||
}
|
||
|
||
/** 다단 흙막이 두 채널 — 유출측(`extras`)과 집수정 계류측·독립 기슭막이 유입측(`basinExtras`). */
|
||
export function buildCulvertTiers(input: {
|
||
section: CrossSection;
|
||
outletStart: OffsetPoint | null;
|
||
outletBottom: number;
|
||
basinStart: OffsetPoint | null;
|
||
basinBottom: number;
|
||
outletInfo: SideInfo;
|
||
inletInfo: SideInfo;
|
||
groundAt: (offset: number) => number;
|
||
extras: WallAdjust[];
|
||
basinExtras: WallAdjust[];
|
||
outletForm: string;
|
||
inletForm: string;
|
||
equalize: boolean;
|
||
}): {
|
||
extras: OutletExtrasResult;
|
||
basinExtras: OutletExtrasResult;
|
||
extrasForArea: OutletExtrasResult;
|
||
basinExtrasForArea: OutletExtrasResult;
|
||
} {
|
||
const { section, groundAt } = input;
|
||
const culvert = section.culvert;
|
||
// 다단 벽 기울기 — 같은 측점·같은 설치 측 규칙으로 높이마다 표준경사(형태 무관 · B08 은 다단을 안 셈).
|
||
const extraLean = (form: string, pureHeightM: number): number =>
|
||
outlineLeanOf({
|
||
form,
|
||
height_m: pureHeightM,
|
||
section_mode: section.design?.section_mode,
|
||
side: culvert?.hidden_pipe ? culvert.inlet.face_side : null,
|
||
});
|
||
// 성토부선 + 다단 기슭막이(2026-08-22 — 보호공 삭제, 윗면 선만 성토부선으로).
|
||
// 유출측과 **집수정 계류측**이 같은 체계를 쓴다: 5m 넘으면 다단을 둘 수 있다.
|
||
const outletInput = {
|
||
startBottomElevation: input.outletBottom,
|
||
outward: input.outletInfo.outward,
|
||
groundAt,
|
||
limitOffset: input.outletInfo.limit,
|
||
adjusts: input.extras,
|
||
ownerForm: input.outletForm,
|
||
equalize: input.equalize,
|
||
leanFor: extraLean,
|
||
};
|
||
const extras = buildExtrasAt(input.outletStart, outletInput);
|
||
// 독립 기슭막이(관 숨김)는 집수정이 없어 이 채널이 **유입측 벽의 성토부선·다단**이다 —
|
||
// 유출측(`extras`)과 같은 시작점(관 하단 꼭짓점)·같은 `bextra` 키(2026-08-29 사용자).
|
||
const basinInput = {
|
||
startBottomElevation: input.basinBottom,
|
||
outward: input.inletInfo.outward,
|
||
groundAt,
|
||
limitOffset: input.inletInfo.limit,
|
||
adjusts: input.basinExtras,
|
||
ownerForm: input.inletForm,
|
||
equalize: false,
|
||
leanFor: extraLean,
|
||
};
|
||
const basinExtras = buildExtrasAt(input.basinStart, basinInput);
|
||
/** ⭐ 면적용 다단 — **미확정 단(높이 안 적음)부터 아래는 없는 것**으로 봄(2026-09-14 브레인 판정
|
||
* 「미확정 벽은 성토도 안 깎음 · 벽 금액과 성토 감소가 함께」). 그림은 그대로 다 그림.
|
||
* B08 도 첫 미확정 단 아래는 미확정으로 셈(`facility_structures`) — 두 곳이 같은 선에서 끊김. */
|
||
const confirmedOnly = (
|
||
built: OutletExtrasResult,
|
||
start: OffsetPoint | null,
|
||
channel: typeof outletInput,
|
||
): OutletExtrasResult => {
|
||
const firstUnset = built.appliedAdjusts.findIndex((applied) => applied.h == null);
|
||
if (firstUnset < 0) return built;
|
||
return buildExtrasAt(start, {
|
||
...channel,
|
||
adjusts: channel.adjusts.slice(0, firstUnset),
|
||
equalize: false,
|
||
});
|
||
};
|
||
return {
|
||
extras,
|
||
basinExtras,
|
||
extrasForArea: confirmedOnly(extras, input.outletStart, outletInput),
|
||
basinExtrasForArea: confirmedOnly(basinExtras, input.basinStart, basinInput),
|
||
};
|
||
}
|