fix(abut-rebar): 날개벽 WR7-1 · 7-2 · 7-3 평면 형상 (긴 대각 + 양끝 갈고리 394)
- 사용자 도면(2026-11-05): 헌치 빗변과 나란한 대각이 안쪽 모서리를 c 떨어져 지나, 교대 쪽은 전면 − c (WR7-1 · 7-2 흉벽 전면, WR7-3 벽체 전면), 날개벽 쪽은 날개벽 바깥면 − c에서 끝남. 양끝 평면 90° 갈고리 394 (교대 안쪽 / 날개벽 끝 쪽) - WR7-3의 긴 대각이 더 낮은 이웃 계단의 교좌면 위로 나오는 단은 WR7-2로 (교좌면 계단을 날개벽 형상에 전달) - 테스트: 갈고리 394 · 끝점 · 대각 길이, WR7-1 · 7-2 끝, 우측 재분류, 콘크리트 안 검사 통과 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
89ebf852a9
commit
7b9de649e5
5 files changed
+86
-31
No files matched your search
@@ -37,7 +37,8 @@ const res: Record<string, { out: number; total: number }> = {};
|
||||
const span = slabSpanAt(abutPlanOutline(model, members, wings, slab).slab, tM, k)!;
|
||||
const pg = abutParapetGeom(wg, members.shape, model.bearings[0].s, { B: model.wing!.slabWidthMm, a: span.a, b: span.b, nearT: members.shape.parapetBackM * 1000 - slab.parapetGapMm, chamferA: 300, chamferB: 300 });
|
||||
const para = abutParapetRebar(pg, wall);
|
||||
const wingR = wings.map((w) => abutWingRebar(abutWingGeom(model, members, w, footing.z.B68)));
|
||||
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 group = buildAbutGroup(model, members, wings);
|
||||
group.updateMatrixWorld(true);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { abutFootingGeom, abutFootingRebar } from '../src/core/abut/rebar/footin
|
||||
import { skewAngle } from '../src/core/abut/rebar/skew-layout';
|
||||
import { abutWingGeom, abutWingRebar, wingLevelCount } from '../src/core/abut/rebar/wing';
|
||||
import { DEFAULT_MATERIAL } from '../src/core/rebar/common';
|
||||
import { abutSkewK } from '../src/view/abut-scene';
|
||||
|
||||
// 예제 A1 좌측 날개벽 (교대날개벽철근.md §11). 기획서 값은 fck 27 · 벽체 높이 2500 기준 (흉벽 상단 46.835 / 47.180).
|
||||
const RAG = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
|
||||
@@ -19,7 +20,8 @@ const members = buildMembers(model, { bottomEl: rec.foundationBottomEl, pileLeng
|
||||
const wings = buildWings(model, members);
|
||||
const footing = abutFootingRebar(abutFootingGeom(model.length, members.shape, skewAngle(rec.skewDeg)));
|
||||
const fck27 = { ...DEFAULT_MATERIAL, fck: 27 };
|
||||
const geomOf = (side: 'left' | 'right') => abutWingGeom(model, members, wings.find((w) => w.side === side)!, footing.z.B68);
|
||||
const seats = members.wallSegments.map((sg) => ({ from: sg.sFrom * 1000, to: sg.sTo * 1000, z: (sg.seatEl - members.footingBottomEl!) * 1000 }));
|
||||
const geomOf = (side: 'left' | 'right') => abutWingGeom(model, members, wings.find((w) => w.side === side)!, footing.z.B68, seats, abutSkewK(model));
|
||||
const left = geomOf('left');
|
||||
const L1 = abutWingRebar(left, undefined, fck27, 'A1');
|
||||
const bar = (r: typeof L1, mark: string) => r.bars.find((b) => b.mark === mark);
|
||||
@@ -137,3 +139,34 @@ describe('③ 날개벽 삽도', () => {
|
||||
for (const m of ['WR7', 'WR10', 'WR9']) expect(svg).toContain(`data-pick="${m}"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('WR7 평면 형상 (사용자 도면 2026-11-05)', () => {
|
||||
it('WR7-3: 벽체 전면 − c에서 교대 안쪽으로 갈고리 394 → 안쪽 모서리를 c 떨어져 지나는 긴 대각 → 날개벽 바깥면 − c에서 날개벽 쪽 갈고리 394', () => {
|
||||
const p = L1.paths.find((q) => q.mark === 'WR7-3')!;
|
||||
expect(p.pts.length).toBe(4);
|
||||
const [h, F, G, e] = p.pts;
|
||||
expect(F[1]).toBeCloseTo(left.wallFrontT - 100, 6);
|
||||
expect(h[1]).toBeCloseTo(F[1], 6); // 갈고리는 전면 선을 따라
|
||||
expect(Math.hypot(h[0] - F[0], h[1] - F[1])).toBeCloseTo(394, 6);
|
||||
// G는 날개벽 바깥면에서 c 안쪽.
|
||||
const [ws, wt] = left.w;
|
||||
const iw = left.inward[0] * ws + left.inward[1] * wt;
|
||||
const nv = [left.inward[0] - iw * ws, left.inward[1] - iw * wt];
|
||||
const T = Math.hypot(nv[0], nv[1]);
|
||||
const depth = ((G[0] - left.p0[0]) * nv[0] + (G[1] - left.p0[1]) * nv[1]) / T;
|
||||
expect(depth).toBeCloseTo(100, 6);
|
||||
expect(Math.hypot(e[0] - G[0], e[1] - G[1])).toBeCloseTo(394, 6);
|
||||
// 긴 대각: 벽체 두께를 가로지름 (3 m 이상).
|
||||
expect(Math.hypot(G[0] - F[0], G[1] - F[1])).toBeGreaterThan(3000);
|
||||
});
|
||||
|
||||
it('WR7-1 · 7-2는 흉벽 전면 − c에서 끝남', () => {
|
||||
for (const m of ['WR7-1', 'WR7-2']) expect(L1.paths.find((q) => q.mark === m)!.pts[1][1]).toBeCloseTo(-100, 6);
|
||||
});
|
||||
|
||||
it('우측: 긴 대각이 더 낮은 이웃 계단까지 가는 단은 WR7-3 대신 WR7-2 (교좌면 위로 나오지 않게)', () => {
|
||||
const R = abutWingRebar(geomOf('right'), undefined, fck27);
|
||||
const total = R.haunchLevels['WR7-1'] + R.haunchLevels['WR7-2'] + R.haunchLevels['WR7-3'];
|
||||
expect(R.haunchLevels['WR7-3']).toBeLessThan(total - R.haunchLevels['WR7-1'] - 6);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user