@vesium/geometry 1.0.1-beta.54

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/dist/index.cjs ADDED
@@ -0,0 +1,1278 @@
1
+
2
+ //#region src/helper.ts
3
+ const FITTING_COUNT = 100;
4
+ const HALF_PI = Math.PI / 2;
5
+ const ZERO_TOLERANCE = 1e-4;
6
+ const TWO_PI = Math.PI * 2;
7
+ /**
8
+ * 计算两个坐标之间的距离
9
+ * @param coord1
10
+ * @param coord2
11
+ */
12
+ function mathDistance(coord1, coord2) {
13
+ return Math.hypot(coord1[0] - coord2[0], coord1[1] - coord2[1]);
14
+ }
15
+ /**
16
+ * 计算点集合的总距离
17
+ * @param points
18
+ */
19
+ function wholeDistance(points) {
20
+ let distance = 0;
21
+ if (points && Array.isArray(points) && points.length > 0) points.forEach((item, index) => {
22
+ if (index < points.length - 1) distance += mathDistance(item, points[index + 1]);
23
+ });
24
+ return distance;
25
+ }
26
+ /**
27
+ * 获取基础长度
28
+ * @param points
29
+ */
30
+ const getBaseLength = (points) => wholeDistance(points) ** .99;
31
+ /**
32
+ * 求取两个坐标的中间坐标
33
+ * @param coord1
34
+ * @param coord2
35
+ */
36
+ function mid(coord1, coord2) {
37
+ return [(coord1[0] + coord2[0]) / 2, (coord1[1] + coord2[1]) / 2];
38
+ }
39
+ /**
40
+ * 通过三个点确定一个圆的中心点
41
+ * @param coord1
42
+ * @param coord2
43
+ * @param coord3
44
+ */
45
+ function getCircleCenterOfThreeCoords(coord1, coord2, coord3) {
46
+ const coordA = [(coord1[0] + coord2[0]) / 2, (coord1[1] + coord2[1]) / 2];
47
+ const coordB = [coordA[0] - coord1[1] + coord2[1], coordA[1] + coord1[0] - coord2[0]];
48
+ const coordC = [(coord1[0] + coord3[0]) / 2, (coord1[1] + coord3[1]) / 2];
49
+ return getIntersectCoord(coordA, coordB, coordC, [coordC[0] - coord1[1] + coord3[1], coordC[1] + coord1[0] - coord3[0]]);
50
+ }
51
+ /**
52
+ * 获取交集的点
53
+ * @param coordA
54
+ * @param coordB
55
+ * @param coordC
56
+ * @param coordD
57
+ */
58
+ function getIntersectCoord(coordA, coordB, coordC, coordD) {
59
+ if (coordA[1] === coordB[1]) return [(coordD[0] - coordC[0]) / (coordD[1] - coordC[1]) * (coordA[1] - coordC[1]) + coordC[0], coordA[1]];
60
+ if (coordC[1] === coordD[1]) return [(coordB[0] - coordA[0]) / (coordB[1] - coordA[1]) * (coordC[1] - coordA[1]) + coordA[0], coordC[1]];
61
+ const e = (coordB[0] - coordA[0]) / (coordB[1] - coordA[1]);
62
+ const f = (coordD[0] - coordC[0]) / (coordD[1] - coordC[1]);
63
+ const y = (e * coordA[1] - coordA[0] - f * coordC[1] + coordC[0]) / (e - f);
64
+ return [e * y - e * coordA[1] + coordA[0], y];
65
+ }
66
+ /**
67
+ * 获取方位角(地平经度)
68
+ * @param startCoord
69
+ * @param endCoord
70
+ */
71
+ function getAzimuth(startCoord, endCoord) {
72
+ let azimuth = 0;
73
+ const angle = Math.asin(Math.abs(endCoord[1] - startCoord[1]) / mathDistance(startCoord, endCoord));
74
+ if (endCoord[1] >= startCoord[1] && endCoord[0] >= startCoord[0]) azimuth = angle + Math.PI;
75
+ else if (endCoord[1] >= startCoord[1] && endCoord[0] < startCoord[0]) azimuth = Math.PI * 2 - angle;
76
+ else if (endCoord[1] < startCoord[1] && endCoord[0] < startCoord[0]) azimuth = angle;
77
+ else if (endCoord[1] < startCoord[1] && endCoord[0] >= startCoord[0]) azimuth = Math.PI - angle;
78
+ return azimuth;
79
+ }
80
+ /**
81
+ * 通过三个点获取方位角
82
+ * @param coordA
83
+ * @param coordB
84
+ * @param coordC
85
+ */
86
+ function getAngleOfThreeCoords(coordA, coordB, coordC) {
87
+ const angle = getAzimuth(coordB, coordA) - getAzimuth(coordB, coordC);
88
+ return angle < 0 ? angle + Math.PI * 2 : angle;
89
+ }
90
+ /**
91
+ * 判断是否是顺时针
92
+ * @param coord1
93
+ * @param coord2
94
+ * @param coord3
95
+ */
96
+ function isClockWise(coord1, coord2, coord3) {
97
+ return (coord3[1] - coord1[1]) * (coord2[0] - coord1[0]) > (coord2[1] - coord1[1]) * (coord3[0] - coord1[0]);
98
+ }
99
+ /**
100
+ * 获取线上的点
101
+ * @param t
102
+ * @param startCoord
103
+ * @param endCoord
104
+ */
105
+ function getCoordOnLine(t, startCoord, endCoord) {
106
+ return [startCoord[0] + t * (endCoord[0] - startCoord[0]), startCoord[1] + t * (endCoord[1] - startCoord[1])];
107
+ }
108
+ /**
109
+ * 获取立方值
110
+ */
111
+ function getCubicValue(t, startCoord, coord1, coord2, endCoord) {
112
+ t = Math.max(Math.min(t, 1), 0);
113
+ const [tp, t2] = [1 - t, t * t];
114
+ const t3 = t2 * t;
115
+ const tp2 = tp * tp;
116
+ const tp3 = tp2 * tp;
117
+ return [tp3 * startCoord[0] + 3 * tp2 * t * coord1[0] + 3 * tp * t2 * coord2[0] + t3 * endCoord[0], tp3 * startCoord[1] + 3 * tp2 * t * coord1[1] + 3 * tp * t2 * coord2[1] + t3 * endCoord[1]];
118
+ }
119
+ /**
120
+ * 根据起止点和旋转方向求取第三个点
121
+ * @param startCoord
122
+ * @param endCoord
123
+ * @param angle
124
+ * @param distance
125
+ * @param clockWise
126
+ */
127
+ function getThirdCoord(startCoord, endCoord, angle, distance, clockWise) {
128
+ const azimuth = getAzimuth(startCoord, endCoord);
129
+ const alpha = clockWise ? azimuth + angle : azimuth - angle;
130
+ const dx = distance * Math.cos(alpha);
131
+ const dy = distance * Math.sin(alpha);
132
+ return [endCoord[0] + dx, endCoord[1] + dy];
133
+ }
134
+ /**
135
+ * 插值弓形线段点
136
+ * @param center
137
+ * @param radius
138
+ * @param startAngle
139
+ * @param endAngle
140
+ */
141
+ function getArcCoords(center, radius, startAngle, endAngle) {
142
+ let [x, y, coords, angleDiff] = [
143
+ 0,
144
+ 0,
145
+ [],
146
+ endAngle - startAngle
147
+ ];
148
+ angleDiff = angleDiff < 0 ? angleDiff + Math.PI * 2 : angleDiff;
149
+ for (let i = 0; i <= 100; i++) {
150
+ const angle = startAngle + angleDiff * i / 100;
151
+ x = center[0] + radius * Math.cos(angle);
152
+ y = center[1] + radius * Math.sin(angle);
153
+ coords.push([x, y]);
154
+ }
155
+ return coords;
156
+ }
157
+ /**
158
+ * getBisectorNormals
159
+ * @param t
160
+ * @param coord1
161
+ * @param coord2
162
+ * @param coord3
163
+ */
164
+ function getBisectorNormals(t, coord1, coord2, coord3) {
165
+ const normal = getNormal(coord1, coord2, coord3);
166
+ let [bisectorNormalRight, bisectorNormalLeft, dt, x, y] = [
167
+ [0, 0],
168
+ [0, 0],
169
+ 0,
170
+ 0,
171
+ 0
172
+ ];
173
+ const dist = Math.hypot(normal[0], normal[1]);
174
+ const uX = normal[0] / dist;
175
+ const uY = normal[1] / dist;
176
+ const d1 = mathDistance(coord1, coord2);
177
+ const d2 = mathDistance(coord2, coord3);
178
+ if (dist > ZERO_TOLERANCE) if (isClockWise(coord1, coord2, coord3)) {
179
+ dt = t * d1;
180
+ x = coord2[0] - dt * uY;
181
+ y = coord2[1] + dt * uX;
182
+ bisectorNormalRight = [x, y];
183
+ dt = t * d2;
184
+ x = coord2[0] + dt * uY;
185
+ y = coord2[1] - dt * uX;
186
+ bisectorNormalLeft = [x, y];
187
+ } else {
188
+ dt = t * d1;
189
+ x = coord2[0] + dt * uY;
190
+ y = coord2[1] - dt * uX;
191
+ bisectorNormalRight = [x, y];
192
+ dt = t * d2;
193
+ x = coord2[0] - dt * uY;
194
+ y = coord2[1] + dt * uX;
195
+ bisectorNormalLeft = [x, y];
196
+ }
197
+ else {
198
+ x = coord2[0] + t * (coord1[0] - coord2[0]);
199
+ y = coord2[1] + t * (coord1[1] - coord2[1]);
200
+ bisectorNormalRight = [x, y];
201
+ x = coord2[0] + t * (coord3[0] - coord2[0]);
202
+ y = coord2[1] + t * (coord3[1] - coord2[1]);
203
+ bisectorNormalLeft = [x, y];
204
+ }
205
+ return [bisectorNormalRight, bisectorNormalLeft];
206
+ }
207
+ /**
208
+ * 获取默认三点的内切圆
209
+ * @param coord1
210
+ * @param coord2
211
+ * @param coord3
212
+ */
213
+ function getNormal(coord1, coord2, coord3) {
214
+ let dX1 = coord1[0] - coord2[0];
215
+ let dY1 = coord1[1] - coord2[1];
216
+ const d1 = Math.hypot(dX1, dY1);
217
+ dX1 /= d1;
218
+ dY1 /= d1;
219
+ let dX2 = coord3[0] - coord2[0];
220
+ let dY2 = coord3[1] - coord2[1];
221
+ const d2 = Math.hypot(dX2, dY2);
222
+ dX2 /= d2;
223
+ dY2 /= d2;
224
+ return [dX1 + dX2, dY1 + dY2];
225
+ }
226
+ /**
227
+ * 获取左边控制点
228
+ * @param controlCoords
229
+ * @param t
230
+ */
231
+ function getLeftMostControlCoord(controlCoords, t) {
232
+ let [coord1, coord2, coord3, controlX, controlY] = [
233
+ controlCoords[0],
234
+ controlCoords[1],
235
+ controlCoords[2],
236
+ 0,
237
+ 0
238
+ ];
239
+ const normalRight = getBisectorNormals(0, coord1, coord2, coord3)[0];
240
+ const normal = getNormal(coord1, coord2, coord3);
241
+ if (Math.hypot(normal[0], normal[1]) > ZERO_TOLERANCE) {
242
+ const midCoord = mid(coord1, coord2);
243
+ const pX = coord1[0] - midCoord[0];
244
+ const pY = coord1[1] - midCoord[1];
245
+ const n = 2 / mathDistance(coord1, coord2);
246
+ const nX = -n * pY;
247
+ const nY = n * pX;
248
+ const a11 = nX * nX - nY * nY;
249
+ const a12 = 2 * nX * nY;
250
+ const a22 = nY * nY - nX * nX;
251
+ const dX = normalRight[0] - midCoord[0];
252
+ const dY = normalRight[1] - midCoord[1];
253
+ controlX = midCoord[0] + a11 * dX + a12 * dY;
254
+ controlY = midCoord[1] + a12 * dX + a22 * dY;
255
+ } else {
256
+ controlX = coord1[0] + t * (coord2[0] - coord1[0]);
257
+ controlY = coord1[1] + t * (coord2[1] - coord1[1]);
258
+ }
259
+ return [controlX, controlY];
260
+ }
261
+ /**
262
+ * 获取右边控制点
263
+ * @param controlCoords
264
+ * @param t
265
+ */
266
+ function getRightMostControlCoord(controlCoords, t) {
267
+ const coordlength = controlCoords.length;
268
+ const coord1 = controlCoords[coordlength - 3];
269
+ const coord2 = controlCoords[coordlength - 2];
270
+ const coord3 = controlCoords[coordlength - 1];
271
+ const normalLeft = getBisectorNormals(0, coord1, coord2, coord3)[1];
272
+ const normal = getNormal(coord1, coord2, coord3);
273
+ const dist = Math.hypot(normal[0], normal[1]);
274
+ let [controlX, controlY] = [0, 0];
275
+ if (dist > ZERO_TOLERANCE) {
276
+ const midCoord = mid(coord2, coord3);
277
+ const pX = coord3[0] - midCoord[0];
278
+ const pY = coord3[1] - midCoord[1];
279
+ const n = 2 / mathDistance(coord2, coord3);
280
+ const nX = -n * pY;
281
+ const nY = n * pX;
282
+ const a11 = nX * nX - nY * nY;
283
+ const a12 = 2 * nX * nY;
284
+ const a22 = nY * nY - nX * nX;
285
+ const dX = normalLeft[0] - midCoord[0];
286
+ const dY = normalLeft[1] - midCoord[1];
287
+ controlX = midCoord[0] + a11 * dX + a12 * dY;
288
+ controlY = midCoord[1] + a12 * dX + a22 * dY;
289
+ } else {
290
+ controlX = coord3[0] + t * (coord2[0] - coord3[0]);
291
+ controlY = coord3[1] + t * (coord2[1] - coord3[1]);
292
+ }
293
+ return [controlX, controlY];
294
+ }
295
+ /**
296
+ * 插值曲线点
297
+ * @param t
298
+ * @param controlCoords
299
+ */
300
+ function getCurveCoords(t, controlCoords) {
301
+ let normals = [getLeftMostControlCoord(controlCoords, t)];
302
+ const coords = [];
303
+ let coord1, coord2, coord3;
304
+ for (let i = 0; i < controlCoords.length - 2; i++) {
305
+ [coord1, coord2, coord3] = [
306
+ controlCoords[i],
307
+ controlCoords[i + 1],
308
+ controlCoords[i + 2]
309
+ ];
310
+ const normalCoords = getBisectorNormals(t, coord1, coord2, coord3);
311
+ normals = normals.concat(normalCoords);
312
+ }
313
+ const rightControl = getRightMostControlCoord(controlCoords, t);
314
+ if (rightControl) normals.push(rightControl);
315
+ for (let i = 0; i < controlCoords.length - 1; i++) {
316
+ coord1 = controlCoords[i];
317
+ coord2 = controlCoords[i + 1];
318
+ coords.push(coord1);
319
+ for (let j = 0; j < FITTING_COUNT; j++) {
320
+ const coord = getCubicValue(j / FITTING_COUNT, coord1, normals[i * 2], normals[i * 2 + 1], coord2);
321
+ coords.push(coord);
322
+ }
323
+ coords.push(coord2);
324
+ }
325
+ return coords;
326
+ }
327
+ /**
328
+ * 贝塞尔曲线
329
+ * @param points
330
+ */
331
+ function getBezierCoords(points) {
332
+ if (points.length <= 2) return points;
333
+ const bezierCoords = [];
334
+ const n = points.length - 1;
335
+ for (let t = 0; t <= 1; t += .01) {
336
+ let [x, y] = [0, 0];
337
+ for (let index = 0; index <= n; index++) {
338
+ const factor = getBinomialFactor(n, index);
339
+ const a = t ** index;
340
+ const b = (1 - t) ** (n - index);
341
+ x += factor * a * b * points[index][0];
342
+ y += factor * a * b * points[index][1];
343
+ }
344
+ bezierCoords.push([x, y]);
345
+ }
346
+ bezierCoords.push(points[n]);
347
+ return bezierCoords;
348
+ }
349
+ /**
350
+ * 获取阶乘数据
351
+ * @param n
352
+ */
353
+ function getFactorial(n) {
354
+ let result = 1;
355
+ switch (true) {
356
+ case n <= 1:
357
+ result = 1;
358
+ break;
359
+ case n === 2:
360
+ result = 2;
361
+ break;
362
+ case n === 3:
363
+ result = 6;
364
+ break;
365
+ case n === 24:
366
+ result = 24;
367
+ break;
368
+ case n === 5:
369
+ result = 120;
370
+ break;
371
+ default:
372
+ for (let i = 1; i <= n; i++) result *= i;
373
+ break;
374
+ }
375
+ return result;
376
+ }
377
+ /**
378
+ * 获取二项分布
379
+ * @param n
380
+ * @param index
381
+ */
382
+ function getBinomialFactor(n, index) {
383
+ return getFactorial(n) / (getFactorial(index) * getFactorial(n - index));
384
+ }
385
+ /**
386
+ * 插值线性点
387
+ * @param points
388
+ */
389
+ function getQBSplineCoords(points) {
390
+ if (points.length <= 2) return points;
391
+ const [n, bSplineCoords] = [2, []];
392
+ const m = points.length - n - 1;
393
+ bSplineCoords.push(points[0]);
394
+ for (let i = 0; i <= m; i++) for (let t = 0; t <= 1; t += .05) {
395
+ let [x, y] = [0, 0];
396
+ for (let k = 0; k <= n; k++) {
397
+ const factor = getQuadricBSplineFactor(k, t);
398
+ x += factor * points[i + k][0];
399
+ y += factor * points[i + k][1];
400
+ }
401
+ bSplineCoords.push([x, y]);
402
+ }
403
+ bSplineCoords.push(points.at(-1));
404
+ return bSplineCoords;
405
+ }
406
+ /**
407
+ * 得到二次线性因子
408
+ * @param k
409
+ * @param t
410
+ */
411
+ function getQuadricBSplineFactor(k, t) {
412
+ let res = 0;
413
+ if (k === 0) res = (t - 1) ** 2 / 2;
414
+ else if (k === 1) res = (-2 * t ** 2 + 2 * t + 1) / 2;
415
+ else if (k === 2) res = t ** 2 / 2;
416
+ return res;
417
+ }
418
+
419
+ //#endregion
420
+ //#region src/arc.ts
421
+ /**
422
+ * 标绘画弓形算法,继承线要素相关方法和属性
423
+ */
424
+ function arc(coords) {
425
+ if (coords.length <= 2) throw new Error("coords.length must >= 3");
426
+ else {
427
+ let [coord1, coord2, coord3, startAngle, endAngle] = [
428
+ coords[0],
429
+ coords[1],
430
+ coords[2],
431
+ 0,
432
+ 0
433
+ ];
434
+ const center = getCircleCenterOfThreeCoords(coord1, coord2, coord3);
435
+ const radius = mathDistance(coord1, center);
436
+ const angle1 = getAzimuth(coord1, center);
437
+ const angle2 = getAzimuth(coord2, center);
438
+ if (isClockWise(coord1, coord2, coord3)) {
439
+ startAngle = angle2;
440
+ endAngle = angle1;
441
+ } else {
442
+ startAngle = angle1;
443
+ endAngle = angle2;
444
+ }
445
+ return getArcCoords(center, radius, startAngle, endAngle);
446
+ }
447
+ }
448
+
449
+ //#endregion
450
+ //#region src/arrowAttackDirection.ts
451
+ /**
452
+ * 尖曲箭头
453
+ */
454
+ function arrowAttackDirection(coords, options = {}) {
455
+ if (coords.length < 3) throw new Error("coords.length must >= 3");
456
+ else {
457
+ let [tailLeft, tailRight] = [coords[0], coords[1]];
458
+ if (isClockWise(coords[0], coords[1], coords[2])) {
459
+ tailLeft = coords[1];
460
+ tailRight = coords[0];
461
+ }
462
+ const boneCoords = [mid(tailLeft, tailRight)].concat(coords.slice(2));
463
+ const headCoords = getArrowHeadCoords(boneCoords, {
464
+ tailLeft,
465
+ tailRight,
466
+ ...options
467
+ });
468
+ if (headCoords && headCoords.length > 4) {
469
+ const [neckLeft, neckRight] = [headCoords[0], headCoords[4]];
470
+ const bodyCoords = getArrowBodyCoords(boneCoords, neckLeft, neckRight, mathDistance(tailLeft, tailRight) / getBaseLength(boneCoords));
471
+ const coordlength = bodyCoords.length;
472
+ let leftCoords = [tailLeft].concat(bodyCoords.slice(0, coordlength / 2));
473
+ leftCoords.push(neckLeft);
474
+ let rightCoords = [tailRight].concat(bodyCoords.slice(coordlength / 2, coordlength));
475
+ rightCoords.push(neckRight);
476
+ leftCoords = getQBSplineCoords(leftCoords);
477
+ rightCoords = getQBSplineCoords(rightCoords);
478
+ return leftCoords.concat(headCoords, rightCoords.reverse());
479
+ } else return [];
480
+ }
481
+ }
482
+ /**
483
+ * 插值箭形上的点
484
+ * @param coord1
485
+ * @param coord2
486
+ * @param coord3
487
+ * @param clockWise
488
+ */
489
+ function getArrowCoords(coord1, coord2, coord3, clockWise, options = {}) {
490
+ const midCoord = mid(coord1, coord2);
491
+ const len = mathDistance(midCoord, coord3);
492
+ let midCoord1 = getThirdCoord(coord3, midCoord, 0, len * .3, true);
493
+ let midCoord2 = getThirdCoord(coord3, midCoord, 0, len * .5, true);
494
+ midCoord1 = getThirdCoord(midCoord, midCoord1, HALF_PI, len / 5, clockWise);
495
+ midCoord2 = getThirdCoord(midCoord, midCoord2, HALF_PI, len / 4, clockWise);
496
+ const points = [
497
+ midCoord,
498
+ midCoord1,
499
+ midCoord2,
500
+ coord3
501
+ ];
502
+ const arrowCoords = getArrowHeadCoords(points, options);
503
+ if (arrowCoords && Array.isArray(arrowCoords) && arrowCoords.length > 0) {
504
+ const [neckLeftCoord, neckRightCoord] = [arrowCoords[0], arrowCoords[4]];
505
+ const bodyCoords = getArrowBodyCoords(points, neckLeftCoord, neckRightCoord, mathDistance(coord1, coord2) / getBaseLength(points) / 2);
506
+ if (bodyCoords) {
507
+ const n = bodyCoords.length;
508
+ let lCoords = bodyCoords.slice(0, n / 2);
509
+ let rCoords = bodyCoords.slice(n / 2, n);
510
+ lCoords.push(neckLeftCoord);
511
+ rCoords.push(neckRightCoord);
512
+ lCoords = lCoords.reverse();
513
+ lCoords.push(coord2);
514
+ rCoords = rCoords.reverse();
515
+ rCoords.push(coord1);
516
+ return lCoords.reverse().concat(arrowCoords, rCoords);
517
+ }
518
+ } else throw new Error("插值出错");
519
+ }
520
+ /**
521
+ * 插值头部点
522
+ */
523
+ function getArrowHeadCoords(points, options) {
524
+ const { tailLeft, tailRight, headHeightFactor = .18, headWidthFactor = .3, neckHeightFactor = .85, neckWidthFactor = .15, headTailFactor = .8 } = options;
525
+ let len = getBaseLength(points);
526
+ let headHeight = len * headHeightFactor;
527
+ const headCoord = points.at(-1);
528
+ len = mathDistance(headCoord, points.at(-2));
529
+ let tailWidth = 0;
530
+ if (tailLeft && tailRight) tailWidth = mathDistance(tailLeft, tailRight);
531
+ if (headHeight > tailWidth * headTailFactor) headHeight = tailWidth * headTailFactor;
532
+ const headWidth = headHeight * headWidthFactor;
533
+ const neckWidth = headHeight * neckWidthFactor;
534
+ headHeight = Math.min(headHeight, len);
535
+ const neckHeight = headHeight * neckHeightFactor;
536
+ const headEndCoord = getThirdCoord(points.at(-2), headCoord, 0, headHeight, true);
537
+ const neckEndCoord = getThirdCoord(points.at(-2), headCoord, 0, neckHeight, true);
538
+ const headLeft = getThirdCoord(headCoord, headEndCoord, HALF_PI, headWidth, false);
539
+ const headRight = getThirdCoord(headCoord, headEndCoord, HALF_PI, headWidth, true);
540
+ return [
541
+ getThirdCoord(headCoord, neckEndCoord, HALF_PI, neckWidth, false),
542
+ headLeft,
543
+ headCoord,
544
+ headRight,
545
+ getThirdCoord(headCoord, neckEndCoord, HALF_PI, neckWidth, true)
546
+ ];
547
+ }
548
+ /**
549
+ * 插值面部分数据
550
+ * @param points
551
+ * @param neckLeft
552
+ * @param neckRight
553
+ * @param tailWidthFactor
554
+ */
555
+ function getArrowBodyCoords(points, neckLeft, neckRight, tailWidthFactor) {
556
+ const allLen = wholeDistance(points);
557
+ const tailWidth = getBaseLength(points) * tailWidthFactor;
558
+ const widthDif = (tailWidth - mathDistance(neckLeft, neckRight)) / 2;
559
+ let tempLen = 0;
560
+ const leftBodyCoords = [];
561
+ const rightBodyCoords = [];
562
+ for (let i = 1; i < points.length - 1; i++) {
563
+ const angle = getAngleOfThreeCoords(points[i - 1], points[i], points[i + 1]) / 2;
564
+ tempLen += mathDistance(points[i - 1], points[i]);
565
+ const w = (tailWidth / 2 - tempLen / allLen * widthDif) / Math.sin(angle);
566
+ const left = getThirdCoord(points[i - 1], points[i], Math.PI - angle, w, true);
567
+ const right = getThirdCoord(points[i - 1], points[i], angle, w, false);
568
+ leftBodyCoords.push(left);
569
+ rightBodyCoords.push(right);
570
+ }
571
+ return leftBodyCoords.concat(rightBodyCoords);
572
+ }
573
+ /**
574
+ * 获取对称点
575
+ * @param lineCoord1
576
+ * @param lineCoord2
577
+ * @param coord
578
+ */
579
+ function getTempCoord4(lineCoord1, lineCoord2, coord) {
580
+ const midCoord = mid(lineCoord1, lineCoord2);
581
+ const len = mathDistance(midCoord, coord);
582
+ const angle = getAngleOfThreeCoords(lineCoord1, midCoord, coord);
583
+ let symCoord;
584
+ let distance1 = 0;
585
+ let distance2 = 0;
586
+ let midCoord2;
587
+ if (angle < HALF_PI) {
588
+ distance1 = len * Math.sin(angle);
589
+ distance2 = len * Math.cos(angle);
590
+ midCoord2 = getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, false);
591
+ symCoord = getThirdCoord(midCoord, midCoord2, HALF_PI, distance2, true);
592
+ } else if (angle >= HALF_PI && angle < Math.PI) {
593
+ distance1 = len * Math.sin(Math.PI - angle);
594
+ distance2 = len * Math.cos(Math.PI - angle);
595
+ midCoord2 = getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, false);
596
+ symCoord = getThirdCoord(midCoord, midCoord2, HALF_PI, distance2, false);
597
+ } else if (angle >= Math.PI && angle < Math.PI * 1.5) {
598
+ distance1 = len * Math.sin(angle - Math.PI);
599
+ distance2 = len * Math.cos(angle - Math.PI);
600
+ midCoord2 = getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, true);
601
+ symCoord = getThirdCoord(midCoord, midCoord2, HALF_PI, distance2, true);
602
+ } else {
603
+ distance1 = len * Math.sin(Math.PI * 2 - angle);
604
+ distance2 = len * Math.cos(Math.PI * 2 - angle);
605
+ midCoord2 = getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, true);
606
+ symCoord = getThirdCoord(midCoord, midCoord2, HALF_PI, distance2, false);
607
+ }
608
+ return symCoord;
609
+ }
610
+
611
+ //#endregion
612
+ //#region src/arrowAttackDirectionTailed.ts
613
+ /**
614
+ * 燕尾尖曲箭头
615
+ */
616
+ function arrowAttackDirectionTailed(coords, options = {}) {
617
+ const { headHeightFactor = .18, headWidthFactor = .3, neckHeightFactor = .85, neckWidthFactor = .15, tailWidthFactor = .1, swallowTailFactor = 1 } = options;
618
+ if (coords.length < 3) throw new Error("coords.length must >= 3");
619
+ let [tailLeft, tailRight] = [coords[0], coords[1]];
620
+ if (isClockWise(coords[0], coords[1], coords[2])) {
621
+ tailLeft = coords[1];
622
+ tailRight = coords[0];
623
+ }
624
+ const boneCoords = [mid(tailLeft, tailRight)].concat(coords.slice(2));
625
+ const headCoords = getArrowHeadCoords(boneCoords, {
626
+ tailLeft,
627
+ tailRight,
628
+ headHeightFactor,
629
+ headWidthFactor,
630
+ neckWidthFactor,
631
+ neckHeightFactor
632
+ });
633
+ if (headCoords && headCoords.length > 4) {
634
+ const [neckLeft, neckRight] = [headCoords[0], headCoords[4]];
635
+ const tailWidth = mathDistance(tailLeft, tailRight);
636
+ const allLen = getBaseLength(boneCoords);
637
+ const len = allLen * tailWidthFactor * swallowTailFactor;
638
+ const swallowTailCoord = getThirdCoord(boneCoords[1], boneCoords[0], 0, len, true);
639
+ const bodyCoords = getArrowBodyCoords(boneCoords, neckLeft, neckRight, tailWidth / allLen);
640
+ const coordlength = bodyCoords.length;
641
+ let leftCoords = [tailLeft].concat(bodyCoords.slice(0, coordlength / 2));
642
+ leftCoords.push(neckLeft);
643
+ let rightCoords = [tailRight].concat(bodyCoords.slice(coordlength / 2, coordlength));
644
+ rightCoords.push(neckRight);
645
+ leftCoords = getQBSplineCoords(leftCoords);
646
+ rightCoords = getQBSplineCoords(rightCoords);
647
+ return leftCoords.concat(headCoords, rightCoords.reverse(), [swallowTailCoord, leftCoords[0]]);
648
+ } else return [];
649
+ }
650
+
651
+ //#endregion
652
+ //#region src/arrowClamped.ts
653
+ /**
654
+ * 钳击箭头 有效点位长度3,4,5
655
+ */
656
+ function arrowClamped(coords) {
657
+ const options = {
658
+ headHeightFactor: .25,
659
+ headWidthFactor: .3,
660
+ neckHeightFactor: .85,
661
+ neckWidthFactor: .15
662
+ };
663
+ if (coords.length < 3) throw new Error(`coords.length must >= 3`);
664
+ const [coord1, coord2, coord3] = coords;
665
+ let tempCoord4, connCoord;
666
+ if (coords.length === 3) {
667
+ tempCoord4 = getTempCoord4$1(coord1, coord2, coord3);
668
+ connCoord = mid(coord1, coord2);
669
+ } else if (coords.length === 4) {
670
+ tempCoord4 = coords[3];
671
+ connCoord = mid(coord1, coord2);
672
+ } else {
673
+ tempCoord4 = coords[3];
674
+ connCoord = coords[4];
675
+ }
676
+ let leftArrowCoords;
677
+ let rightArrowCoords;
678
+ if (isClockWise(coord1, coord2, coord3)) {
679
+ leftArrowCoords = getArrowCoords$1(coord1, connCoord, tempCoord4, false, options);
680
+ rightArrowCoords = getArrowCoords$1(connCoord, coord2, coord3, true, options);
681
+ } else {
682
+ leftArrowCoords = getArrowCoords$1(coord2, connCoord, coord3, false, options);
683
+ rightArrowCoords = getArrowCoords$1(connCoord, coord1, tempCoord4, true, options);
684
+ }
685
+ const m = leftArrowCoords.length;
686
+ const t = (m - 5) / 2;
687
+ const llBodyCoords = leftArrowCoords.slice(0, t);
688
+ const lArrowCoords = leftArrowCoords.slice(t, t + 5);
689
+ let lrBodyCoords = leftArrowCoords.slice(t + 5, m);
690
+ let rlBodyCoords = rightArrowCoords.slice(0, t);
691
+ const rArrowCoords = rightArrowCoords.slice(t, t + 5);
692
+ const rrBodyCoords = rightArrowCoords.slice(t + 5, m);
693
+ rlBodyCoords = getBezierCoords(rlBodyCoords);
694
+ const bodyCoords = getBezierCoords(rrBodyCoords.concat(llBodyCoords.slice(1)));
695
+ lrBodyCoords = getBezierCoords(lrBodyCoords);
696
+ return rlBodyCoords.concat(rArrowCoords, bodyCoords, lArrowCoords, lrBodyCoords);
697
+ }
698
+ /**
699
+ * 插值箭形上的点
700
+ * @param coord1 - Wgs84坐标
701
+ * @param coord2 - Wgs84坐标
702
+ * @param coord3 - Wgs84坐标
703
+ * @param clockWise - 是否顺时针
704
+ */
705
+ function getArrowCoords$1(coord1, coord2, coord3, clockWise, options) {
706
+ const midCoord = mid(coord1, coord2);
707
+ const len = mathDistance(midCoord, coord3);
708
+ let midCoord1 = getThirdCoord(coord3, midCoord, 0, len * .3, true);
709
+ let midCoord2 = getThirdCoord(coord3, midCoord, 0, len * .5, true);
710
+ midCoord1 = getThirdCoord(midCoord, midCoord1, HALF_PI, len / 5, clockWise);
711
+ midCoord2 = getThirdCoord(midCoord, midCoord2, HALF_PI, len / 4, clockWise);
712
+ const coords = [
713
+ midCoord,
714
+ midCoord1,
715
+ midCoord2,
716
+ coord3
717
+ ];
718
+ const arrowCoords = getArrowHeadCoords$1(coords, options);
719
+ if (arrowCoords && Array.isArray(arrowCoords) && arrowCoords.length > 0) {
720
+ const [neckLeftCoord, neckRightCoord] = [arrowCoords[0], arrowCoords[4]];
721
+ const bodyCoords = getArrowBodyCoords$1(coords, neckLeftCoord, neckRightCoord, mathDistance(coord1, coord2) / getBaseLength(coords) / 2);
722
+ const n = bodyCoords.length;
723
+ let lCoords = bodyCoords.slice(0, n / 2);
724
+ let rCoords = bodyCoords.slice(n / 2, n);
725
+ lCoords.push(neckLeftCoord);
726
+ rCoords.push(neckRightCoord);
727
+ lCoords = lCoords.reverse();
728
+ lCoords.push(coord2);
729
+ rCoords = rCoords.reverse();
730
+ rCoords.push(coord1);
731
+ return lCoords.reverse().concat(arrowCoords, rCoords);
732
+ } else throw new Error("插值出错");
733
+ }
734
+ /**
735
+ * 插值头部点
736
+ * @param coords
737
+ */
738
+ function getArrowHeadCoords$1(coords, options) {
739
+ const { headHeightFactor, headWidthFactor, neckWidthFactor, neckHeightFactor } = options;
740
+ const headHeight = getBaseLength(coords) * headHeightFactor;
741
+ const headCoord = coords.at(-1);
742
+ const headWidth = headHeight * headWidthFactor;
743
+ const neckWidth = headHeight * neckWidthFactor;
744
+ const neckHeight = headHeight * neckHeightFactor;
745
+ const headEndCoord = getThirdCoord(coords.at(-2), headCoord, 0, headHeight, true);
746
+ const neckEndCoord = getThirdCoord(coords.at(-2), headCoord, 0, neckHeight, true);
747
+ const headLeft = getThirdCoord(headCoord, headEndCoord, HALF_PI, headWidth, false);
748
+ const headRight = getThirdCoord(headCoord, headEndCoord, HALF_PI, headWidth, true);
749
+ return [
750
+ getThirdCoord(headCoord, neckEndCoord, HALF_PI, neckWidth, false),
751
+ headLeft,
752
+ headCoord,
753
+ headRight,
754
+ getThirdCoord(headCoord, neckEndCoord, HALF_PI, neckWidth, true)
755
+ ];
756
+ }
757
+ /**
758
+ * 插值面部分数据
759
+ * @param coords
760
+ * @param neckLeft
761
+ * @param neckRight
762
+ * @param tailWidthFactor
763
+ */
764
+ function getArrowBodyCoords$1(coords, neckLeft, neckRight, tailWidthFactor) {
765
+ const allLen = wholeDistance(coords);
766
+ const tailWidth = getBaseLength(coords) * tailWidthFactor;
767
+ const widthDif = (tailWidth - mathDistance(neckLeft, neckRight)) / 2;
768
+ let tempLen = 0;
769
+ const leftBodyCoords = [];
770
+ const rightBodyCoords = [];
771
+ for (let i = 1; i < coords.length - 1; i++) {
772
+ const angle = getAngleOfThreeCoords(coords[i - 1], coords[i], coords[i + 1]) / 2;
773
+ tempLen += mathDistance(coords[i - 1], coords[i]);
774
+ const w = (tailWidth / 2 - tempLen / allLen * widthDif) / Math.sin(angle);
775
+ const left = getThirdCoord(coords[i - 1], coords[i], Math.PI - angle, w, true);
776
+ const right = getThirdCoord(coords[i - 1], coords[i], angle, w, false);
777
+ leftBodyCoords.push(left);
778
+ rightBodyCoords.push(right);
779
+ }
780
+ return leftBodyCoords.concat(rightBodyCoords);
781
+ }
782
+ /**
783
+ * 获取对称点
784
+ * @param lineCoord1
785
+ * @param lineCoord2
786
+ * @param coord
787
+ */
788
+ function getTempCoord4$1(lineCoord1, lineCoord2, coord) {
789
+ const midCoord = mid(lineCoord1, lineCoord2);
790
+ const len = mathDistance(midCoord, coord);
791
+ const angle = getAngleOfThreeCoords(lineCoord1, midCoord, coord);
792
+ if (angle < HALF_PI) {
793
+ const distance1 = len * Math.sin(angle);
794
+ const distance2 = len * Math.cos(angle);
795
+ return getThirdCoord(midCoord, getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, false), HALF_PI, distance2, true);
796
+ } else if (angle >= HALF_PI && angle < Math.PI) {
797
+ const distance1 = len * Math.sin(Math.PI - angle);
798
+ const distance2 = len * Math.cos(Math.PI - angle);
799
+ return getThirdCoord(midCoord, getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, false), HALF_PI, distance2, false);
800
+ } else if (angle >= Math.PI && angle < Math.PI * 1.5) {
801
+ const distance1 = len * Math.sin(angle - Math.PI);
802
+ const distance2 = len * Math.cos(angle - Math.PI);
803
+ return getThirdCoord(midCoord, getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, true), HALF_PI, distance2, true);
804
+ } else {
805
+ const distance1 = len * Math.sin(Math.PI * 2 - angle);
806
+ const distance2 = len * Math.cos(Math.PI * 2 - angle);
807
+ return getThirdCoord(midCoord, getThirdCoord(lineCoord1, midCoord, HALF_PI, distance1, true), HALF_PI, distance2, false);
808
+ }
809
+ }
810
+
811
+ //#endregion
812
+ //#region src/arrowStraightSharp.ts
813
+ /**
814
+ * 尖箭头
815
+ *
816
+ */
817
+ function arrowStraightSharp(coords, options = {}) {
818
+ const { tailWidthFactor = .1, neckWidthFactor = .2, headWidthFactor = .25, headAngle = Math.PI / 8.5, neckAngle = Math.PI / 13 } = options;
819
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
820
+ const [coord1, coord2] = [coords[0], coords[1]];
821
+ const len = getBaseLength(coords);
822
+ const tailWidth = len * tailWidthFactor;
823
+ const neckWidth = len * neckWidthFactor;
824
+ const headWidth = len * headWidthFactor;
825
+ const tailLeft = getThirdCoord(coord2, coord1, HALF_PI, tailWidth, true);
826
+ const tailRight = getThirdCoord(coord2, coord1, HALF_PI, tailWidth, false);
827
+ const headLeft = getThirdCoord(coord1, coord2, headAngle, headWidth, false);
828
+ const headRight = getThirdCoord(coord1, coord2, headAngle, headWidth, true);
829
+ return [
830
+ tailLeft,
831
+ getThirdCoord(coord1, coord2, neckAngle, neckWidth, false),
832
+ headLeft,
833
+ coord2,
834
+ headRight,
835
+ getThirdCoord(coord1, coord2, neckAngle, neckWidth, true),
836
+ tailRight
837
+ ];
838
+ }
839
+
840
+ //#endregion
841
+ //#region src/arrowStraight.ts
842
+ /**
843
+ * 直箭头
844
+ */
845
+ function arrowStraight(coords) {
846
+ return arrowStraightSharp(coords, {
847
+ tailWidthFactor: .05,
848
+ neckWidthFactor: .1,
849
+ headWidthFactor: .15,
850
+ headAngle: Math.PI / 4,
851
+ neckAngle: Math.PI * .17741
852
+ });
853
+ }
854
+
855
+ //#endregion
856
+ //#region src/arrowStraightFine.ts
857
+ /**
858
+ * 细直箭头
859
+ */
860
+ function arrowStraightFine(coords) {
861
+ const maxArrowLength = 3e6;
862
+ const arrowLengthScale = 5;
863
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
864
+ const [coord1, coord2] = [coords[0], coords[1]];
865
+ let len = mathDistance(coord1, coord2) / arrowLengthScale;
866
+ len = Math.min(len, maxArrowLength);
867
+ return [
868
+ coord1,
869
+ coord2,
870
+ getThirdCoord(coord1, coord2, Math.PI / 6, len, false),
871
+ coord2,
872
+ getThirdCoord(coord1, coord2, Math.PI / 6, len, true)
873
+ ];
874
+ }
875
+
876
+ //#endregion
877
+ //#region src/arrowUnitCombatOperation.ts
878
+ /**
879
+ * 分队战斗行动(尖曲箭头)
880
+ */
881
+ function arrowUnitCombatOperation(coords, options = {}) {
882
+ const { headHeightFactor = .18, headWidthFactor = .3, neckHeightFactor = .85, neckWidthFactor = .15, tailWidthFactor = .1 } = options;
883
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
884
+ else {
885
+ const tailWidth = getBaseLength(coords) * tailWidthFactor;
886
+ const tailLeft = getThirdCoord(coords[1], coords[0], HALF_PI, tailWidth, false);
887
+ const tailRight = getThirdCoord(coords[1], coords[0], HALF_PI, tailWidth, true);
888
+ const headCoords = getArrowHeadCoords(coords, {
889
+ tailLeft,
890
+ tailRight,
891
+ headHeightFactor,
892
+ headWidthFactor,
893
+ neckWidthFactor,
894
+ neckHeightFactor
895
+ });
896
+ if (headCoords && headCoords.length > 4) {
897
+ const neckLeft = headCoords[0];
898
+ const neckRight = headCoords[4];
899
+ const bodyCoords = getArrowBodyCoords(coords, neckLeft, neckRight, tailWidthFactor);
900
+ const coordlength = bodyCoords.length;
901
+ let leftCoords = [tailLeft].concat(bodyCoords.slice(0, coordlength / 2));
902
+ leftCoords.push(neckLeft);
903
+ let rightCoords = [tailRight].concat(bodyCoords.slice(coordlength / 2, coordlength));
904
+ rightCoords.push(neckRight);
905
+ leftCoords = getQBSplineCoords(leftCoords);
906
+ rightCoords = getQBSplineCoords(rightCoords);
907
+ return leftCoords.concat(headCoords, rightCoords.reverse());
908
+ } else return [];
909
+ }
910
+ }
911
+
912
+ //#endregion
913
+ //#region src/arrowUnitCombatOperationTailed.ts
914
+ /**
915
+ * 燕尾尖箭头
916
+ */
917
+ function arrowUnitCombatOperationTailed(coords, options = {}) {
918
+ const { headHeightFactor = .18, headWidthFactor = .3, neckHeightFactor = .85, neckWidthFactor = .15, tailWidthFactor = .1, swallowTailFactor = 1 } = options;
919
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
920
+ const tailWidth = getBaseLength(coords) * tailWidthFactor;
921
+ const tailLeft = getThirdCoord(coords[1], coords[0], HALF_PI, tailWidth, false);
922
+ const tailRight = getThirdCoord(coords[1], coords[0], HALF_PI, tailWidth, true);
923
+ const len = tailWidth * swallowTailFactor;
924
+ const tailCoords = [
925
+ tailLeft,
926
+ getThirdCoord(coords[1], coords[0], 0, len, true),
927
+ tailRight
928
+ ];
929
+ const headCoords = getArrowHeadCoords(coords, {
930
+ tailLeft: tailCoords[0],
931
+ tailRight: tailCoords[2],
932
+ headHeightFactor,
933
+ headWidthFactor,
934
+ neckWidthFactor,
935
+ neckHeightFactor
936
+ });
937
+ if (headCoords && headCoords.length > 4) {
938
+ const neckLeft = headCoords[0];
939
+ const neckRight = headCoords[4];
940
+ const bodyCoords = getArrowBodyCoords(coords, neckLeft, neckRight, tailWidthFactor);
941
+ const coordlength = bodyCoords.length;
942
+ let leftCoords = [tailCoords[0]].concat(bodyCoords.slice(0, coordlength / 2));
943
+ leftCoords.push(neckLeft);
944
+ let rightCoords = [tailCoords[2]].concat(bodyCoords.slice(coordlength / 2, coordlength));
945
+ rightCoords.push(neckRight);
946
+ leftCoords = getQBSplineCoords(leftCoords);
947
+ rightCoords = getQBSplineCoords(rightCoords);
948
+ return leftCoords.concat(headCoords, rightCoords.reverse(), [tailCoords[1], leftCoords[0]]);
949
+ }
950
+ return [];
951
+ }
952
+
953
+ //#endregion
954
+ //#region src/assemblingPlace.ts
955
+ /**
956
+ * 集结地
957
+ *
958
+ */
959
+ function assemblingPlace(coords) {
960
+ if (coords.length < 3) throw new Error(`coords.length must >= 3`);
961
+ const t = .4;
962
+ const midCoord = mid(coords[0], coords[2]);
963
+ coords.push(midCoord, coords[0], coords[1]);
964
+ let normals = [];
965
+ const pList = [];
966
+ for (let i = 0; i < coords.length - 2; i++) {
967
+ const coord1 = coords[i];
968
+ const coord2 = coords[i + 1];
969
+ const coord3 = coords[i + 2];
970
+ const normalCoords = getBisectorNormals(t, coord1, coord2, coord3);
971
+ normals = normals.concat(normalCoords);
972
+ }
973
+ const count = normals.length;
974
+ normals = [normals[count - 1]].concat(normals.slice(0, count - 1));
975
+ for (let i = 0; i < coords.length - 2; i++) {
976
+ const coord1 = coords[i];
977
+ const coord2 = coords[i + 1];
978
+ pList.push(coord1);
979
+ for (let t$1 = 0; t$1 <= FITTING_COUNT; t$1++) {
980
+ const coord = getCubicValue(t$1 / FITTING_COUNT, coord1, normals[i * 2], normals[i * 2 + 1], coord2);
981
+ pList.push(coord);
982
+ }
983
+ pList.push(coord2);
984
+ }
985
+ return pList;
986
+ }
987
+
988
+ //#endregion
989
+ //#region src/circle.ts
990
+ /**
991
+ * 标绘画圆算法,继承面要素相关方法和属性
992
+ */
993
+ function circle(coords) {
994
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
995
+ const center = coords[0];
996
+ const radius = mathDistance(center, coords[1]);
997
+ let [x, y, angle] = [
998
+ 0,
999
+ 0,
1000
+ 0
1001
+ ];
1002
+ const _coords = [];
1003
+ for (let i = 0; i <= 100; i++) {
1004
+ angle = Math.PI * 2 * i / 100;
1005
+ x = center[0] + radius * Math.cos(angle);
1006
+ y = center[1] + radius * Math.sin(angle);
1007
+ _coords.push([x, y]);
1008
+ }
1009
+ return _coords;
1010
+ }
1011
+
1012
+ //#endregion
1013
+ //#region src/closedCurve.ts
1014
+ /**
1015
+ * 闭合曲面
1016
+ *
1017
+ */
1018
+ function closedCurve(coords) {
1019
+ const t = .3;
1020
+ if (coords.length < 3) throw new Error("coords.length must >= 3");
1021
+ else {
1022
+ coords.push(coords[0], coords[1]);
1023
+ let normals = [];
1024
+ const pList = [];
1025
+ for (let i = 0; i < coords.length - 2; i++) {
1026
+ const normalCoords = getBisectorNormals(t, coords[i], coords[i + 1], coords[i + 2]);
1027
+ normals = normals.concat(normalCoords);
1028
+ }
1029
+ const coordlength = normals.length;
1030
+ normals = [normals[coordlength - 1]].concat(normals.slice(0, coordlength - 1));
1031
+ for (let i = 0; i < coords.length - 2; i++) {
1032
+ const coord1 = coords[i];
1033
+ const coord2 = coords[i + 1];
1034
+ pList.push(coord1);
1035
+ for (let t$1 = 0; t$1 <= FITTING_COUNT; t$1++) {
1036
+ const coord = getCubicValue(t$1 / FITTING_COUNT, coord1, normals[i * 2], normals[i * 2 + 1], coord2);
1037
+ pList.push(coord);
1038
+ }
1039
+ pList.push(coord2);
1040
+ }
1041
+ return pList;
1042
+ }
1043
+ }
1044
+
1045
+ //#endregion
1046
+ //#region src/curve.ts
1047
+ /**
1048
+ * 标绘曲线算法
1049
+ */
1050
+ function curve(coords) {
1051
+ const t = .3;
1052
+ if (coords.length < 3) throw new Error("coords.length must >= 2");
1053
+ else return getCurveCoords(t, coords);
1054
+ }
1055
+
1056
+ //#endregion
1057
+ //#region src/ellipse.ts
1058
+ /**
1059
+ * 标绘画椭圆算法,继承面要素相关方法和属性
1060
+ */
1061
+ function ellipse(coords) {
1062
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
1063
+ const [coord1, coord2] = [coords[0], coords[1]];
1064
+ const center = mid(coord1, coord2);
1065
+ const majorRadius = Math.abs((coord1[0] - coord2[0]) / 2);
1066
+ const minorRadius = Math.abs((coord1[1] - coord2[1]) / 2);
1067
+ let [x, y, angle] = [
1068
+ 0,
1069
+ 0,
1070
+ 0
1071
+ ];
1072
+ const _coords = [];
1073
+ for (let i = 0; i <= FITTING_COUNT; i++) {
1074
+ angle = Math.PI * 2 * i / FITTING_COUNT;
1075
+ x = center[0] + majorRadius * Math.cos(angle);
1076
+ y = center[1] + minorRadius * Math.sin(angle);
1077
+ coords.push([x, y]);
1078
+ }
1079
+ return _coords;
1080
+ }
1081
+
1082
+ //#endregion
1083
+ //#region src/lune.ts
1084
+ /**
1085
+ * 弓形
1086
+ */
1087
+ function lune(coords) {
1088
+ coords = [...coords];
1089
+ const coordLength = coords.length;
1090
+ if (coordLength < 2) throw new Error("coords.length must >= 2");
1091
+ if (coordLength === 2) {
1092
+ const midCoord = mid(coords[0], coords[1]);
1093
+ const d = mathDistance(coords[0], midCoord);
1094
+ const coord = getThirdCoord(coords[0], midCoord, HALF_PI, d);
1095
+ coords.push(coord);
1096
+ }
1097
+ let [coord1, coord2, coord3, startAngle, endAngle] = [
1098
+ coords[0],
1099
+ coords[1],
1100
+ coords[2],
1101
+ 0,
1102
+ 0
1103
+ ];
1104
+ const center = getCircleCenterOfThreeCoords(coord1, coord2, coord3);
1105
+ const radius = mathDistance(coord1, center);
1106
+ const angle1 = getAzimuth(coord1, center);
1107
+ const angle2 = getAzimuth(coord2, center);
1108
+ if (isClockWise(coord1, coord2, coord3)) {
1109
+ startAngle = angle2;
1110
+ endAngle = angle1;
1111
+ } else {
1112
+ startAngle = angle1;
1113
+ endAngle = angle2;
1114
+ }
1115
+ coords = getArcCoords(center, radius, startAngle, endAngle);
1116
+ coords.push(coords[0]);
1117
+ return coords;
1118
+ }
1119
+
1120
+ //#endregion
1121
+ //#region src/rectAngle.ts
1122
+ /**
1123
+ * 规则矩形
1124
+ *
1125
+ */
1126
+ function rectAngle(coords) {
1127
+ if (coords.length < 2) throw new Error("coords.length must >= 2");
1128
+ const [startCoord, endCoord] = coords;
1129
+ return [
1130
+ startCoord,
1131
+ [startCoord[0], endCoord[1]],
1132
+ endCoord,
1133
+ [endCoord[0], startCoord[1]],
1134
+ startCoord
1135
+ ];
1136
+ }
1137
+
1138
+ //#endregion
1139
+ //#region src/rectinclined1.ts
1140
+ /**
1141
+ * 斜矩形1
1142
+ *
1143
+ */
1144
+ function rectinclined1(coords) {
1145
+ if (coords.length < 3) throw new Error("coords.length must >= 3");
1146
+ else {
1147
+ const [coord1, coord2, mouse] = [
1148
+ coords[0],
1149
+ coords[1],
1150
+ coords[2]
1151
+ ];
1152
+ const d = calculatePerpendicularDistance(coord1, coord2, mouse);
1153
+ const coord3 = calculatePerpendicularCoord(coord1, coord2, calculatePositionRelativeToLine(coord1, coord2, mouse) * d);
1154
+ const coord4 = calculateFourthCoord(coord1, coord2, coord3);
1155
+ const pList = [];
1156
+ pList.push(coord1, coord2, coord3, coord4, coord1);
1157
+ return pList;
1158
+ }
1159
+ }
1160
+ /**
1161
+ * 已知p1,p2,p3三点,计算p3到p1p2的垂直距离
1162
+ * @param {*} p1
1163
+ * @param {*} p2
1164
+ * @param {*} p3
1165
+ */
1166
+ function calculatePerpendicularDistance(p1, p2, p3) {
1167
+ const vx = p2[0] - p1[0];
1168
+ const vy = p2[1] - p1[1];
1169
+ const px = p3[0] - p1[0];
1170
+ const py = p3[1] - p1[1];
1171
+ const vMagnitude = Math.hypot(vx, vy);
1172
+ const projectionLength = (px * vx + py * vy) / vMagnitude;
1173
+ const pMagnitude = Math.hypot(px, py);
1174
+ return Math.sqrt(pMagnitude * pMagnitude - projectionLength * projectionLength);
1175
+ }
1176
+ /**
1177
+ * 已知p1,p2,两点,判断p3点在p1p2的左右,返回-1右侧,0线上,1左侧
1178
+ * @param {*} p1
1179
+ * @param {*} p2
1180
+ * @param {*} p3
1181
+ */
1182
+ function calculatePositionRelativeToLine(p1, p2, p3) {
1183
+ const v1 = {
1184
+ x: p2[0] - p1[0],
1185
+ y: p2[1] - p1[1]
1186
+ };
1187
+ const v2 = {
1188
+ x: p3[0] - p1[0],
1189
+ y: p3[1] - p1[1]
1190
+ };
1191
+ const direction = v1.x * v2.y - v1.y * v2.x > 0 ? 1 : -1;
1192
+ if (p1[1] > p2[1]) return direction;
1193
+ return -direction;
1194
+ }
1195
+ /**
1196
+ * 已知p1,p2,p3点求矩形的p4点
1197
+ * @param {*} p1
1198
+ * @param {*} p2
1199
+ * @param {*} p3
1200
+ */
1201
+ function calculateFourthCoord(p1, p2, p3) {
1202
+ return [p1[0] + p3[0] - p2[0], p1[1] + p3[1] - p2[1]];
1203
+ }
1204
+ /**
1205
+ * 已知p1,p2两点和距离d,求距离p1p2垂直距离为d的点p3
1206
+ * @param {*} p1
1207
+ * @param {*} p2
1208
+ * @param {*} d
1209
+ */
1210
+ function calculatePerpendicularCoord(p1, p2, d) {
1211
+ const m = (p2[1] - p1[1]) / (p2[0] - p1[0]);
1212
+ let x, y;
1213
+ if (m !== 0) {
1214
+ const perpendicularSlope = -1 / m;
1215
+ const c = p2[1] - perpendicularSlope * p2[0];
1216
+ x = d * Math.sqrt(1 / (1 + perpendicularSlope ** 2)) + p2[0];
1217
+ y = perpendicularSlope * x + c;
1218
+ } else {
1219
+ x = p2[0];
1220
+ y = p2[1] - d;
1221
+ }
1222
+ return [x, y];
1223
+ }
1224
+
1225
+ //#endregion
1226
+ exports.FITTING_COUNT = FITTING_COUNT;
1227
+ exports.HALF_PI = HALF_PI;
1228
+ exports.TWO_PI = TWO_PI;
1229
+ exports.ZERO_TOLERANCE = ZERO_TOLERANCE;
1230
+ exports.arc = arc;
1231
+ exports.arrowAttackDirection = arrowAttackDirection;
1232
+ exports.arrowAttackDirectionTailed = arrowAttackDirectionTailed;
1233
+ exports.arrowClamped = arrowClamped;
1234
+ exports.arrowStraight = arrowStraight;
1235
+ exports.arrowStraightFine = arrowStraightFine;
1236
+ exports.arrowStraightSharp = arrowStraightSharp;
1237
+ exports.arrowUnitCombatOperation = arrowUnitCombatOperation;
1238
+ exports.arrowUnitCombatOperationTailed = arrowUnitCombatOperationTailed;
1239
+ exports.assemblingPlace = assemblingPlace;
1240
+ exports.calculateFourthCoord = calculateFourthCoord;
1241
+ exports.calculatePerpendicularCoord = calculatePerpendicularCoord;
1242
+ exports.calculatePerpendicularDistance = calculatePerpendicularDistance;
1243
+ exports.calculatePositionRelativeToLine = calculatePositionRelativeToLine;
1244
+ exports.circle = circle;
1245
+ exports.closedCurve = closedCurve;
1246
+ exports.curve = curve;
1247
+ exports.ellipse = ellipse;
1248
+ exports.getAngleOfThreeCoords = getAngleOfThreeCoords;
1249
+ exports.getArcCoords = getArcCoords;
1250
+ exports.getArrowBodyCoords = getArrowBodyCoords;
1251
+ exports.getArrowCoords = getArrowCoords;
1252
+ exports.getArrowHeadCoords = getArrowHeadCoords;
1253
+ exports.getAzimuth = getAzimuth;
1254
+ exports.getBaseLength = getBaseLength;
1255
+ exports.getBezierCoords = getBezierCoords;
1256
+ exports.getBinomialFactor = getBinomialFactor;
1257
+ exports.getBisectorNormals = getBisectorNormals;
1258
+ exports.getCircleCenterOfThreeCoords = getCircleCenterOfThreeCoords;
1259
+ exports.getCoordOnLine = getCoordOnLine;
1260
+ exports.getCubicValue = getCubicValue;
1261
+ exports.getCurveCoords = getCurveCoords;
1262
+ exports.getFactorial = getFactorial;
1263
+ exports.getIntersectCoord = getIntersectCoord;
1264
+ exports.getLeftMostControlCoord = getLeftMostControlCoord;
1265
+ exports.getNormal = getNormal;
1266
+ exports.getQBSplineCoords = getQBSplineCoords;
1267
+ exports.getQuadricBSplineFactor = getQuadricBSplineFactor;
1268
+ exports.getRightMostControlCoord = getRightMostControlCoord;
1269
+ exports.getTempCoord4 = getTempCoord4;
1270
+ exports.getThirdCoord = getThirdCoord;
1271
+ exports.isClockWise = isClockWise;
1272
+ exports.lune = lune;
1273
+ exports.mathDistance = mathDistance;
1274
+ exports.mid = mid;
1275
+ exports.rectAngle = rectAngle;
1276
+ exports.rectinclined1 = rectinclined1;
1277
+ exports.wholeDistance = wholeDistance;
1278
+ //# sourceMappingURL=index.cjs.map