feat(view): solplate in the 3D model (2단계): wedges from the drawing's A, B, S; read the solplate table from DXF
Each bearing gets a solplate wedge: tapered along the 교축 with T1 on the 시점 side, underside at the bearing top (block top + h3). A, B come from the drawing's ELEVATION table, S and T1/T2 from the SOLPLATE table (NO, S(%), L, W, T, T1, T2), read by position. The 공통 규칙 (T 30, margin 100, h3 181) feed the plan; changing them regenerates the piers. A new "솔플레이트" part can be shown or hidden. A solplate table is read only when its S values are found; a missing S is reported. Also commits the option-1 test change (drawing EL.X minus Excel z). Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1d8746d533
commit
a50f4f5ee5
10 files changed
+579
-13
No files matched your search
@@ -31,14 +31,16 @@ describe('교량받침 reference (도면값, 읽기 전용, 1단계)', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('EL.X = block top incl. the 50 mm mortar: coping top = EL.X − h1 − h2 matches the model on all ten bearings (within 2 mm)', () => {
|
||||
it('Excel z is EL.X (option 1): the model keeps z; the drawing EL.X minus Excel z is +64 mm (전열) and −11 mm (후열)', () => {
|
||||
const m = buildPier(loadP1());
|
||||
const back = m.blocks.filter((b) => b.row === '후열');
|
||||
const diffs = BEARING_ELEVATION_REF.map((r) => {
|
||||
const modelTop = r.row === '전열' ? m.segments[r.no - 1].top : back[r.no - 6].bottom;
|
||||
return modelTop - (r.elx - (r.h1 + r.h2) / 1000);
|
||||
const front = m.blocks.filter((b) => b.row === '전열');
|
||||
BEARING_ELEVATION_REF.forEach((r) => {
|
||||
const z = r.row === '전열' ? front[r.no - 1].padTop : back[r.no - 6].padTop;
|
||||
const diffMm = (r.elx - z) * 1000; // 도면 − 엑셀
|
||||
// About +64 mm on the front row and −11 mm on the back row (varies by a millimetre or two per bearing).
|
||||
expect(Math.abs(diffMm - (r.row === '전열' ? 64 : -11)), `No ${r.no}`).toBeLessThan(2);
|
||||
});
|
||||
for (const d of diffs) expect(Math.abs(d)).toBeLessThan(0.002);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -40,3 +40,25 @@ describe('도면 받침 ELEVATION TABLE 읽기 (DXF 텍스트, 승인 2026-10-23
|
||||
expect(readDxfTexts(dxf)).toEqual([{ x: 100.5, y: 200.25, text: 'EL. "X"' }]);
|
||||
});
|
||||
});
|
||||
|
||||
import { parseSolplateTable } from '../src/core/dxf-table';
|
||||
import { SOLPLATE_REF } from '../src/core/bearing-ref';
|
||||
|
||||
describe('솔플레이트 TABLE 읽기 (승인 2026-10-23)', () => {
|
||||
const sp = JSON.parse(readFileSync(new URL('./fixtures/solplate-table-texts.json', import.meta.url), 'utf-8')) as DxfText[];
|
||||
|
||||
it('reads S, L, W, T, T1 and T2 for all ten bearings, and they equal the reference values', () => {
|
||||
const r = parseSolplateTable(sp);
|
||||
expect(r.errors).toEqual([]);
|
||||
expect(r.rows.map((x) => x.no)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
for (const ref of SOLPLATE_REF) {
|
||||
const got = r.rows.find((x) => x.no === ref.no)!;
|
||||
expect(got.S, `No ${ref.no} S`).toBeCloseTo(ref.s, 3);
|
||||
expect(got.L, `No ${ref.no} L`).toBe(ref.L);
|
||||
expect(got.W, `No ${ref.no} W`).toBe(ref.W);
|
||||
expect(got.T, `No ${ref.no} T`).toBe(30);
|
||||
expect(got.T1, `No ${ref.no} T1`).toBe(38);
|
||||
expect(got.T2, `No ${ref.no} T2`).toBe(22);
|
||||
}
|
||||
});
|
||||
});
|
||||
+407
@@ -0,0 +1,407 @@
|
||||
[
|
||||
{
|
||||
"x": 6995.713250393052,
|
||||
"y": 6754.627068450442,
|
||||
"text": "교량받침 연단거리 검토"
|
||||
},
|
||||
{
|
||||
"x": 2481.474417619672,
|
||||
"y": 12500.89064770541,
|
||||
"text": "NO."
|
||||
},
|
||||
{
|
||||
"x": 3480.342593385318,
|
||||
"y": 12500.89064770541,
|
||||
"text": "S(%)"
|
||||
},
|
||||
{
|
||||
"x": 4683.73806608838,
|
||||
"y": 12500.89064770541,
|
||||
"text": "L"
|
||||
},
|
||||
{
|
||||
"x": 5583.73806608838,
|
||||
"y": 12500.89064770541,
|
||||
"text": "W"
|
||||
},
|
||||
{
|
||||
"x": 6483.73806608838,
|
||||
"y": 12500.89064770541,
|
||||
"text": "T"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 12500.89064770541,
|
||||
"text": "T1"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 12500.89064770541,
|
||||
"text": "T2"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 12020.89064770541,
|
||||
"text": "1"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 12020.89064770541,
|
||||
"text": "-1.910"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 12020.89064770541,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 12020.89064770541,
|
||||
"text": "740"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 12020.89064770541,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 12020.89064770541,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 12020.89064770541,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 11540.89064770541,
|
||||
"text": "2"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 11540.89064770541,
|
||||
"text": "-1.907"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 11540.89064770541,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 11540.89064770541,
|
||||
"text": "740"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 11540.89064770541,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 11540.89064770541,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 11540.89064770541,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 11060.89064770541,
|
||||
"text": "3"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 11060.89064770541,
|
||||
"text": "-1.905"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 11060.89064770541,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 11060.89064770541,
|
||||
"text": "890"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 11060.89064770541,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 11060.89064770541,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 11060.89064770541,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 10580.89064770541,
|
||||
"text": "4"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 10580.89064770541,
|
||||
"text": "-1.903"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 10580.89064770541,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 10580.89064770541,
|
||||
"text": "740"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 10580.89064770541,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 10580.89064770541,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 10580.89064770541,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 10100.89064770541,
|
||||
"text": "5"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 10100.89064770541,
|
||||
"text": "-1.901"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 10100.89064770541,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 10100.89064770541,
|
||||
"text": "740"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 10100.89064770541,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 10100.89064770541,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 10100.89064770541,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 9620.890647705412,
|
||||
"text": "6"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 9620.890647705412,
|
||||
"text": "-1.910"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 9620.890647705412,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 9620.890647705412,
|
||||
"text": "640"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 9620.890647705412,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 9620.890647705412,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 9620.890647705412,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 9140.890647705412,
|
||||
"text": "7"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 9140.890647705412,
|
||||
"text": "-1.907"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 9140.890647705412,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 9140.890647705412,
|
||||
"text": "640"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 9140.890647705412,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 9140.890647705412,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 9140.890647705412,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 8660.890647705412,
|
||||
"text": "8"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 8660.890647705412,
|
||||
"text": "-1.905"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 8660.890647705412,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 8660.890647705412,
|
||||
"text": "750"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 8660.890647705412,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 8660.890647705412,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 8660.890647705412,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2583.73806608838,
|
||||
"y": 8180.890647705412,
|
||||
"text": "9"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 8180.890647705412,
|
||||
"text": "-1.903"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 8180.890647705412,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 8180.890647705412,
|
||||
"text": "640"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 8180.890647705412,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 8180.890647705412,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 8180.890647705412,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 2532.606241854026,
|
||||
"y": 7700.890647705412,
|
||||
"text": "10"
|
||||
},
|
||||
{
|
||||
"x": 3378.078944916609,
|
||||
"y": 7700.890647705412,
|
||||
"text": "-1.901"
|
||||
},
|
||||
{
|
||||
"x": 4581.474417619672,
|
||||
"y": 7700.890647705412,
|
||||
"text": "800"
|
||||
},
|
||||
{
|
||||
"x": 5481.474417619672,
|
||||
"y": 7700.890647705412,
|
||||
"text": "640"
|
||||
},
|
||||
{
|
||||
"x": 6432.606241854026,
|
||||
"y": 7700.890647705412,
|
||||
"text": "30"
|
||||
},
|
||||
{
|
||||
"x": 7332.606241854026,
|
||||
"y": 7700.890647705412,
|
||||
"text": "38"
|
||||
},
|
||||
{
|
||||
"x": 8232.606241854026,
|
||||
"y": 7700.890647705412,
|
||||
"text": "22"
|
||||
},
|
||||
{
|
||||
"x": 4052.185026156749,
|
||||
"y": 5992.968147136969,
|
||||
"text": "구 분"
|
||||
},
|
||||
{
|
||||
"x": 3694.26225651627,
|
||||
"y": 5512.968147136969,
|
||||
"text": "필요연단길이"
|
||||
},
|
||||
{
|
||||
"x": 7809.175705251289,
|
||||
"y": 5512.968147136969,
|
||||
"text": "s = 200 + 5.0L = 200 + 5.0 X 50.2 = 451.2mm"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import * as THREE from 'three';
|
||||
import { buildPier } from '../src/core/geometry';
|
||||
import { solplateGeometry } from '../src/core/solplate';
|
||||
import { BEARING_ELEVATION_REF, SOLPLATE_REF } from '../src/core/bearing-ref';
|
||||
import { buildPierScene } from '../src/view/scene';
|
||||
import { loadP1 } from './helpers';
|
||||
|
||||
const plans = SOLPLATE_REF.map((s, i) => ({ no: s.no, A: BEARING_ELEVATION_REF[i].A, B: BEARING_ELEVATION_REF[i].B, S: s.s }));
|
||||
|
||||
describe('솔플레이트 모델과 3D (2단계, 승인 2026-10-23)', () => {
|
||||
it('without plans there is no solplate; with plans every bearing has one', () => {
|
||||
expect(buildPier(loadP1()).blocks.every((b) => b.plan === undefined)).toBe(true);
|
||||
const m = buildPier({ ...loadP1(), bearingPlans: plans, solplate: { T: 30, margin: 100, h3: 181 } });
|
||||
expect(m.blocks.every((b) => b.plan !== undefined)).toBe(true);
|
||||
expect(m.blocks[0].plan!.A).toBe(700);
|
||||
});
|
||||
|
||||
it('the 3D scene has one solplate wedge per bearing, and its height is the bearing top plus T', () => {
|
||||
const m = buildPier({ ...loadP1(), bearingPlans: plans, solplate: { T: 30, margin: 100, h3: 181 } });
|
||||
const scene = buildPierScene(m);
|
||||
const wedges = scene.parts.solplates.children;
|
||||
expect(wedges.length).toBe(10);
|
||||
const box = new THREE.Box3().setFromObject(scene.parts.solplates);
|
||||
// The highest point is the thick (시점) end of the tallest wedge: underside (block top + h3) + T1.
|
||||
const top = Math.max(...m.blocks.map((b) => solplateGeometry(b, 181, { A: b.plan!.A, B: b.plan!.B, margin: 100, T: 30, slopePct: b.plan!.S }).bottom + solplateGeometry(b, 181, { A: b.plan!.A, B: b.plan!.B, margin: 100, T: 30, slopePct: b.plan!.S }).T1));
|
||||
expect(box.max.y).toBeCloseTo(top, 3);
|
||||
});
|
||||
|
||||
it('without plans the scene has an empty solplate part', () => {
|
||||
const scene = buildPierScene(buildPier(loadP1()));
|
||||
expect(scene.parts.solplates.children.length).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user