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:
HHY
2026-09-21 03:43:26 -07:00
parent 56c154bf81
commit e1572f969d
6 changed files with 136 additions and 37 deletions
+1 -36
View File
@@ -56,6 +56,7 @@ import {
bboxOf, inferSashGlyphs, parseDrawing, regionPoints, replayShape,
type DrawingData, type Pt,
} from '../types/drawing'
import { profileGeo } from '../three/profileGeo'
interface BBox { x0: number; y0: number; x1: number; y1: number }
@@ -110,42 +111,6 @@ function overlapArea(a: BBox, b: BBox): number {
}
/** 型材截面: 多腔体 + 玻璃槽(比例依据真实 DXF 截面学习: 深度46-90/面宽65-130/腔体3-6/壁厚≈深度1/30) */
function profileGeo(len: number, fw: number, depth: number, chambers: number): 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=0 侧开玻璃槽
s.moveTo(0, t)
s.lineTo(g, t)
s.lineTo(g, fw - t)
s.lineTo(0, fw - t)
s.lineTo(0, 0)
s.lineTo(depth, 0)
s.lineTo(depth, fw)
s.lineTo(g, fw)
s.closePath()
// 腔体孔洞(隔热/加强腔)
const cH = fw - t * 2
const usable = depth - g - t * (chambers + 1)
const cw = usable / chambers
if (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
}
/** 沿 X 轴的型材杆(槽口朝 -Z 玻璃面) */
function barX(parent: THREE.Group, mat: THREE.Material, len: number, fw: number,
depth: number, cx: number, cy: number, cz: number, chambers = 2) {
const geo = profileGeo(len, fw, depth, chambers)