xl-public-utils 1.0.11 → 1.0.12

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
@@ -979,4 +979,56 @@ declare module "xl-public-utils" {
979
979
  ): void;
980
980
  }
981
981
  }
982
+ export interface FontParameters {
983
+ font: Record<string, any>; // 字体数据由 FontLoader 加载,结构可进一步细化
984
+ size: number;
985
+ height: number;
986
+ curveSegments: number;
987
+ bevelThickness: number;
988
+ bevelSize: number;
989
+ bevelEnabled: boolean;
990
+ }
991
+
992
+ export class FontManager {
993
+ private constructor(); // 使用单例模式
994
+ static Mgr(): FontManager;
995
+
996
+ private cacheFontMap: Record<string, vtkPolyData>;
997
+ private cacheFontPointMap: Record<string, IndexData>;
998
+ private fontJsonMap: Record<string, any>;
999
+ private parameters: FontParameters & { font: Record<string, any> };
1000
+
1001
+ /**
1002
+ * 加载字体文件
1003
+ * @param url JSON 字体文件地址
1004
+ * @param fontName 字体名称
1005
+ * @param bevelEnabled 是否启用 bevel
1006
+ */
1007
+ loadFontFile(url: string, fontName?: string, bevelEnabled?: boolean): Promise<void>;
1008
+
1009
+ /**
1010
+ * 生成文字的 PolyData 以及前后顶点索引映射数据
1011
+ * @param text 要生成的文字
1012
+ * @param fontName 字体名
1013
+ * @param scale 缩放向量
1014
+ */
1015
+ generateShapes(
1016
+ text: string,
1017
+ fontName?: string,
1018
+ scale?: vec3
1019
+ ): {
1020
+ polyData: vtkPolyData;
1021
+ indexData: IndexData;
1022
+ };
1023
+
1024
+ /**
1025
+ * 获取顶点索引映射
1026
+ */
1027
+ getPointsMapData(polydata: vtkPolyData): IndexData;
1028
+
1029
+ /**
1030
+ * 创建 vtkPolyData 对象
1031
+ */
1032
+ createPolyData(verts: any, faces: any): vtkPolyData;
1033
+ }
982
1034
  }
package/index.js CHANGED
@@ -3,4 +3,5 @@ import * as utils from './src/utils.js'
3
3
  import * as qrcode from './src/qrcode.js'
4
4
  import * as BwipJs from './src/bwip-js.js';
5
5
  import * as drcUtils from './src/drcUtils.js';
6
- export { vtkUtils, utils, qrcode, BwipJs, drcUtils };
6
+ import FontManager from './src/threeFont/index.js';
7
+ export { vtkUtils, utils, qrcode, BwipJs, drcUtils, FontManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xl-public-utils",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -30,7 +30,9 @@
30
30
  "./qrcode": "./src/qrcode.js",
31
31
  "./vtkUtils": "./src/vtkUtils.js",
32
32
  "./utils": "./src/utils.js",
33
- "./bwipJs": "./src/bwip-js.js"
33
+ "./bwipJs": "./src/bwip-js.js",
34
+ "./drcUtils": "./src/drcUtils.js",
35
+ "./threeFont": "./src/threeFont/index.js"
34
36
  },
