xl-public-utils 1.0.6 → 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 +965 -901
- package/index.js +5 -5
- package/package.json +33 -8
- package/src/{bwip-js.mjs → bwip-js.js} +1 -1
- package/src/{drcUtils.mjs → drcUtils.js} +4 -4
- package/src/{exportPLY.mjs → exportPLY.js} +1 -2
- package/src/{exportSTL.mjs → exportSTL.js} +1 -1
- package/src/{qrcode.mjs → qrcode.js} +1 -1
- package/src/{utils.mjs → utils.js} +10 -0
- package/src/{vtkUtils.mjs → vtkUtils.js} +252 -27
- package/tsconfig.json +2 -2
- package/types/{bwip-js.d.mts → bwip-js.d.ts} +1 -1
- package/types/{drcUtils.d.mts → drcUtils.d.ts} +5 -5
- package/types/{exportPLY.d.mts → exportPLY.d.ts} +1 -1
- package/types/{exportSTL.d.mts → exportSTL.d.ts} +1 -1
- package/types/{utils.d.mts → utils.d.ts} +6 -0
- package/types/{vtkUtils.d.mts → vtkUtils.d.ts} +81 -12
- /package/src/{bwipp.mjs → bwipp.js} +0 -0
- /package/types/{bwipp.d.mts → bwipp.d.ts} +0 -0
- /package/types/{qrcode.d.mts → qrcode.d.ts} +0 -0
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as vtkUtils from './src/vtkUtils.
|
|
2
|
-
import * as utils from './src/utils.
|
|
3
|
-
import * as qrcode from './src/qrcode.
|
|
4
|
-
import * as BwipJs from './src/bwip-js.
|
|
5
|
-
import * as drcUtils from './src/drcUtils.
|
|
1
|
+
import * as vtkUtils from './src/vtkUtils.js';
|
|
2
|
+
import * as utils from './src/utils.js'
|
|
3
|
+
import * as qrcode from './src/qrcode.js'
|
|
4
|
+
import * as BwipJs from './src/bwip-js.js';
|
|
5
|
+
import * as drcUtils from './src/drcUtils.js';
|
|
6
6
|
export { vtkUtils, utils, qrcode, BwipJs, drcUtils };
|
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xl-public-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "",
|
|
5
|
-
"type": "module",
|
|
6
5
|
"main": "index.js",
|
|
7
6
|
"module": "index.js",
|
|
8
7
|
"types": "index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"src/",
|
|
10
|
+
"types/",
|
|
11
|
+
"index.d.ts",
|
|
12
|
+
"index.js",
|
|
13
|
+
"package.json",
|
|
14
|
+
"tsconfig.json"
|
|
15
|
+
],
|
|
9
16
|
"peerDependencies": {
|
|
10
17
|
"@kitware/vtk.js": ">=25.7.2",
|
|
11
18
|
"gl-matrix": ">=3.4.3"
|
|
@@ -20,13 +27,17 @@
|
|
|
20
27
|
},
|
|
21
28
|
"exports": {
|
|
22
29
|
".": "./index.js",
|
|
23
|
-
"./qrcode": "./src/qrcode.
|
|
24
|
-
"./vtkUtils": "./src/vtkUtils.
|
|
25
|
-
"./utils": "./src/utils.
|
|
26
|
-
"./bwipJs": "./src/bwip-js.
|
|
30
|
+
"./qrcode": "./src/qrcode.js",
|
|
31
|
+
"./vtkUtils": "./src/vtkUtils.js",
|
|
32
|
+
"./utils": "./src/utils.js",
|
|
33
|
+
"./bwipJs": "./src/bwip-js.js"
|
|
27
34
|
},
|
|
28
35
|
"scripts": {
|
|
29
|
-
"test": "
|
|
36
|
+
"test": "karma start",
|
|
37
|
+
"docs:dev": "vitepress dev docs",
|
|
38
|
+
"docs:build": "vitepress build docs",
|
|
39
|
+
"docs:preview": "vitepress preview docs",
|
|
40
|
+
"docs:gen": "dts2md types/*.d.ts -o docs"
|
|
30
41
|
},
|
|
31
42
|
"keywords": [
|
|
32
43
|
"一些通用方法"
|
|
@@ -34,6 +45,20 @@
|
|
|
34
45
|
"author": "xl",
|
|
35
46
|
"license": "ISC",
|
|
36
47
|
"devDependencies": {
|
|
37
|
-
"
|
|
48
|
+
"@babel/core": "^7.26.0",
|
|
49
|
+
"@babel/preset-env": "^7.26.0",
|
|
50
|
+
"babel-loader": "^9.2.1",
|
|
51
|
+
"chai": "^5.1.2",
|
|
52
|
+
"karma": "^6.4.4",
|
|
53
|
+
"karma-chai": "^0.1.0",
|
|
54
|
+
"karma-chrome-launcher": "^3.2.0",
|
|
55
|
+
"karma-cli": "^2.0.0",
|
|
56
|
+
"karma-mocha": "^2.0.1",
|
|
57
|
+
"karma-mocha-reporter": "^2.2.5",
|
|
58
|
+
"karma-webpack": "^5.0.1",
|
|
59
|
+
"mocha": "^10.8.2",
|
|
60
|
+
"typescript": "^5.6.3",
|
|
61
|
+
"vitepress": "^1.5.0",
|
|
62
|
+
"webpack": "^5.96.1"
|
|
38
63
|
}
|
|
39
64
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
//
|
|
31
31
|
"use strict";
|
|
32
32
|
|
|
33
|
-
import { bwipp_datamatrix,bwipp_qrcode,bwipp_lookup,bwipp_encode,BWIPP_VERSION } from './bwipp.
|
|
33
|
+
import { bwipp_datamatrix,bwipp_qrcode,bwipp_lookup,bwipp_encode,BWIPP_VERSION } from './bwipp.js';
|
|
34
34
|
|
|
35
35
|
// exports.js
|
|
36
36
|
const BWIPJS_VERSION = '4.5.1 (2024-08-12)';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { vec3 } from "gl-matrix";
|
|
2
|
-
import { int8ArrayToBase64 } from './utils.
|
|
3
|
-
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
|
|
2
|
+
import { int8ArrayToBase64 } from './utils.js'
|
|
3
|
+
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {Object} AttrOption
|
|
6
6
|
* @property {number[]} [colors] 颜色数组
|
|
@@ -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
|
/**
|
|
@@ -71,4 +71,14 @@ export function arrayBufferToBase64(outputBuffer) {
|
|
|
71
71
|
const outputData = new Int8Array(outputBuffer);
|
|
72
72
|
|
|
73
73
|
return int8ArrayToBase64(outputData)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取文件后缀
|
|
78
|
+
* @param {string} fileName 文件名,或者文件地址
|
|
79
|
+
* @returns 文件后缀
|
|
80
|
+
*/
|
|
81
|
+
export function getFileExtension(fileName) {
|
|
82
|
+
const _str = fileName.split('?')[0].split('.').pop();
|
|
83
|
+
return _str ? _str.toLowerCase() : '';
|
|
74
84
|
}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import vtkRenderer from "@kitware/vtk.js/Rendering/Core/Renderer";
|
|
2
|
-
import vtkInteractorStyleManipulator from "@kitware/vtk.js/Interaction/Style/InteractorStyleManipulator"
|
|
3
|
-
import vtkMouseCameraTrackballPanManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballPanManipulator";
|
|
4
|
-
import vtkMouseCameraTrackballRotateManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballRotateManipulator";
|
|
5
|
-
import vtkMouseCameraTrackballZoomManipulator from "@kitware/vtk.js/Interaction/Manipulators/MouseCameraTrackballZoomManipulator";
|
|
6
|
-
import vtkRenderWindowInteractor from "@kitware/vtk.js/Rendering/Core/RenderWindowInteractor";
|
|
7
|
-
import vtkMatrixBuilder from "@kitware/vtk.js/Common/Core/MatrixBuilder";
|
|
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
|
+
import vtkRenderWindowInteractor from "@kitware/vtk.js/Rendering/Core/RenderWindowInteractor.js";
|
|
7
|
+
import vtkMatrixBuilder from "@kitware/vtk.js/Common/Core/MatrixBuilder.js";
|
|
8
|
+
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
|
|
9
|
+
import vtkPLYReader from '@kitware/vtk.js/IO/Geometry/PLYReader';
|
|
10
|
+
import vtkSTLReader from '@kitware/vtk.js/IO/Geometry/STLReader';
|
|
11
|
+
import vtkDracoReader from '@kitware/vtk.js/IO/Geometry/DracoReader';
|
|
12
|
+
import vtkTriangleFilter from "@kitware/vtk.js/Filters/General/TriangleFilter";
|
|
8
13
|
import { vec3, mat4, mat3 } from 'gl-matrix';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { int8ArrayToBase64 } from "./utils.mjs";
|
|
14
|
+
import { exportBinarySTL } from './exportSTL.js';
|
|
15
|
+
import { writePLY } from "./exportPLY.js";
|
|
16
|
+
import { enCodeMesh } from './drcUtils.js';
|
|
17
|
+
import { getFileExtension, int8ArrayToBase64 } from "./utils.js";
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* 计算屏幕坐标到三维坐标
|
|
@@ -418,8 +422,6 @@ export function vecTransfromByMat4(vec, matrix) {
|
|
|
418
422
|
* @returns {Blob} 网格的ply文件Blob
|
|
419
423
|
*/
|
|
420
424
|
export function createPlyBlob(mesh, format = 'ascii') {
|
|
421
|
-
// const data = deduplicatePolyData(mesh)
|
|
422
|
-
// const deduplicateData = deduplicatePolyData(mesh);
|
|
423
425
|
const fileContents = writePLY(mesh, format);
|
|
424
426
|
const blob = new Blob([fileContents], { type: "application/octet-steam" });
|
|
425
427
|
return blob;
|
|
@@ -435,13 +437,20 @@ export function createStlBlob(mesh) {
|
|
|
435
437
|
return blob;
|
|
436
438
|
}
|
|
437
439
|
|
|
440
|
+
/**
|
|
441
|
+
* @typedef {Object} Mesh
|
|
442
|
+
* @property {number[][] | vec3[]} vertices 点信息
|
|
443
|
+
* @property {number[][] | vec3[]} faces 面信息
|
|
444
|
+
*/
|
|
445
|
+
|
|
438
446
|
/**
|
|
439
447
|
* 将网格压缩为drc文件,导出drc需要先加载draco_encode.js,并调用initDrcCoder初始化
|
|
440
|
-
* @param {vtkPolyData} mesh 网格文件
|
|
448
|
+
* @param {vtkPolyData | Mesh} mesh 网格文件
|
|
449
|
+
* @param {number} byteLength=14 压缩率
|
|
441
450
|
* @returns {Blob} drc文件
|
|
442
451
|
*/
|
|
443
|
-
export function createDrcBlob(mesh) {
|
|
444
|
-
const blob = new Blob([enCodeMesh(mesh)]);
|
|
452
|
+
export function createDrcBlob(mesh, byteLength = 14) {
|
|
453
|
+
const blob = new Blob([enCodeMesh(mesh ,byteLength)]);
|
|
445
454
|
return blob;
|
|
446
455
|
}
|
|
447
456
|
|
|
@@ -472,12 +481,11 @@ export function createMeshTypeBlob(
|
|
|
472
481
|
|
|
473
482
|
|
|
474
483
|
/**
|
|
475
|
-
* vtkPolyData的顶点去重
|
|
476
|
-
* 用于3倍顶点的stl和老版本的vtkMarchingCube
|
|
484
|
+
* vtkPolyData的顶点去重 用于3倍顶点的stl和老版本的vtkMarchingCube
|
|
477
485
|
* @param {vtkPolyData} data 网格的vtkPolyData
|
|
478
486
|
* @returns {vtkPolyData} 去重之后的vtkPolyData
|
|
479
487
|
*/
|
|
480
|
-
export
|
|
488
|
+
export function deduplicatePolyData(data) {
|
|
481
489
|
const OFFSET_BOUNDS = 10;
|
|
482
490
|
const vMap = new Map();
|
|
483
491
|
const vIndexMap = new Map();
|
|
@@ -706,19 +714,22 @@ export function convEular2matrixZYX(rmat, xangle, yangle, zangle) {
|
|
|
706
714
|
}
|
|
707
715
|
|
|
708
716
|
/**
|
|
709
|
-
* 将
|
|
710
|
-
* @param {vtkPolyData} mesh
|
|
717
|
+
* 将polyData转换为Base64string
|
|
718
|
+
* @param {vtkPolyData | Mesh} mesh 网格数据
|
|
711
719
|
* @param {mat4} [matrix] 变换矩阵
|
|
720
|
+
* @param {number} byteLength=14 压缩率
|
|
712
721
|
* @returns {string} drc压缩之后的网格base64
|
|
713
722
|
*/
|
|
714
|
-
export function enCodeMeshToBase64(mesh, matrix = undefined) {
|
|
715
|
-
const encodePolydata = vtkPolyData.newInstance();
|
|
716
|
-
encodePolydata.getPoints().setData([...mesh.getPoints().getData()]);
|
|
717
|
-
encodePolydata.getPolys().setData([...mesh.getPolys().getData()]);
|
|
723
|
+
export function enCodeMeshToBase64(mesh, matrix = undefined, byteLength = 14) {
|
|
718
724
|
if(matrix) {
|
|
725
|
+
const encodePolydata = vtkPolyData.newInstance();
|
|
726
|
+
encodePolydata.getPoints().setData([...mesh.getPoints().getData()]);
|
|
727
|
+
encodePolydata.getPolys().setData([...mesh.getPolys().getData()]);
|
|
719
728
|
pointsApplyMat4(matrix, encodePolydata);
|
|
729
|
+
return int8ArrayToBase64(enCodeMesh(encodePolydata, byteLength))
|
|
730
|
+
} else {
|
|
731
|
+
return int8ArrayToBase64(enCodeMesh(mesh, byteLength))
|
|
720
732
|
}
|
|
721
|
-
return int8ArrayToBase64(enCodeMesh(encodePolydata))
|
|
722
733
|
}
|
|
723
734
|
|
|
724
735
|
/**
|
|
@@ -804,4 +815,218 @@ export function getAxisFormMat4(matrix) {
|
|
|
804
815
|
vec3.normalize(axis_y, axis_y);
|
|
805
816
|
vec3.normalize(axis_z, axis_z);
|
|
806
817
|
return { x: axis_x, y: axis_y, z: axis_z };
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* 判断一个矩阵是否是正交矩阵
|
|
822
|
+
* @param {mat4} matrix 矩阵
|
|
823
|
+
* @returns {boolean} 是否是正交矩阵
|
|
824
|
+
*/
|
|
825
|
+
export function isRotationMatrix(matrix) {
|
|
826
|
+
// 检查左上子矩阵是否是正交矩阵
|
|
827
|
+
const rotationMatrix = mat3.create();
|
|
828
|
+
mat3.fromMat4(rotationMatrix, matrix);
|
|
829
|
+
|
|
830
|
+
const transposeMatrix = mat3.transpose(mat3.create(), rotationMatrix);
|
|
831
|
+
const inverseMatrix = mat3.invert(mat3.create(), rotationMatrix);
|
|
832
|
+
|
|
833
|
+
if (!mat3.equals(transposeMatrix, inverseMatrix)) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
// console.log('determinant', mat4.determinant(matrix));
|
|
837
|
+
if (Math.abs(mat4.determinant(matrix) - 1) > 0.000001) {
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
// 检查最后一个元素是否为1
|
|
841
|
+
if (matrix[15] !== 1) {
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* 将vtkPolyData进行三角化
|
|
851
|
+
* @param {vtkPolyData} polydata 需要三角化的vtkPolydata
|
|
852
|
+
* @returns {vtkPolyData} 三角化之后的vtkPolydata
|
|
853
|
+
*/
|
|
854
|
+
export function trianglePolys(polydata) {
|
|
855
|
+
const triangleFilter = vtkTriangleFilter.newInstance();
|
|
856
|
+
triangleFilter.setInputData(polydata);
|
|
857
|
+
return triangleFilter.getOutputData();
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* 加载网格
|
|
863
|
+
* @param {string | File | Blob} file 文件或者文件链接
|
|
864
|
+
* @param {'drc' | 'stl' | 'ply'} [type] 文件类型,当file为string | File的时候可以不传根据文件后缀自动获取,drc需要先进行初始化
|
|
865
|
+
* @param {boolean} [process] 是否需要预先对数据进行处理,stl默认(去重)
|
|
866
|
+
* @returns {Promise<vtkPolyData>} vtkPolyData
|
|
867
|
+
*/
|
|
868
|
+
export async function loadMeshData(file, type = undefined, process = undefined) {
|
|
869
|
+
let _fileBuffer;
|
|
870
|
+
if(typeof file === 'string') {
|
|
871
|
+
type = getFileExtension(file);
|
|
872
|
+
const _file = await fetch(file)
|
|
873
|
+
_fileData = _file.arrayBuffer()
|
|
874
|
+
} else if(file instanceof Blob && type !== undefined) {
|
|
875
|
+
_fileBuffer = await file.arrayBuffer();
|
|
876
|
+
} else if(file instanceof File) {
|
|
877
|
+
_fileBuffer = await file.arrayBuffer();
|
|
878
|
+
if(!type) {
|
|
879
|
+
type = getFileExtension(file.name);
|
|
880
|
+
}
|
|
881
|
+
} else {
|
|
882
|
+
throw('error: file type error')
|
|
883
|
+
}
|
|
884
|
+
/** @type {vtkPLYReader | vtkSTLReader | vtkDracoReader} */
|
|
885
|
+
let reader;
|
|
886
|
+
switch (type) {
|
|
887
|
+
case 'ply':
|
|
888
|
+
reader = vtkPLYReader.newInstance();
|
|
889
|
+
if(process === undefined) {
|
|
890
|
+
process = false;
|
|
891
|
+
}
|
|
892
|
+
break;
|
|
893
|
+
case 'stl':
|
|
894
|
+
reader = vtkSTLReader.newInstance();
|
|
895
|
+
if(process === undefined) {
|
|
896
|
+
process = true;
|
|
897
|
+
}
|
|
898
|
+
break;
|
|
899
|
+
case 'drc':
|
|
900
|
+
reader = vtkDracoReader.newInstance();
|
|
901
|
+
break;
|
|
902
|
+
default:
|
|
903
|
+
throw('error: file type error')
|
|
904
|
+
}
|
|
905
|
+
reader.parseAsArrayBuffer(_fileBuffer);
|
|
906
|
+
let polyData = reader.getOutputData();
|
|
907
|
+
if(process) {
|
|
908
|
+
if(type === 'stl') {
|
|
909
|
+
return deduplicatePolyData(polyData);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
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
|
+
};
|
|
807
1032
|
}
|
package/tsconfig.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"allowJs": true,
|
|
4
4
|
"declaration": true,
|
|
5
5
|
"emitDeclarationOnly": true,
|
|
6
|
-
"
|
|
6
|
+
"outDir": "types" // 可选,定义.d.ts文件输出目录
|
|
7
7
|
},
|
|
8
|
-
"include": ["
|
|
8
|
+
"include": ["src/*.js", "src/vtkUtils.js",] // 指定包含的 JavaScript 文件路径
|
|
9
9
|
}
|
|
@@ -58,7 +58,7 @@ declare function DrawingSVG(): {
|
|
|
58
58
|
end(): string;
|
|
59
59
|
};
|
|
60
60
|
export const BWIPJS_VERSION: "4.5.1 (2024-08-12)";
|
|
61
|
-
import { BWIPP_VERSION } from './bwipp.
|
|
61
|
+
import { BWIPP_VERSION } from './bwipp.js';
|
|
62
62
|
declare function ToRaw(bcid: any, text: any, options: any, ...args: any[]): true | any[];
|
|
63
63
|
declare function FixupOptions(opts: any): any;
|
|
64
64
|
declare namespace FontLib {
|
|
@@ -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
|
-
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
|
|
129
|
+
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
* @returns {string | DataView} 返回文件内容
|
|
14
14
|
*/
|
|
15
15
|
export function writePLY(polyData: vtkPolyData, format: "ascii" | "binary", dataByteOrder?: 0 | 1, headerComments?: string[], textureFileName?: string, textureCoordinatesName?: ["u", "v"], withNormals?: boolean, withUVs?: boolean, withColors?: boolean, withIndices?: boolean): string | DataView;
|
|
16
|
-
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
|
|
16
|
+
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData.js";
|
|
@@ -16,4 +16,4 @@ export function exportBinarySTL(polydata: vtkPolyData, colorMagic?: boolean): Bl
|
|
|
16
16
|
* @returns {string} 网格的asciiSTL文件内容
|
|
17
17
|
*/
|
|
18
18
|
export function exportAsciiSTL(polydata: vtkPolyData): string;
|
|
19
|
-
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
|
|
19
|
+
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData.js';
|
|
@@ -21,6 +21,12 @@ export function int8ArrayToBase64(int8: Int8Array): string;
|
|
|
21
21
|
* @returns {string} base64格式的字符串
|
|
22
22
|
*/
|
|
23
23
|
export function arrayBufferToBase64(outputBuffer: ArrayBuffer): string;
|
|
24
|
+
/**
|
|
25
|
+
* 获取文件后缀
|
|
26
|
+
* @param {string} fileName 文件名,或者文件地址
|
|
27
|
+
* @returns 文件后缀
|
|
28
|
+
*/
|
|
29
|
+
export function getFileExtension(fileName: string): string;
|
|
24
30
|
/**
|
|
25
31
|
* 获取当前屏幕分辨率(百分制,默认100)
|
|
26
32
|
* @returns {number} 当前屏幕分辨率
|