poly-extrude 0.19.0 → 0.20.0

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.
@@ -1,62 +1,29 @@
1
1
  /*!
2
- * poly-extrude v0.19.0
2
+ * poly-extrude v0.20.0
3
3
  */
4
- function _defineProperties(target, props) {
5
- for (var i = 0; i < props.length; i++) {
6
- var descriptor = props[i];
7
- descriptor.enumerable = descriptor.enumerable || false;
8
- descriptor.configurable = true;
9
- if ("value" in descriptor) descriptor.writable = true;
10
- Object.defineProperty(target, descriptor.key, descriptor);
11
- }
12
- }
4
+ var earcut$2 = {exports: {}};
13
5
 
14
- function _createClass(Constructor, protoProps, staticProps) {
15
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
16
- if (staticProps) _defineProperties(Constructor, staticProps);
17
- Object.defineProperty(Constructor, "prototype", {
18
- writable: false
19
- });
20
- return Constructor;
21
- }
22
-
23
- function _inheritsLoose(subClass, superClass) {
24
- subClass.prototype = Object.create(superClass.prototype);
25
- subClass.prototype.constructor = subClass;
26
-
27
- _setPrototypeOf(subClass, superClass);
28
- }
6
+ earcut$2.exports = earcut;
29
7
 
30
- function _setPrototypeOf(o, p) {
31
- _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
32
- o.__proto__ = p;
33
- return o;
34
- };
35
- return _setPrototypeOf(o, p);
36
- }
8
+ earcut$2.exports["default"] = earcut;
37
9
 
