- integrated-block.ts: per pair (전열 k · 후열 k) one block centred on the pair midpoint, 2500 across the 교축 and 1200 along the 교각축, with a stepped top (each half to its own bearing row top). Only when 일체 is chosen and every pair is within 100 mm; otherwise 분리 is kept (B02). - Rebar: S2 19 bars at 125 across the 2500 (10 front half, 9 back half), each leg from its half's top; S1 8 bars across the 1200, 3800 long, depth from the lower top. Totals per pier: S1 40, S2 95 (분리: 80 / 80). - Scene and 3D rebar draw the stepped blocks instead of the per-bearing blocks. - The per-bearing blocks stay for the solplate, the pads, and the body. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
84 lines
4.0 KiB
TypeScript
84 lines
4.0 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
||
import { buildPier, type BlockModel } from '../src/core/geometry';
|
||
import { buildIntegratedBlocks, INTEGRATED_BLOCK } from '../src/core/integrated-block';
|
||
import { bearingBlockRebar, integratedBlockBars, totals } from '../src/core/rebar/bearing-block';
|
||
import { loadP1 } from './helpers';
|
||
|
||
const input = { ...loadP1(), bearingLayout: '일체' as const };
|
||
const model = buildPier(input);
|
||
|
||
describe('일체 블록 모델 (승인 2026-10-26)', () => {
|
||
it('P1 with 일체: one stepped block per pair (5), 2500 along the 교축 and 1200 along the 교각축', () => {
|
||
expect(model.integratedBlocks).toHaveLength(5);
|
||
expect(INTEGRATED_BLOCK).toEqual({ length: 2500, depth: 1200 });
|
||
const first = model.integratedBlocks[0];
|
||
expect(first.frontNo).toBe(1);
|
||
expect(first.backNo).toBe(6);
|
||
});
|
||
|
||
it('the block is centred on the pair midpoint, and its two halves keep their own tops (단이 있는 블록)', () => {
|
||
const ib = model.integratedBlocks[0];
|
||
const f = model.blocks.find((b) => b.no === 1)!;
|
||
const b = model.blocks.find((x) => x.no === 6)!;
|
||
expect(ib.n).toBeCloseTo((f.n + b.n) / 2, 9);
|
||
expect(ib.s).toBeCloseTo((f.s + b.s) / 2, 9);
|
||
expect(ib.topFront).toBe(f.top);
|
||
expect(ib.topBack).toBe(b.top);
|
||
// the front and back tops differ on P1 (150 vs 200 mm), so the block is stepped
|
||
expect(Math.abs(ib.topFront - ib.topBack)).toBeGreaterThan(0.01);
|
||
});
|
||
|
||
it('the 2500 block covers the pair: the front and back bearings sit 600 mm inside each end (C1 600)', () => {
|
||
const ib = model.integratedBlocks[0];
|
||
const f = model.blocks.find((b) => b.no === 1)!;
|
||
const b = model.blocks.find((x) => x.no === 6)!;
|
||
const half = INTEGRATED_BLOCK.length / 2000;
|
||
expect(ib.n - half).toBeCloseTo(f.n - 0.6, 2);
|
||
expect(ib.n + half).toBeCloseTo(b.n + 0.6, 2);
|
||
});
|
||
|
||
it('분리 keeps no integrated blocks', () => {
|
||
expect(buildPier(loadP1()).integratedBlocks).toEqual([]);
|
||
});
|
||
|
||
it('a staggered pair blocks 일체: no integrated blocks, the model stays 분리', () => {
|
||
const blocks = [{ no: 1, row: '전열', s: 1, n: -0.7, top: 0.5, bottom: 0, rowSkewDeg: 0 }, { no: 1, row: '후열', s: 1.2, n: 0.6, top: 0.5, bottom: 0, rowSkewDeg: 0 }] as unknown as BlockModel[];
|
||
expect(buildIntegratedBlocks(blocks, true)).toEqual([]);
|
||
});
|
||
});
|
||
|
||
describe('일체 블록 철근 (승인 2026-10-26, 받침블럭철근.md 일체 a 2500)', () => {
|
||
it('S2: 19 bars across the 2500 length, 10 on the front half and 9 on the back half (the centre bar on the front)', () => {
|
||
const rows = integratedBlockBars(model.integratedBlocks[0]).filter((r) => r.name === 'S2');
|
||
expect(rows.reduce((s, r) => s + r.count, 0)).toBe(19);
|
||
expect(rows.map((r) => r.count)).toEqual([10, 9]);
|
||
expect(rows[0].length).toBe(2500);
|
||
});
|
||
|
||
it('S1: 8 bars across the 1200 depth, 3800 long (2500 − 100 + 2 × 700)', () => {
|
||
const s1 = integratedBlockBars(model.integratedBlocks[0]).find((r) => r.name === 'S1')!;
|
||
expect(s1.count).toBe(8);
|
||
expect(s1.length).toBe(3800);
|
||
});
|
||
|
||
it('a pier of five integrated blocks has S1 40 and S2 95 (per-bearing 분리 gives 80 and 80)', () => {
|
||
const t = totals(bearingBlockRebar(model));
|
||
expect(t).toEqual({ S1: 40, S2: 95 });
|
||
const sep = totals(bearingBlockRebar(buildPier(loadP1())));
|
||
expect(sep).toEqual({ S1: 80, S2: 80 });
|
||
});
|
||
});
|
||
|
||
describe('일체 블록 3D 철근과 장면', () => {
|
||
it('the 3D rebar and the scene build for a 일체 pier, with the S2 bars counted per pair (19 each)', async () => {
|
||
const { buildRebar3D } = await import('../src/view/rebar3d');
|
||
const { buildPierScene } = await import('../src/view/scene');
|
||
const rb = buildRebar3D(model);
|
||
expect(rb.group.children.length).toBeGreaterThan(0);
|
||
const scene = buildPierScene(model, undefined);
|
||
// the blocks group holds the stepped halves (2 per pair) and no per-bearing blocks
|
||
expect(scene.parts.blocks.children.length).toBeGreaterThan(0);
|
||
expect(scene.parts.blocks.children.length).toBe(model.integratedBlocks.length * 2);
|
||
});
|
||
});
|