fix(abut): 날개벽 헌치를 내측면 기준으로 재배치
- 뒷굽 헌치 삭제 - 연직 헌치 2개(흉벽 배면, 벽체 배면)를 날개벽 내측면 모서리에 평면 삼각형 기둥으로 둠 - 저판 상면 헌치 추가: 저판 상면과 날개벽 내측면 사이의 수평 헌치 (벽체 배면 → 뒷굽 구간, 다리 0.3 m) - 테스트 갱신 (헌치 6개, 저판 상면 헌치 범위). 전체 639건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea36df58cc
commit
e5134cdb68
4 files changed
+40
-38
No files matched your search
+12
-20
@@ -41,10 +41,10 @@ export interface WingSolid {
|
||||
/** 헌치 300 × 300 (위 헌치, 흉벽 배면 모서리). 평면 삼각형과 높이 범위. */
|
||||
haunches: Haunch[];
|
||||
/**
|
||||
* 뒷굽 헌치 (삽도, 날개벽과 확대기초): (t, EL) 직각삼각형. 꼭짓점은 뒷굽 끝 H, 날개벽 하면을 따라 0.3 m, 뒷굽 면을 따라 아래로 0.3 m.
|
||||
* 날개벽 두께(0.45 m)만큼 s 방향으로 민다. 단축형 날개벽에는 없다.
|
||||
* 저판 상면 헌치 (수평, 2026-11-03): between the 저판 상면 and the 날개벽 내측면. The triangle lies in the plane EL–s,
|
||||
* with legs HAUNCH_LEG_M along the 저판 상면 and along the 내측면; it runs along the wing from dMFrom (벽체 배면) to dMTo (뒷굽).
|
||||
*/
|
||||
heelHaunch?: [number, number][];
|
||||
footingHaunch?: { dMFrom: number; dMTo: number; el: number };
|
||||
/** 수평 단 (QA-12, spec_abut §4.7): 등단면 / 변화단면1 / 변화단면2. 경계는 단부 높이 1.5 m와 교좌면 EL. */
|
||||
bands: WingBand[];
|
||||
}
|
||||
@@ -130,23 +130,15 @@ export function buildWings(model: AbutModel, members: AbutMembers, forms?: { lef
|
||||
zTopEl: kind === 'upper' ? topAt(d) : bracketTop,
|
||||
};
|
||||
};
|
||||
const haunches = [haunchAt('upper', members.shape.parapetBackM)];
|
||||
// 연직 헌치 (2026-11-03, 내측면 모서리): upper at the 흉벽 배면, lower at the 벽체 배면.
|
||||
const haunches = [haunchAt('upper', members.shape.parapetBackM), haunchAt('lower', members.shape.wallBackM)];
|
||||
|
||||
// 뒷굽 헌치 (삽도): at the heel H = (footing back, footing top). The 300 legs run along the wing underside and down the 뒷굽 face.
|
||||
const tOf = (dM: number) => (members.shape.footingBackM * dM) / heelDistanceM;
|
||||
const underside = bottomLine.find((p) => p.dM > heelDistanceM + 1e-9);
|
||||
const heelHaunch: [number, number][] | undefined =
|
||||
underside === undefined
|
||||
? undefined
|
||||
: (() => {
|
||||
const H: [number, number] = [members.shape.footingBackM, footingTop];
|
||||
const ux = tOf(underside.dM) - H[0];
|
||||
const uy = underside.el - H[1];
|
||||
const len = Math.hypot(ux, uy);
|
||||
const A: [number, number] = [H[0] + (0.3 * ux) / len, H[1] + (0.3 * uy) / len];
|
||||
const B: [number, number] = [H[0], H[1] - 0.3];
|
||||
return [H, A, B];
|
||||
})();
|
||||
// 저판 상면 헌치 (수평): from the 벽체 배면 to the 뒷굽, on the 저판 상면 next to the 날개벽 내측면.
|
||||
const footingHaunch = {
|
||||
dMFrom: Math.abs(members.shape.wallBackM) / k,
|
||||
dMTo: heelDistanceM,
|
||||
el: footingTop,
|
||||
};
|
||||
|
||||
// 수평 단 (QA-12): 등단면 = 끝 상단 − 1.5 m 위, 변화단면1 = 그 아래 ~ 교좌면 EL, 변화단면2 = 교좌면 EL ~ 저판 상면.
|
||||
// 교좌면 EL은 날개벽 끝에 가장 가까운 받침의 교좌면이다.
|
||||
@@ -172,7 +164,7 @@ export function buildWings(model: AbutModel, members: AbutMembers, forms?: { lef
|
||||
topLine,
|
||||
bottomLine,
|
||||
haunches,
|
||||
heelHaunch,
|
||||
footingHaunch,
|
||||
bands,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import * as THREE from 'three';
|
||||
import type { AbutModel, AbutPoint } from '../core/abut/geometry';
|
||||
import { buildMembers, type AbutMembers } from '../core/abut/members';
|
||||
import { buildWings, WING_THICKNESS_M, type WingSolid } from '../core/abut/wings';
|
||||
import { buildWings, HAUNCH_LEG_M, WING_THICKNESS_M, type WingSolid } from '../core/abut/wings';
|
||||
import type { TerrainGrid } from '../core/ground-model';
|
||||
import { terrainGeometry } from './terrain';
|
||||
|
||||
@@ -284,10 +284,14 @@ export function buildAbutGroup(
|
||||
const lower = prism(clipBelowX(below, members.shape.wallBackM / dir.wt), WING_THICKNESS_M, new THREE.Vector3(sEnd, 0, 0), ax, ey, new THREE.Vector3(a, 0, 0));
|
||||
add('wings', upper, 0xc9a77c);
|
||||
add('wings', lower, 0xc9a77c);
|
||||
// 뒷굽 헌치 (삽도): (t, EL) triangle, extruded across the wing thickness along s.
|
||||
if (wing.heelHaunch) {
|
||||
const profile = wing.heelHaunch;
|
||||
add('haunches', prism(profile, WING_THICKNESS_M, new THREE.Vector3(sEnd, 0, 0), ez, ey, new THREE.Vector3(a, 0, 0)), 0xc9a77c);
|
||||
// 저판 상면 헌치 (수평, 2026-11-03): a right triangle in the plane EL–s on the 저판 상면, next to the 날개벽 내측면,
|
||||
// extruded along the wing from the 벽체 배면 to the 뒷굽.
|
||||
if (wing.footingHaunch) {
|
||||
const f = wing.footingHaunch;
|
||||
const leg = HAUNCH_LEG_M;
|
||||
const triangle: [number, number][] = [[0, 0], [leg, 0], [0, leg]];
|
||||
const origin = new THREE.Vector3(sEnd + a * WING_THICKNESS_M + dir.ws * f.dMFrom, f.el, dir.wt * f.dMFrom);
|
||||
add('haunches', prism(triangle, f.dMTo - f.dMFrom, origin, new THREE.Vector3(a, 0, 0), ey, new THREE.Vector3(dir.ws, 0, dir.wt)), 0xc9a77c);
|
||||
}
|
||||
for (const h of wing.haunches) {
|
||||
const shape: [number, number][] = h.corners.map((c) => {
|
||||
|
||||
Reference in new issue
Block a user