xl-public-utils 1.0.7 → 1.0.8

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
@@ -262,10 +262,14 @@ declare module "xl-public-utils" {
262
262
  export function createStlBlob(mesh: vtkPolyData): Blob;
263
263
  /**
264
264
  * 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
265
- * @param {vtkPolyData} mesh 网格文件
265
+ * @param {vtkPolyData | Mesh} mesh 网格文件
266
+ * @param {number} byteLength=14 压缩率
266
267
  * @returns {Blob} drc文件
267
268
  */
268
- export function createDrcBlob(mesh: vtkPolyData): Blob;
269
+ export function createDrcBlob(
270
+ mesh: vtkPolyData | Mesh,
271
+ byteLength?: number
272
+ ): Blob;
269
273
  /**
270
274
  * 将网格输出为对应类型的Blob,均采用默认参数,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
271
275
  * @param {vtkPolyData} mesh 网格文件
@@ -355,14 +359,16 @@ declare module "xl-public-utils" {
355
359
  zangle: number
356
360
  ): mat3;
357
361
  /**
358
- * 将drc
359
- * @param {vtkPolyData} mesh 网格polyData
362
+ * 将polyData转换为Base64string
363
+ * @param {vtkPolyData | Mesh} mesh 网格数据
360
364
  * @param {mat4} [matrix] 变换矩阵
365
+ * @param {number} byteLength=14 压缩率
361
366
  * @returns {string} drc压缩之后的网格base64
362
367
  */
363
368
  export function enCodeMeshToBase64(
364
- mesh: vtkPolyData,
365
- matrix?: mat4
369
+ mesh: vtkPolyData | Mesh,
370
+ matrix?: mat4,
371
+ byteLength?: number
366
372
  ): string;
367
373
  /**
368
374
  * 将一圈有序点按指定size进行平滑
@@ -444,7 +450,28 @@ declare module "xl-public-utils" {
444
450
  * @param {boolean} [process] 是否需要预先对数据进行处理,stl默认(去重)
445
451
  * @returns {Promise<vtkPolyData>} vtkPolyData
446
452
  */
447
- export function loadMeshData(file: string | File | Blob, type?: "drc" | "stl" | "ply", process?: boolean): Promise<vtkPolyData>;
453
+ export function loadMeshData(
454
+ file: string | File | Blob,
455
+ type?: "drc" | "stl" | "ply",
456
+ process?: boolean
457
+ ): Promise<vtkPolyData>;
458
+ /**
459
+ * @typedef Plane
460
+ * @property {vec3} origin 对应vtk坐标系的x值
461
+ * @property {vec3} normal 对应vtk坐标系的y值
462
+ */
463
+ /**
464
+ * 将一组离散的三维点是使用PCA拟合一个平面结果和最小二乘结果近似
465
+ * @param {vec3[]} points 三维点
466
+ * @returns {Plane| null} 拟合的平面
467
+ */
468
+ export function pcaFitPlane(points: vec3[]): Plane | null;
469
+ /**
470
+ * 计算一组 3D 点的最佳拟合平面(最小二乘法)。
471
+ * @param {Array<vec3>} points - 3D 点数组,每个点是一个 vec3 向量。
472
+ * @returns {Plane|null} - 返回平面的 origin(质心)和 normal(法向量),如果点数少于 3 个则返回 null。
473
+ */
474
+ export function leastSquaresFitPlane(points: Array<vec3>): Plane | null;
448
475
  export type Position = {
449
476
  /**
450
477
  * 对应vtk坐标系的x值
@@ -476,6 +503,26 @@ declare module "xl-public-utils" {
476
503
  */
477
504
  z: vec3;
478
505
  };
506
+ export type Mesh = {
507
+ /**
508
+ * 点信息
509
+ */
510
+ vertices: number[][] | vec3[];
511
+ /**
512
+ * 面信息
513
+ */
514
+ faces: number[][] | vec3[];
515
+ };
516
+ export type Plane = {
517
+ /**
518
+ * 对应vtk坐标系的x值
519
+ */
520
+ origin: vec3;
521
+ /**
522
+ * 对应vtk坐标系的y值
523
+ */
524
+ normal: vec3;
525
+ };
479
526
  }
