fix: v2.1 3D 渲染问题根治(profileGeo 自交破面+扇矩形 NaN)
- profileGeo 外轮廓路径自相交(闭合斜边穿过槽口)导致三角剖分破面 重写为正确顶点顺序的 U 槽简单多边形 - 型材截面挤出抽为共享模块 three/profileGeo.ts(+geometryIsValid 校验器) - inferSashGlyphs 兜底 bboxOf 误传段对象→修正为有限值点集 (修复扇矩形 NaN 序列化为 null 的问题) - 新增 scripts/validate3d.cjs: 254 样板×3700 网格×798 扇 逐网格 NaN 检测全部通过; 窄条扇合法跳过
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 型材截面挤出几何(自研实现,思路对齐源站 DXF 截面挤出方案)
|
||||
* U 型槽多腔体截面:沿长度方向(Z)挤出并居中,槽口朝玻璃面(u=0 侧)。
|
||||
* 截面比例依据真实 DXF 学习:深度 46-90 / 面宽 65-130 / 腔体 3-6 / 壁厚≈深度 1/7(视觉强化)。
|
||||
*/
|
||||
import * as THREE from 'three'
|
||||
|
||||
export function profileGeo(len: number, fw: number, depth: number, chambers = 2): THREE.BufferGeometry {
|
||||
const t = Math.max(0.004, depth * 0.14) // 壁厚
|
||||
const g = Math.max(0.006, depth * 0.2) // 玻璃槽深
|
||||
const s = new THREE.Shape()
|
||||
// 外轮廓(U 槽口在 u=0 侧, v∈[t, fw-t]) — 顶点顺序保证简单多边形不自交
|
||||
s.moveTo(0, 0)
|
||||
s.lineTo(depth, 0)
|
||||
s.lineTo(depth, fw)
|
||||
s.lineTo(0, fw)
|
||||
s.lineTo(0, fw - t)
|
||||
s.lineTo(g, fw - t)
|
||||
s.lineTo(g, t)
|
||||
s.lineTo(0, t)
|
||||
s.closePath()
|
||||
// 腔体孔洞(隔热/加强腔)
|
||||
const cH = fw - t * 2
|
||||
const usable = depth - g - t * (chambers + 1)
|
||||
const cw = usable / chambers
|
||||
if (Number.isFinite(cw) && cw > t) {
|
||||
for (let i = 0; i < chambers; i++) {
|
||||
const hx = g + t + i * (cw + t)
|
||||
const hole = new THREE.Path()
|
||||
hole.moveTo(hx, t)
|
||||
hole.lineTo(hx + cw, t)
|
||||
hole.lineTo(hx + cw, t + cH)
|
||||
hole.lineTo(hx, t + cH)
|
||||
hole.closePath()
|
||||
s.holes.push(hole)
|
||||
}
|
||||
}
|
||||
const geo = new THREE.ExtrudeGeometry(s, { depth: len, bevelEnabled: false })
|
||||
geo.translate(0, 0, -len / 2)
|
||||
return geo
|
||||
}
|
||||
|
||||
/** 校验几何: 位置属性全部有限 且 包围球半径有限 */
|
||||
export function geometryIsValid(geo: THREE.BufferGeometry): boolean {
|
||||
geo.computeBoundingSphere()
|
||||
if (!Number.isFinite(geo.boundingSphere?.radius ?? NaN)) return false
|
||||
const pos = geo.getAttribute('position')
|
||||
if (!pos) return false
|
||||
for (let i = 0; i < pos.count * 3; i++) {
|
||||
if (!Number.isFinite(pos.array[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user