xl-public-utils 1.0.4 → 1.0.6
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 +677 -79
- package/index.js +2 -1
- package/package.json +12 -4
- package/src/drcUtils.mjs +353 -0
- package/src/exportPLY.mjs +285 -0
- package/src/exportSTL.mjs +222 -0
- package/src/qrcode.mjs +16 -16
- package/src/utils.mjs +43 -1
- package/src/vtkUtils.mjs +780 -1
- package/tsconfig.json +9 -0
- package/types/bwip-js.d.mts +106 -0
- package/types/bwipp.d.mts +5 -0
- package/types/drcUtils.d.mts +129 -0
- package/types/exportPLY.d.mts +16 -0
- package/types/exportSTL.d.mts +19 -0
- package/types/qrcode.d.mts +92 -0
- package/types/utils.d.mts +28 -0
- package/types/vtkUtils.d.mts +320 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
|
|
2
|
+
import { vec3 } from 'gl-matrix';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 离散stl重复的点并格式化输出
|
|
6
|
+
* @param {vtkPolyData} polydata 网格
|
|
7
|
+
* @returns 离散化之后的PolyData
|
|
8
|
+
*/
|
|
9
|
+
var getResult = function (polydata) {
|
|
10
|
+
var points = [...polydata.getPoints().getData()];
|
|
11
|
+
// 离散化
|
|
12
|
+
dispersedPoints2Stl(points)
|
|
13
|
+
var vAr = new Float32Array(points);
|
|
14
|
+
var iAr = new Uint32Array([...polydata.getPolys().getData()]);
|
|
15
|
+
const nbTriangles = iAr.length / 4;
|
|
16
|
+
const { set, sub, cross, normalize, create} = vec3
|
|
17
|
+
var v1 = create();
|
|
18
|
+
var v2 = create();
|
|
19
|
+
var v3 = create();
|
|
20
|
+
var nAr = new Float32Array(nbTriangles * 3);
|
|
21
|
+
for (var i = 0; i < nbTriangles; ++i) {
|
|
22
|
+
var id = i * 4;
|
|
23
|
+
var i1 = iAr[id + 1] * 3;
|
|
24
|
+
var i2 = iAr[id + 2] * 3;
|
|
25
|
+
var i3 = iAr[id + 3] * 3;
|
|
26
|
+
set(v1, vAr[i1], vAr[i1 + 1], vAr[i1 + 2]);
|
|
27
|
+
set(v2, vAr[i2], vAr[i2 + 1], vAr[i2 + 2]);
|
|
28
|
+
set(v3, vAr[i3], vAr[i3 + 1], vAr[i3 + 2]);
|
|
29
|
+
|
|
30
|
+
sub(v2, v2, v1); // v2 = v2 - v1
|
|
31
|
+
sub(v3, v3, v2); // v3 = v3 - v1
|
|
32
|
+
cross(v1, v2, v3); // v1 = v2 ^ v3
|
|
33
|
+
normalize(v1, v1);
|
|
34
|
+
|
|
35
|
+
nAr[id] = v1[0];
|
|
36
|
+
nAr[id + 1] = v1[1];
|
|
37
|
+
nAr[id + 2] = v1[2];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
nbTriangles,
|
|
42
|
+
vertices: vAr,
|
|
43
|
+
triangles: iAr,
|
|
44
|
+
faceNormals: nAr,
|
|
45
|
+
nbVertices: vAr.length / 3,
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 获取网格的AsciiSTL文件类容
|
|
51
|
+
* @param {vtkPolyData} polydata 网格
|
|
52
|
+
* @returns {string} 网格的asciiSTL文件内容
|
|
53
|
+
*/
|
|
54
|
+
const exportAsciiSTL = function (polydata) {
|
|
55
|
+
var res = getResult(polydata);
|
|
56
|
+
var nbTriangles = res.nbTriangles;
|
|
57
|
+
var vAr = res.vertices;
|
|
58
|
+
var iAr = res.triangles;
|
|
59
|
+
var fnAr = res.faceNormals;
|
|
60
|
+
|
|
61
|
+
var data = 'solid mesh\n';
|
|
62
|
+
for (var i = 0; i < nbTriangles; ++i) {
|
|
63
|
+
var id = i * 3;
|
|
64
|
+
const fid = i * 4;
|
|
65
|
+
data += ' facet normal ' + fnAr[id] + ' ' + fnAr[id + 1] + ' ' + fnAr[id + 2] + '\n';
|
|
66
|
+
data += ' outer loop\n';
|
|
67
|
+
var iv1 = iAr[fid + 1] * 3;
|
|
68
|
+
var iv2 = iAr[fid + 2] * 3;
|
|
69
|
+
var iv3 = iAr[fid + 3] * 3;
|
|
70
|
+
data += ' vertex ' + vAr[iv1] + ' ' + vAr[iv1 + 1] + ' ' + vAr[iv1 + 2] + '\n';
|
|
71
|
+
data += ' vertex ' + vAr[iv2] + ' ' + vAr[iv2 + 1] + ' ' + vAr[iv2 + 2] + '\n';
|
|
72
|
+
data += ' vertex ' + vAr[iv3] + ' ' + vAr[iv3 + 1] + ' ' + vAr[iv3 + 2] + '\n';
|
|
73
|
+
data += ' endloop\n';
|
|
74
|
+
data += ' endfacet\n';
|
|
75
|
+
}
|
|
76
|
+
data += 'endsolid mesh\n';
|
|
77
|
+
return new Blob([data]);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 获取网格的BinarySTL文件类容
|
|
82
|
+
* @param {vtkPolyData} polydata 网格
|
|
83
|
+
* @param {boolean} colorMagic=false 颜色
|
|
84
|
+
* @returns {Blob} 网格的BinarySTL文件内容
|
|
85
|
+
*/
|
|
86
|
+
const exportBinarySTL = function (polydata, colorMagic = false) {
|
|
87
|
+
var res = getResult(polydata);
|
|
88
|
+
var nbTriangles = res.nbTriangles;
|
|
89
|
+
var vAr = res.vertices;
|
|
90
|
+
// var cAr = res.colors;
|
|
91
|
+
var iAr = res.triangles;
|
|
92
|
+
// var fnAr = res.faceNormals;
|
|
93
|
+
var i, k;
|
|
94
|
+
|
|
95
|
+
var data = new Uint8Array(84 + nbTriangles * 50);
|
|
96
|
+
if (colorMagic) {
|
|
97
|
+
// COLOR=255,255,255,255
|
|
98
|
+
var hdr = [67, 79, 76, 79, 82, 61, 255, 255, 255, 255];
|
|
99
|
+
for (i = 0; i < hdr.length; ++i) {
|
|
100
|
+
data[i] = hdr[i];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
(new DataView(data.buffer)).setUint32(80, nbTriangles, true);
|
|
105
|
+
// var verBuffer = new Uint8Array((vAr as any).buffer);
|
|
106
|
+
// var norBuffer = new Uint8Array(fnAr.buffer);
|
|
107
|
+
var offset = 84;
|
|
108
|
+
var inc = 0;
|
|
109
|
+
|
|
110
|
+
// var colorActivate = colorMagic ? 0 : (1 << 15);
|
|
111
|
+
|
|
112
|
+
const dataView = new DataView(data.buffer)
|
|
113
|
+
// var mulc = 31 / 3;
|
|
114
|
+
for (i = 0; i < nbTriangles; ++i) {
|
|
115
|
+
k = i * 12;
|
|
116
|
+
// for (inc = 0; inc < 12; ++inc) {
|
|
117
|
+
// offset++
|
|
118
|
+
// // data[offset++] = norBuffer[k++];
|
|
119
|
+
// }
|
|
120
|
+
offset += 12
|
|
121
|
+
k = i * 3;
|
|
122
|
+
const fid = i * 4;
|
|
123
|
+
var iv1 = iAr[fid + 1] * 3;
|
|
124
|
+
var iv2 = iAr[fid + 2] * 3;
|
|
125
|
+
var iv3 = iAr[fid + 3] * 3;
|
|
126
|
+
var id1 = iv1 * 4;
|
|
127
|
+
// for (inc = 0; inc < 12; ++inc) {
|
|
128
|
+
// data[offset++] = verBuffer[id1++];
|
|
129
|
+
// }
|
|
130
|
+
// var id2 = iv2 * 4;
|
|
131
|
+
// for (inc = 0; inc < 12; ++inc) {
|
|
132
|
+
// data[offset++] = verBuffer[id2++];
|
|
133
|
+
// }
|
|
134
|
+
// var id3 = iv3 * 4;
|
|
135
|
+
// for (inc = 0; inc < 12; ++inc) {
|
|
136
|
+
// data[offset++] = verBuffer[id3++];
|
|
137
|
+
// }
|
|
138
|
+
for(inc =0; inc < 3; ++inc){
|
|
139
|
+
dataView.setFloat32(offset, vAr[iv1 + inc], true);
|
|
140
|
+
offset = offset + 4;
|
|
141
|
+
}
|
|
142
|
+
for(inc =0; inc < 3; ++inc){
|
|
143
|
+
dataView.setFloat32(offset, vAr[iv2 + inc], true);
|
|
144
|
+
offset = offset + 4;
|
|
145
|
+
}
|
|
146
|
+
for(inc =0; inc < 3; ++inc){
|
|
147
|
+
dataView.setFloat32(offset, vAr[iv3 + inc], true);
|
|
148
|
+
offset = offset + 4;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
offset++;
|
|
152
|
+
offset++
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
return new Blob([data]);
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* 对数值进行处理,保留几位小数
|
|
159
|
+
* @param {number} num 数值
|
|
160
|
+
* @param {number} fix=4 保留几位小数
|
|
161
|
+
* @returns 格式化之后的数值
|
|
162
|
+
*/
|
|
163
|
+
function getFixed4(num, fix = 4) {
|
|
164
|
+
return +num.toFixed(fix)
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 根据点生成key
|
|
168
|
+
* @param {number[]} point 三位点
|
|
169
|
+
* @returns 根据点xyz生成key,取小数位前4位置
|
|
170
|
+
*/
|
|
171
|
+
function getPointKey(point) {
|
|
172
|
+
return `${getFixed4(point[0])},${getFixed4(point[1])},${getFixed4(point[2])}`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 返回噪点随机数
|
|
176
|
+
* @returns {number} 早点随机数
|
|
177
|
+
*/
|
|
178
|
+
function randNum() {
|
|
179
|
+
return (
|
|
180
|
+
(Math.random() > 0.5 ? 1 : -1) * (Math.random() * (1e-4 - 1e-5)) + 1e-5
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* 导出stl模型的时候 需要离散点 防止被认为是同一个点 精度到e-7就够了
|
|
185
|
+
* @param {number[]} points 网格点
|
|
186
|
+
*/
|
|
187
|
+
export function dispersedPoints2Stl(points) {
|
|
188
|
+
let pointMap = new Map();
|
|
189
|
+
for (let i = 0; i < points.length; i += 3) {
|
|
190
|
+
let transformPoint = [points[i], points[i + 1], points[i + 2]];
|
|
191
|
+
const key = getPointKey(transformPoint);
|
|
192
|
+
if (pointMap.has(key)) {
|
|
193
|
+
let randPoint = [
|
|
194
|
+
transformPoint[0] + randNum(),
|
|
195
|
+
transformPoint[1] + randNum(),
|
|
196
|
+
transformPoint[2] + randNum(),
|
|
197
|
+
];
|
|
198
|
+
let randKey = getPointKey(randPoint);
|
|
199
|
+
let attemptTimes = 0;
|
|
200
|
+
while (pointMap.has(randKey) && attemptTimes < 1000) {
|
|
201
|
+
randPoint = [
|
|
202
|
+
transformPoint[0] + randNum(),
|
|
203
|
+
transformPoint[1] + randNum(),
|
|
204
|
+
transformPoint[2] + randNum(),
|
|
205
|
+
];
|
|
206
|
+
randKey = getPointKey(randPoint);
|
|
207
|
+
attemptTimes++;
|
|
208
|
+
}
|
|
209
|
+
points[i] = randPoint[0];
|
|
210
|
+
points[i + 1] = randPoint[1];
|
|
211
|
+
points[i + 2] = randPoint[2];
|
|
212
|
+
pointMap.set(randKey, true);
|
|
213
|
+
// import.meta.env.DEV && console.log('重复点', [points[i], points[i + 1], points[i + 2]])
|
|
214
|
+
} else {
|
|
215
|
+
pointMap.set(key, true);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export {
|
|
220
|
+
exportBinarySTL,
|
|
221
|
+
exportAsciiSTL,
|
|
222
|
+
}
|
package/src/qrcode.mjs
CHANGED
|
@@ -2,22 +2,22 @@ import { qrcode, datamatrix} from './bwip-js.mjs';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {Object} QrCodeOptions
|
|
5
|
-
* @property {'qrcode' | 'dataMatrix'}
|
|
6
|
-
* @property {number}
|
|
7
|
-
* @property {number}
|
|
8
|
-
* @property {number}
|
|
9
|
-
* @property {number}
|
|
10
|
-
* @property {boolean}
|
|
11
|
-
* @property {number}
|
|
12
|
-
* @property {number}
|
|
13
|
-
* @property {number}
|
|
14
|
-
* @property {number}
|
|
15
|
-
* @property {string}
|
|
16
|
-
* @property {string}
|
|
17
|
-
* @property {number}
|
|
18
|
-
* @property {boolean}
|
|
19
|
-
* @property {string}
|
|
20
|
-
* @property {string}
|
|
5
|
+
* @property {'qrcode' | 'dataMatrix'} bcid='qrcode' - 二维码类型,具体支持请查看文档
|
|
6
|
+
* @property {number} width=1056 - 最终图片宽度
|
|
7
|
+
* @property {number} height=342 - 最终图片高度
|
|
8
|
+
* @property {number} qrcodeW=300 - 二维码宽度
|
|
9
|
+
* @property {number} qrcodeH=300 - 二维码高度
|
|
10
|
+
* @property {boolean} addText=true - 是否在右侧添加文字
|
|
11
|
+
* @property {number} top=10 - 顶部距离
|
|
12
|
+
* @property {number} left=10 - 左侧距离
|
|
13
|
+
* @property {number} lineHeight=1 - 文字行高,换行后下一行文字的y位置计算为fontSize * lineHeight
|
|
14
|
+
* @property {number} fontSize=60 - 文字大小
|
|
15
|
+
* @property {string} fontFamily='黑体' - 字体类型
|
|
16
|
+
* @property {string} bgColor='#fff' - 背景颜色
|
|
17
|
+
* @property {number} textLeftMargin=20 - 文字距离二维码间隔
|
|
18
|
+
* @property {boolean} fontWeight=700 - 字体加粗
|
|
19
|
+
* @property {string} textColor='#000' - 字体颜色
|
|
20
|
+
* @property {string} textContent - 右侧文字内容
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
/**
|
package/src/utils.mjs
CHANGED
|
@@ -29,4 +29,46 @@ export function getRatio() {
|
|
|
29
29
|
* Alias for {@link getRatio}
|
|
30
30
|
* @function
|
|
31
31
|
*/
|
|
32
|
-
export const detectZoom = getRatio;
|
|
32
|
+
export const detectZoom = getRatio;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 将Base64转换为ArrayBuffer
|
|
36
|
+
* @param {string} base64String
|
|
37
|
+
* @returns {ArrayBuffer} base64的ArrayBuffer
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export function base64ToArrayBuffer(base64String) {
|
|
41
|
+
const binary_string = window.atob(base64String);
|
|
42
|
+
const len = binary_string.length;
|
|
43
|
+
const bytes = new Uint8Array(len);
|
|
44
|
+
for (var i = 0; i < len; i++) {
|
|
45
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
46
|
+
}
|
|
47
|
+
return bytes.buffer
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 将Int8Array转换为Base64格式的字符串
|
|
52
|
+
* @param {Int8Array} int8
|
|
53
|
+
* @returns {string} base64格式的字符串
|
|
54
|
+
*/
|
|
55
|
+
export function int8ArrayToBase64(int8) {
|
|
56
|
+
const data = new Uint8Array(int8)
|
|
57
|
+
let base64String = '';
|
|
58
|
+
for (let i = 0; i < data.length; i++) {
|
|
59
|
+
base64String += String.fromCharCode(data[i])
|
|
60
|
+
}
|
|
61
|
+
return window.btoa(base64String)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 将ArrayBuffer转换为Base64格式的字符串
|
|
67
|
+
* @param {ArrayBuffer} outputBuffer
|
|
68
|
+
* @returns {string} base64格式的字符串
|
|
69
|
+
*/
|
|
70
|
+
export function arrayBufferToBase64(outputBuffer) {
|
|
71
|
+
const outputData = new Int8Array(outputBuffer);
|
|
72
|
+
|
|
73
|
+
return int8ArrayToBase64(outputData)
|
|
74
|
+
}
|