xl-public-utils 1.0.22 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -248,6 +248,12 @@ declare module "xl-public-utils" {
248
248
  * @param {vtkPolyData} data 需要应用变换的polydata
249
249
  */
250
250
  export function pointsApplyMat4(mt4: mat4, data: vtkPolyData): void;
251
+ /**
252
+ * 对一个polydata应用矩阵变化,直接改变点位置
253
+ * @param {mat4} mt4 变换矩阵
254
+ * @param {number[]} vertices 需要应用变换的polydata
255
+ */
256
+ export function verticesApplyMat4(mt4: mat4, vertices: number[]): Float32Array;
251
257
  /**
252
258
  * 将点应用矩阵变换
253
259
  * @param {vec3} point 三维点
@@ -470,6 +476,14 @@ declare module "xl-public-utils" {
470
476
  * @returns {vtkPolyData} 去重之后的vtkPolyData
471
477
  */
472
478
  export function deduplicatePolyData(data: vtkPolyData): vtkPolyData;
479
+ /**
480
+ * 顶点去重,用于 STL
481
+ * @param {Float32Array} vertices 输入顶点数组 [x,y,z, x,y,z, ...]
482
+ * @param {Int32Array} faces 输入面索引数组 [3,i1,i2,i3, 3,i4,i5,i6, ...]
483
+ * @param {number} [precision=1e-10] 精度,用于判断顶点相等(默认 1e-10)
484
+ * @returns {{ vertices: Float32Array, faces: Int32Array }} 去重后的网格数据
485
+ */
486
+ export function deduplicateVF(vertices: Float32Array | number[], faces: Int32Array | number[], precision = 1e-10): { vertices: Float32Array, faces: Int32Array };
473
487
  /**
474
488
  * 判断一个矩阵是否是正交矩阵
475
489
  * @param {mat4} matrix 矩阵
@@ -715,7 +729,7 @@ declare module "xl-public-utils" {
715
729
  * @param { vec3 } axisX 朝向 X 轴,默认 [1, 0, 0]
716
730
  * @param { vec3 } axisY 朝向 Y 轴,默认 [0, 1, 0]
717
731
  * @param { vec3 } axisZ 朝向 Z 轴,默认 [0, 0, 1]
718
- * @returns { vtkPolyData } polydata 六边形网格
732
+ * @returns { vertices: Float32Array, faces: Int32Array } 点和面 六边形网格
719
733
  */
720
734
  export function createHexagonPolydata(
721
735
  rows:number,
@@ -727,7 +741,7 @@ declare module "xl-public-utils" {
727
741
  axisX?: vec3,
728
742
  axisY?: vec3,
729
743
  axisZ?: vec3
730
- ): vtkPolyData
744
+ ): { vertices: Float32Array, faces: Int32Array }
731
745
  }
732
746
 
733
747
  export namespace utils {
@@ -1066,18 +1080,14 @@ declare module "xl-public-utils" {
1066
1080
  fontName?: string,
1067
1081
  scale?: vec3
1068
1082
  ): {
1069
- polyData: vtkPolyData;
1070
- indexData: IndexData;
1083
+ vertices: number[],
1084
+ faces: number[],
1085
+ indexData: IndexData,
1071
1086
  };
1072
1087
 
1073
1088
  /**
1074
1089
  * 获取顶点索引映射
1075
1090
  */
1076
- getPointsMapData(polydata: vtkPolyData): IndexData;
1077
-
1078
- /**
1079
- * 创建 vtkPolyData 对象
1080
- */
1081
- createPolyData(verts: any, faces: any): vtkPolyData;
1091
+ getPointsMapData(polydata: ArrayLike<number>): IndexData;
1082
1092
  }
1083
1093
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xl-public-utils",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
package/src/drcUtils.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { vec3 } from "gl-matrix";
2
2
  import { int8ArrayToBase64 } from './utils.js'
3
- import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
4
3
  import vtkDracoReader from "@kitware/vtk.js/IO/Geometry/DracoReader";
