B05 세월교 옵션에 BOX암거 날개벽 한 벌(설치·짧은쪽 높이 1m·길이 2m·각도 45°)을 그대로 붙이고, B06 횡단도에 세월교 구체를 그린다. 구체는 양측 ㄴ형 집수정 측벽 + 그 사이를 잇는 바닥판 + 바닥판 상면에 안힌 관 + 관 위 성토(노체) 채움이다. - 바닥판 편측 연장 = 날개벽 길이 × cos(각도) — 각도는 관축 기준 벌어짐각 - 측벽은 buildBasin 재사용이라 1:0.3 기움·좌우·상하 대각 이동·계류측 성토부선이 집수정과 같은 규칙으로 따라온다 (기슭막이 다단·재질과는 연계하지 않음) - 구체는 월류 폭만큼 도로 방향으로 이어져 기준 측점 전후 절반까지 붙는다 - 조정창: 측벽 높이·좌우·상하, 관경·수량(정본 pipe_points 되쓰기). 높이·좌우·상하는 세션 + design.ford_adjust에 저장 - 3D 예상형상: 구체 부재는 월류 폭 구간 스윕, 관은 련수만큼 폭 안 등간격 - 부재 두께: 바닥판 0.3m(교본 물넘이 물받이 최소 30cm), 측벽 0.2m(집수정 승계) 700줄 제한으로 카드 렌더러·측점 제어기·페이지에서 배선을 분리했다 (_Cross_View_Ford, _Page_Ford_Controls, _Page_Patches, Culvert_Const 구간값 헬퍼). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
53 lines
2.4 KiB
TypeScript
53 lines
2.4 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_UI_Cross_View_Ford.ts
|
|
* 횡단 카드 ↔ **세월교 조정창** 배선 — 카드 렌더러(`_UI_Cross_View.ts`)에서 700줄
|
|
* 제한으로 분리했다(2026-08-25). 조정창이 부르는 동작을 제어기로 넘기는 얇은 층이고,
|
|
* 기하나 그리기는 하지 않는다.
|
|
* ========================================================================== */
|
|
|
|
import type { CrossSection } from "./B06_Section_Api_Fetch";
|
|
import type { FordPanelDeps, FordControl } from "./B06_Section_UI_Cross_Ford_Panel";
|
|
import type { FordWallRole } from "./B06_Section_UI_Cross_Ford";
|
|
|
|
/** 조정창 배선에 필요한 카드 상태. 계산 결과는 그릴 때마다 바뀌므로 함수로 받는다. */
|
|
export interface FordPanelContext {
|
|
section: CrossSection;
|
|
ford: FordControl;
|
|
/** 마지막 계산의 측벽 높이(m) — 높이 조작의 시작값. */
|
|
heightFor: (role: FordWallRole) => number;
|
|
/** 마지막 계산의 바닥판 길이(m). */
|
|
slabLengthM: () => number;
|
|
close: () => void;
|
|
}
|
|
|
|
/** 화면 좌(◀) 방향을 벽 기준 바깥 부호로 환산한다. 유입 = 상단측. */
|
|
function outwardOf(section: CrossSection, role: FordWallRole): number {
|
|
return ((section.uphill_side ?? "left") === "left") === (role === "inlet") ? 1 : -1;
|
|
}
|
|
|
|
export function fordPanelDeps(context: FordPanelContext): FordPanelDeps {
|
|
const { section, ford } = context;
|
|
const chainage = section.chainage_m;
|
|
return {
|
|
adjustFor: (role) => ford.adjustFor(chainage)[role],
|
|
heightFor: context.heightFor,
|
|
nudgeHeight: (role, deltaM) =>
|
|
ford.update(chainage, role, { heightM: context.heightFor(role) + deltaM }),
|
|
nudge: (role, screenDeltaM) =>
|
|
ford.update(chainage, role, {
|
|
lateralM: ford.adjustFor(chainage)[role].lateralM + screenDeltaM * outwardOf(section, role),
|
|
}),
|
|
nudgeSlope: (role, deltaM) =>
|
|
ford.update(chainage, role, {
|
|
slopeM: ford.adjustFor(chainage)[role].slopeM + deltaM,
|
|
}),
|
|
reset: (role) => ford.reset(chainage, role),
|
|
pipeDiameterMm: () => Math.round((section.ford?.diameter_m ?? 1) * 1000),
|
|
setPipeDiameterMm: (value) => ford.setPipe(chainage, { pipe_diameter_mm: value }),
|
|
pipeCount: () => section.ford?.pipe_count ?? 1,
|
|
setPipeCount: (value) => ford.setPipe(chainage, { pipe_count: value }),
|
|
slabLengthM: context.slabLengthM,
|
|
close: context.close,
|
|
};
|
|
}
|