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

+22 -4
View File
@@ -3,6 +3,7 @@ import type { PierModel } from '../core/geometry';
import { solplateGeometry } from '../core/solplate';
import type { TerrainGrid } from '../core/ground-model';
import { terrainGeometry } from './terrain';
import { INTEGRATED_BLOCK } from '../core/integrated-block';
export type PartName = 'coping' | 'columns' | 'footings' | 'piles' | 'blinding' | 'blocks' | 'pads' | 'bearings' | 'solplates' | 'ground';
@@ -131,14 +132,18 @@ export function buildPierScene(m: PierModel, terrain?: TerrainGrid): PierScene {
add('piles', g, 1, p.k, planesOf(m, p.k));
}
// 일체 (승인 2026-10-26): the per-bearing concrete blocks give way to one stepped block per pair (below).
const integrated = m.integratedBlocks.length > 0;
for (const b of m.blocks) {
// Turn the block so its sides follow the bearing row (rowSkewDeg); the 3D turn is rotateY(−skew).
const turn = (-b.rowSkewDeg * Math.PI) / 180;
const h = b.top - b.bottom;
const g = new THREE.BoxGeometry(1.2, h, 1.2);
g.rotateY(turn);
g.translate(b.s, b.bottom + h / 2, b.n);
add('blocks', g, 1, b.k);
if (!integrated) {
const g = new THREE.BoxGeometry(1.2, h, 1.2);
g.rotateY(turn);
g.translate(b.s, b.bottom + h / 2, b.n);
add('blocks', g, 1, b.k);
}
const pad = new THREE.BoxGeometry(1.0, 0.05, 1.0);
pad.rotateY(turn);
pad.translate(b.s, b.padTop - 0.025, b.n);
@@ -155,6 +160,19 @@ export function buildPierScene(m: PierModel, terrain?: TerrainGrid): PierScene {
}
}
for (const ib of m.integratedBlocks) {
const k = m.blocks.find((b) => b.no === ib.frontNo && b.row === '전열')!.k;
const turn = (-ib.rowSkewDeg * Math.PI) / 180;
// Two halves of 1250 across the 교축, each to its own top: the front half (lower n) and the back half.
for (const [top, zc] of [[ib.topFront, ib.n - INTEGRATED_BLOCK.length / 4000], [ib.topBack, ib.n + INTEGRATED_BLOCK.length / 4000]] as const) {
const h = top - ib.bottom;
const g = new THREE.BoxGeometry(INTEGRATED_BLOCK.depth / 1000, h, INTEGRATED_BLOCK.length / 2000);
g.rotateY(turn);
g.translate(ib.s, ib.bottom + h / 2, zc);
add('blocks', g, 1, k);
}
}
// Ground: the terrain grid around the piers when the ground model has one (수 m 떨어진 지형까지 보임),
// otherwise a translucent plane at the ground EL, used only to judge soil cover (not a computed input).
if (terrain) {