5
4
  /**
6
5
  * @typedef {Object} AttrOption
package/src/exportPLY.js CHANGED
@@ -1,4 +1,3 @@
1
- import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
2
1
  var FormatTypes = {
3
2
  ASCII: 'ascii',
4
3
  BINARY: 'binary'
package/src/exportSTL.js CHANGED
@@ -1,4 +1,3 @@
1
- import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData.js';
2
1
  import { vec3 } from 'gl-matrix';
3
2
 
4
3
  /**
package/src/meshUtils.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { ExtrudeGeometry } from './threeFont/TextGeometry/ExtrudeGeometry.js';
2
2
  import { Shape } from './threeFont/Curve/Shape.js';
3
3
  import { vec3, mat4 } from 'gl-matrix';
4
- import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData.js';
5
- import { clonePolyData, createPolyData, getL2WMatrix, getPolydataCenterOffset, mergePolyData, pointsApplyMat4 } from './vtkUtils.js';
4
+ import { getL2WMatrix, getPolydataCenterOffset, mergeMeshes, verticesApplyMat4 } from './vtkUtils.js';
6
5
 
7
6
 
8
7
  /**
@@ -60,7 +59,7 @@ export function createHexagonGeometry(radius, height, wallThickness) {
60
59
  * @param { vec3 } axisX 朝向 X 轴,默认 [1, 0, 0]
61
60
  * @param { vec3 } axisY 朝向 Y 轴,默认 [0, 1, 0]
62
61
  * @param { vec3 } axisZ 朝向 Z 轴,默认 [0, 0, 1]
63
- * @returns { vtkPolyData } polydata 六边形网格
62
+ * @returns { vertices: Float32Array, faces: Int32Array } 点和面 六边形网格
64
63
  */
