feat(bearing): 일체 block as one stepped block per pair, with its rebar (승인 2026-10-26)

- 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>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-26 12:02:33 +09:00
1 parent 2af5cfb144
commit 43a18182f3
7 files changed
+216 -6

No files matched your search

+29
View File
@@ -1,4 +1,5 @@
import type { PierModel } from '../geometry';
import { INTEGRATED_BLOCK, type IntegratedBlock } from '../integrated-block';
/**
* 받침블럭 철근 (spec §6.3 · plan C2), 배치 분리: one block per bearing, 1200 × 1200.
@@ -64,6 +65,10 @@ export interface BlockRebar {
* since the bar depths are measured from the block top. h1 / h2 include the 50 pad and would count it twice.
*/
export function bearingBlockRebar(model: PierModel): BlockRebar[] {
// 일체 (승인 2026-10-26): one block per pair replaces the two per-bearing blocks.
if (model.integratedBlocks.length > 0) {
return model.integratedBlocks.map((ib) => ({ no: ib.frontNo, row: '전열', bars: integratedBlockBars(ib) }));
}
return model.blocks.map((b) => ({
no: b.no,
row: b.row,
@@ -71,6 +76,30 @@ export function bearingBlockRebar(model: PierModel): BlockRebar[] {
}));
}
/**
* Rebar of one 일체 block (승인 2026-10-26, 받침블럭철근.md "일체 a 2500").
* S2 runs along the 교각축 (1200), so its bars are spaced across the 2500 length: 19 bars at 125. Its legs are measured
* from the top of the half it sits in; the bar at the step line (centre) counts with the front half.
* S1 runs along the 2500 length, 8 bars across the 1200 depth, its depth taken from the lower top (cover on the higher half is larger).
*/
export function integratedBlockBars(ib: IntegratedBlock): BarRow[] {
const half = INTEGRATED_BLOCK.length / 2;
const s2 = barsAcross(INTEGRATED_BLOCK.length);
const frontCount = Array.from({ length: s2.count }, (_, k) => s2.firstEnd + k * s2.spacing).filter((x) => x <= half + 1e-9).length;
const backCount = s2.count - frontCount;
const hFront = (ib.topFront - ib.bottom) * 1000;
const hBack = (ib.topBack - ib.bottom) * 1000;
const legS2 = (h: number) => BLOCK_REBAR.legLength - (h - BLOCK_REBAR.depthS2);
const s1 = barsAcross(INTEGRATED_BLOCK.depth);
const hLow = Math.min(hFront, hBack);
const rows: BarRow[] = [
{ name: 'S2', count: frontCount, spacing: s2.spacing, firstEnd: s2.firstEnd, length: barLength(INTEGRATED_BLOCK.depth), embedment: legS2(hFront) },
];
if (backCount > 0) rows.push({ name: 'S2', count: backCount, spacing: s2.spacing, firstEnd: s2.firstEnd, length: barLength(INTEGRATED_BLOCK.depth), embedment: legS2(hBack) });
rows.push({ name: 'S1', count: s1.count, spacing: s1.spacing, firstEnd: s1.firstEnd, length: barLength(INTEGRATED_BLOCK.length), embedment: BLOCK_REBAR.legLength - (hLow - BLOCK_REBAR.depthS1) });
return rows;
}
/** Total bars of one pier: bars per block × blocks, for S1 and S2 separately. */
export function totals(rebar: BlockRebar[]): { S1: number; S2: number } {
return rebar.reduce(