fix(rebar): pass the ③ material to C15/C16, coping bottom and column bars
The stair bars in the 철근표 and the 3D model, and the 3D bottom and column bars, were built with the default fck, so a changed fck did not reach them. buildRebar3D now takes the material, and a material change rebuilds the scene. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b35f5ff0ed
commit
d8fd6adcf0
4 files changed
+25
-7
No files matched your search
@@ -182,7 +182,7 @@ export function rebarSummary(model: PierModel, m: Material = DEFAULT_MATERIAL):
|
|||||||
const lineCount = (line: number) => c14.filter((b) => b.line === line).length;
|
const lineCount = (line: number) => c14.filter((b) => b.line === line).length;
|
||||||
const omitted = c14.filter((b) => !b.legs).length;
|
const omitted = c14.filter((b) => !b.legs).length;
|
||||||
rows.push({ member: 'coping', name: 'C14', size: 'H19', count: c14.length, length: c14Length(model.copingB * 1000), note: `위 2 줄 ${lineCount(1)} · ${lineCount(2)}본씩, 아래 ${[3, 4, 5, 6].map(lineCount).join(' · ')} (합 ${c14.length}) · 연직 발 생략 ${omitted}개 (하면 밖)` });
|
rows.push({ member: 'coping', name: 'C14', size: 'H19', count: c14.length, length: c14Length(model.copingB * 1000), note: `위 2 줄 ${lineCount(1)} · ${lineCount(2)}본씩, 아래 ${[3, 4, 5, 6].map(lineCount).join(' · ')} (합 ${c14.length}) · 연직 발 생략 ${omitted}개 (하면 밖)` });
|
||||||
const stairs = stairBars(model.copingL * 1000, model.copingB * 1000, model.copingRefTop);
|
const stairs = stairBars(model.copingL * 1000, model.copingB * 1000, model.copingRefTop, m);
|
||||||
rows.push({ member: 'coping', name: 'C15', size: 'H19', count: stairs.c15.length, length: stairs.c15[0].length, note: '계단부, 가장 높은 구간 (거꾸로 U)' });
|
rows.push({ member: 'coping', name: 'C15', size: 'H19', count: stairs.c15.length, length: stairs.c15[0].length, note: '계단부, 가장 높은 구간 (거꾸로 U)' });
|
||||||
rows.push({ member: 'coping', name: 'C16', size: 'H19', count: stairs.c16.length, length: stairs.c16[0].length, note: `계단부, 3·4구간 (${Math.round(stairs.c16[0].length)} / ${Math.round(stairs.c16[stairs.c16.length - 1].length)})` });
|
rows.push({ member: 'coping', name: 'C16', size: 'H19', count: stairs.c16.length, length: stairs.c16[0].length, note: `계단부, 3·4구간 (${Math.round(stairs.c16[0].length)} / ${Math.round(stairs.c16[stairs.c16.length - 1].length)})` });
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -225,7 +225,7 @@ function setupScene(): void {
|
|||||||
rebar3d = null;
|
rebar3d = null;
|
||||||
const pier = activePier();
|
const pier = activePier();
|
||||||
if (pier?.model) {
|
if (pier?.model) {
|
||||||
rebar3d = buildRebar3D(pier.model);
|
rebar3d = buildRebar3D(pier.model, state.material);
|
||||||
rebar3d.group.visible = state.stage === 'rebar';
|
rebar3d.group.visible = state.stage === 'rebar';
|
||||||
world.add(rebar3d.group);
|
world.add(rebar3d.group);
|
||||||
const scene = buildPierScene(pier.model);
|
const scene = buildPierScene(pier.model);
|
||||||
@@ -926,6 +926,8 @@ function setMaterial(key: keyof Material, raw: string): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.material = { ...state.material, [key]: value };
|
state.material = { ...state.material, [key]: value };
|
||||||
|
// The 3D bars depend on the material too (their lengths), so the scene is rebuilt with it.
|
||||||
|
setupScene();
|
||||||
renderAll();
|
renderAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -5,7 +5,7 @@ import { bottomPiece, MAIN, widthLayout } from '../core/rebar/coping-main';
|
|||||||
import { C14_INSET, c14Bars, CAP, COPING_REBAR, shearBars, shearBarsMulti, shearUHeight, copingSideBars, SIDE_HOOK_LEG, stairBars, undersideAt } from '../core/rebar/coping';
|
import { C14_INSET, c14Bars, CAP, COPING_REBAR, shearBars, shearBarsMulti, shearUHeight, copingSideBars, SIDE_HOOK_LEG, stairBars, undersideAt } from '../core/rebar/coping';
|
||||||
import { columnRebar, COLUMN_P1 } from '../core/rebar/column';
|
import { columnRebar, COLUMN_P1 } from '../core/rebar/column';
|
||||||
import { barsAcross, BLOCK_REBAR } from '../core/rebar/bearing-block';
|
import { barsAcross, BLOCK_REBAR } from '../core/rebar/bearing-block';
|
||||||
import { hookLength, NOMINAL_DIAMETER } from '../core/rebar/common';
|
import { DEFAULT_MATERIAL, hookLength, Material, NOMINAL_DIAMETER } from '../core/rebar/common';
|
||||||
import { stretchMatrix } from './scene';
|
import { stretchMatrix } from './scene';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +34,7 @@ const COLOR = {
|
|||||||
|
|
||||||
const mm = (v: number) => v / 1000;
|
const mm = (v: number) => v / 1000;
|
||||||
|
|
||||||
export function buildRebar3D(m: PierModel): RebarScene {
|
export function buildRebar3D(m: PierModel, mat: Material = DEFAULT_MATERIAL): RebarScene {
|
||||||
const group = new THREE.Group();
|
const group = new THREE.Group();
|
||||||
const byName = new Map<string, THREE.Mesh[]>();
|
const byName = new Map<string, THREE.Mesh[]>();
|
||||||
const Ms = m.stretches.map((_, k) => stretchMatrix(m, k));
|
const Ms = m.stretches.map((_, k) => stretchMatrix(m, k));
|
||||||
@@ -87,7 +87,7 @@ export function buildRebar3D(m: PierModel): RebarScene {
|
|||||||
// at each end to the C1 level. Each bar is two pieces spliced at the column centre (overlap l_s). The slope runs x_L0 from each end (T형).
|
// at each end to the C1 level. Each bar is two pieces spliced at the column centre (overlap l_s). The slope runs x_L0 from each end (T형).
|
||||||
const xL0 = L / 2 - COPING_REBAR.levelWidth / 2000;
|
const xL0 = L / 2 - COPING_REBAR.levelWidth / 2000;
|
||||||
const under = (x: number) => undersideAt(L * 1000, x * 1000, m.endBottom, m.levelBottom);
|
const under = (x: number) => undersideAt(L * 1000, x * 1000, m.endBottom, m.levelBottom);
|
||||||
const lap = bottomPiece().ls / 2000;
|
const lap = bottomPiece(mat).ls / 2000;
|
||||||
xs.forEach((n, j) => {
|
xs.forEach((n, j) => {
|
||||||
const z = (x: number) => under(x) + 0.127;
|
const z = (x: number) => under(x) + 0.127;
|
||||||
const left: [number, number, number][] = [
|
const left: [number, number, number][] = [
|
||||||
@@ -166,7 +166,7 @@ export function buildRebar3D(m: PierModel): RebarScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// C15 (거꾸로 된 U) and C16 (L형) on the stair (코핑철근.md §7): 11 bars each across the width.
|
// C15 (거꾸로 된 U) and C16 (L형) on the stair (코핑철근.md §7): 11 bars each across the width.
|
||||||
const stairs = stairBars(L * 1000, B * 1000, topEl);
|
const stairs = stairBars(L * 1000, B * 1000, topEl, mat);
|
||||||
for (const s of stairs.c15) {
|
for (const s of stairs.c15) {
|
||||||
const n = mm(s.n);
|
const n = mm(s.n);
|
||||||
const ld = mm(s.leg);
|
const ld = mm(s.leg);
|
||||||
@@ -187,7 +187,7 @@ export function buildRebar3D(m: PierModel): RebarScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Columns: P1 / P2 main bars on their radii, ties P3 / P5 / P4 as rings, P6 crossties across the column.
|
// Columns: P1 / P2 main bars on their radii, ties P3 / P5 / P4 as rings, P6 crossties across the column.
|
||||||
const col = columnRebar(COLUMN_P1);
|
const col = columnRebar(COLUMN_P1, mat);
|
||||||
const zBot = col.zBot; // mm
|
const zBot = col.zBot; // mm
|
||||||
const ring = (name: string, k: number, sc: number, y: number, r: number, d: number) => {
|
const ring = (name: string, k: number, sc: number, y: number, r: number, d: number) => {
|
||||||
const N = 36;
|
const N = 36;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest';
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { buildPier } from '../src/core/geometry';
|
import { buildPier } from '../src/core/geometry';
|
||||||
import { buildRebar3D } from '../src/view/rebar3d';
|
import { buildRebar3D } from '../src/view/rebar3d';
|
||||||
|
import { DEFAULT_MATERIAL } from '../src/core/rebar/common';
|
||||||
import { loadP1 } from './helpers';
|
import { loadP1 } from './helpers';
|
||||||
|
|
||||||
const rb = buildRebar3D(buildPier(loadP1()));
|
const rb = buildRebar3D(buildPier(loadP1()));
|
||||||
@@ -103,3 +104,18 @@ describe('확대기초 B9 · B10 · B11 · B12 in 3D (확대기초철근 (1).md
|
|||||||
expect(rb.byName.get('B12')!.length).toBe(47 * 3);
|
expect(rb.byName.get('B12')!.length).toBe(47 * 3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('3D 철근 모델은 ③ 공통 설정 fck를 따른다', () => {
|
||||||
|
const model = buildPier(loadP1());
|
||||||
|
const height = (scene: ReturnType<typeof buildRebar3D>, name: string) => {
|
||||||
|
const b = new THREE.Box3();
|
||||||
|
for (const mesh of scene.byName.get(name)!) b.expandByObject(mesh);
|
||||||
|
return b.max.y - b.min.y;
|
||||||
|
};
|
||||||
|
|
||||||
|
it('C15 stair bars are shorter with a higher fck, as in the 철근표 (stepDevLength)', () => {
|
||||||
|
const base = height(buildRebar3D(model), 'C15');
|
||||||
|
const high = height(buildRebar3D(model, { ...DEFAULT_MATERIAL, fck: 35 }), 'C15');
|
||||||
|
expect(high).toBeLessThan(base - 0.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user