65
64
  export function createHexagonPolydata(
66
65
  rows,
@@ -81,30 +80,31 @@ export function createHexagonPolydata(
81
80
  const b = (radius / 2) * z - _wall / 2 / z;
82
81
 
83
82
  const geometry = createHexagonGeometry(radius, height, _wall);
84
- const polyData = createPolyData(geometry.vertices, geometry.faces);
85
83
 
86
84
  let polyDataArr = [];
87
85
  // 生成网格
88
86
  for (let i = 0; i < rows; i++) {
89
87
  let q = i % 2; // 奇偶行偏移
90
88
  for (let j = 1; j <= cols; j++) {
91
- let _polyData = clonePolyData(polyData);
92
89
 
93
90
  // 根据形状和OpenSCAD公式计算位置
94
91
  let x = i * a;
95
92
  let y = j * b * 2 + q * b - b;
96
93
  let _trans = mat4.fromTranslation(mat4.create(), [x, y, 0]);
97
- pointsApplyMat4(_trans, _polyData);
98
- polyDataArr.push(_polyData);
94
+ const newVertices = verticesApplyMat4(_trans, geometry.vertices);
95
+ polyDataArr.push({
96
+ vertices: newVertices,
97
+ faces: geometry.faces
98
+ });
99
99
  }
100
100
  }
101
101
 
102
- const resultPolyData = mergePolyData(polyDataArr);
103
- const _offset = getPolydataCenterOffset(resultPolyData);
102
+ const resultPolyData = mergeMeshes(polyDataArr);
103
+ const _offset = getPolydataCenterOffset(resultPolyData.vertices);
104
104
  const offsetM4 = mat4.translate(mat4.create(), mat4.create(), [_offset.x, _offset.y, 0]);
105
- pointsApplyMat4(offsetM4, resultPolyData);
105
+ resultPolyData.vertices = verticesApplyMat4(offsetM4, resultPolyData.vertices);
106
106
 
107
107
  const _matrix = getL2WMatrix(center, axisX, axisY, axisZ);
108
- pointsApplyMat4(_matrix, resultPolyData);
108
+ resultPolyData.vertices = verticesApplyMat4(_matrix, resultPolyData.vertices);
109
109
  return resultPolyData;
110
110
  }
@@ -3,13 +3,11 @@ import { ExtrudeGeometry } from './TextGeometry/ExtrudeGeometry.js';
3
3
  import { mat4, vec3 } from 'gl-matrix';
4
4
 
5
5
  import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData.js';
6
- import vtkPoints from '@kitware/vtk.js/Common/Core/Points.js';
7
- import vtkCellArray from '@kitware/vtk.js/Common/Core/CellArray.js';
8
6
 
9
7
  import {
10
8
  clonePolyData,
11
- deduplicatePolyData,
12
- pointsApplyMat4
9
+ deduplicateVF,
10
+ verticesApplyMat4
13
11
  } from '../vtkUtils.js';
14
12
 
15
13
  /**
@@ -21,7 +19,7 @@ class FontManager {
21
19
  constructor() {
22
20
  if (FontManager.instance) return FontManager.instance;
23
21
 
24
- /** @type {Object.<string, vtkPolyData>} */
22
+ /** @type {Object.<string, {vertices: ArrayLike<number>, faces: ArrayLike<number>}}>} */
25
23
  this.cacheFontMap = {};
26
24
  /** @type {Object.<string, { zeroIndexs: number[], oneIndexs: number[] }>} */
27
25
  this.cacheFontPointMap = {};
@@ -68,48 +66,44 @@ class FontManager {
68
66
  * @param {string} text
69
67
  * @param {string} fontName
70
68
  * @param {vec3} scale
71
- * @returns {{ polyData: vtkPolyData, indexData: { zeroIndexs: number[], oneIndexs: number[] } }}
69
+ * @returns {{ vertices: ArrayLike<number>, faces: ArrayLike<number>, indexData: { zeroIndexs: number[], oneIndexs: number[] } }}
72
70
  */
73
71
  generateShapes(text, fontName = 'defaultFont', scale = [0.018, 0.018, 0.018]) {
74
72
  const scaleM4 = mat4.scale(mat4.create(), mat4.create(), scale);
75
73
 
76
74
  if (this.cacheFontMap[text]) {
77
- const newPolyData = clonePolyData(this.cacheFontMap[text]);
78
- pointsApplyMat4(scaleM4, newPolyData);
75
+ const newVertices = verticesApplyMat4(scaleM4, this.cacheFontMap[text].vertices);
79
76
  return {
80
- polyData: newPolyData,
77
+ vertices: newVertices,
78
+ faces: this.cacheFontMap[text].faces,
81
79
  indexData: this.cacheFontPointMap[text]
82
80
  };
83
81
  }
84
82
 
85
83
  const shapes = this.parameters.font[fontName].generateShapes(text, this.parameters.size);
86
84
  const extrude = new ExtrudeGeometry(shapes, this.parameters);
87
-
88
- let polyData = this.createPolyData(extrude.vertices, extrude.faces);
89
- polyData = deduplicatePolyData(polyData);
90
- polyData = this.reIndexPolyData(polyData);
91
- const indexData = this.getPointsMapData(polyData);
85
+ let vfData = deduplicateVF(extrude.vertices, extrude.faces);
86
+ vfData = this.reIndexByVF(vfData.vertices, vfData.faces);
87
+ const indexData = this.getPointsMapData(vfData.vertices);
92
88
  // console.log(indexData);
93
-
94
- const _polyData = clonePolyData(polyData);
95
- pointsApplyMat4(scaleM4, _polyData);
96
-
97
- this.cacheFontMap[text] = polyData;
89
+ const newVertices = verticesApplyMat4(scaleM4, vfData.vertices);
90
+ this.cacheFontMap[text] = vfData;
98
91
  this.cacheFontPointMap[text] = indexData;
99
92
 
100
93
  return {
101
- polyData: _polyData,
94
+ vertices: newVertices,
95
+ faces: vfData.faces,
102
96
  indexData
103
97
  };
104
98
  }
105
99
 
106
100
  /**
107
- * 获取前后层顶点索引映射数据
108
- * @param {vtkPolyData} polydata
101
+ * 根据指定索引集合重新组织点和面
102
+ * @param {Float32Array} vertices 点数组 [x,y,z, x,y,z, ...]
109
103
  * @returns {{ zeroIndexs: number[], oneIndexs: number[] }}
110
104
  */
111
- getPointsMapData(polydata) {
112
- const points = polydata.getPoints().getData();
105
+ getPointsMapData(vertices) {
106
+ const points = vertices
113
107
  const zeroIndexs = [];
114
108
  const oneIndexs = [];
115
109
  const pointIndexMap = {};
@@ -137,65 +131,36 @@ class FontManager {
137
131
  };
138
132
  }
139
133
  /**
140
- *
141
- * @param {vtkPolyData} polydata
142
- * @returns {vtkPolyData} 重组索引之后的polydata
134
+ * 根据指定索引集合重新组织点和面
135
+ * @param {Float32Array} vertices 点数组 [x,y,z, x,y,z, ...]
136
+ * @param {Int32Array} faces 面索引数组 (VTK风格: [3,i1,i2,i3, 3,i4,i5,i6,...])
143
137
  */
144
- reIndexPolyData(polydata) {
145
- const indexData = this.getPointsMapData(polydata);
138
+ reIndexByVF(vertices, faces) {
139
+ const indexData = this.getPointsMapData(vertices);
146
140
  const allIndexData = [...indexData.zeroIndexs, ...indexData.oneIndexs]
147
- const nowPoints = polydata.getPoints().getData();
148
- const nowFaces = polydata.getPolys().getData();
149
- const newPoints = new Float32Array(nowPoints.length);
141
+ const newPoints = new Float32Array(vertices.length);
150
142
  const indexMap = {};
151
143
  for(let i = 0; i < allIndexData.length; i++) {
152
144
  const index = allIndexData[i];
153
- const x = nowPoints[index * 3];
154
- const y = nowPoints[index * 3 + 1];
155
- const z = nowPoints[index * 3 + 2];
145
+ const x = vertices[index * 3];
146
+ const y = vertices[index * 3 + 1];
147
+ const z = vertices[index * 3 + 2];
156
148
  newPoints[i * 3] = x
157
149
  newPoints[i * 3 + 1] = y
158
150
  newPoints[i * 3 + 2] = z
159
151
  indexMap[index] = i;
160
152
  }
161
- for(let i =0; i< nowFaces.length; i += 4) {
162
- const p1 = nowFaces[i + 1];
163
- const p2 = nowFaces[i + 2]
164
- const p3 = nowFaces[i + 3]
165
- nowFaces[i + 1] = indexMap[p1]
166
- nowFaces[i + 2] = indexMap[p2]
167
- nowFaces[i + 3] = indexMap[p3]
153
+ const newFaces = new Int32Array(faces.length);
154
+ for(let i =0; i< faces.length; i += 4) {
155
+ newFaces[i] = 3;
156
+ newFaces[i + 1] = indexMap[faces[i + 1]];
157
+ newFaces[i + 2] = indexMap[faces[i + 2]];
158
+ newFaces[i + 3] = indexMap[faces[i + 3]];
168
159
  }
169
- polydata.getPoints().setData(newPoints);
170
- polydata.getPolys().setData(nowFaces);
171
- return polydata
172
- }
173
-
174
- /**
175
- * 创建 vtkPolyData 对象
176
- * @param {any} verts
177
- * @param {any} faces
178
- * @returns {vtkPolyData}
179
- */
180
- createPolyData(verts, faces) {
181
- const values_v = Object.values(verts);
182
- const values_f = Object.values(faces);
183
-
184
- const _verts = values_v.map(v => parseFloat(v));
185
- const _faces = values_f.map(f => parseInt(f));
186
-
187
- const vpoints = vtkPoints.newInstance();
188
- const cellArray = vtkCellArray.newInstance();
189
-
190
- vpoints.setData(_verts, 3);
191
- cellArray.setNumberOfComponents(4);
192
- cellArray.setData(_faces);
193
-
194
- const polyData = vtkPolyData.newInstance();
195
- polyData.setPoints(vpoints);
196
- polyData.setPolys(cellArray);
197
-
198
- return polyData;
160
+ return {
161
+ vertices: newPoints,
162
+ faces: newFaces,
163
+ };
199
164
  }
200
165
  }
201
166
 
package/src/vtkUtils.js CHANGED
@@ -1,8 +1,4 @@
1
1
  import vtkRenderer from "@kitware/vtk.js/Rendering/Core/Renderer.js";
2
- import vtkInteractorStyleManipulator from "@kitware/vtk.js/Interaction/Style/InteractorStyleManipulator.js"
3
- import vtkMouseCameraTrackballPanManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballPanManipulator.js";
4
- import vtkMouseCameraTrackballRotateManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballRotateManipulator.js";
5
- import vtkMouseCameraTrackballZoomManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballZoomManipulator.js";
6
2
  import vtkRenderWindowInteractor from "@kitware/vtk.js/Rendering/Core/RenderWindowInteractor.js";
7
3
  import vtkMatrixBuilder from "@kitware/vtk.js/Common/Core/MatrixBuilder.js";
8
4
  import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
@@ -18,7 +14,6 @@ import { exportBinarySTL } from './exportSTL.js';
18
14
  import { writePLY } from "./exportPLY.js";
19
15
  import { enCodeMesh } from './drcUtils.js';
20
16
  import { getFileExtension, int8ArrayToBase64 } from "./utils.js";
21
-
22
17
  /**
23
18
  * 计算屏幕坐标到三维坐标
24
19
  * @param {vtkRenderer} renderer vtkRenderer
@@ -153,42 +148,6 @@ export function getL2WMatrix(
153
148
  */
154
149
  export const getmatofl2w = getL2WMatrix;
155
150
 
156
- /**
157
- * 返回交互的interactorStyle
158
- * @returns {vtkInteractorStyleManipulator} 交互的interactorStyle
159
- */
160
- export function make3DInteractorStyle() {
161
- const interactorStyle = vtkInteractorStyleManipulator.newInstance();
162
- const cameraRotate = vtkMouseCameraTrackballRotateManipulator.newInstance({
163
- button: 1,
164
- });
165
- const cameraPan = vtkMouseCameraTrackballPanManipulator.newInstance({
166
- button: 3,
167
- });
168
- // const cameraPanControl = vtkMouseCameraTrackballPanManipulator.newInstance({
169
- // button: 1,
170
- // shift: true,
171
- // });
172
- // const cameraRoll = vtkMouseCameraTrackballRollManipulator.newInstance({
173
- // button: 3,
174
- // control: true,
175
- // });
176
- const cameraZoom = vtkMouseCameraTrackballZoomManipulator.newInstance({
177
- button: 2,
178
- });
179
- const cameraZoomDrag = vtkMouseCameraTrackballZoomManipulator.newInstance({
180
- scrollEnabled: true,
181
- dragEnabled: false,
182
- });
183
-
184
- interactorStyle.addMouseManipulator(cameraRotate);
185
- interactorStyle.addMouseManipulator(cameraPan);
186
- // interactorStyle.addMouseManipulator(cameraPanControl);
187
- // interactorStyle.addMouseManipulator(cameraRoll);
188
- // interactorStyle.addMouseManipulator(cameraZoom);
189
- interactorStyle.addMouseManipulator(cameraZoomDrag);
190
- return interactorStyle;
191
- }
192
151
 
193
152
  /**
194
153
  * 移除并返回当前renderWindow的所有鼠标交互设定
@@ -402,6 +361,29 @@ export function pointsApplyMat4(mt4, data) {
402
361
  .apply(data.getPoints().getData());
403
362
  }
404
363
 
364
+ /**
365
+ * 对点集合应用 4x4 变换矩阵
366
+ * @param {mat4} mt4 变换矩阵
367
+ * @param {number[]} points 点数组 [x1,y1,z1, x2,y2,z2, ...]
368
+ * @returns {Float32Array} 变换后的点数组(新的数组,不改变原数组)
369
+ */
370
+ export function verticesApplyMat4(mt4, points) {
371
+ const result = new Float32Array(points.length);
372
+ const v = vec3.create();
373
+
374
+ for (let i = 0; i < points.length; i += 3) {
375
+ v[0] = points[i];
376
+ v[1] = points[i + 1];
377
+ v[2] = points[i + 2];
378
+ vec3.transformMat4(v, v, mt4); // v = mt4 * v
379
+ result[i] = v[0];
380
+ result[i + 1] = v[1];
381
+ result[i + 2] = v[2];
382
+ }
383
+
384
+ return result;
385
+ }
386
+
405
387
  /**
406
388
  * 将点应用矩阵变换
407
389
  * @param {vec3} point 三维点
@@ -548,6 +530,58 @@ export function deduplicatePolyData(data) {
548
530
  return p;
549
531
  };
550
532
 
533
+ /**
534
+ * 顶点去重,用于 STL
535
+ * @param {Float32Array} vertices 输入顶点数组 [x,y,z, x,y,z, ...]
536
+ * @param {Int32Array} faces 输入面索引数组 [3,i1,i2,i3, 3,i4,i5,i6, ...]
537
+ * @param {number} [precision=1e-10] 精度,用于判断顶点相等(默认 1e-10)
538
+ * @returns {{ vertices: Float32Array, faces: Int32Array }} 去重后的网格数据
539
+ */
540
+ export function deduplicateVF(vertices, faces, precision = 1e-10) {
541
+ const OFFSET_BOUNDS = Math.log10(1 / precision); // 比如 precision=1e-10 => 10
542
+ const vMap = new Map(); // key -> newIndex
543
+ const vIndexMap = new Map(); // oldIndex -> newIndex
544
+ let vInc = 0;
545
+
546
+ // 建立映射
547
+ for (let i = 0; i < vertices.length; i += 3) {
548
+ const key = `${(vertices[i] * Math.pow(10, OFFSET_BOUNDS)).toFixed(0)},` +
549
+ `${(vertices[i + 1] * Math.pow(10, OFFSET_BOUNDS)).toFixed(0)},` +
550
+ `${(vertices[i + 2] * Math.pow(10, OFFSET_BOUNDS)).toFixed(0)}`;
551
+ if (vMap.has(key)) {
552
+ vIndexMap.set(i / 3, vMap.get(key));
553
+ } else {
554
+ vMap.set(key, vInc);
555
+ vIndexMap.set(i / 3, vInc);
556
+ vInc++;
557
+ }
558
+ }
559
+
560
+ // 重建顶点数组
561
+ const tVertices = new Float32Array(vMap.size * 3);
562
+ for (const [key, idx] of vMap.entries()) {
563
+ const j = idx * 3;
564
+ const [x, y, z] = key.split(",").map((e) => +e * Math.pow(10, -OFFSET_BOUNDS));
565
+ tVertices[j] = x;
566
+ tVertices[j + 1] = y;
567
+ tVertices[j + 2] = z;
568
+ }
569
+
570
+ // 重建面索引
571
+ const tFaces = new Int32Array(faces.length);
572
+ for (let i = 0; i < faces.length; i += 4) {
573
+ tFaces[i] = 3; // 三角面
574
+ tFaces[i + 1] = vIndexMap.get(faces[i + 1]);
575
+ tFaces[i + 2] = vIndexMap.get(faces[i + 2]);
576
+ tFaces[i + 3] = vIndexMap.get(faces[i + 3]);
577
+ }
578
+
579
+ return {
580
+ vertices: tVertices,
581
+ faces: tFaces
582
+ };
583
+ }
584
+
551
585
  /**
552
586
  * 计算一组三维点的中心点
553
587
  * @param {vec3[]} points 三维点数组
@@ -1089,18 +1123,68 @@ export function mergePolyData(params) {
1089
1123
  return appendPolyData.getOutputData();
1090
1124
  }
1091
1125
 
1126
+ /**
1127
+ * 合并多个 mesh
1128
+ * @param {Array<{ vertices: Float32Array, faces: Uint32Array }>} meshes
1129
+ * - vertices: Float32Array,长度 = 顶点数 * 3
1130
+ * - faces: Uint32Array 或 Int32Array,格式为 [n, i1, i2, i3, n, j1, j2, j3, ...] (和 vtkPolyData.getPolys().getData() 一样)
1131
+ * @returns {{ vertices: Float32Array, faces: Uint32Array }}
1132
+ */
1133
+ export function mergeMeshes(meshes) {
1134
+ // 先算总点数和总面索引数
1135
+ let totalPoints = 0;
1136
+ let totalFaces = 0;
1137
+ meshes.forEach(mesh => {
1138
+ totalPoints += mesh.vertices.length;
1139
+ totalFaces += mesh.faces.length;
1140
+ });
1141
+
1142
+ // 合并数组
1143
+ const mergedPoints = new Float32Array(totalPoints);
1144
+ const mergedFaces = new Uint32Array(totalFaces);
1145
+
1146
+ let pointOffset = 0; // 顶点偏移量 (按点坐标数量, 即 *3 后的下标)
1147
+ let faceOffset = 0; // 面的写入位置
1148
+ let indexOffset = 0; // 索引偏移量 (按顶点数量)
1149
+
1150
+ for (const mesh of meshes) {
1151
+ // 复制点
1152
+ mergedPoints.set(mesh.vertices, pointOffset);
1153
+
1154
+ // faces 要改索引
1155
+ const faces = mesh.faces;
1156
+ let i = 0;
1157
+ while (i < faces.length) {
1158
+ const n = faces[i]; // 面的顶点数量
1159
+ mergedFaces[faceOffset++] = n;
1160
+ for (let j = 1; j <= n; j++) {
1161
+ mergedFaces[faceOffset++] = faces[i + j] + indexOffset;
1162
+ }
1163
+ i += n + 1;
1164
+ }
1165
+
1166
+ pointOffset += mesh.vertices.length;
1167
+ indexOffset += mesh.vertices.length / 3; // 每个顶点占 3 个数
1168
+ }
1169
+
1170
+ return {
1171
+ vertices: mergedPoints,
1172
+ faces: mergedFaces,
1173
+ };
1174
+ }
1175
+
1092
1176
  /**
1093
1177
  * 计算网格的boundingBox
1094
- * @param { vtkPolyData } polydata 网格数据
1178
+ * @param { number[] | Float32Array } vertices 点数据
1095
1179
  * @returns 返回网格的boundingBox
1096
1180
  */
1097
- export function computeBoundingBox(polydata) {
1181
+ export function computeBoundingBox(vertices) {
1098
1182
  // 初始化最小值和最大值
1099
1183
  const min = vec3.fromValues(Infinity, Infinity, Infinity);
1100
1184
  const max = vec3.fromValues(-Infinity, -Infinity, -Infinity);
1101
1185
 
1102
1186
  // 从 vtkPolyData 中提取顶点数据(假设是 Float32Array 格式)
1103
- const points = polydata.getPoints().getData();
1187
+ const points = vertices;
1104
1188
  const numPoints = points.length / 3;
1105
1189
 
1106
1190
  // 遍历所有顶点
@@ -1124,11 +1208,11 @@ export function computeBoundingBox(polydata) {
1124
1208
 
1125
1209
  /**
1126
1210
  * 计算网格移动到相对自己中心位置的xyz偏移量
1127
- * @param { vtkPolyData } _polydata 网格
1211
+ * @param { number[] | Float32Array } vertices 点数据
1128
1212
  * @returns {{x: number, y: number, z: number}} 网格自己居中所需要的xyz偏移量
1129
1213
  */
1130
- export function getPolydataCenterOffset(_polydata) {
1131
- const _boundBox = computeBoundingBox(_polydata);
1214
+ export function getPolydataCenterOffset(vertices) {
1215
+ const _boundBox = computeBoundingBox(vertices);
1132
1216
  const _width = Math.abs(_boundBox.min[0] - _boundBox.max[0]);
1133
1217
  const _height = Math.abs(_boundBox.min[1] - _boundBox.max[1]);
1134
1218
  const _surface =Math.abs(_boundBox.min[2] - _boundBox.max[2]);