35
37
  "scripts": {
36
38
  "test": "karma start",
@@ -0,0 +1,349 @@
1
+ import { Vector2 } from '../Math/Vector2.js';
2
+ import { Vector3 } from '../Math/Vector3.js';
3
+ import { Matrix4 } from '../Math/Matrix4.js';
4
+
5
+ /**
6
+ * Extensible curve object.
7
+ *
8
+ * Some common of curve methods:
9
+ * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
10
+ * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
11
+ * .getPoints(), .getSpacedPoints()
12
+ * .getLength()
13
+ * .updateArcLengths()
14
+ *
15
+ * This following curves inherit from THREE.Curve:
16
+ *
17
+ * -- 2D curves --
18
+ * THREE.ArcCurve
19
+ * THREE.CubicBezierCurve
20
+ * THREE.EllipseCurve
21
+ * THREE.LineCurve
22
+ * THREE.QuadraticBezierCurve
23
+ * THREE.SplineCurve
24
+ *
25
+ * -- 3D curves --
26
+ * THREE.CatmullRomCurve3
27
+ * THREE.CubicBezierCurve3
28
+ * THREE.LineCurve3
29
+ * THREE.QuadraticBezierCurve3
30
+ *
31
+ * A series of curves can be represented as a THREE.CurvePath.
32
+ *
33
+ **/
34
+
35
+ class Curve {
36
+ constructor() {
37
+ this.type = 'Curve';
38
+ this.arcLengthDivisions = 200;
39
+ this.cacheArcLengths = [];
40
+ }
41
+
42
+ // Virtual base class method to overwrite and implement in subclasses
43
+ // - t [0 .. 1]
44
+
45
+ getPoint(/* t, optionalTarget */) {
46
+ console.warn('THREE.Curve: .getPoint() not implemented.');
47
+ return null;
48
+ }
49
+
50
+ // Get point at relative position in curve according to arc length
51
+ // - u [0 .. 1]
52
+
53
+ getPointAt(u, optionalTarget) {
54
+ const t = this.getUtoTmapping(u);
55
+ return this.getPoint(t, optionalTarget);
56
+ }
57
+
58
+ // Get sequence of points using getPoint( t )
59
+
60
+ getPoints(divisions = 5) {
61
+ const points = [];
62
+
63
+ for (let d = 0; d <= divisions; d++) {
64
+ points.push(this.getPoint(d / divisions));
65
+ }
66
+
67
+ return points;
68
+ }
69
+
70
+ // Get sequence of points using getPointAt( u )
71
+
72
+ getSpacedPoints(divisions = 5) {
73
+ const points = [];
74
+
75
+ for (let d = 0; d <= divisions; d++) {
76
+ points.push(this.getPointAt(d / divisions));
77
+ }
78
+
79
+ return points;
80
+ }
81
+
82
+ // Get total curve arc length
83
+
84
+ getLength() {
85
+ const lengths = this.getLengths();
86
+ return lengths[lengths.length - 1];
87
+ }
88
+
89
+ // Get list of cumulative segment lengths
90
+
91
+ getLengths(divisions = this.arcLengthDivisions) {
92
+ if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) {
93
+ return this.cacheArcLengths;
94
+ }
95
+
96
+ this.needsUpdate = false;
97
+
98
+ const cache = [];
99
+ let current,
100
+ last = this.getPoint(0);
101
+ let sum = 0;
102
+
103
+ cache.push(0);
104
+
105
+ for (let p = 1; p <= divisions; p++) {
106
+ current = this.getPoint(p / divisions);
107
+ sum += current.distanceTo(last);
108
+ cache.push(sum);
109
+ last = current;
110
+ }
111
+
112
+ this.cacheArcLengths = cache;
113
+
114
+ return cache; // { sums: cache, sum: sum }; Sum is in the last element.
115
+ }
116
+
117
+ updateArcLengths() {
118
+ this.needsUpdate = true;
119
+ this.getLengths();
120
+ }
121
+
122
+ // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
123
+
124
+ getUtoTmapping(u, distance = null) {
125
+ const arcLengths = this.getLengths();
126
+
127
+ let i = 0;
128
+ const il = arcLengths.length;
129
+
130
+ let targetArcLength; // The targeted u distance value to get
131
+
132
+ if (distance) {
133
+ targetArcLength = distance;
134
+ } else {
135
+ targetArcLength = u * arcLengths[il - 1];
136
+ }
137
+
138
+ // binary search for the index with largest value smaller than target u distance
139
+
140
+ let low = 0,
141
+ high = il - 1,
142
+ comparison;
143
+
144
+ while (low <= high) {
145
+ i = Math.floor(low + (high - low) / 2); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
146
+
147
+ comparison = arcLengths[i] - targetArcLength;
148
+
149
+ if (comparison < 0) {
150
+ low = i + 1;
151
+ } else if (comparison > 0) {
152
+ high = i - 1;
153
+ } else {
154
+ high = i;
155
+ break;
156
+
157
+ // DONE
158
+ }
159
+ }
160
+
161
+ i = high;
162
+
163
+ if (arcLengths[i] === targetArcLength) {
164
+ return i / (il - 1);
165
+ }
166
+
167
+ // we could get finer grain at lengths, or use simple interpolation between two points
168
+
169
+ const lengthBefore = arcLengths[i];
170
+ const lengthAfter = arcLengths[i + 1];
171
+
172
+ const segmentLength = lengthAfter - lengthBefore;
173
+
174
+ // determine where we are between the 'before' and 'after' points
175
+
176
+ const segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
177
+
178
+ // add that fractional amount to t
179
+
180
+ const t = (i + segmentFraction) / (il - 1);
181
+
182
+ return t;
183
+ }
184
+
185
+ // Returns a unit vector tangent at t
186
+ // In case any sub curve does not implement its tangent derivation,
187
+ // 2 points a small delta apart will be used to find its gradient
188
+ // which seems to give a reasonable approximation
189
+
190
+ getTangent(t, optionalTarget) {
191
+ const delta = 0.0001;
192
+ let t1 = t - delta;
193
+ let t2 = t + delta;
194
+
195
+ // Capping in case of danger
196
+
197
+ if (t1 < 0) t1 = 0;
198
+ if (t2 > 1) t2 = 1;
199
+
200
+ const pt1 = this.getPoint(t1);
201
+ const pt2 = this.getPoint(t2);
202
+
203
+ const tangent = optionalTarget || (pt1.isVector2 ? new Vector2() : new Vector3());
204
+
205
+ tangent.copy(pt2).sub(pt1).normalize();
206
+
207
+ return tangent;
208
+ }
209
+
210
+ getTangentAt(u, optionalTarget) {
211
+ const t = this.getUtoTmapping(u);
212
+ return this.getTangent(t, optionalTarget);
213
+ }
214
+
215
+ computeFrenetFrames(segments, closed) {
216
+ // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
217
+ /**
218
+ * 将数值限制在范围 [min, max] 之间
219
+ * @param {number} number 要限制的数值
220
+ * @param {number} min 最小值
221
+ * @param {number} max 最大值
222
+ * @returns {number}
223
+ */
224
+ function clamp(number, min, max) {
225
+ return Math.min(Math.max(number, min), max);
226
+ }
227
+ const normal = new Vector3();
228
+
229
+ const tangents = [];
230
+ const normals = [];
231
+ const binormals = [];
232
+
233
+ const vec = new Vector3();
234
+ const mat = new Matrix4();
235
+
236
+ // compute the tangent vectors for each segment on the curve
237
+
238
+ for (let i = 0; i <= segments; i++) {
239
+ const u = i / segments;
240
+
241
+ tangents[i] = this.getTangentAt(u, new Vector3());
242
+ }
243
+
244
+ // select an initial normal vector perpendicular to the first tangent vector,
245
+ // and in the direction of the minimum tangent xyz component
246
+
247
+ normals[0] = new Vector3();
248
+ binormals[0] = new Vector3();
249
+ let min = Number.MAX_VALUE;
250
+ const tx = Math.abs(tangents[0].x);
251
+ const ty = Math.abs(tangents[0].y);
252
+ const tz = Math.abs(tangents[0].z);
253
+
254
+ if (tx <= min) {
255
+ min = tx;
256
+ normal.set(1, 0, 0);
257
+ }
258
+
259
+ if (ty <= min) {
260
+ min = ty;
261
+ normal.set(0, 1, 0);
262
+ }
263
+
264
+ if (tz <= min) {
265
+ normal.set(0, 0, 1);
266
+ }
267
+
268
+ vec.crossVectors(tangents[0], normal).normalize();
269
+
270
+ normals[0].crossVectors(tangents[0], vec);
271
+ binormals[0].crossVectors(tangents[0], normals[0]);
272
+
273
+ // compute the slowly-varying normal and binormal vectors for each segment on the curve
274
+
275
+ for (let i = 1; i <= segments; i++) {
276
+ normals[i] = normals[i - 1].clone();
277
+
278
+ binormals[i] = binormals[i - 1].clone();
279
+
280
+ vec.crossVectors(tangents[i - 1], tangents[i]);
281
+
282
+ if (vec.length() > Number.EPSILON) {
283
+ vec.normalize();
284
+
285
+ const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors
286
+
287
+ normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
288
+ }
289
+
290
+ binormals[i].crossVectors(tangents[i], normals[i]);
291
+ }
292
+
293
+ // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
294
+
295
+ if (closed === true) {
296
+ let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1));
297
+ theta /= segments;
298
+
299
+ if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
300
+ theta = -theta;
301
+ }
302
+
303
+ for (let i = 1; i <= segments; i++) {
304
+ // twist a little...
305
+ normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
306
+ binormals[i].crossVectors(tangents[i], normals[i]);
307
+ }
308
+ }
309
+
310
+ return {
311
+ tangents: tangents,
312
+ normals: normals,
313
+ binormals: binormals,
314
+ };
315
+ }
316
+
317
+ clone() {
318
+ return new this.constructor().copy(this);
319
+ }
320
+
321
+ copy(source) {
322
+ this.arcLengthDivisions = source.arcLengthDivisions;
323
+
324
+ return this;
325
+ }
326
+
327
+ toJSON() {
328
+ const data = {
329
+ metadata: {
330
+ version: 4.5,
331
+ type: 'Curve',
332
+ generator: 'Curve.toJSON',
333
+ },
334
+ };
335
+
336
+ data.arcLengthDivisions = this.arcLengthDivisions;
337
+ data.type = this.type;
338
+
339
+ return data;
340
+ }
341
+
342
+ fromJSON(json) {
343
+ this.arcLengthDivisions = json.arcLengthDivisions;
344
+
345
+ return this;
346
+ }
347
+ }
348
+
349
+ export { Curve };
@@ -0,0 +1,202 @@
1
+ import { Curve } from './Curve.js';
2
+ import * as Curves from '../curves/Curves.js';
3
+
4
+ /**************************************************************
5
+ * Curved Path - a curve path is simply a array of connected
6
+ * curves, but retains the api of a curve
7
+ **************************************************************/
8
+
9
+ class CurvePath extends Curve {
10
+ constructor() {
11
+ super();
12
+
13
+ this.type = 'CurvePath';
14
+
15
+ this.curves = [];
16
+ this.autoClose = false; // Automatically closes the path
17
+ }
18
+
19
+ add(curve) {
20
+ this.curves.push(curve);
21
+ }
22
+
23
+ closePath() {
24
+ // Add a line curve if start and end of lines are not connected
25
+ const startPoint = this.curves[0].getPoint(0);
26
+ const endPoint = this.curves[this.curves.length - 1].getPoint(1);
27
+
28
+ if (!startPoint.equals(endPoint)) {
29
+ this.curves.push(new Curves['LineCurve'](endPoint, startPoint));
30
+ }
31
+ }
32
+
33
+ // To get accurate point with reference to
34
+ // entire path distance at time t,
35
+ // following has to be done:
36
+
37
+ // 1. Length of each sub path have to be known
38
+ // 2. Locate and identify type of curve
39
+ // 3. Get t for the curve
40
+ // 4. Return curve.getPointAt(t')
41
+
42
+ getPoint(t, optionalTarget) {
43
+ const d = t * this.getLength();
44
+ const curveLengths = this.getCurveLengths();
45
+ let i = 0;
46
+
47
+ // To think about boundaries points.
48
+
49
+ while (i < curveLengths.length) {
50
+ if (curveLengths[i] >= d) {
51
+ const diff = curveLengths[i] - d;
52
+ const curve = this.curves[i];
53
+
54
+ const segmentLength = curve.getLength();
55
+ const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
56
+
57
+ return curve.getPointAt(u, optionalTarget);
58
+ }
59
+
60
+ i++;
61
+ }
62
+
63
+ return null;
64
+
65
+ // loop where sum != 0, sum > d , sum+1 <d
66
+ }
67
+
68
+ // We cannot use the default THREE.Curve getPoint() with getLength() because in
69
+ // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
70
+ // getPoint() depends on getLength
71
+
72
+ getLength() {
73
+ const lens = this.getCurveLengths();
74
+ return lens[lens.length - 1];
75
+ }
76
+
77
+ // cacheLengths must be recalculated.
78
+ updateArcLengths() {
79
+ this.needsUpdate = true;
80
+ this.cacheLengths = null;
81
+ this.getCurveLengths();
82
+ }
83
+
84
+ // Compute lengths and cache them
85
+ // We cannot overwrite getLengths() because UtoT mapping uses it.
86
+
87
+ getCurveLengths() {
88
+ // We use cache values if curves and cache array are same length
89
+
90
+ if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
91
+ return this.cacheLengths;
92
+ }
93
+
94
+ // Get length of sub-curve
95
+ // Push sums into cached array
96
+
97
+ const lengths = [];
98
+ let sums = 0;
99
+
100
+ for (let i = 0, l = this.curves.length; i < l; i++) {
101
+ sums += this.curves[i].getLength();
102
+ lengths.push(sums);
103
+ }
104
+
105
+ this.cacheLengths = lengths;
106
+
107
+ return lengths;
108
+ }
109
+
110
+ getSpacedPoints(divisions = 40) {
111
+ const points = [];
112
+
113
+ for (let i = 0; i <= divisions; i++) {
114
+ points.push(this.getPoint(i / divisions));
115
+ }
116
+
117
+ if (this.autoClose) {
118
+ points.push(points[0]);
119
+ }
120
+
121
+ return points;
122
+ }
123
+
124
+ getPoints(divisions = 12) {
125
+ const points = [];
126
+ let last;
127
+
128
+ for (let i = 0, curves = this.curves; i < curves.length; i++) {
129
+ const curve = curves[i];
130
+ const resolution = curve.isEllipseCurve
131
+ ? divisions * 2
132
+ : curve.isLineCurve || curve.isLineCurve3
133
+ ? 1
134
+ : curve.isSplineCurve
135
+ ? divisions * curve.points.length
136
+ : divisions;
137
+
138
+ const pts = curve.getPoints(resolution);
139
+
140
+ for (let j = 0; j < pts.length; j++) {
141
+ const point = pts[j];
142
+
143
+ if (last && last.equals(point)) continue; // ensures no consecutive points are duplicates
144
+
145
+ points.push(point);
146
+ last = point;
147
+ }
148
+ }
149
+
150
+ if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) {
151
+ points.push(points[0]);
152
+ }
153
+
154
+ return points;
155
+ }
156
+
157
+ copy(source) {
158
+ super.copy(source);
159
+
160
+ this.curves = [];
161
+
162
+ for (let i = 0, l = source.curves.length; i < l; i++) {
163
+ const curve = source.curves[i];
164
+
165
+ this.curves.push(curve.clone());
166
+ }
167
+
168
+ this.autoClose = source.autoClose;
169
+
170
+ return this;
171
+ }
172
+
173
+ toJSON() {
174
+ const data = super.toJSON();
175
+
176
+ data.autoClose = this.autoClose;
177
+ data.curves = [];
178
+
179
+ for (let i = 0, l = this.curves.length; i < l; i++) {
180
+ const curve = this.curves[i];
181
+ data.curves.push(curve.toJSON());
182
+ }
183
+
184
+ return data;
185
+ }
186
+
187
+ fromJSON(json) {
188
+ super.fromJSON(json);
189
+
190
+ this.autoClose = json.autoClose;
191
+ this.curves = [];
192
+
193
+ for (let i = 0, l = json.curves.length; i < l; i++) {
194
+ const curve = json.curves[i];
195
+ this.curves.push(new Curves[curve.type]().fromJSON(curve));
196
+ }
197
+
198
+ return this;
199
+ }
200
+ }
201
+
202
+ export { CurvePath };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Bezier Curves formulas obtained from
3
+ * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
4
+ */
5
+
6
+ function CatmullRom(t, p0, p1, p2, p3) {
7
+ const v0 = (p2 - p0) * 0.5;
8
+ const v1 = (p3 - p1) * 0.5;
9
+ const t2 = t * t;
10
+ const t3 = t * t2;
11
+ return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
12
+ }
13
+
14
+ //
15
+
16
+ function QuadraticBezierP0(t, p) {
17
+ const k = 1 - t;
18
+ return k * k * p;
19
+ }
20
+
21
+ function QuadraticBezierP1(t, p) {
22
+ return 2 * (1 - t) * t * p;
23
+ }
24
+
25
+ function QuadraticBezierP2(t, p) {
26
+ return t * t * p;
27
+ }
28
+
29
+ function QuadraticBezier(t, p0, p1, p2) {
30
+ return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) + QuadraticBezierP2(t, p2);
31
+ }
32
+
33
+ //
34
+
35
+ function CubicBezierP0(t, p) {
36
+ const k = 1 - t;
37
+ return k * k * k * p;
38
+ }
39
+
40
+ function CubicBezierP1(t, p) {
41
+ const k = 1 - t;
42
+ return 3 * k * k * t * p;
43
+ }
44
+
45
+ function CubicBezierP2(t, p) {
46
+ return 3 * (1 - t) * t * t * p;
47
+ }
48
+
49
+ function CubicBezierP3(t, p) {
50
+ return t * t * t * p;
51
+ }
52
+
53
+ function CubicBezier(t, p0, p1, p2, p3) {
54
+ return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) + CubicBezierP3(t, p3);
55
+ }
56
+
57
+ export { CatmullRom, QuadraticBezier, CubicBezier };