xl-public-utils 1.0.9 → 1.0.11
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 +19 -29
- package/package.json +1 -1
- package/src/drcUtils.js +6 -1
- package/src/vtkUtils.js +73 -86
- package/types/vtkUtils.d.ts +20 -12
package/index.d.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
|
|
2
|
+
import vtkRenderer from "@kitware/vtk.js/Rendering/Core/Renderer";
|
|
3
|
+
import { mat3, mat4, vec3 } from "gl-matrix";
|
|
4
|
+
import vtkInteractorStyleManipulator from "@kitware/vtk.js/Interaction/Style/InteractorStyleManipulator.js"
|
|
5
|
+
import vtkRenderWindowInteractor from "@kitware/vtk.js/Rendering/Core/RenderWindowInteractor.js";
|
|
6
|
+
|
|
2
7
|
declare module "xl-public-utils" {
|
|
8
|
+
|
|
9
|
+
export type Mesh = {
|
|
10
|
+
/**
|
|
11
|
+
* 点信息
|
|
12
|
+
*/
|
|
13
|
+
vertices: number[][] | vec3[];
|
|
14
|
+
/**
|
|
15
|
+
* 面信息
|
|
16
|
+
*/
|
|
17
|
+
faces: number[][] | vec3[];
|
|
18
|
+
};
|
|
3
19
|
export interface QrCodeOptions {
|
|
4
20
|
/** 二维码类型,具体支持请查看文档 */
|
|
5
21
|
bcid?: string; // 默认值 'qrcode'
|
|
@@ -391,14 +407,14 @@ declare module "xl-public-utils" {
|
|
|
391
407
|
* @param {number} smaSize=3 平滑点的数量通常值为奇数
|
|
392
408
|
* @returns {vec3[]} 平滑之后的点
|
|
393
409
|
*/
|
|
394
|
-
export function
|
|
410
|
+
export function smoothLoop(points: vec3[], smaSize?: number): vec3[];
|
|
395
411
|
/**
|
|
396
412
|
* 将一段有序点按指定size进行平滑
|
|
397
413
|
* @param {vec3[]} points 一段有序点
|
|
398
|
-
* @param {number}
|
|
414
|
+
* @param {number} smoothSize=3 平滑点的数量通常值为奇数
|
|
399
415
|
* @returns {vec3[]} 平滑之后的点
|
|
400
416
|
*/
|
|
401
|
-
export function
|
|
417
|
+
export function smoothCurve(points: vec3[], smoothSize?: number): vec3[];
|
|
402
418
|
/**
|
|
403
419
|
* 表示一个包含三个轴向的对象
|
|
404
420
|
* @typedef {Object} AxisObject
|
|
@@ -481,12 +497,6 @@ declare module "xl-public-utils" {
|
|
|
481
497
|
* @returns {Plane| null} 拟合的平面
|
|
482
498
|
*/
|
|
483
499
|
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;
|
|
490
500
|
export type Position = {
|
|
491
501
|
/**
|
|
492
502
|
* 对应vtk坐标系的x值
|
|
@@ -518,16 +528,6 @@ declare module "xl-public-utils" {
|
|
|
518
528
|
*/
|
|
519
529
|
z: vec3;
|
|
520
530
|
};
|
|
521
|
-
export type Mesh = {
|
|
522
|
-
/**
|
|
523
|
-
* 点信息
|
|
524
|
-
*/
|
|
525
|
-
vertices: number[][] | vec3[];
|
|
526
|
-
/**
|
|
527
|
-
* 面信息
|
|
528
|
-
*/
|
|
529
|
-
faces: number[][] | vec3[];
|
|
530
|
-
};
|
|
531
531
|
export type Plane = {
|
|
532
532
|
/**
|
|
533
533
|
* 对应vtk坐标系的x值
|
|
@@ -577,16 +577,6 @@ declare module "xl-public-utils" {
|
|
|
577
577
|
normals?: Float32Array;
|
|
578
578
|
};
|
|
579
579
|
export type Decoder = any;
|
|
580
|
-
export type Mesh = {
|
|
581
|
-
/**
|
|
582
|
-
* 点信息
|
|
583
|
-
*/
|
|
584
|
-
vertices: number[][] | vec3[];
|
|
585
|
-
/**
|
|
586
|
-
* 面信息
|
|
587
|
-
*/
|
|
588
|
-
faces: number[][] | vec3[];
|
|
589
|
-
};
|
|
590
580
|
/**
|
|
591
581
|
* @typedef {Object} AttrOption
|
|
592
582
|
* @property {number[]} [colors] 颜色数组
|
package/package.json
CHANGED
package/src/drcUtils.js
CHANGED
|
@@ -301,7 +301,12 @@ export function enCodeMesh(mesh, byteLength = 14, attr = undefined) {
|
|
|
301
301
|
let faces = [];
|
|
302
302
|
let vertices = [];
|
|
303
303
|
if(mesh.vertices && mesh.faces) {
|
|
304
|
-
|
|
304
|
+
for(let i =0; i<mesh.vertices.length; i++) {
|
|
305
|
+
const vertice = mesh.vertices[i];
|
|
306
|
+
vertices.push(vertice[0]);
|
|
307
|
+
vertices.push(vertice[1]);
|
|
308
|
+
vertices.push(vertice[2]);
|
|
309
|
+
}
|
|
305
310
|
for(let i = 0; i < mesh.faces.length; i++) {
|
|
306
311
|
const face = mesh.faces[i];
|
|
307
312
|
faces.push(face[0]);
|
package/src/vtkUtils.js
CHANGED
|
@@ -10,7 +10,7 @@ import vtkPLYReader from '@kitware/vtk.js/IO/Geometry/PLYReader';
|
|
|
10
10
|
import vtkSTLReader from '@kitware/vtk.js/IO/Geometry/STLReader';
|
|
11
11
|
import vtkDracoReader from '@kitware/vtk.js/IO/Geometry/DracoReader';
|
|
12
12
|
import vtkTriangleFilter from "@kitware/vtk.js/Filters/General/TriangleFilter";
|
|
13
|
-
import { vec3, mat4, mat3 } from 'gl-matrix';
|
|
13
|
+
import { vec3, mat4, mat3, quat } from 'gl-matrix';
|
|
14
14
|
import { exportBinarySTL } from './exportSTL.js';
|
|
15
15
|
import { writePLY } from "./exportPLY.js";
|
|
16
16
|
import { enCodeMesh } from './drcUtils.js';
|
|
@@ -619,40 +619,46 @@ export function calculateSimpleLerp(from, to, step) {
|
|
|
619
619
|
/**
|
|
620
620
|
* 将 mat3 解析为 3 个自由度的 欧拉角(Eular)(弧度)
|
|
621
621
|
* @param {mat3} rmat 3 * 3的矩阵
|
|
622
|
-
* @param {[number, number, number]}
|
|
622
|
+
* @param {[number, number, number]} euler 输出的欧拉角度数(弧度)
|
|
623
623
|
* @returns {[number, number, number]} 3个自由度的欧拉角
|
|
624
624
|
* @example
|
|
625
625
|
* const mt4: mat4;
|
|
626
626
|
* const mt3 = mat3.fromMat4(mt3, mt4);
|
|
627
627
|
* mat3.transpose(mt3, mt3);
|
|
628
|
-
* let
|
|
629
|
-
* convMatrix2EularZYX(mt3,
|
|
630
|
-
*/
|
|
631
|
-
export function convMatrix2EularZYX(rmat,
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
628
|
+
* let euler = [0, 0, 0];
|
|
629
|
+
* convMatrix2EularZYX(mt3, euler);
|
|
630
|
+
*/
|
|
631
|
+
export function convMatrix2EularZYX(rmat, euler) {
|
|
632
|
+
const R = mat3.transpose(mat3.create(),rmat);
|
|
633
|
+
// 计算pitch(绕Y轴)
|
|
634
|
+
const pitch = Math.atan2(-R[6], Math.sqrt(R[7] * R[7] + R[8] * R[8]));
|
|
635
|
+
|
|
636
|
+
// 处理万向节死锁(Gimbal Lock)
|
|
637
|
+
if (Math.abs(pitch - Math.PI/2) < 1e-3) { // pitch接近90度
|
|
638
|
+
vec3.set(
|
|
639
|
+
euler,
|
|
640
|
+
0.0, // roll
|
|
641
|
+
Math.PI/2, // pitch
|
|
642
|
+
Math.atan2(R[1], R[0]), // yaw
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
else if (Math.abs(pitch + Math.PI/2) < 1e-3) { // pitch接近-90度
|
|
646
|
+
vec3.set(
|
|
647
|
+
euler,
|
|
648
|
+
0.0, // roll
|
|
649
|
+
-Math.PI/2, // pitch
|
|
650
|
+
-Math.atan2(R[1], R[0]), // yaw
|
|
651
|
+
);
|
|
636
652
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
m32 = rmat[7],
|
|
645
|
-
m33 = rmat[8];
|
|
646
|
-
|
|
647
|
-
eular[1] = Math.asin(-fclamp(m31, -1, 1));
|
|
648
|
-
if (Math.abs(m31) < 0.9999999) {
|
|
649
|
-
eular[0] = Math.atan2(m32, m33);
|
|
650
|
-
eular[2] = Math.atan2(m21, m11);
|
|
651
|
-
} else {
|
|
652
|
-
eular[0] = 0;
|
|
653
|
-
eular[2] = Math.atan2(-m12, m22);
|
|
653
|
+
else {
|
|
654
|
+
vec3.set(
|
|
655
|
+
euler,
|
|
656
|
+
Math.atan2(R[7], R[8]), // roll
|
|
657
|
+
pitch, // pitch
|
|
658
|
+
Math.atan2(R[3], R[0]), // yaw
|
|
659
|
+
);
|
|
654
660
|
}
|
|
655
|
-
return
|
|
661
|
+
return euler;
|
|
656
662
|
}
|
|
657
663
|
|
|
658
664
|
|
|
@@ -668,7 +674,7 @@ export function convMatrix2EularZYX(rmat, eular) {
|
|
|
668
674
|
* const rotateY = 0.5;
|
|
669
675
|
* const rotateZ = 0.5;
|
|
670
676
|
* const mt3 = mat3.create();
|
|
671
|
-
* convEular2matrixZYX(mt3,
|
|
677
|
+
* convEular2matrixZYX(mt3, rotateX, rotateY, rotateZ)
|
|
672
678
|
*/
|
|
673
679
|
export function convEular2matrixZYX(rmat, xangle, yangle, zangle) {
|
|
674
680
|
let UnitZ = vec3.create();
|
|
@@ -739,8 +745,11 @@ export function enCodeMeshToBase64(mesh, matrix = undefined, byteLength = 14) {
|
|
|
739
745
|
* @returns {vec3[]} 平滑之后的点
|
|
740
746
|
*/
|
|
741
747
|
|
|
742
|
-
export function
|
|
748
|
+
export function smoothLoop(points, smaSize = 3) {
|
|
743
749
|
const newPoints = [];
|
|
750
|
+
if(points.length < smaSize) {
|
|
751
|
+
return points;
|
|
752
|
+
}
|
|
744
753
|
for (let i = 0; i < points.length; i++) {
|
|
745
754
|
const step = Math.floor(smaSize / 2);
|
|
746
755
|
const sumPoint = vec3.clone(points[i]);
|
|
@@ -760,13 +769,16 @@ export function smaPoint(points, smaSize = 3) {
|
|
|
760
769
|
/**
|
|
761
770
|
* 将一段有序点按指定size进行平滑
|
|
762
771
|
* @param {vec3[]} points 一段有序点
|
|
763
|
-
* @param {number}
|
|
772
|
+
* @param {number} smoothSize=3 平滑点的数量通常值为奇数
|
|
764
773
|
* @returns {vec3[]} 平滑之后的点
|
|
765
774
|
*/
|
|
766
|
-
export function
|
|
775
|
+
export function smoothCurve(points, smoothSize = 3) {
|
|
767
776
|
const newPoints= [];
|
|
777
|
+
if(points.length < smoothSize) {
|
|
778
|
+
return points;
|
|
779
|
+
}
|
|
768
780
|
for (let i = 0; i < points.length; i++) {
|
|
769
|
-
const step = Math.floor(
|
|
781
|
+
const step = Math.floor(smoothSize / 2);
|
|
770
782
|
let sumPoint = vec3.clone(points[i]);
|
|
771
783
|
for (let j = 1; j <= step; j++) {
|
|
772
784
|
let lastIndex = i - j;
|
|
@@ -786,7 +798,7 @@ export function smaPointNotRound(points, smaSize = 3) {
|
|
|
786
798
|
if (vec3.equals(sumPoint, points[i])) {
|
|
787
799
|
centerPoint = sumPoint;
|
|
788
800
|
} else {
|
|
789
|
-
centerPoint = vec3.scale(vec3.create(), sumPoint, 1 /
|
|
801
|
+
centerPoint = vec3.scale(vec3.create(), sumPoint, 1 / smoothSize);
|
|
790
802
|
}
|
|
791
803
|
newPoints.push(centerPoint);
|
|
792
804
|
}
|
|
@@ -970,63 +982,38 @@ export function pcaFitPlane(points) {
|
|
|
970
982
|
}
|
|
971
983
|
}
|
|
972
984
|
|
|
973
|
-
|
|
974
985
|
/**
|
|
975
|
-
*
|
|
976
|
-
* @param {
|
|
977
|
-
* @returns {
|
|
986
|
+
* 计算曲线长度
|
|
987
|
+
* @param {vec3[]} points 曲线
|
|
988
|
+
* @returns {number} 曲线长度
|
|
978
989
|
*/
|
|
979
|
-
export function leastSquaresFitPlane(points) {
|
|
980
|
-
if (points.length < 3) {
|
|
981
|
-
return null;
|
|
982
|
-
}
|
|
983
990
|
|
|
984
|
-
|
|
985
|
-
let
|
|
986
|
-
for (let
|
|
987
|
-
|
|
991
|
+
export function getCurveLength(points) {
|
|
992
|
+
let dist = 0;
|
|
993
|
+
for (let i = 1; i < points.length; i++) {
|
|
994
|
+
dist += vec3.dist(points[i - 1], points[i]);
|
|
988
995
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
// Step 2: 构建协方差矩阵
|
|
992
|
-
let xx = 0, xy = 0, xz = 0;
|
|
993
|
-
let yy = 0, yz = 0, zz = 0;
|
|
996
|
+
return dist;
|
|
997
|
+
}
|
|
994
998
|
|
|
995
|
-
for (let point of points) {
|
|
996
|
-
let r = vec3.sub(vec3.create(), point, centroid); // r = point - centroid
|
|
997
999
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1000
|
+
/**
|
|
1001
|
+
*
|
|
1002
|
+
* @param {vec3[]} points 曲线
|
|
1003
|
+
* @param {number} dist 目标点距离,绝对距离或者相对距离
|
|
1004
|
+
* @param {boolean} [absDist=true] 是否使用绝对距离
|
|
1005
|
+
* @returns
|
|
1006
|
+
*/
|
|
1007
|
+
export function getCurvePointIndexByLength(points, dist, absDist = true) {
|
|
1008
|
+
let allDist = getCurvePointDist(points);
|
|
1009
|
+
const targetDist = absDist ? dist : dist * allDist;
|
|
1010
|
+
let targetDistanceSubs = [targetDist];
|
|
1011
|
+
let distance = 0;
|
|
1012
|
+
for (let i = 1; i < points.length; i++) {
|
|
1013
|
+
distance += vec3.dist(points[i], points[i - 1])
|
|
1014
|
+
targetDistanceSubs.push(Math.abs(distance - targetDist))
|
|
1004
1015
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
-
};
|
|
1016
|
+
const minSub = Math.min(...targetDistanceSubs);
|
|
1017
|
+
const targetIndex = targetDistanceSubs.findIndex(i => i === minSub)
|
|
1018
|
+
return targetIndex;
|
|
1032
1019
|
}
|
package/types/vtkUtils.d.ts
CHANGED
|
@@ -215,16 +215,16 @@ export function calculateSimpleLerp(from: number, to: number, step: number): num
|
|
|
215
215
|
/**
|
|
216
216
|
* 将 mat3 解析为 3 个自由度的 欧拉角(Eular)(弧度)
|
|
217
217
|
* @param {mat3} rmat 3 * 3的矩阵
|
|
218
|
-
* @param {[number, number, number]}
|
|
218
|
+
* @param {[number, number, number]} euler 输出的欧拉角度数(弧度)
|
|
219
219
|
* @returns {[number, number, number]} 3个自由度的欧拉角
|
|
220
220
|
* @example
|
|
221
221
|
* const mt4: mat4;
|
|
222
222
|
* const mt3 = mat3.fromMat4(mt3, mt4);
|
|
223
223
|
* mat3.transpose(mt3, mt3);
|
|
224
|
-
* let
|
|
225
|
-
* convMatrix2EularZYX(mt3,
|
|
224
|
+
* let euler = [0, 0, 0];
|
|
225
|
+
* convMatrix2EularZYX(mt3, euler);
|
|
226
226
|
*/
|
|
227
|
-
export function convMatrix2EularZYX(rmat: mat3,
|
|
227
|
+
export function convMatrix2EularZYX(rmat: mat3, euler: [number, number, number]): [number, number, number];
|
|
228
228
|
/**
|
|
229
229
|
* 将欧拉角(Eular)转换为mat3
|
|
230
230
|
* @param {mat3} rmat 变换矩阵
|
|
@@ -237,7 +237,7 @@ export function convMatrix2EularZYX(rmat: mat3, eular: [number, number, number])
|
|
|
237
237
|
* const rotateY = 0.5;
|
|
238
238
|
* const rotateZ = 0.5;
|
|
239
239
|
* const mt3 = mat3.create();
|
|
240
|
-
* convEular2matrixZYX(mt3,
|
|
240
|
+
* convEular2matrixZYX(mt3, rotateX, rotateY, rotateZ)
|
|
241
241
|
*/
|
|
242
242
|
export function convEular2matrixZYX(rmat: mat3, xangle: number, yangle: number, zangle: number): mat3;
|
|
243
243
|
/**
|
|
@@ -254,14 +254,14 @@ export function enCodeMeshToBase64(mesh: vtkPolyData | Mesh, matrix?: mat4, byte
|
|
|
254
254
|
* @param {number} smaSize=3 平滑点的数量通常值为奇数
|
|
255
255
|
* @returns {vec3[]} 平滑之后的点
|
|
256
256
|
*/
|
|
257
|
-
export function
|
|
257
|
+
export function smoothLoop(points: vec3[], smaSize?: number): vec3[];
|
|
258
258
|
/**
|
|
259
259
|
* 将一段有序点按指定size进行平滑
|
|
260
260
|
* @param {vec3[]} points 一段有序点
|
|
261
|
-
* @param {number}
|
|
261
|
+
* @param {number} smoothSize=3 平滑点的数量通常值为奇数
|
|
262
262
|
* @returns {vec3[]} 平滑之后的点
|
|
263
263
|
*/
|
|
264
|
-
export function
|
|
264
|
+
export function smoothCurve(points: vec3[], smoothSize?: number): vec3[];
|
|
265
265
|
/**
|
|
266
266
|
* 表示一个包含三个轴向的对象
|
|
267
267
|
* @typedef {Object} AxisObject
|
|
@@ -307,11 +307,19 @@ export function loadMeshData(file: string | File | Blob, type?: "drc" | "stl" |
|
|
|
307
307
|
*/
|
|
308
308
|
export function pcaFitPlane(points: vec3[]): Plane | null;
|
|
309
309
|
/**
|
|
310
|
-
*
|
|
311
|
-
* @param {
|
|
312
|
-
* @returns {
|
|
310
|
+
* 计算曲线长度
|
|
311
|
+
* @param {vec3[]} points 曲线
|
|
312
|
+
* @returns {number} 曲线长度
|
|
313
|
+
*/
|
|
314
|
+
export function getCurveLength(points: vec3[]): number;
|
|
315
|
+
/**
|
|
316
|
+
*
|
|
317
|
+
* @param {vec3[]} points 曲线
|
|
318
|
+
* @param {number} dist 目标点距离,绝对距离或者相对距离
|
|
319
|
+
* @param {boolean} [absDist=true] 是否使用绝对距离
|
|
320
|
+
* @returns
|
|
313
321
|
*/
|
|
314
|
-
export function
|
|
322
|
+
export function getCurvePointIndexByLength(points: vec3[], dist: number, absDist?: boolean): number;
|
|
315
323
|
/**
|
|
316
324
|
* 计算 w2l(word 2 local, word to local) 的变换矩阵
|
|
317
325
|
* @param {vec3} center 中心点
|