feat(abut-rebar): ③ 교대 접속슬래브 3D 철근 (R1–R8)

- 접속슬래브 배근 경로를 교대 3D 철근에 추가 (선택 · 색 기준 공통)
- 콘크리트 안 검사에 접속슬래브 포함: 모든 교대 철근 (P10 다웰 포함) 밖으로 나간 점 없음

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-11-05 09:27:52 +09:00
1 parent a282618d90
commit b75f3d4855
4 files changed
+29 -19

No files matched your search

+11 -12
View File
@@ -7,7 +7,8 @@ import { buildAbut } from '../src/core/abut/geometry';
import { parseAbutments, toAbutInput } from '../src/core/abut/parse';
import { buildMembers } from '../src/core/abut/members';
import { buildWings } from '../src/core/abut/wings';
import { resolveSlab } from '../src/core/abut/slab';
import { resolveSlab, slabGradePct, slabSection } from '../src/core/abut/slab';
import { abutSlabGeom, abutSlabRebar } from '../src/core/abut/rebar/slab';
import { abutFootingGeom, abutFootingRebar } from '../src/core/abut/rebar/footing';
import { skewAngle } from '../src/core/abut/rebar/skew-layout';
import { abutWallGeom, abutWallRebar } from '../src/core/abut/rebar/wall';
@@ -39,12 +40,14 @@ const res: Record<string, { out: number; total: number }> = {};
const para = abutParapetRebar(pg, wall);
const seats = members.wallSegments.map((sg) => ({ from: sg.sFrom * 1000, to: sg.sTo * 1000, z: (sg.seatEl - members.footingBottomEl!) * 1000 }));
const wingR = wings.map((w) => abutWingRebar(abutWingGeom(model, members, w, footing.z.B68, seats, k)));
const rebar = buildAbutRebar3D(fg, footing, k, members.shape.footingBackM, members.footingBottomEl!, wall, para, wingR);
const grade = slabGradePct(slab, model.wing?.slopePct ?? 0);
const slabG = abutSlabGeom(slab.form, abutPlanOutline(model, members, wings, slab).slab, slabSection(slab, grade, members.shape), { startEl: members.parapetTopStartEl, endEl: members.parapetTopEndEl, L: model.length, bottomEl: members.footingBottomEl! }, [300, 300], slab.lengthMm, grade);
const rebar = buildAbutRebar3D(fg, footing, k, members.shape.footingBackM, members.footingBottomEl!, wall, para, wingR, abutSlabRebar(slabG));
const group = buildAbutGroup(model, members, wings);
group.updateMatrixWorld(true);
const solids: THREE.Mesh[] = [];
group.traverse((o) => {
if (o instanceof THREE.Mesh && !['ground', 'slab', 'blinding', 'piles'].some((n) => o.parent?.name === n || o.name === n)) solids.push(o);
if (o instanceof THREE.Mesh && !['ground', 'blinding', 'piles'].some((n) => o.parent?.name === n || o.name === n)) solids.push(o);
});
const ray = new THREE.Raycaster();
const inside = (p: THREE.Vector3) =>
@@ -74,15 +77,11 @@ const res: Record<string, { out: number; total: number }> = {};
}
}
describe('교대 A1 3D 철근이 콘크리트 안에 있음', () => {
it('저판 · 벽체 · 흉벽 · 날개벽 철근은 밖으로 나간 점이 없음 (P10 제외)', () => {
const outside = Object.entries(res).filter(([name, v]) => name !== 'P10' && v.out > 0).map(([name, v]) => `${name} ${v.out}/${v.total}`);
describe('교대 A1 3D 철근이 콘크리트 안에 있음 (접속슬래브 포함)', () => {
it('저판 · 벽체 · 흉벽 · 날개벽 · 접속슬래브 철근과 P10 다웰 모두 밖으로 나간 점이 없음', () => {
const outside = Object.entries(res).filter(([, v]) => v.out > 0).map(([name, v]) => `${name} ${v.out}/${v.total}`);
expect(outside).toEqual([]);
expect(Object.keys(res).length).toBeGreaterThan(30);
});
it('P10 다웰: 슬래브 쪽 절반만 밖 (브라켓 안 300은 콘크리트 안)', () => {
expect(res.P10.out / res.P10.total).toBeLessThan(0.6);
expect(res.P10.out / res.P10.total).toBeGreaterThan(0.4);
expect(Object.keys(res).length).toBeGreaterThan(36);
for (const m of ['R1', 'R2', 'R3', 'R4', 'R7', 'R8', 'P10']) expect(res[m]?.total, m).toBeGreaterThan(0);
});
});