feat(rebar): coping front view and 단면·폐합 section from the 3D bar records (승인 2026-10-26)
- rebar3d records every bar (name, stretch, local points, diameter) next to its mesh, so the 2D drawings use the same data as the 3D view. - view/coping-rebar-svg.ts: the 정면 (along the coping length, EL vertical) and the 단면·폐합 at a chosen station (the bars crossing it, C9–C11 loops included). - ③ coping tab: 정면 / 단면·폐합 toggle and the station input. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
32e8dad7dc
commit
57f7c148ec
4 files changed
+157
-1
No files matched your search
+14
-1
@@ -17,9 +17,19 @@ import { stretchMatrix } from './scene';
|
||||
* named by its 철근표 number (C1, P3, B5, S2 …), so the table and the model can point at each other.
|
||||
* Local frame: x = along the axis s, y = absolute EL (m), z = across n. Stretch matrices map it to the scene.
|
||||
*/
|
||||
/** One bar in the local frame (x = along s, y = EL, z = across n), before the stretch matrix. For the 정면 projection (승인 2026-10-26). */
|
||||
export interface BarRecord {
|
||||
name: string;
|
||||
k: number;
|
||||
pts: [number, number, number][];
|
||||
dMm: number;
|
||||
}
|
||||
|
||||
export interface RebarScene {
|
||||
group: THREE.Group;
|
||||
byName: Map<string, THREE.Mesh[]>;
|
||||
/** Every bar as recorded (same data as the meshes). */
|
||||
records: BarRecord[];
|
||||
/** Highlight one bar name (or none): the others are dimmed. */
|
||||
/** Emphasise the bars in `names` (all when null). The others are dimmed, or hidden when `isolate` is on (선택만 보기). */
|
||||
show(names: ReadonlySet<string> | null, isolate: boolean): void;
|
||||
@@ -60,6 +70,7 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
const mColumn = materialFor(common, byMember, 'column');
|
||||
const group = new THREE.Group();
|
||||
const byName = new Map<string, THREE.Mesh[]>();
|
||||
const records: BarRecord[] = [];
|
||||
const Ms = m.stretches.map((_, k) => stretchMatrix(m, k));
|
||||
const L = m.copingL;
|
||||
const B = m.copingB;
|
||||
@@ -71,6 +82,7 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
*/
|
||||
const addPath = (name: string, k: number, pts: [number, number, number][], dMm: number, color: number) => {
|
||||
if (pts.length < 2) return;
|
||||
records.push({ name, k, pts: pts.map((p) => [...p] as [number, number, number]), dMm });
|
||||
const R = mm(bendRadius(dMm, common.bend));
|
||||
const pv = pts.map((p) => new THREE.Vector3(p[0], p[1], p[2]));
|
||||
const path = new THREE.CurvePath<THREE.Vector3>();
|
||||
@@ -110,6 +122,7 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
};
|
||||
|
||||
const addBar = (name: string, k: number, a: [number, number, number], b: [number, number, number], dMm: number, color: number) => {
|
||||
records.push({ name, k, pts: [[...a], [...b]], dMm });
|
||||
const dir = new THREE.Vector3(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
||||
const len = dir.length();
|
||||
if (len < 1e-6) return;
|
||||
@@ -564,5 +577,5 @@ export function buildRebar3D(m: PierModel, common: Material = DEFAULT_MATERIAL,
|
||||
const items = DIAMETER_GROUPS.map((g, i) => ({ label: g.label, color: hex(DIAMETER_COLORS[i]) })).filter((_, i) => present.has(i));
|
||||
return present.has(-1) ? [...items, { label: '기타', color: hex(OTHER_COLOR) }] : items;
|
||||
};
|
||||
return { group, byName, show, setColorMode, legend };
|
||||
return { group, byName, records, show, setColorMode, legend };
|
||||
}
|
||||
Reference in new issue
Block a user