feat(view): solplate taper across the 교각축 직각 (thick T1 at the (−) side); 교량받침 본체 as a box
The solplate's L (A + margin) runs across the 교각축 직각 and its W (B + margin) along the 교축; the top tapers across L with T1 at the (−) side (T1 = T + L·|S|/200). The 교량받침 본체 is one box per bearing: the solplate plan less 100 mm on each side, from the mortar top (EL.X) up h3 = 181 mm, turned with the bearing row. It is shown with the bearing group. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a108a76707
commit
22fd1dc5f4
4 files changed
+36
-17
No files matched your search
+15
-14
@@ -1,12 +1,13 @@
|
||||
/**
|
||||
* 솔플레이트 기하 (1단계, 승인 2026-10-23). Pure: the solplate of one bearing, from its block (position, rowSkew) and the
|
||||
* 공통 규칙 values. The solplate sits on the bearing (h3) and tapers along the 교축 방향 (s): the thick end T1 is on the
|
||||
* 시점 side (s = −L/2), the thin end T2 on the 종점 side (s = +L/2). Lengths in m, as in the model.
|
||||
* 솔플레이트 기하 (승인 2026-10-23). Pure: the solplate of one bearing, from its block (position, rowSkew) and the
|
||||
* 공통 규칙 values. The plan is L = A + margin across the 교각축 직각 (n) and W = B + margin along the 교축 (s). The top
|
||||
* tapers across L: the thick end T1 is at the (−) side of the 교각축 직각 direction (n = −L/2), the thin end T2 at (+) (n = +L/2).
|
||||
* The underside is the bearing top (block top EL.X + h3). Lengths in m, as in the model.
|
||||
*/
|
||||
import { blockFramePoint, type BlockModel } from './geometry';
|
||||
|
||||
export interface SolplateParams {
|
||||
/** 받침 평면 A (mm, along 교축 s) and B (mm, along the 교각축 직각 n). */
|
||||
/** 받침 평면 A (mm, across the 교각축 직각) and B (mm, along the 교축). */
|
||||
A: number;
|
||||
B: number;
|
||||
/** 솔플 여유 (mm): L = A + margin, W = B + margin. */
|
||||
@@ -18,15 +19,15 @@ export interface SolplateParams {
|
||||
}
|
||||
|
||||
export interface SolplateGeometry {
|
||||
/** Length along 교축 (m) and width along 교각축 직각 (m). */
|
||||
/** Length across the 교각축 직각 (m, = A + margin) and width along the 교축 (m, = B + margin). */
|
||||
L: number;
|
||||
W: number;
|
||||
/** Thickness at the 시점 end (T1) and the 종점 end (T2) (m). */
|
||||
/** Thickness at the (−) side (T1) and the (+) side (T2) of the 교각축 직각 direction (m). */
|
||||
T1: number;
|
||||
T2: number;
|
||||
/** Underside (EL m): the bearing top = block top (EL.X) + h3. */
|
||||
bottom: number;
|
||||
/** Eight corners: [s, y, n] in the model's local frame (EL m). */
|
||||
/** Eight corners: [s, y, n] in the model's local frame (EL m); order (a, c, bottom|top) with a along s and c along n. */
|
||||
corners: [number, number, number][];
|
||||
/** Volume (m³): L·W·(T1 + T2)/2. */
|
||||
volume: number;
|
||||
@@ -34,21 +35,21 @@ export interface SolplateGeometry {
|
||||
|
||||
/** Solplate of the bearing at `block`, with the bearing height h3 (mm) and the 공통 규칙 parameters. */
|
||||
export function solplateGeometry(block: BlockModel, h3: number, p: SolplateParams): SolplateGeometry {
|
||||
const L = (p.A + p.margin) / 1000;
|
||||
const W = (p.B + p.margin) / 1000;
|
||||
// Thickness change from the centre to each end: L·|S|/2, with S in % (mm).
|
||||
const L = (p.A + p.margin) / 1000; // across the 교각축 직각 (n)
|
||||
const W = (p.B + p.margin) / 1000; // along the 교축 (s)
|
||||
// Thickness change from the centre to each side: L·|S|/2, with S in % (mm).
|
||||
const drop = ((p.A + p.margin) * Math.abs(p.slopePct)) / 200 / 1000;
|
||||
const T = p.T / 1000;
|
||||
const T1 = T + drop;
|
||||
const T2 = T - drop;
|
||||
const bottom = block.padTop + h3 / 1000;
|
||||
const thickAt = (a: number) => T1 + ((T2 - T1) * (a + L / 2)) / L;
|
||||
const thickAt = (c: number) => T1 + ((T2 - T1) * (c + L / 2)) / L;
|
||||
const corners: [number, number, number][] = [];
|
||||
for (const a of [-L / 2, L / 2]) {
|
||||
for (const c of [-W / 2, W / 2]) {
|
||||
for (const a of [-W / 2, W / 2]) {
|
||||
for (const c of [-L / 2, L / 2]) {
|
||||
const [s, n] = blockFramePoint(block, a, c);
|
||||
corners.push([s, bottom, n]);
|
||||
corners.push([s, bottom + thickAt(a), n]);
|
||||
corners.push([s, bottom + thickAt(c), n]);
|
||||
}
|
||||
}
|
||||
return { L, W, T1, T2, bottom, corners, volume: (L * W * (T1 + T2)) / 2 };
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ interface Pier extends PierValues {
|
||||
type Stage = 'shape' | 'plan' | 'rebar' | 'quantity';
|
||||
|
||||
const PART_GROUPS: { label: string; parts: PartName[] }[] = [
|
||||
{ label: '받침·받침블럭', parts: ['blocks', 'pads'] },
|
||||
{ label: '받침·받침블럭', parts: ['blocks', 'pads', 'bearings'] },
|
||||
{ label: '솔플레이트', parts: ['solplates'] },
|
||||
{ label: '코핑', parts: ['coping'] },
|
||||
{ label: '기둥', parts: ['columns'] },
|
||||
|
||||
+9
-2
@@ -2,7 +2,7 @@ import * as THREE from 'three';
|
||||
import type { PierModel } from '../core/geometry';
|
||||
import { solplateGeometry } from '../core/solplate';
|
||||
|
||||
export type PartName = 'coping' | 'columns' | 'footings' | 'piles' | 'blinding' | 'blocks' | 'pads' | 'solplates' | 'ground';
|
||||
export type PartName = 'coping' | 'columns' | 'footings' | 'piles' | 'blinding' | 'blocks' | 'pads' | 'bearings' | 'solplates' | 'ground';
|
||||
|
||||
export const PART_LABELS: Record<PartName, string> = {
|
||||
coping: '코핑',
|
||||
@@ -12,6 +12,7 @@ export const PART_LABELS: Record<PartName, string> = {
|
||||
blinding: '버림콘크리트',
|
||||
blocks: '받침블럭',
|
||||
pads: '모르타르 패드',
|
||||
bearings: '교량받침 본체',
|
||||
solplates: '솔플레이트',
|
||||
ground: '지반',
|
||||
};
|
||||
@@ -24,6 +25,7 @@ const COLORS: Record<PartName, number> = {
|
||||
blinding: 0xe6e2d8,
|
||||
blocks: 0xd6dde5,
|
||||
pads: 0x8898aa,
|
||||
bearings: 0x5b6676,
|
||||
solplates: 0x6f7c8a,
|
||||
ground: 0x6b8f4e,
|
||||
};
|
||||
@@ -140,7 +142,12 @@ export function buildPierScene(m: PierModel): PierScene {
|
||||
pad.translate(b.s, b.padTop - 0.025, b.n);
|
||||
add('pads', pad, 1, b.k);
|
||||
if (b.plan) {
|
||||
// Solplate: a wedge that tapers along the 교축 (T1 on the 시점 side), on the bearing (승인 2026-10-23).
|
||||
// 교량받침 본체 (승인 2026-10-23): the solplate plan less 100 mm on each side, from the mortar top up to the solplate.
|
||||
const body = new THREE.BoxGeometry((b.plan.B + b.plan.margin) / 1000 - 0.2, b.plan.h3 / 1000, (b.plan.A + b.plan.margin) / 1000 - 0.2);
|
||||
body.rotateY(turn);
|
||||
body.translate(b.s, b.padTop + b.plan.h3 / 2000, b.n);
|
||||
add('bearings', body, 1, b.k);
|
||||
// Solplate: a wedge that tapers across the 교각축 직각 (T1 at the (−) side), on the bearing (승인 2026-10-23).
|
||||
const sp = solplateGeometry(b, b.plan.h3, { A: b.plan.A, B: b.plan.B, margin: b.plan.margin, T: b.plan.T, slopePct: b.plan.S });
|
||||
add('solplates', wedgeGeometry(sp.corners), 1, b.k);
|
||||
}
|
||||
|
||||
@@ -31,4 +31,15 @@ describe('솔플레이트 모델과 3D (2단계, 승인 2026-10-23)', () => {
|
||||
const scene = buildPierScene(buildPier(loadP1()));
|
||||
expect(scene.parts.solplates.children.length).toBe(0);
|
||||
});
|
||||
|
||||
it('the 교량받침 본체 is one box per bearing: the solplate plan less 100 mm on each side, height h3 (181 mm)', () => {
|
||||
const m = buildPier({ ...loadP1(), bearingPlans: plans, solplate: { T: 30, margin: 100, h3: 181 } });
|
||||
const scene = buildPierScene(m);
|
||||
const bodies = scene.parts.bearings.children;
|
||||
expect(bodies.length).toBe(10);
|
||||
const one = new THREE.Box3().setFromObject(bodies[0]);
|
||||
expect(one.max.y - one.min.y).toBeCloseTo(0.181, 3);
|
||||
// Body 1: L = 800 − 200 = 600 across the 교각축 직각, W = 740 − 200 = 540 along the 교축; the row skew turns it a few degrees.
|
||||
expect(Math.max(one.max.x - one.min.x, one.max.z - one.min.z)).toBeGreaterThan(0.54);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user