- 받침 종류 · 용량 입력칸과 받침 규칙의 kind 값을 제거 - 예전 프로젝트 파일에 저장된 kind 값은 읽을 때 무시 (불러오기 오류 없음) - 테스트 갱신. 전체 651건 통과, 타입 검사·빌드 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
147 lines
6.4 KiB
TypeScript
147 lines
6.4 KiB
TypeScript
/**
|
||
* 교대 받침 카드 (2026-11-03, 시안 ② 교량받침·받침블럭·솔플레이트, 교각 카드와 같은 형식). 순수 함수.
|
||
*
|
||
* - 솔플레이트는 교각과 같은 규칙(C안, src/core/solplate-rule.ts)을 쓴다: 받침높이 H(솔플레이트 포함)는 교대 받침 시트 값
|
||
* (운곡교 A1 275 mm)으로 고정하고, 교직 L · 교축 W · 종단 기울기 S를 입력한다. 중심 두께 T = ⌈22 + L·|S|/200⌉,
|
||
* T1·T2 = T ± L·|S|/200, 받침 본체 h3 = H − T. 기본값은 교각과 같은 1000 × 1100 · −0.5 % (가정, QA-15, 결정 2026-11-03).
|
||
* - 높이: E = h1 (블럭 콘크리트) + h2 (몰탈패드 50) + h3 + h4 (= T) = h1 + h2 + H. z = 패드 상면 = EL.X.
|
||
*/
|
||
import { solplatePlan, solplateRuleIssues } from '../solplate-rule';
|
||
import type { SolplatePlan, SolplateRule } from '../types';
|
||
import { ABUT_PAD_MM, type AbutModel } from './geometry';
|
||
import type { AbutMembers } from './members';
|
||
|
||
export interface AbutBearingRule {
|
||
/** 솔플레이트 교직 L (mm). */
|
||
lengthMm: number;
|
||
/** 솔플레이트 교축 W (mm). */
|
||
widthMm: number;
|
||
/** 종단 기울기 S (%). */
|
||
slopePct: number;
|
||
}
|
||
|
||
/** 기본값: 교각 솔플레이트 규칙과 같은 1000 × 1100 · −0.5 % (QA-15, 사용자 결정 2026-11-03). */
|
||
export const ABUT_BEARING_RULE_DEFAULT: AbutBearingRule = { lengthMm: 1000, widthMm: 1100, slopePct: -0.5 };
|
||
/** 받침블럭 평면 (mm, 정사각) and 몰탈패드 평면 (mm), spec_abut §4.2. */
|
||
export const ABUT_BLOCK_MM = 1200;
|
||
export const ABUT_PAD_PLAN_MM = 1000;
|
||
/** I01: 블럭 콘크리트 높이가 피복 50 + 철근 지름 13보다 작으면 블럭 철근을 교좌면 아래로 묻는다 (spec_abut §6.6). */
|
||
const I01_MIN_MM = 50 + 13;
|
||
|
||
const CIRCLED = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩'];
|
||
|
||
export function resolveBearingRule(changes?: Partial<AbutBearingRule>): AbutBearingRule {
|
||
return { ...ABUT_BEARING_RULE_DEFAULT, ...(changes ?? {}) };
|
||
}
|
||
|
||
/** The pier rule with the 교대 받침높이 H (from the 받침 sheet). */
|
||
export function abutSolplateRule(rule: AbutBearingRule, heightMm: number): SolplateRule {
|
||
return { heightMm, lengthMm: rule.lengthMm, widthMm: rule.widthMm, slopePct: rule.slopePct };
|
||
}
|
||
|
||
export function abutSolplatePlan(rule: AbutBearingRule, heightMm: number): SolplatePlan {
|
||
return solplatePlan(abutSolplateRule(rule, heightMm));
|
||
}
|
||
|
||
export interface AbutElevationRow {
|
||
no: number;
|
||
/** IP3(① 쪽)에서 잰 위치 (m). */
|
||
sFromIp3M: number;
|
||
seg: string;
|
||
seatEl: number;
|
||
h1: number;
|
||
h2: number;
|
||
/** 패드 상면 = EL.X (m). */
|
||
z: number;
|
||
h3: number;
|
||
h4: number;
|
||
E: number;
|
||
/** 솔플레이트 상면 EL (m) = 교좌면 + E. */
|
||
solplateTopEl: number;
|
||
/** 블럭 끝에서 가장 가까운 계단 경계까지 (m). 경계가 없으면 null. */
|
||
stepGapM: number | null;
|
||
/** 받침 방위각 (deg): CAD (엑셀 값, 동 = 0° 반시계) / 진북 (북에서 시계). 입력이 없으면 null. */
|
||
azimuthCadDeg: number | null;
|
||
azimuthNorthDeg: number | null;
|
||
/** 블럭 평면 회전 (deg), 교대축 직각 기준. */
|
||
rotDeg: number;
|
||
}
|
||
|
||
export function abutElevationRows(model: AbutModel, rule: AbutBearingRule, heightMm: number): AbutElevationRow[] {
|
||
const half = ABUT_BLOCK_MM / 2000;
|
||
const plan = abutSolplatePlan(rule, heightMm);
|
||
return model.bearings.map((b) => {
|
||
const h1 = b.blockHeightMm - ABUT_PAD_MM;
|
||
const E = h1 + ABUT_PAD_MM + plan.h3 + plan.T;
|
||
const gaps = model.stepBounds.map((x) => Math.abs(x - b.s) - half);
|
||
return {
|
||
no: b.no,
|
||
sFromIp3M: model.length - b.s,
|
||
seg: CIRCLED[b.no - 1] ?? String(b.no),
|
||
seatEl: b.seatEl,
|
||
h1,
|
||
h2: ABUT_PAD_MM,
|
||
z: b.z,
|
||
h3: plan.h3,
|
||
h4: plan.T,
|
||
E,
|
||
solplateTopEl: b.seatEl + E / 1000,
|
||
stepGapM: gaps.length ? Math.min(...gaps) : null,
|
||
azimuthCadDeg: b.azimuthDeg === undefined ? null : (((90 - b.azimuthDeg) % 360) + 360) % 360,
|
||
azimuthNorthDeg: b.azimuthDeg === undefined ? null : ((b.azimuthDeg % 360) + 360) % 360,
|
||
rotDeg: b.rotDeg,
|
||
};
|
||
});
|
||
}
|
||
|
||
export interface AbutSolplateRow {
|
||
no: number;
|
||
/** 기울기 (%). */
|
||
S: number;
|
||
L: number;
|
||
W: number;
|
||
T: number;
|
||
T1: number;
|
||
T2: number;
|
||
/** 검산 문구 "T1 − T2 = L·|S|/100". */
|
||
check: string;
|
||
}
|
||
|
||
export function abutSolplateRows(model: AbutModel, rule: AbutBearingRule, heightMm: number): AbutSolplateRow[] {
|
||
const p = abutSolplatePlan(rule, heightMm);
|
||
return model.bearings.map((b) => ({
|
||
no: b.no,
|
||
S: p.slopePct,
|
||
L: p.L,
|
||
W: p.W,
|
||
T: p.T,
|
||
T1: p.T1,
|
||
T2: p.T2,
|
||
check: `${(p.T1 - p.T2).toFixed(1)} = ${((p.L * Math.abs(p.slopePct)) / 100).toFixed(1)}`,
|
||
}));
|
||
}
|
||
|
||
/** Input problems of the 교대 받침 규칙 (the pier rule's checks with the 교대 H). Empty when it can build a solplate. */
|
||
export function abutBearingRuleIssues(rule: AbutBearingRule, heightMm: number): string[] {
|
||
return solplateRuleIssues(abutSolplateRule(rule, heightMm));
|
||
}
|
||
|
||
/** 검사 줄 (시안): W02 블럭 콘크리트, W04 블럭이 교좌면 안, W03 블럭 끝 ~ 계단 경계, I01 블럭 철근. 문제 없으면 "없음". */
|
||
export function abutBearingChecks(model: AbutModel, members: AbutMembers, rule: AbutBearingRule, heightMm: number): string[] {
|
||
const rows = abutElevationRows(model, rule, heightMm);
|
||
const minH1 = Math.min(...rows.map((r) => r.h1));
|
||
const half = ABUT_BLOCK_MM / 2000;
|
||
// Block plan across the wall: centre t = frontSide × lateral, between the 흉벽 front (t 0) and the 벽체 front.
|
||
const tCentres = model.bearings.map((b) => model.frontSide * b.lateral);
|
||
const backGap = Math.min(...tCentres.map((t) => t - half));
|
||
const frontGap = Math.min(...tCentres.map((t) => members.shape.wallFrontM - (t + half)));
|
||
const stepGaps = rows.map((r) => r.stepGapM).filter((g): g is number => g !== null);
|
||
const minStep = stepGaps.length ? Math.min(...stepGaps) : null;
|
||
return [
|
||
`블럭 콘크리트 ${minH1} > 0 (W02 ${minH1 > 0 ? '없음' : '있음'})`,
|
||
`블럭이 교좌면 안 (흉벽 ${Math.round(backGap * 1000)} · 전면 ${Math.round(frontGap * 1000)}, W04 ${backGap >= 0 && frontGap >= 0 ? '없음' : '있음'})`,
|
||
minStep === null ? '블럭 끝 ~ 계단 경계: 경계 없음 (W03 없음)' : `블럭 끝 ~ 계단 경계 최소 ${minStep.toFixed(3)} m (W03 ${minStep >= 0 ? '없음' : '있음'})`,
|
||
`${minH1} ≥ ${I01_MIN_MM} → I01 ${minH1 >= I01_MIN_MM ? '없음' : '있음 (블럭 철근을 교좌면 아래로)'}`,
|
||
];
|
||
}
|