xl-public-utils 1.0.7 → 1.0.9

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
@@ -1,3 +1,4 @@
1
+ import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
1
2
  declare module "xl-public-utils" {
2
3
  export interface QrCodeOptions {
3
4
  /** 二维码类型,具体支持请查看文档 */
@@ -263,9 +264,23 @@ declare module "xl-public-utils" {
263
264
  /**
264
265
  * 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
265
266
  * @param {vtkPolyData} mesh 网格文件
267
+ * @param {number} byteLength=14 压缩率
268
+ * @returns {Blob} drc文件
269
+ */
270
+ export function createDrcBlob(
271
+ mesh: vtkPolyData,
272
+ byteLength?: number
273
+ ): Blob;
274
+ /**
275
+ * 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
276
+ * @param {Mesh} mesh 网格文件
277
+ * @param {number} byteLength=14 压缩率
266
278
  * @returns {Blob} drc文件
267
279
  */
268
- export function createDrcBlob(mesh: vtkPolyData): Blob;
280
+ export function createDrcBlob(
281
+ mesh: Mesh,
282
+ byteLength?: number
283
+ ): Blob;
269
284
  /**
270
285
  * 将网格输出为对应类型的Blob,均采用默认参数,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
271
286
  * @param {vtkPolyData} mesh 网格文件
@@ -355,15 +370,21 @@ declare module "xl-public-utils" {
355
370
  zangle: number
356
371
  ): mat3;
357
372
  /**
358
- * 将drc
359
- * @param {vtkPolyData} mesh 网格polyData
373
+ * 将polyData转换为Base64string
374
+ * @param {vtkPolyData} mesh 网格数据
360
375
  * @param {mat4} [matrix] 变换矩阵
376
+ * @param {number} byteLength=14 压缩率
361
377
  * @returns {string} drc压缩之后的网格base64
362
378
  */
363
- export function enCodeMeshToBase64(
364
- mesh: vtkPolyData,
365
- matrix?: mat4
366
- ): string;
379
+ export function enCodeMeshToBase64(mesh: vtkPolyData,matrix?: mat4,byteLength?: number): string;
380
+ /**
381
+ * 将polyData转换为Base64string
382
+ * @param {Mesh} mesh 网格数据
383
+ * @param {mat4} [matrix] 变换矩阵
384
+ * @param {number} byteLength=14 压缩率
385
+ * @returns {string} drc压缩之后的网格base64
386
+ */
387
+ export function enCodeMeshToBase64(mesh: Mesh,matrix?: mat4,byteLength?: number): string;
367
388
  /**
368
389
  * 将一圈有序点按指定size进行平滑
369
390
  * @param {vec3[]} points 一圈有序点
@@ -444,7 +465,28 @@ declare module "xl-public-utils" {
444
465
  * @param {boolean} [process] 是否需要预先对数据进行处理,stl默认(去重)
445
466
  * @returns {Promise<vtkPolyData>} vtkPolyData
446
467
  */
447
- export function loadMeshData(file: string | File | Blob, type?: "drc" | "stl" | "ply", process?: boolean): Promise<vtkPolyData>;
468
+ export function loadMeshData(
469
+ file: string | File | Blob,
470
+ type?: "drc" | "stl" | "ply",
471
+ process?: boolean
472
+ ): Promise<vtkPolyData>;
473
+ /**
474
+ * @typedef Plane
475
+ * @property {vec3} origin 对应vtk坐标系的x值
476
+ * @property {vec3} normal 对应vtk坐标系的y值
477
+ */
478
+ /**
479
+ * 将一组离散的三维点是使用PCA拟合一个平面结果和最小二乘结果近似
480
+ * @param {vec3[]} points 三维点
481
+ * @returns {Plane| null} 拟合的平面
482
+ */
483
+ export function pcaFitPlane(points: vec3[]): Plane | null;
484
+ /**
485
+ * 计算一组 3D 点的最佳拟合平面(最小二乘法)。
486
+ * @param {Array<vec3>} points - 3D 点数组,每个点是一个 vec3 向量。
487
+ * @returns {Plane|null} - 返回平面的 origin(质心)和 normal(法向量),如果点数少于 3 个则返回 null。
488
+ */
489
+ export function leastSquaresFitPlane(points: Array<vec3>): Plane | null;
448
490
  export type Position = {
449
491
  /**
450
492
  * 对应vtk坐标系的x值
@@ -476,6 +518,26 @@ declare module "xl-public-utils" {
476
518
  */
477
519
  z: vec3;
478
520
  };
521
+ export type Mesh = {
522
+ /**
523
+ * 点信息
524
+ */
525
+ vertices: number[][] | vec3[];
526
+ /**
527
+ * 面信息
528
+ */
529
+ faces: number[][] | vec3[];
530
+ };
531
+ export type Plane = {
532
+ /**
533
+ * 对应vtk坐标系的x值
534
+ */
535
+ origin: vec3;
536
+ /**
537
+ * 对应vtk坐标系的y值
538
+ */
539
+ normal: vec3;
540
+ };
479
541
  }
480
542
  export namespace drcUtils {
481
543
  export type AttrOption = {
@@ -519,11 +581,11 @@ declare module "xl-public-utils" {
519
581
  /**
520
582
  * 点信息
521
583
  */
522
- vertices: number[][];
584
+ vertices: number[][] | vec3[];
523
585
  /**
524
586
  * 面信息
525
587
  */
526
- faces: number[][];
588
+ faces: number[][] | vec3[];
527
589
  };
528
590
  /**
529
591
  * @typedef {Object} AttrOption
@@ -598,18 +660,30 @@ declare module "xl-public-utils" {
598
660
  export function enCloudPointTobase64(points: vec3[] | number[]): string;
599
661
  /**
600
662
  * @typedef {Object} Mesh
601
- * @property {number[][]} vertices 点信息
602
- * @property {number[][]} faces 面信息
663
+ * @property {number[][] | vec3[]} vertices 点信息
664
+ * @property {number[][] | vec3[]} faces 面信息
665
+ */
666
+ /**
667
+ * 使用drc压缩网格信息
668
+ * @param {vtkPolyData} mesh
669
+ * @param {number} byteLength=14 压缩率
670
+ * @param {AttrOption} [attr] 其他需要压缩的属性
671
+ * @returns {Int8Array} 压缩之后的DRC数据
603
672
  */
673
+ export function enCodeMesh(
674
+ mesh: vtkPolyData,
675
+ byteLength?: number,
676
+ attr?: AttrOption
677
+ ): Int8Array;
604
678
  /**
605
679
  * 使用drc压缩网格信息
606
- * @param {Mesh | vtkPolyData} mesh
680
+ * @param {Mesh} mesh
607
681
  * @param {number} byteLength=14 压缩率
608
682
  * @param {AttrOption} [attr] 其他需要压缩的属性
609
683
  * @returns {Int8Array} 压缩之后的DRC数据
610
684
  */
611
685
  export function enCodeMesh(
612
- mesh: Mesh | vtkPolyData,
686
+ mesh: Mesh,
613
687
  byteLength?: number,
614
688
  attr?: AttrOption
615
689
  ): Int8Array;
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.9",
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';