480
527
  export namespace drcUtils {
481
528
  export type AttrOption = {
@@ -519,11 +566,11 @@ declare module "xl-public-utils" {
519
566
  /**
520
567
  * 点信息
521
568
  */
522
- vertices: number[][];
569
+ vertices: number[][] | vec3[];
523
570
  /**
524
571
  * 面信息
525
572
  */
526
- faces: number[][];
573
+ faces: number[][] | vec3[];
527
574
  };
528
575
  /**
529
576
  * @typedef {Object} AttrOption
@@ -598,8 +645,8 @@ declare module "xl-public-utils" {
598
645
  export function enCloudPointTobase64(points: vec3[] | number[]): string;
599
646
  /**
600
647
  * @typedef {Object} Mesh
601
- * @property {number[][]} vertices 点信息
602
- * @property {number[][]} faces 面信息
648
+ * @property {number[][] | vec3[]} vertices 点信息
649
+ * @property {number[][] | vec3[]} faces 面信息
603
650
  */
604
651
  /**
605
652
  * 使用drc压缩网格信息
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xl-public-utils",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
package/src/drcUtils.js CHANGED
@@ -285,8 +285,8 @@ export function enCloudPointTobase64(points) {
285
285
 
286
286
  /**
287
287
  * @typedef {Object} Mesh
288
- * @property {number[][]} vertices 点信息
289
- * @property {number[][]} faces 面信息
288
+ * @property {number[][] | vec3[]} vertices 点信息
289
+ * @property {number[][] | vec3[]} faces 面信息
290
290
  */
291
291
 
292
292
  /**
package/src/vtkUtils.js CHANGED
@@ -437,13 +437,20 @@ export function createStlBlob(mesh) {
437
437
  return blob;
438
438
  }
439
439
 
440
+ /**
441
+ * @typedef {Object} Mesh
442
+ * @property {number[][] | vec3[]} vertices 点信息
443
+ * @property {number[][] | vec3[]} faces 面信息
444
+ */
445
+
440
446
  /**
441
447
  * 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
442
- * @param {vtkPolyData} mesh 网格文件
448
+ * @param {vtkPolyData | Mesh} mesh 网格文件
449
+ * @param {number} byteLength=14 压缩率
443
450
  * @returns {Blob} drc文件
444
451
  */
445
- export function createDrcBlob(mesh) {
446
- const blob = new Blob([enCodeMesh(mesh)]);
452
+ export function createDrcBlob(mesh, byteLength = 14) {
453
+ const blob = new Blob([enCodeMesh(mesh ,byteLength)]);
447
454
  return blob;
448
455
  }
449
456
 
@@ -707,19 +714,22 @@ export function convEular2matrixZYX(rmat, xangle, yangle, zangle) {
707
714
  }
708
715
 
709
716
  /**
710
- * 将drc
711
- * @param {vtkPolyData} mesh 网格polyData
717
+ * 将polyData转换为Base64string
718
+ * @param {vtkPolyData | Mesh} mesh 网格数据
712
719
  * @param {mat4} [matrix] 变换矩阵
720
+ * @param {number} byteLength=14 压缩率
713
721
  * @returns {string} drc压缩之后的网格base64
714
722
  */
715
- export function enCodeMeshToBase64(mesh, matrix = undefined) {
716
- const encodePolydata = vtkPolyData.newInstance();
717
- encodePolydata.getPoints().setData([...mesh.getPoints().getData()]);
718
- encodePolydata.getPolys().setData([...mesh.getPolys().getData()]);
723
+ export function enCodeMeshToBase64(mesh, matrix = undefined, byteLength = 14) {
719
724
  if(matrix) {
725
+ const encodePolydata = vtkPolyData.newInstance();
726
+ encodePolydata.getPoints().setData([...mesh.getPoints().getData()]);
727
+ encodePolydata.getPolys().setData([...mesh.getPolys().getData()]);
720
728
  pointsApplyMat4(matrix, encodePolydata);
729
+ return int8ArrayToBase64(enCodeMesh(encodePolydata, byteLength))
730
+ } else {
731
+ return int8ArrayToBase64(enCodeMesh(mesh, byteLength))
721
732
  }
722
- return int8ArrayToBase64(enCodeMesh(encodePolydata))
723
733
  }
724
734
 
725
735
  /**
@@ -900,4 +910,123 @@ export async function loadMeshData(file, type = undefined, process = undefined)
900
910
  }
901
911
  }
902
912
  return polyData;
913
+ }
914
+
915
+ /**
916
+ * @typedef Plane
917
+ * @property {vec3} origin 对应vtk坐标系的x值
918
+ * @property {vec3} normal 对应vtk坐标系的y值
919
+ */
920
+
921
+ /**
922
+ * 将一组离散的三维点是使用PCA拟合一个平面结果和最小二乘结果近似
923
+ * @param {vec3[]} points 三维点
924
+ * @returns {Plane| null} 拟合的平面
925
+ */
926
+ export function pcaFitPlane(points) {
927
+ if (points.length < 3) {
928
+ return null;
929
+ }
930
+ let sum = vec3.create();
931
+ for(let i of points) {
932
+ vec3.add(sum, sum, i)
933
+ }
934
+ const centroid = vec3.scale(vec3.create(), sum, 1 / points.length)
935
+ let xx = 0, xy = 0, xz = 0, yy = 0, yz= 0, zz = 0;
936
+ for(let i of points) {
937
+ let r = vec3.sub(vec3.create(), i, centroid);
938
+ xx += r[0] * r[0];
939
+ xy += r[0] * r[1];
940
+ xz += r[0] * r[2];
941
+ yy += r[1] * r[1];
942
+ yz += r[1] * r[2];
943
+ zz += r[2] * r[2];
944
+ }
945
+ let det_x = yy * zz - yz * yz;
946
+ let det_y = xx * zz - xz * xz;
947
+ let det_z = xx * yy - xy * xy;
948
+ let det_max = Math.max(det_x, det_y, det_z);
949
+ if(det_max <= 0.0) {
950
+ return null;
951
+ }
952
+ let normal = vec3.create();
953
+ if(det_max === det_x) {
954
+ normal[0] = det_x;
955
+ normal[1] = xz * yz - xy * zz;
956
+ normal[2] = xy * yz - xz * yy;
957
+ } else if(det_max === det_y) {
958
+ normal[0] = xz * yz - xy * zz;
959
+ normal[1] = det_x;
960
+ normal[2] = xy * xz - yz * xx;
961
+ } else {
962
+ normal[0] = xy * yz - xz * yy;
963
+ normal[1] = xy * xz - yz * xx;
964
+ normal[2] = det_z;
965
+ }
966
+ vec3.normalize(normal, normal);
967
+ return {
968
+ origin: centroid,
969
+ normal: normal,
970
+ }
971
+ }
972
+
973
+
974
+ /**
975
+ * 计算一组 3D 点的最佳拟合平面(最小二乘法)。
976
+ * @param {Array<vec3>} points - 3D 点数组,每个点是一个 vec3 向量。
977
+ * @returns {Plane|null} - 返回平面的 origin(质心)和 normal(法向量),如果点数少于 3 个则返回 null。
978
+ */
979
+ export function leastSquaresFitPlane(points) {
980
+ if (points.length < 3) {
981
+ return null;
982
+ }
983
+
984
+ // Step 1: 计算质心(origin)
985
+ let centroid = vec3.create();
986
+ for (let point of points) {
987
+ vec3.add(centroid, centroid, point);
988
+ }
989
+ vec3.scale(centroid, centroid, 1 / points.length);
990
+
991
+ // Step 2: 构建协方差矩阵
992
+ let xx = 0, xy = 0, xz = 0;
993
+ let yy = 0, yz = 0, zz = 0;
994
+
995
+ for (let point of points) {
996
+ let r = vec3.sub(vec3.create(), point, centroid); // r = point - centroid
997
+
998
+ xx += r[0] * r[0];
999
+ xy += r[0] * r[1];
1000
+ xz += r[0] * r[2];
1001
+ yy += r[1] * r[1];
1002
+ yz += r[1] * r[2];
1003
+ zz += r[2] * r[2];
1004
+ }
1005
+
1006
+ // 协方差矩阵
1007
+ const covarianceMatrix = mat3.fromValues(
1008
+ xx, xy, xz,
1009
+ xy, yy, yz,
1010
+ xz, yz, zz
1011
+ );
1012
+
1013
+ // Step 3: 计算协方差矩阵的特征值和特征向量
1014
+ const eigenVectors = mat3.create();
1015
+ const eigenValues = vec3.create();
1016
+ mat3.eigenDecomposition(eigenValues, eigenVectors, covarianceMatrix);
1017
+
1018
+ // Step 4: 选择最小特征值对应的特征向量作为法向量
1019
+ const minEigenIndex = eigenValues.indexOf(Math.min(...eigenValues));
1020
+ const normal = vec3.fromValues(
1021
+ eigenVectors[3 * minEigenIndex + 0],
1022
+ eigenVectors[3 * minEigenIndex + 1],
1023
+ eigenVectors[3 * minEigenIndex + 2]
1024
+ );
1025
+
1026
+ vec3.normalize(normal, normal); // 单位化法向量
1027
+
1028
+ return {
1029
+ origin: centroid,
1030
+ normal: normal
1031
+ };
903
1032
  }
@@ -63,8 +63,8 @@ export function getDracoAttributeAsFloat32Array(dracoGeometry: Decoder, attribut
63
63
  export function enCloudPointTobase64(points: vec3[] | number[]): string;
64
64
  /**
65
65
  * @typedef {Object} Mesh
66
- * @property {number[][]} vertices 点信息
67
- * @property {number[][]} faces 面信息
66
+ * @property {number[][] | vec3[]} vertices 点信息
67
+ * @property {number[][] | vec3[]} faces 面信息
68
68
  */
69
69
  /**
70
70
  * 使用drc压缩网格信息
@@ -119,11 +119,11 @@ export type Mesh = {
119
119
  /**
120
120
  * 点信息
121
121
  */
122
- vertices: number[][];
122
+ vertices: number[][] | vec3[];
123
123
  /**
124
124
  * 面信息
125
125
  */
126
- faces: number[][];
126
+ faces: number[][] | vec3[];
127
127
  };
128
128
  import { vec3 } from "gl-matrix";
129
129
  import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
@@ -154,12 +154,18 @@ export function createPlyBlob(mesh: vtkPolyData, format?: "ascii" | "binary"): B
154
154
  * @returns {Blob} 网格的BinarySTL文件Blob
155
155
  */
156
156
  export function createStlBlob(mesh: vtkPolyData): Blob;
157
+ /**
158
+ * @typedef {Object} Mesh
159
+ * @property {number[][] | vec3[]} vertices 点信息
160
+ * @property {number[][] | vec3[]} faces 面信息
161
+ */
157
162
  /**
158
163
  * 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
159
- * @param {vtkPolyData} mesh 网格文件
164
+ * @param {vtkPolyData | Mesh} mesh 网格文件
165
+ * @param {number} byteLength=14 压缩率
160
166
  * @returns {Blob} drc文件
161
167
  */
162
- export function createDrcBlob(mesh: vtkPolyData): Blob;
168
+ export function createDrcBlob(mesh: vtkPolyData | Mesh, byteLength?: number): Blob;
163
169
  /**
164
170
  * 将网格输出为对应类型的Blob,均采用默认参数,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
165
171
  * @param {vtkPolyData} mesh 网格文件
@@ -235,12 +241,13 @@ export function convMatrix2EularZYX(rmat: mat3, eular: [number, number, number])
235
241
  */
236
242
  export function convEular2matrixZYX(rmat: mat3, xangle: number, yangle: number, zangle: number): mat3;
237
243
  /**
238
- * 将drc
239
- * @param {vtkPolyData} mesh 网格polyData
244
+ * 将polyData转换为Base64string
245
+ * @param {vtkPolyData | Mesh} mesh 网格数据
240
246
  * @param {mat4} [matrix] 变换矩阵
247
+ * @param {number} byteLength=14 压缩率
241
248
  * @returns {string} drc压缩之后的网格base64
242
249
  */
243
- export function enCodeMeshToBase64(mesh: vtkPolyData, matrix?: mat4): string;
250
+ export function enCodeMeshToBase64(mesh: vtkPolyData | Mesh, matrix?: mat4, byteLength?: number): string;
244
251
  /**
245
252
  * 将一圈有序点按指定size进行平滑
246
253
  * @param {vec3[]} points 一圈有序点
@@ -288,6 +295,23 @@ export function trianglePolys(polydata: vtkPolyData): vtkPolyData;
288
295
  * @returns {Promise<vtkPolyData>} vtkPolyData
289
296
  */
290
297
  export function loadMeshData(file: string | File | Blob, type?: "drc" | "stl" | "ply", process?: boolean): Promise<vtkPolyData>;
298
+ /**
299
+ * @typedef Plane
300
+ * @property {vec3} origin 对应vtk坐标系的x值
301
+ * @property {vec3} normal 对应vtk坐标系的y值
302
+ */
303
+ /**
304
+ * 将一组离散的三维点是使用PCA拟合一个平面结果和最小二乘结果近似
305
+ * @param {vec3[]} points 三维点
306
+ * @returns {Plane| null} 拟合的平面
307
+ */
308
+ export function pcaFitPlane(points: vec3[]): Plane | null;
309
+ /**
310
+ * 计算一组 3D 点的最佳拟合平面(最小二乘法)。
311
+ * @param {Array<vec3>} points - 3D 点数组,每个点是一个 vec3 向量。
312
+ * @returns {Plane|null} - 返回平面的 origin(质心)和 normal(法向量),如果点数少于 3 个则返回 null。
313
+ */
314
+ export function leastSquaresFitPlane(points: Array<vec3>): Plane | null;
291
315
  /**
292
316
  * 计算 w2l(word 2 local, word to local) 的变换矩阵
293
317
  * @param {vec3} center 中心点
@@ -306,6 +330,16 @@ export function getmatw2l(center: vec3, xaxis: vec3, yaxis: vec3, zaxis: vec3):
306
330
  * @returns { mat4 } 变换矩阵
307
331
  */
308
332
  export function getmatofl2w(center: vec3, xaxis: vec3, yaxis: vec3, zaxis: vec3): mat4;
333
+ export type Mesh = {
334
+ /**
335
+ * 点信息
336
+ */
337
+ vertices: number[][] | vec3[];
338
+ /**
339
+ * 面信息
340
+ */
341
+ faces: number[][] | vec3[];
342
+ };
309
343
  export type Position = {
310
344
  /**
311
345
  * 对应vtk坐标系的x值
@@ -337,6 +371,16 @@ export type AxisObject = {
337
371
  */
338
372
  z: vec3;
339
373
  };
374
+ export type Plane = {
375
+ /**
376
+ * 对应vtk坐标系的x值
377
+ */
378
+ origin: vec3;
379
+ /**
380
+ * 对应vtk坐标系的y值
381
+ */
382
+ normal: vec3;
383
+ };
340
384
  import vtkRenderer from "@kitware/vtk.js/Rendering/Core/Renderer.js";
341
385
  import { vec3 } from 'gl-matrix';
342
386
  import { mat4 } from 'gl-matrix';