feat(abut-rebar): ③ 교대 저판 3D 철근 (B1–B10)

- 배근 결과(abutFootingRebar)로 저판 철근을 교대 좌표에 그림: B1 ⊓ · B2 ⊔ · B3 · B4, B5 ⊓ · B6 ⊔ · B7 · B8, B9, B10-1 · B10-2, 옵션 ② B1-S · B2-S
- 교대 선택 시 ③ 철근(rebar3d)으로 사용: 철근표 · 삽도 선택, 선택만 보기, 색 기준, 3D 클릭 선택 공통
- 교각 rebar3d의 강조 · 색 · 범례를 rebarControls로 공용화
- 테스트: 철근표 개수 = 3D 개수, 모든 철근이 저판 안 (skew · 교대축 직각)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-11-04 16:01:56 +09:00
1 parent d7714f7ef2
commit 8361487b6b
4 files changed
+188 -4

No files matched your search

+15 -2
View File
@@ -70,6 +70,7 @@ import { pileGeometry } from './core/geometry';
import { rebarSummary, type RebarRow } from './core/rebar/summary';
import { shearSegments } from './core/rebar/coping';
import { buildRebar3D, type RebarColorMode, type RebarScene } from './view/rebar3d';
import { buildAbutFootingRebar3D } from './view/abut-rebar3d';
import { DEFAULT_MATERIAL, FCK_MEMBERS, fckChanged, fyOf, GRADE_CHOICES, IMPORTED_FCK, isAssumedMaterial, materialFor, 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 { groundElFor, parseGroundModel, strataRowsFor, type GroundMapLayer, type GroundModelFile } from './core/ground-model';
@@ -676,6 +677,17 @@ function setupScene(): void {
state.scene = scene;
setView(state.view);
}
// ③ 교대 (2026-11-04): with the piers hidden, the selected abutment's 저판 rebar is the ③ rebar (표 · 3D 선택 공통).
const abutRec = piersShown(state.stage, state.abutActive) ? undefined : state.abutments.find((a) => a.name === state.abutActive);
const abutGroup = abutRec ? abutGroupByName.get(abutRec.name) : undefined;
const footing = abutRec ? abutFootingBuilt(abutRec) : null;
if (abutGroup && footing && footing.bottomEl !== undefined) {
rebar3d = buildAbutFootingRebar3D(footing.geom, footing.result, footing.skewK, footing.backM, footing.bottomEl);
rebar3d.group.applyMatrix4(abutGroup.matrix);
rebar3d.group.visible = state.stage === 'rebar';
rebar3d.setColorMode(state.rebarColor);
world.add(rebar3d.group);
}
}
// --- main list (시안 ① 교각 목록) ----------------------------------------------------
@@ -3093,13 +3105,13 @@ const ABUT_REBAR_MEMBERS: { id: AbutRebarMemberId; label: string; marks: string;
];
/** The 저판 rebar of an abutment (null when the abutment does not build). */
function abutFootingBuilt(rec: AbutRecord): { geom: AbutFootingGeom; result: AbutFootingRebar; skewK: number } | null {
function abutFootingBuilt(rec: AbutRecord): { geom: AbutFootingGeom; result: AbutFootingRebar; skewK: number; backM: number; bottomEl: number | undefined } | null {
try {
const model = buildAbut(toAbutInput(rec));
const members = buildMembers(model, { bottomEl: rec.foundationBottomEl, pileLengthMm: rec.pileLengthMm }, rec.shape);
const geom = abutFootingGeom(model.length, members.shape, skewAngle(rec.skewDeg));
const result = abutFootingRebar(geom, rec.rebar?.footing, materialFor(state.material, state.fckByMember, 'abutFooting'), rec.name);
return { geom, result, skewK: abutSkewK(model) };
return { geom, result, skewK: abutSkewK(model), backM: members.shape.footingBackM, bottomEl: members.footingBottomEl };
} catch {
return null;
}
@@ -3151,6 +3163,7 @@ function renderAbutRebar(rec: AbutRecord): void {
}
if (issues.childElementCount === 0) issues.appendChild(el('li', '알림이 없습니다.'));
$('step3-status').textContent = `${rec.name} 확대기초 계산됨 · 경고 ${warn}`;
rebar3d?.show(state.rebarSelection.size ? state.rebarSelection : null, state.rebarIsolate);
}
/** ③ 교대 확대기초 카드 (시안, 교대확대기초철근.md §10): 보기 탭 · 삽도 → 범례 → 기본간격 · 배근 방향 · 입력 → 자동 값 → 철근표 → 근거. */