38
10
  function earcut(data, holeIndices, dim) {
39
- if (dim === void 0) {
40
- dim = 2;
41
- }
42
-
43
- var hasHoles = holeIndices && holeIndices.length;
44
- var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
45
- var outerNode = linkedList(data, 0, outerLen, dim, true);
46
- var triangles = [];
11
+ dim = dim || 2;
12
+ var hasHoles = holeIndices && holeIndices.length,
13
+ outerLen = hasHoles ? holeIndices[0] * dim : data.length,
14
+ outerNode = linkedList(data, 0, outerLen, dim, true),
15
+ triangles = [];
47
16
  if (!outerNode || outerNode.next === outerNode.prev) return triangles;
48
- var minX, minY, invSize;
17
+ var minX, minY, maxX, maxY, x, y, invSize;
49
18
  if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
50
19
 
51
20
  if (data.length > 80 * dim) {
52
- minX = Infinity;
53
- minY = Infinity;
54
- var maxX = -Infinity;
55
- var maxY = -Infinity;
21
+ minX = maxX = data[0];
22
+ minY = maxY = data[1];
56
23
 
57
24
  for (var i = dim; i < outerLen; i += dim) {
58
- var x = data[i];
59
- var y = data[i + 1];
25
+ x = data[i];
26
+ y = data[i + 1];
60
27
  if (x < minX) minX = x;
61
28
  if (y < minY) minY = y;
62
29
  if (x > maxX) maxX = x;
@@ -72,16 +39,17 @@ function earcut(data, holeIndices, dim) {
72
39
  return triangles;
73
40
  } // create a circular doubly linked list from polygon points in the specified winding order
74
41
 
42
+
75
43
  function linkedList(data, start, end, dim, clockwise) {
76
- var last;
44
+ var i, last;
77
45
 
78
46
  if (clockwise === signedArea(data, start, end, dim) > 0) {
79
- for (var i = start; i < end; i += dim) {
80
- last = insertNode(i / dim | 0, data[i], data[i + 1], last);
47
+ for (i = start; i < end; i += dim) {
48
+ last = insertNode(i, data[i], data[i + 1], last);
81
49
  }
82
50
  } else {
83
- for (var _i = end - dim; _i >= start; _i -= dim) {
84
- last = insertNode(_i / dim | 0, data[_i], data[_i + 1], last);
51
+ for (i = end - dim; i >= start; i -= dim) {
52
+ last = insertNode(i, data[i], data[i + 1], last);
85
53
  }
86
54
  }
87
55
 
@@ -121,15 +89,19 @@ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
121
89
  if (!ear) return; // interlink polygon nodes in z-order
122
90
 
123
91
  if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
124
- var stop = ear; // iterate through ears, slicing them one by one
92
+ var stop = ear,
93
+ prev,
94
+ next; // iterate through ears, slicing them one by one
125
95
 
126
96
  while (ear.prev !== ear.next) {
127
- var prev = ear.prev;
128
- var next = ear.next;
97
+ prev = ear.prev;
98
+ next = ear.next;
129
99
 
130
100
  if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
131
- triangles.push(prev.i, ear.i, next.i); // cut off the triangle
132
-
101
+ // cut off the triangle
102
+ triangles.push(prev.i / dim | 0);
103
+ triangles.push(ear.i / dim | 0);
104
+ triangles.push(next.i / dim | 0);
133
105
  removeNode(ear); // skipping the next vertex leads to less sliver triangles
134
106
 
135
107
  ear = next.next;
@@ -144,7 +116,7 @@ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
144
116
  if (!pass) {
145
117
  earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); // if this didn't work, try curing all small self-intersections locally
146
118
  } else if (pass === 1) {
147
- ear = cureLocalIntersections(filterPoints(ear), triangles);
119
+ ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
148
120
  earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); // as a last resort, try splitting the remaining polygon into two
149
121
  } else if (pass === 2) {
150
122
  splitEarcut(ear, triangles, dim, minX, minY, invSize);
@@ -168,16 +140,16 @@ function isEar(ear) {
168
140
  cx = c.x,
169
141
  ay = a.y,
170
142
  by = b.y,
171
- cy = c.y; // triangle bbox
143
+ cy = c.y; // triangle bbox; min & max are calculated like this for speed
172
144
 
173
- var x0 = Math.min(ax, bx, cx),
174
- y0 = Math.min(ay, by, cy),
175
- x1 = Math.max(ax, bx, cx),
176
- y1 = Math.max(ay, by, cy);
145
+ var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
146
+ y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
147
+ x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
148
+ y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
177
149
  var p = c.next;
178
150
 
179
151
  while (p !== a) {
180
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
152
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
181
153
  p = p.next;
182
154
  }
183
155
 
@@ -195,12 +167,12 @@ function isEarHashed(ear, minX, minY, invSize) {
195
167
  cx = c.x,
196
168
  ay = a.y,
197
169
  by = b.y,
198
- cy = c.y; // triangle bbox
170
+ cy = c.y; // triangle bbox; min & max are calculated like this for speed
199
171
 
200
- var x0 = Math.min(ax, bx, cx),
201
- y0 = Math.min(ay, by, cy),
202
- x1 = Math.max(ax, bx, cx),
203
- y1 = Math.max(ay, by, cy); // z-order range for the current triangle bbox;
172
+ var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
173
+ y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
174
+ x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
175
+ y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy; // z-order range for the current triangle bbox;
204
176
 
205
177
  var minZ = zOrder(x0, y0, minX, minY, invSize),
206
178
  maxZ = zOrder(x1, y1, minX, minY, invSize);
@@ -208,21 +180,21 @@ function isEarHashed(ear, minX, minY, invSize) {
208
180
  n = ear.nextZ; // look for points inside the triangle in both directions
209
181
 
210
182
  while (p && p.z >= minZ && n && n.z <= maxZ) {
211
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
183
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
212
184
  p = p.prevZ;
213
- if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
185
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
214
186
  n = n.nextZ;
215
187
  } // look for remaining points in decreasing z-order
216
188
 
217
189
 
218
190
  while (p && p.z >= minZ) {
219
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
191
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
220
192
  p = p.prevZ;
221
193
  } // look for remaining points in increasing z-order
222
194
 
223
195
 
224
196
  while (n && n.z <= maxZ) {
225
- if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
197
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
226
198
  n = n.nextZ;
227
199
  }
228
200
 
@@ -230,7 +202,7 @@ function isEarHashed(ear, minX, minY, invSize) {
230
202
  } // go through all polygon nodes and cure small local self-intersections
231
203
 
232
204
 
233
- function cureLocalIntersections(start, triangles) {
205
+ function cureLocalIntersections(start, triangles, dim) {
234
206
  var p = start;
235
207
 
236
208
  do {
@@ -238,7 +210,9 @@ function cureLocalIntersections(start, triangles) {
238
210
  b = p.next.next;
239
211
 
240
212
  if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
241
- triangles.push(a.i, p.i, b.i); // remove two nodes involved
213
+ triangles.push(a.i / dim | 0);
214
+ triangles.push(p.i / dim | 0);
215
+ triangles.push(b.i / dim | 0); // remove two nodes involved
242
216
 
243
217
  removeNode(p);
244
218
  removeNode(p.next);
@@ -281,40 +255,32 @@ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
281
255
 
282
256
 
283
257
  function eliminateHoles(data, holeIndices, outerNode, dim) {
284
- var queue = [];
285
-
286
- for (var i = 0, len = holeIndices.length; i < len; i++) {
287
- var start = holeIndices[i] * dim;
288
- var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
289
- var list = linkedList(data, start, end, dim, false);
258
+ var queue = [],
259
+ i,
260
+ len,
261
+ start,
262
+ end,
263
+ list;
264
+
265
+ for (i = 0, len = holeIndices.length; i < len; i++) {
266
+ start = holeIndices[i] * dim;
267
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
268
+ list = linkedList(data, start, end, dim, false);
290
269
  if (list === list.next) list.steiner = true;
291
270
  queue.push(getLeftmost(list));
292
271
  }
293
272
 
294
- queue.sort(compareXYSlope); // process holes from left to right
273
+ queue.sort(compareX); // process holes from left to right
295
274
 
296
- for (var _i2 = 0; _i2 < queue.length; _i2++) {
297
- outerNode = eliminateHole(queue[_i2], outerNode);
275
+ for (i = 0; i < queue.length; i++) {
276
+ outerNode = eliminateHole(queue[i], outerNode);
298
277
  }
299
278
 
300
279
  return outerNode;
301
280
  }
302
281
 
303
- function compareXYSlope(a, b) {
304
- var result = a.x - b.x; // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find
305
- // the bridge to the outer shell is always the point that they meet at.
306
-
307
- if (result === 0) {
308
- result = a.y - b.y;
309
-
310
- if (result === 0) {
311
- var aSlope = (a.next.y - a.y) / (a.next.x - a.x);
312
- var bSlope = (b.next.y - b.y) / (b.next.x - b.x);
313
- result = aSlope - bSlope;
314
- }
315
- }
316
-
317
- return result;
282
+ function compareX(a, b) {
283
+ return a.x - b.x;
318
284
  } // find a bridge between vertices that connects hole with an outer ring and and link it
319
285
 
320
286
 
@@ -333,18 +299,15 @@ function eliminateHole(hole, outerNode) {
333
299
 
334
300
 
335
301
  function findHoleBridge(hole, outerNode) {
336
- var p = outerNode;
337
- var hx = hole.x;
338
- var hy = hole.y;
339
- var qx = -Infinity;
340
- var m; // find a segment intersected by a ray from the hole's leftmost point to the left;
302
+ var p = outerNode,
303
+ hx = hole.x,
304
+ hy = hole.y,
305
+ qx = -Infinity,
306
+ m; // find a segment intersected by a ray from the hole's leftmost point to the left;
341
307
  // segment's endpoint with lesser x will be potential connection point
342
- // unless they intersect at a vertex, then choose the vertex
343
-
344
- if (equals(hole, p)) return p;
345
308
 
346
309
  do {
347
- if (equals(hole, p.next)) return p.next;else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
310
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
348
311
  var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
349
312
 
350
313
  if (x <= hx && x > qx) {
@@ -353,6 +316,7 @@ function findHoleBridge(hole, outerNode) {
353
316
  if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
354
317
  }
355
318
  }
319
+
356
320
  p = p.next;
357
321
  } while (p !== outerNode);
358
322
 
@@ -360,15 +324,16 @@ function findHoleBridge(hole, outerNode) {
360
324
  // if there are no points found, we have a valid connection;
361
325
  // otherwise choose the point of the minimum angle with the ray as connection point
362
326
 
363
- var stop = m;
364
- var mx = m.x;
365
- var my = m.y;
366
- var tanMin = Infinity;
327
+ var stop = m,
328
+ mx = m.x,
329
+ my = m.y,
330
+ tanMin = Infinity,
331
+ tan;
367
332
  p = m;
368
333
 
369
334
  do {
370
335
  if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
371
- var tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
336
+ tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
372
337
 
373
338
  if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
374
339
  m = p;
@@ -406,28 +371,34 @@ function indexCurve(start, minX, minY, invSize) {
406
371
 
407
372
 
408
373
  function sortLinked(list) {
409
- var numMerges;
410
- var inSize = 1;
374
+ var i,
375
+ p,
376
+ q,
377
+ e,
378
+ tail,
379
+ numMerges,
380
+ pSize,
381
+ qSize,
382
+ inSize = 1;
411
383
 
412
384
  do {
413
- var p = list;
414
- var e = void 0;
385
+ p = list;
415
386
  list = null;
416
- var tail = null;
387
+ tail = null;
417
388
  numMerges = 0;
418
389
 
419
390
  while (p) {
420
391
  numMerges++;
421
- var q = p;
422
- var pSize = 0;
392
+ q = p;
393
+ pSize = 0;
423
394
 
424
- for (var i = 0; i < inSize; i++) {
395
+ for (i = 0; i < inSize; i++) {
425
396
  pSize++;
426
397
  q = q.nextZ;
427
398
  if (!q) break;
428
399
  }
429
400
 
430
- var qSize = inSize;
401
+ qSize = inSize;
431
402
 
432
403
  while (pSize > 0 || qSize > 0 && q) {
433
404
  if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
@@ -487,11 +458,6 @@ function getLeftmost(start) {
487
458
 
488
459
  function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
489
460
  return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
490
- } // check if a point lies within a convex triangle but false if its equal to the first point of the triangle
491
-
492
-
493
- function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
494
- return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
495
461
  } // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
496
462
 
497
463
 
@@ -559,10 +525,10 @@ function locallyInside(a, b) {
559
525
 
560
526
 
561
527
  function middleInside(a, b) {
562
- var p = a;
563
- var inside = false;
564
- var px = (a.x + b.x) / 2;
565
- var py = (a.y + b.y) / 2;
528
+ var p = a,
529
+ inside = false,
530
+ px = (a.x + b.x) / 2,
531
+ py = (a.y + b.y) / 2;
566
532
 
567
533
  do {
568
534
  if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x) inside = !inside;
@@ -575,8 +541,8 @@ function middleInside(a, b) {
575
541
 
576
542
 
577
543
  function splitPolygon(a, b) {
578
- var a2 = createNode(a.i, a.x, a.y),
579
- b2 = createNode(b.i, b.x, b.y),
544
+ var a2 = new Node(a.i, a.x, a.y),
545
+ b2 = new Node(b.i, b.x, b.y),
580
546
  an = a.next,
581
547
  bp = b.prev;
582
548
  a.next = b;
@@ -592,7 +558,7 @@ function splitPolygon(a, b) {
592
558
 
593
559
 
594
560
  function insertNode(i, x, y, last) {
595
- var p = createNode(i, x, y);
561
+ var p = new Node(i, x, y);
596
562
 
597
563
  if (!last) {
598
564
  p.prev = p;
@@ -614,25 +580,50 @@ function removeNode(p) {
614
580
  if (p.nextZ) p.nextZ.prevZ = p.prevZ;
615
581
  }
616
582
 
617
- function createNode(i, x, y) {
618
- return {
619
- i: i,
620
- // vertex index in coordinates array
621
- x: x,
622
- y: y,
623
- // vertex coordinates
624
- prev: null,
625
- // previous and next vertex nodes in a polygon ring
626
- next: null,
627
- z: 0,
628
- // z-order curve value
629
- prevZ: null,
630
- // previous and next nodes in z-order
631
- nextZ: null,
632
- steiner: false // indicates whether this is a steiner point
583
+ function Node(i, x, y) {
584
+ // vertex index in coordinates array
585
+ this.i = i; // vertex coordinates
633
586
 
634
- };
587
+ this.x = x;
588
+ this.y = y; // previous and next vertex nodes in a polygon ring
589
+
590
+ this.prev = null;
591
+ this.next = null; // z-order curve value
592
+
593
+ this.z = 0; // previous and next nodes in z-order
594
+
595
+ this.prevZ = null;
596
+ this.nextZ = null; // indicates whether this is a steiner point
597
+
598
+ this.steiner = false;
635
599
  } // return a percentage difference between the polygon area and its triangulation area;
600
+ // used to verify correctness of triangulation
601
+
602
+
603
+ earcut.deviation = function (data, holeIndices, dim, triangles) {
604
+ var hasHoles = holeIndices && holeIndices.length;
605
+ var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
606
+ var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
607
+
608
+ if (hasHoles) {
609
+ for (var i = 0, len = holeIndices.length; i < len; i++) {
610
+ var start = holeIndices[i] * dim;
611
+ var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
612
+ polygonArea -= Math.abs(signedArea(data, start, end, dim));
613
+ }
614
+ }
615
+
616
+ var trianglesArea = 0;
617
+
618
+ for (i = 0; i < triangles.length; i += 3) {
619
+ var a = triangles[i] * dim;
620
+ var b = triangles[i + 1] * dim;
621
+ var c = triangles[i + 2] * dim;
622
+ trianglesArea += Math.abs((data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
623
+ }
624
+
625
+ return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea);
626
+ };
636
627
 
637
628
  function signedArea(data, start, end, dim) {
638
629
  var sum = 0;
@@ -645,6 +636,68 @@ function signedArea(data, start, end, dim) {
645
636
  return sum;
646
637
  } // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
647
638
 
639
+
640
+ earcut.flatten = function (data) {
641
+ var dim = data[0][0].length,
642
+ result = {
643
+ vertices: [],
644
+ holes: [],
645
+ dimensions: dim
646
+ },
647
+ holeIndex = 0;
648
+
649
+ for (var i = 0; i < data.length; i++) {
650
+ for (var j = 0; j < data[i].length; j++) {
651
+ for (var d = 0; d < dim; d++) {
652
+ result.vertices.push(data[i][j][d]);
653
+ }
654
+ }
655
+
656
+ if (i > 0) {
657
+ holeIndex += data[i - 1].length;
658
+ result.holes.push(holeIndex);
659
+ }
660
+ }
661
+
662
+ return result;
663
+ };
664
+
665
+ var earcut$1 = earcut$2.exports;
666
+
667
+ function _defineProperties(target, props) {
668
+ for (var i = 0; i < props.length; i++) {
669
+ var descriptor = props[i];
670
+ descriptor.enumerable = descriptor.enumerable || false;
671
+ descriptor.configurable = true;
672
+ if ("value" in descriptor) descriptor.writable = true;
673
+ Object.defineProperty(target, descriptor.key, descriptor);
674
+ }
675
+ }
676
+
677
+ function _createClass(Constructor, protoProps, staticProps) {
678
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
679
+ if (staticProps) _defineProperties(Constructor, staticProps);
680
+ Object.defineProperty(Constructor, "prototype", {
681
+ writable: false
682
+ });
683
+ return Constructor;
684
+ }
685
+
686
+ function _inheritsLoose(subClass, superClass) {
687
+ subClass.prototype = Object.create(superClass.prototype);
688
+ subClass.prototype.constructor = subClass;
689
+
690
+ _setPrototypeOf(subClass, superClass);
691
+ }
692
+
693
+ function _setPrototypeOf(o, p) {
694
+ _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
695
+ o.__proto__ = p;
696
+ return o;
697
+ };
698
+ return _setPrototypeOf(o, p);
699
+ }
700
+
648
701
  // code copy from https://github.com/mrdoob/three.js/blob/dev/src/math/Quaternion.js
649
702
  // import { clamp } from './MathUtils.js';
650
703
  var Quaternion = /*#__PURE__*/function () {
@@ -1980,7 +2033,7 @@ function extrudePolygons(polygons, opts) {
1980
2033
  validatePolygon(polygon, true);
1981
2034
  const result = flatVertices(polygon, options);
1982
2035
  result.polygon = polygon;
1983
- const triangles = earcut(result.flatVertices, result.holes, 2);
2036
+ const triangles = earcut$1(result.flatVertices, result.holes, 2);
1984
2037
  generateTopAndBottom$1(result, triangles, options);
1985
2038
  generateSides$1(result, options);
1986
2039
  result.position = new Float32Array(result.points);
@@ -2126,7 +2179,7 @@ function simplePolygon(polygon, options = {}) {
2126
2179
  uv[++uvIndex] = c[1];
2127
2180
  }
2128
2181
  }
2129
- const triangles = earcut(flatVertices, holes, 2);
2182
+ const triangles = earcut$1(flatVertices, holes, 2);
2130
2183
  const normal = generateNormal(triangles, points);
2131
2184
  return {
2132
2185
  normal,
@@ -2223,10 +2276,15 @@ function generateTopAndBottom(result, options) {
2223
2276
  const { leftPoints, rightPoints } = result;
2224
2277
  const line = result.line;
2225
2278
  const pathUV = options.pathUV;
2279
+ let uvCalPath = line;
2280
+ // let needCalUV = false;
2281
+ if (leftPoints.length > uvCalPath.length) {
2282
+ uvCalPath = leftPoints;
2283
+ }
2226
2284
  if (pathUV) {
2227
- calLineDistance(line);
2228
- for (let i = 0, len = line.length; i < len; i++) {
2229
- leftPoints[i].distance = rightPoints[i].distance = line[i].distance;
2285
+ calLineDistance(uvCalPath);
2286
+ for (let i = 0, len = uvCalPath.length; i < len; i++) {
2287
+ leftPoints[i].distance = rightPoints[i].distance = uvCalPath[i].distance;
2230
2288
  }
2231
2289
  }
2232
2290
  let i = 0, len = leftPoints.length;
@@ -2238,12 +2296,14 @@ function generateTopAndBottom(result, options) {
2238
2296
  points[idx0] = x1;
2239
2297
  points[idx0 + 1] = y1;
2240
2298
  points[idx0 + 2] = lz + z1;
2299
+ // const p1 = leftPoints[i];
2241
2300
  // top right
2242
2301
  const [x2, y2, z2] = rightPoints[i];
2243
2302
  const idx1 = len * 3 + idx0;
2244
2303
  points[idx1] = x2;
2245
2304
  points[idx1 + 1] = y2;
2246
2305
  points[idx1 + 2] = rz + z2;
2306
+ // const p2 = rightPoints[i];
2247
2307
  // bottom left
2248
2308
  const idx2 = (len * 2) * 3 + idx0;
2249
2309
  points[idx2] = x1;
@@ -2262,8 +2322,8 @@ function generateTopAndBottom(result, options) {
2262
2322
  }
2263
2323
  // generate path uv
2264
2324
  if (pathUV) {
2265
- const p = line[i];
2266
- const uvx = p.distance;
2325
+ const p = uvCalPath[i];
2326
+ let uvx = p.distance;
2267
2327
  const uIndex0 = i * 2;
2268
2328
  uv[uIndex0] = uvx;
2269
2329
  uv[uIndex0 + 1] = 1;
@@ -2413,10 +2473,12 @@ function generateSides(result, options) {
2413
2473
  }
2414
2474
  const TEMPV1 = { x: 0, y: 0 }, TEMPV2 = { x: 0, y: 0 };
2415
2475
  function expandLine(line, options) {
2476
+ options = Object.assign({}, { lineWidth: 1, cutCorner: false }, options);
2416
2477
  let radius = options.lineWidth / 2;
2417
2478
  if (options.isSlope) {
2418
2479
  radius *= 2;
2419
2480
  }
2481
+ const { cutCorner } = options;
2420
2482
  const points = [], leftPoints = [], rightPoints = [];
2421
2483
  const len = line.length;
2422
2484
  const repeatVertex = () => {
@@ -2432,7 +2494,9 @@ function expandLine(line, options) {
2432
2494
  return p1[0] === p2[0] && p1[1] === p2[1];
2433
2495
  };
2434
2496
  let i = 0;
2497
+ let preleftline, prerightline;
2435
2498
  while (i < len) {
2499
+ let p0;
2436
2500
  let p1 = line[i], p2 = line[i + 1];
2437
2501
  const currentp = p1;
2438
2502
  // last vertex
@@ -2475,7 +2539,7 @@ function expandLine(line, options) {
2475
2539
  }
2476
2540
  else {
2477
2541
  // 至少3个顶点才会触发
2478
- let p0 = line[i - 1];
2542
+ p0 = line[i - 1];
2479
2543
  if (equal(p0, p2) || equal(p0, p1)) {
2480
2544
  for (let j = line.indexOf(p2); j >= 0; j--) {
2481
2545
  const p = line[j];
@@ -2504,9 +2568,9 @@ function expandLine(line, options) {
2504
2568
  const p3 = currentp;
2505
2569
  const x = Math.cos(rRad) + p3[0], y = Math.sin(rRad) + p3[1];
2506
2570
  const p4 = [x, y];
2507
- const [line1, line2] = translateLine(p1, p2, radius);
2508
- let op1 = lineIntersection(line1[0], line1[1], p3, p4);
2509
- let op2 = lineIntersection(line2[0], line2[1], p3, p4);
2571
+ const [leftline, rightline] = translateLine(p1, p2, radius);
2572
+ let op1 = lineIntersection(leftline[0], leftline[1], p3, p4);
2573
+ let op2 = lineIntersection(rightline[0], rightline[1], p3, p4);
2510
2574
  // 平行,回头路
2511
2575
  if (!op1 || !op2) {
2512
2576
  const len1 = points.length;
@@ -2523,14 +2587,60 @@ function expandLine(line, options) {
2523
2587
  op2[2] = currentp[2] || 0;
2524
2588
  // const [op1, op2] = calOffsetPoint(rRad, radius, p1);
2525
2589
  points.push(op1, op2);
2526
- if (leftOnLine(op1, p1, p2)) {
2527
- leftPoints.push(op1);
2528
- rightPoints.push(op2);
2590
+ let needCut = false;
2591
+ if (cutCorner) {
2592
+ const bufferRadius = radius * 2;
2593
+ if (distance(currentp, op1) > bufferRadius || distance(currentp, op2) > bufferRadius) {
2594
+ needCut = true;
2595
+ }
2596
+ }
2597
+ if (needCut && p0 && preleftline && prerightline) {
2598
+ let cutPoint = op1;
2599
+ if (distance(op1, p0) < distance(op2, p0)) {
2600
+ cutPoint = op2;
2601
+ }
2602
+ const dy = cutPoint[1] - currentp[1], dx = cutPoint[0] - currentp[0];
2603
+ const cutAngle = Math.atan2(dy, dx) / Math.PI * 180;
2604
+ const cutRad = degToRad(cutAngle);
2605
+ const x1 = Math.cos(cutRad) * radius + currentp[0];
2606
+ const y1 = Math.sin(cutRad) * radius + currentp[1];
2607
+ const v1 = [x1, y1];
2608
+ const hcutangle = cutAngle + 90;
2609
+ // console.log(i, cutAngle, hcutangle);
2610
+ const hcutRad = degToRad(hcutangle);
2611
+ const x2 = Math.cos(hcutRad) + x1;
2612
+ const y2 = Math.sin(hcutRad) + y1;
2613
+ const v2 = [x2, y2];
2614
+ let preline = preleftline;
2615
+ let currentLine = leftline;
2616
+ let appendArray = leftPoints;
2617
+ let repeatArray = rightPoints;
2618
+ if (!leftOnLine(cutPoint, p1, p2)) {
2619
+ preline = prerightline;
2620
+ currentLine = rightline;
2621
+ appendArray = rightPoints;
2622
+ repeatArray = leftPoints;
2623
+ }
2624
+ let cross1 = lineIntersection(preline[0], preline[1], v1, v2);
2625
+ let cross2 = lineIntersection(currentLine[0], currentLine[1], v1, v2);
2626
+ cross1[2] = currentp[2] || 0;
2627
+ cross2[2] = currentp[2] || 0;
2628
+ const repeatPoint = cutPoint === op1 ? op2 : op1;
2629
+ appendArray.push(cross1, cross2);
2630
+ repeatArray.push(repeatPoint, [...repeatPoint]);
2529
2631
  }
2530
2632
  else {
2531
- leftPoints.push(op2);
2532
- rightPoints.push(op1);
2633
+ if (leftOnLine(op1, p1, p2)) {
2634
+ leftPoints.push(op1);
2635
+ rightPoints.push(op2);
2636
+ }
2637
+ else {
2638
+ leftPoints.push(op2);
2639
+ rightPoints.push(op1);
2640
+ }
2533
2641
  }
2642
+ preleftline = leftline;
2643
+ prerightline = rightline;
2534
2644
  i++;
2535
2645
  }
2536
2646
  return { offsetPoints: points, leftPoints, rightPoints, line };
@@ -2539,8 +2649,13 @@ const getAngle$1 = ({ x: x1, y: y1 }, { x: x2, y: y2 }) => {
2539
2649
  const dot = x1 * x2 + y1 * y2;
2540
2650
  const det = x1 * y2 - y1 * x2;
2541
2651
  const angle = Math.atan2(det, dot) / Math.PI * 180;
2542
- return (angle + 360) % 360;
2652
+ return (angle);
2653
+ // return (angle + 360) % 360;
2543
2654
  };
2655
+ function distance(p1, p2) {
2656
+ const dx = p2[0] - p1[0], dy = p2[1] - p1[1];
2657
+ return Math.sqrt(dx * dx + dy * dy);
2658
+ }
2544
2659
  function leftOnLine(p, p1, p2) {
2545
2660
  const [x1, y1] = p1;
2546
2661
  const [x2, y2] = p2;
@@ -4715,7 +4830,7 @@ function generateStartAndEnd(result, polygon, options) {
4715
4830
  flatVertices[++pIndex] = c[1];
4716
4831
  }
4717
4832
  }
4718
- const triangles = earcut(flatVertices, holes, 2);
4833
+ const triangles = earcut$1(flatVertices, holes, 2);
4719
4834
  const { points, normal, uv, indices, startPoints, endPoints, polygonLen } = result;
4720
4835
  pIndex = 0;
4721
4836
  let uIndex = 0;