feat(view): bearing reference tables on ② (drawing values, read-only, not used in the model)

The P1 상세도 ELEVATION TABLE and 솔플레이트 TABLE are shown on the bearing card. The model does not use them (Q16). The
ELEVATION table compares the drawing's coping top (EL.X − E) with the model's coping top; the difference is a constant
0.211 m on all ten bearings. The solplate table checks T1 and T2 against T ± L·|S|/2 with the 공통 규칙 T = 30 mm; all
rows match. Tests check E = h1+h2+h3+h4, L and W, the T1/T2 rule, and the constant offset.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-23 14:02:27 +09:00
1 parent 4d5e3cc04e
commit ee6848c418
4 files changed
+170

No files matched your search

+52
View File
@@ -16,6 +16,7 @@ import { buildRebar3D, type RebarColorMode, type RebarScene } from './view/rebar
import { DEFAULT_MATERIAL, FCK_MEMBERS, fyOf, GRADE_CHOICES, isAssumedMaterial, materialFrom, type BendFactors, type FckByMember, type FckMember, type GradeKey, type Material } from './core/rebar/common';
import { buildQuantity, quantityRows, type Quantity, type QuantityLine } from './core/rebar/quantity';
import { P1_COPING_GEOM } from './core/coping-geom';
import { BEARING_ELEVATION_REF, SOLPLATE_REF, SOLPLATE_T_RULE, solplateTs } from './core/bearing-ref';
import { allVisibleChecked, setVisibleChecked, type TypeFilter } from './core/selection';
import { choose, defaultSummary, isSelectable, SHAPE_GROUPS, UNDEFINED_REASON, type MemberId } from './core/shape-options';
import { parseProject, SCHEMA_VERSION, serializeProject, type ProjectFile, type ProjectInfo } from './core/project';
@@ -1246,6 +1247,56 @@ function setMaterial(key: 'fck' | GradeKey, raw: string): void {
renderAll();
}
/** ② 교량받침 reference (1단계, 읽기 전용): the drawing's ELEVATION and 솔플레이트 tables, not used in the model (Q16). */
function renderBearingRef(box: HTMLDivElement, pier: Pier): void {
const m = pier.model;
const wrap = el('div', undefined, 'bearing-ref');
wrap.appendChild(el('p', '교량받침 ELEVATION TABLE (도면값 · 읽기 전용, mm · EL m)', 'lbl'));
wrap.appendChild(el('p', '도면값은 모델에 쓰지 않습니다(Q16). 아래 "차이"는 도면과 모델의 코핑 상면 차이입니다.', 'muted small'));
const front = m?.segments ?? [];
const backBlocks = m?.blocks.filter((b) => b.row === '후열') ?? [];
const et = el('table', undefined, 'grid-table rebar-table');
const eh = el('thead');
const ehr = el('tr');
for (const h of ['No', '열', 'EL.X', 'E', 'A', 'B', 'C1', 'S1', '도면 상면 (EL.X − E)', '모델 코핑 상면', '차이 (m)']) ehr.appendChild(el('th', h));
eh.appendChild(ehr);
et.appendChild(eh);
const eb = el('tbody');
for (const r of BEARING_ELEVATION_REF) {
const drawingTop = r.elx - r.E / 1000;
const modelTop = r.row === '전열' ? front[r.no - 1]?.top : backBlocks[r.no - 6]?.bottom;
const diff = modelTop === undefined ? NaN : modelTop - drawingTop;
eb.appendChild(el('tr')).append(
el('td', String(r.no)), el('td', r.row), el('td', r.elx.toFixed(3)), el('td', String(r.E)),
el('td', String(r.A)), el('td', String(r.B)), el('td', String(r.C1)), el('td', String(r.S1)),
el('td', drawingTop.toFixed(3)), el('td', modelTop === undefined ? '—' : modelTop.toFixed(3)),
el('td', Number.isNaN(diff) ? '—' : diff.toFixed(3)),
);
}
et.appendChild(eb);
wrap.appendChild(el('div', undefined, 'table-scroll')).appendChild(et);
wrap.appendChild(el('p', '솔플레이트 TABLE (도면값, mm)', 'lbl'));
const st = el('table', undefined, 'grid-table rebar-table');
const sh = el('thead');
const shr = el('tr');
for (const h of ['No', 'S (%)', 'L', 'W', 'T', 'T1', 'T2', '식 검산']) shr.appendChild(el('th', h));
sh.appendChild(shr);
st.appendChild(sh);
const sb = el('tbody');
for (const r of SOLPLATE_REF) {
const calc = solplateTs(SOLPLATE_T_RULE, r.L, r.s);
const ok = calc.T1 === r.T1 && calc.T2 === r.T2;
sb.appendChild(el('tr')).append(
el('td', String(r.no)), el('td', r.s.toFixed(3)), el('td', String(r.L)), el('td', String(r.W)),
el('td', String(r.T)), el('td', String(r.T1)), el('td', String(r.T2)), el('td', ok ? '일치' : `식 ${calc.T1} / ${calc.T2}`),
);
}
st.appendChild(sb);
wrap.appendChild(el('div', undefined, 'table-scroll')).appendChild(st);
box.appendChild(wrap);
}
/** ② 코핑 상세 (2단계, 읽기 전용): d_IP2 and the 계단 구간 표 from the model (승인 2026-10-23). */
function renderCopingInfo(box: HTMLDivElement, pier: Pier): void {
const m = pier.model;
@@ -1321,6 +1372,7 @@ function renderPlan(): void {
fieldRows(fields, pier, member.keys);
if (member.id === 'footing') renderPileRows(fields, pier);
if (member.id === 'coping') renderCopingInfo(fields, pier);
if (member.id === 'bearing') renderBearingRef(fields, pier);
if (FCK_MEMBERS.includes(member.id as FckMember)) renderMemberFck(fields, member.id as FckMember);
regen.textContent = `다시 생성 · 변경 ${pendingKeys(pier).length}`;
regen.disabled = pendingKeys(pier).length === 0;