@math.gl/polygon 3.6.3 → 4.0.0-alpha.1

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.
Files changed (56) hide show
  1. package/dist/cut-by-grid.d.ts +4 -1
  2. package/dist/cut-by-grid.d.ts.map +1 -1
  3. package/dist/{esm/cut-by-grid.js → cut-by-grid.js} +10 -11
  4. package/dist/cut-by-grid.js.map +1 -0
  5. package/dist/{esm/cut-by-mercator-bounds.js → cut-by-mercator-bounds.js} +2 -2
  6. package/dist/cut-by-mercator-bounds.js.map +1 -0
  7. package/dist/earcut.d.ts +3 -1
  8. package/dist/earcut.d.ts.map +1 -1
  9. package/dist/{esm/earcut.js → earcut.js} +96 -65
  10. package/dist/earcut.js.map +1 -0
  11. package/dist/index.cjs +1129 -0
  12. package/dist/index.js +8 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/lineclip.d.ts +1 -1
  15. package/dist/lineclip.d.ts.map +1 -1
  16. package/dist/{esm/lineclip.js → lineclip.js} +1 -1
  17. package/dist/lineclip.js.map +1 -0
  18. package/dist/polygon-utils.d.ts +26 -4
  19. package/dist/polygon-utils.d.ts.map +1 -1
  20. package/dist/{esm/polygon-utils.js → polygon-utils.js} +15 -4
  21. package/dist/polygon-utils.js.map +1 -0
  22. package/dist/polygon.d.ts +1 -1
  23. package/dist/polygon.d.ts.map +1 -1
  24. package/dist/{esm/polygon.js → polygon.js} +1 -1
  25. package/dist/polygon.js.map +1 -0
  26. package/dist/{esm/utils.js → utils.js} +0 -0
  27. package/dist/utils.js.map +1 -0
  28. package/package.json +6 -5
  29. package/src/cut-by-grid.ts +26 -9
  30. package/src/earcut.ts +143 -77
  31. package/src/polygon-utils.ts +42 -8
  32. package/dist/es5/cut-by-grid.js +0 -276
  33. package/dist/es5/cut-by-grid.js.map +0 -1
  34. package/dist/es5/cut-by-mercator-bounds.js +0 -194
  35. package/dist/es5/cut-by-mercator-bounds.js.map +0 -1
  36. package/dist/es5/earcut.js +0 -540
  37. package/dist/es5/earcut.js.map +0 -1
  38. package/dist/es5/index.js +0 -104
  39. package/dist/es5/index.js.map +0 -1
  40. package/dist/es5/lineclip.js +0 -150
  41. package/dist/es5/lineclip.js.map +0 -1
  42. package/dist/es5/polygon-utils.js +0 -154
  43. package/dist/es5/polygon-utils.js.map +0 -1
  44. package/dist/es5/polygon.js +0 -79
  45. package/dist/es5/polygon.js.map +0 -1
  46. package/dist/es5/utils.js +0 -54
  47. package/dist/es5/utils.js.map +0 -1
  48. package/dist/esm/cut-by-grid.js.map +0 -1
  49. package/dist/esm/cut-by-mercator-bounds.js.map +0 -1
  50. package/dist/esm/earcut.js.map +0 -1
  51. package/dist/esm/index.js +0 -8
  52. package/dist/esm/index.js.map +0 -1
  53. package/dist/esm/lineclip.js.map +0 -1
  54. package/dist/esm/polygon-utils.js.map +0 -1
  55. package/dist/esm/polygon.js.map +0 -1
  56. package/dist/esm/utils.js.map +0 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,1129 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/index.ts
20
+ var src_exports = {};
21
+ __export(src_exports, {
22
+ Polygon: () => Polygon,
23
+ WINDING: () => WINDING,
24
+ _Polygon: () => Polygon,
25
+ clipPolygon: () => clipPolygon,
26
+ clipPolyline: () => clipPolyline,
27
+ cutPolygonByGrid: () => cutPolygonByGrid,
28
+ cutPolygonByMercatorBounds: () => cutPolygonByMercatorBounds,
29
+ cutPolylineByGrid: () => cutPolylineByGrid,
30
+ cutPolylineByMercatorBounds: () => cutPolylineByMercatorBounds,
31
+ earcut: () => earcut,
32
+ forEachSegmentInPolygon: () => forEachSegmentInPolygon,
33
+ getPolygonSignedArea: () => getPolygonSignedArea,
34
+ getPolygonWindingDirection: () => getPolygonWindingDirection,
35
+ modifyPolygonWindingDirection: () => modifyPolygonWindingDirection
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // src/polygon.ts
40
+ var import_core2 = require("@math.gl/core");
41
+
42
+ // src/polygon-utils.ts
43
+ var import_core = require("@math.gl/core");
44
+ var WINDING = {
45
+ CLOCKWISE: 1,
46
+ COUNTER_CLOCKWISE: -1
47
+ };
48
+ function modifyPolygonWindingDirection(points, direction, options = {}) {
49
+ const windingDirection = getPolygonWindingDirection(points, options);
50
+ if (windingDirection !== direction) {
51
+ reversePolygon(points, options);
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ function getPolygonWindingDirection(points, options = {}) {
57
+ return Math.sign(getPolygonSignedArea(points, options));
58
+ }
59
+ var DimIndex = {
60
+ x: 0,
61
+ y: 1,
62
+ z: 2
63
+ };
64
+ function getPolygonSignedArea(points, options = {}) {
65
+ const { start = 0, end = points.length, plane = "xy" } = options;
66
+ const dim = options.size || 2;
67
+ let area2 = 0;
68
+ const i0 = DimIndex[plane[0]];
69
+ const i1 = DimIndex[plane[1]];
70
+ for (let i = start, j = end - dim; i < end; i += dim) {
71
+ area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
72
+ j = i;
73
+ }
74
+ return area2 / 2;
75
+ }
76
+ function forEachSegmentInPolygon(points, visitor, options = {}) {
77
+ const { start = 0, end = points.length, size = 2, isClosed } = options;
78
+ const numPoints = (end - start) / size;
79
+ for (let i = 0; i < numPoints - 1; ++i) {
80
+ visitor(
81
+ points[start + i * size],
82
+ points[start + i * size + 1],
83
+ points[start + (i + 1) * size],
84
+ points[start + (i + 1) * size + 1],
85
+ i,
86
+ i + 1
87
+ );
88
+ }
89
+ const endPointIndex = start + (numPoints - 1) * size;
90
+ const isClosedEx = isClosed || (0, import_core.equals)(points[start], points[endPointIndex]) && (0, import_core.equals)(points[start + 1], points[endPointIndex + 1]);
91
+ if (!isClosedEx) {
92
+ visitor(
93
+ points[endPointIndex],
94
+ points[endPointIndex + 1],
95
+ points[start],
96
+ points[start + 1],
97
+ numPoints - 1,
98
+ 0
99
+ );
100
+ }
101
+ }
102
+ function reversePolygon(points, options) {
103
+ const { start = 0, end = points.length, size = 2 } = options;
104
+ const numPoints = (end - start) / size;
105
+ const numSwaps = Math.floor(numPoints / 2);
106
+ for (let i = 0; i < numSwaps; ++i) {
107
+ const b1 = start + i * size;
108
+ const b2 = start + (numPoints - 1 - i) * size;
109
+ for (let j = 0; j < size; ++j) {
110
+ const tmp = points[b1 + j];
111
+ points[b1 + j] = points[b2 + j];
112
+ points[b2 + j] = tmp;
113
+ }
114
+ }
115
+ }
116
+ function modifyPolygonWindingDirectionPoints(points, direction, options = {}) {
117
+ const currentDirection = getPolygonWindingDirectionPoints(points, options);
118
+ if (currentDirection !== direction) {
119
+ points.reverse();
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+ function getPolygonWindingDirectionPoints(points, options = {}) {
125
+ return Math.sign(getPolygonSignedAreaPoints(points, options));
126
+ }
127
+ function getPolygonSignedAreaPoints(points, options = {}) {
128
+ const { start = 0, end = points.length, plane = "xy" } = options;
129
+ let area2 = 0;
130
+ const i0 = DimIndex[plane[0]];
131
+ const i1 = DimIndex[plane[1]];
132
+ for (let i = start, j = end - 1; i < end; ++i) {
133
+ area2 += (points[i][i0] - points[j][i0]) * (points[i][i1] + points[j][i1]);
134
+ j = i;
135
+ }
136
+ return area2 / 2;
137
+ }
138
+ function forEachSegmentInPolygonPoints(points, visitor, options = {}) {
139
+ const { start = 0, end = points.length, isClosed } = options;
140
+ for (let i = start; i < end - 1; ++i) {
141
+ visitor(points[i], points[i + 1], i, i + 1);
142
+ }
143
+ const isClosedEx = isClosed || (0, import_core.equals)(points[end - 1], points[0]);
144
+ if (!isClosedEx) {
145
+ visitor(points[end - 1], points[0], end - 1, 0);
146
+ }
147
+ }
148
+
149
+ // src/polygon.ts
150
+ var Polygon = class {
151
+ constructor(points, options = {}) {
152
+ this.points = points;
153
+ this.isFlatArray = !(0, import_core2.isArray)(points[0]);
154
+ this.options = {
155
+ start: options.start || 0,
156
+ end: options.end || points.length,
157
+ size: options.size || 2,
158
+ isClosed: options.isClosed
159
+ };
160
+ Object.freeze(this);
161
+ }
162
+ getSignedArea() {
163
+ if (this.isFlatArray)
164
+ return getPolygonSignedArea(this.points, this.options);
165
+ return getPolygonSignedAreaPoints(this.points, this.options);
166
+ }
167
+ getArea() {
168
+ return Math.abs(this.getSignedArea());
169
+ }
170
+ getWindingDirection() {
171
+ return Math.sign(this.getSignedArea());
172
+ }
173
+ forEachSegment(visitor) {
174
+ if (this.isFlatArray) {
175
+ forEachSegmentInPolygon(
176
+ this.points,
177
+ (x1, y1, x2, y2, i1, i2) => {
178
+ visitor([x1, y1], [x2, y2], i1, i2);
179
+ },
180
+ this.options
181
+ );
182
+ } else {
183
+ forEachSegmentInPolygonPoints(this.points, visitor, this.options);
184
+ }
185
+ }
186
+ modifyWindingDirection(direction) {
187
+ if (this.isFlatArray) {
188
+ return modifyPolygonWindingDirection(this.points, direction, this.options);
189
+ }
190
+ return modifyPolygonWindingDirectionPoints(this.points, direction, this.options);
191
+ }
192
+ };
193
+
194
+ // src/earcut.ts
195
+ function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
196
+ const hasHoles = holeIndices && holeIndices.length;
197
+ const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
198
+ let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
199
+ const triangles = [];
200
+ if (!outerNode || outerNode.next === outerNode.prev)
201
+ return triangles;
202
+ let invSize;
203
+ let maxX;
204
+ let maxY;
205
+ let minX;
206
+ let minY;
207
+ let x;
208
+ let y;
209
+ if (hasHoles)
210
+ outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
211
+ if (positions.length > 80 * dim) {
212
+ minX = maxX = positions[0];
213
+ minY = maxY = positions[1];
214
+ for (let i = dim; i < outerLen; i += dim) {
215
+ x = positions[i];
216
+ y = positions[i + 1];
217
+ if (x < minX)
218
+ minX = x;
219
+ if (y < minY)
220
+ minY = y;
221
+ if (x > maxX)
222
+ maxX = x;
223
+ if (y > maxY)
224
+ maxY = y;
225
+ }
226
+ invSize = Math.max(maxX - minX, maxY - minY);
227
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
228
+ }
229
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
230
+ return triangles;
231
+ }
232
+ function linkedList(data, start, end, dim, clockwise, area2, plane) {
233
+ let i;
234
+ let last;
235
+ if (area2 === void 0) {
236
+ area2 = getPolygonSignedArea(data, { start, end, size: dim, plane });
237
+ }
238
+ let i0 = DimIndex[plane[0]];
239
+ let i1 = DimIndex[plane[1]];
240
+ if (clockwise === area2 < 0) {
241
+ for (i = start; i < end; i += dim)
242
+ last = insertNode(i, data[i + i0], data[i + i1], last);
243
+ } else {
244
+ for (i = end - dim; i >= start; i -= dim)
245
+ last = insertNode(i, data[i + i0], data[i + i1], last);
246
+ }
247
+ if (last && equals2(last, last.next)) {
248
+ removeNode(last);
249
+ last = last.next;
250
+ }
251
+ return last;
252
+ }
253
+ function filterPoints(start, end) {
254
+ if (!start)
255
+ return start;
256
+ if (!end)
257
+ end = start;
258
+ let p = start;
259
+ let again;
260
+ do {
261
+ again = false;
262
+ if (!p.steiner && (equals2(p, p.next) || area(p.prev, p, p.next) === 0)) {
263
+ removeNode(p);
264
+ p = end = p.prev;
265
+ if (p === p.next)
266
+ break;
267
+ again = true;
268
+ } else {
269
+ p = p.next;
270
+ }
271
+ } while (again || p !== end);
272
+ return end;
273
+ }
274
+ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
275
+ if (!ear)
276
+ return;
277
+ if (!pass && invSize)
278
+ indexCurve(ear, minX, minY, invSize);
279
+ let stop = ear;
280
+ let prev;
281
+ let next;
282
+ while (ear.prev !== ear.next) {
283
+ prev = ear.prev;
284
+ next = ear.next;
285
+ if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
286
+ triangles.push(prev.i / dim | 0);
287
+ triangles.push(ear.i / dim | 0);
288
+ triangles.push(next.i / dim | 0);
289
+ removeNode(ear);
290
+ ear = next.next;
291
+ stop = next.next;
292
+ continue;
293
+ }
294
+ ear = next;
295
+ if (ear === stop) {
296
+ if (!pass) {
297
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
298
+ } else if (pass === 1) {
299
+ ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
300
+ earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
301
+ } else if (pass === 2) {
302
+ splitEarcut(ear, triangles, dim, minX, minY, invSize);
303
+ }
304
+ break;
305
+ }
306
+ }
307
+ }
308
+ function isEar(ear) {
309
+ const a = ear.prev;
310
+ const b = ear;
311
+ const c = ear.next;
312
+ if (area(a, b, c) >= 0)
313
+ return false;
314
+ const ax = a.x;
315
+ const bx = b.x;
316
+ const cx = c.x;
317
+ const ay = a.y;
318
+ const by = b.y;
319
+ const cy = c.y;
320
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
321
+ const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
322
+ const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
323
+ const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
324
+ let p = c.next;
325
+ while (p !== a) {
326
+ 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)
327
+ return false;
328
+ p = p.next;
329
+ }
330
+ return true;
331
+ }
332
+ function isEarHashed(ear, minX, minY, invSize) {
333
+ const a = ear.prev;
334
+ const b = ear;
335
+ const c = ear.next;
336
+ if (area(a, b, c) >= 0)
337
+ return false;
338
+ const ax = a.x;
339
+ const bx = b.x;
340
+ const cx = c.x;
341
+ const ay = a.y;
342
+ const by = b.y;
343
+ const cy = c.y;
344
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
345
+ const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
346
+ const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
347
+ const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
348
+ const minZ = zOrder(x0, y0, minX, minY, invSize);
349
+ const maxZ = zOrder(x1, y1, minX, minY, invSize);
350
+ let p = ear.prevZ;
351
+ let n = ear.nextZ;
352
+ while (p && p.z >= minZ && n && n.z <= maxZ) {
353
+ 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)
354
+ return false;
355
+ p = p.prevZ;
356
+ 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)
357
+ return false;
358
+ n = n.nextZ;
359
+ }
360
+ while (p && p.z >= minZ) {
361
+ 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)
362
+ return false;
363
+ p = p.prevZ;
364
+ }
365
+ while (n && n.z <= maxZ) {
366
+ 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)
367
+ return false;
368
+ n = n.nextZ;
369
+ }
370
+ return true;
371
+ }
372
+ function cureLocalIntersections(start, triangles, dim) {
373
+ let p = start;
374
+ do {
375
+ const a = p.prev;
376
+ const b = p.next.next;
377
+ if (!equals2(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
378
+ triangles.push(a.i / dim | 0);
379
+ triangles.push(p.i / dim | 0);
380
+ triangles.push(b.i / dim | 0);
381
+ removeNode(p);
382
+ removeNode(p.next);
383
+ p = start = b;
384
+ }
385
+ p = p.next;
386
+ } while (p !== start);
387
+ return filterPoints(p);
388
+ }
389
+ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
390
+ let a = start;
391
+ do {
392
+ let b = a.next.next;
393
+ while (b !== a.prev) {
394
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
395
+ let c = splitPolygon(a, b);
396
+ a = filterPoints(a, a.next);
397
+ c = filterPoints(c, c.next);
398
+ earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
399
+ earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
400
+ return;
401
+ }
402
+ b = b.next;
403
+ }
404
+ a = a.next;
405
+ } while (a !== start);
406
+ }
407
+ function eliminateHoles(data, holeIndices, outerNode, dim, areas, plane) {
408
+ const queue = [];
409
+ let i;
410
+ let len;
411
+ let start;
412
+ let end;
413
+ let list;
414
+ for (i = 0, len = holeIndices.length; i < len; i++) {
415
+ start = holeIndices[i] * dim;
416
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
417
+ list = linkedList(data, start, end, dim, false, areas && areas[i + 1], plane);
418
+ if (list === list.next)
419
+ list.steiner = true;
420
+ queue.push(getLeftmost(list));
421
+ }
422
+ queue.sort(compareX);
423
+ for (i = 0; i < queue.length; i++) {
424
+ outerNode = eliminateHole(queue[i], outerNode);
425
+ }
426
+ return outerNode;
427
+ }
428
+ function compareX(a, b) {
429
+ return a.x - b.x;
430
+ }
431
+ function eliminateHole(hole, outerNode) {
432
+ const bridge = findHoleBridge(hole, outerNode);
433
+ if (!bridge) {
434
+ return outerNode;
435
+ }
436
+ const bridgeReverse = splitPolygon(bridge, hole);
437
+ filterPoints(bridgeReverse, bridgeReverse.next);
438
+ return filterPoints(bridge, bridge.next);
439
+ }
440
+ function findHoleBridge(hole, outerNode) {
441
+ let p = outerNode;
442
+ const hx = hole.x;
443
+ const hy = hole.y;
444
+ let qx = -Infinity;
445
+ let m;
446
+ do {
447
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
448
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
449
+ if (x <= hx && x > qx) {
450
+ qx = x;
451
+ m = p.x < p.next.x ? p : p.next;
452
+ if (x === hx)
453
+ return m;
454
+ }
455
+ }
456
+ p = p.next;
457
+ } while (p !== outerNode);
458
+ if (!m)
459
+ return null;
460
+ const stop = m;
461
+ const mx = m.x;
462
+ const my = m.y;
463
+ let tanMin = Infinity;
464
+ let tan;
465
+ p = m;
466
+ do {
467
+ 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)) {
468
+ tan = Math.abs(hy - p.y) / (hx - p.x);
469
+ if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
470
+ m = p;
471
+ tanMin = tan;
472
+ }
473
+ }
474
+ p = p.next;
475
+ } while (p !== stop);
476
+ return m;
477
+ }
478
+ function sectorContainsSector(m, p) {
479
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
480
+ }
481
+ function indexCurve(start, minX, minY, invSize) {
482
+ let p = start;
483
+ do {
484
+ if (p.z === 0)
485
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
486
+ p.prevZ = p.prev;
487
+ p.nextZ = p.next;
488
+ p = p.next;
489
+ } while (p !== start);
490
+ p.prevZ.nextZ = null;
491
+ p.prevZ = null;
492
+ sortLinked(p);
493
+ }
494
+ function sortLinked(list) {
495
+ let e;
496
+ let i;
497
+ let inSize = 1;
498
+ let numMerges;
499
+ let p;
500
+ let pSize;
501
+ let q;
502
+ let qSize;
503
+ let tail;
504
+ do {
505
+ p = list;
506
+ list = null;
507
+ tail = null;
508
+ numMerges = 0;
509
+ while (p) {
510
+ numMerges++;
511
+ q = p;
512
+ pSize = 0;
513
+ for (i = 0; i < inSize; i++) {
514
+ pSize++;
515
+ q = q.nextZ;
516
+ if (!q)
517
+ break;
518
+ }
519
+ qSize = inSize;
520
+ while (pSize > 0 || qSize > 0 && q) {
521
+ if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
522
+ e = p;
523
+ p = p.nextZ;
524
+ pSize--;
525
+ } else {
526
+ e = q;
527
+ q = q.nextZ;
528
+ qSize--;
529
+ }
530
+ if (tail)
531
+ tail.nextZ = e;
532
+ else
533
+ list = e;
534
+ e.prevZ = tail;
535
+ tail = e;
536
+ }
537
+ p = q;
538
+ }
539
+ tail.nextZ = null;
540
+ inSize *= 2;
541
+ } while (numMerges > 1);
542
+ return list;
543
+ }
544
+ function zOrder(x, y, minX, minY, invSize) {
545
+ x = (x - minX) * invSize | 0;
546
+ y = (y - minY) * invSize | 0;
547
+ x = (x | x << 8) & 16711935;
548
+ x = (x | x << 4) & 252645135;
549
+ x = (x | x << 2) & 858993459;
550
+ x = (x | x << 1) & 1431655765;
551
+ y = (y | y << 8) & 16711935;
552
+ y = (y | y << 4) & 252645135;
553
+ y = (y | y << 2) & 858993459;
554
+ y = (y | y << 1) & 1431655765;
555
+ return x | y << 1;
556
+ }
557
+ function getLeftmost(start) {
558
+ let p = start;
559
+ let leftmost = start;
560
+ do {
561
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
562
+ leftmost = p;
563
+ p = p.next;
564
+ } while (p !== start);
565
+ return leftmost;
566
+ }
567
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
568
+ 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);
569
+ }
570
+ function isValidDiagonal(a, b) {
571
+ return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (area(a.prev, a, b.prev) || area(a, b.prev, b)) || equals2(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
572
+ }
573
+ function area(p, q, r) {
574
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
575
+ }
576
+ function equals2(p1, p2) {
577
+ return p1.x === p2.x && p1.y === p2.y;
578
+ }
579
+ function intersects(p1, q1, p2, q2) {
580
+ const o1 = sign(area(p1, q1, p2));
581
+ const o2 = sign(area(p1, q1, q2));
582
+ const o3 = sign(area(p2, q2, p1));
583
+ const o4 = sign(area(p2, q2, q1));
584
+ if (o1 !== o2 && o3 !== o4)
585
+ return true;
586
+ if (o1 === 0 && onSegment(p1, p2, q1))
587
+ return true;
588
+ if (o2 === 0 && onSegment(p1, q2, q1))
589
+ return true;
590
+ if (o3 === 0 && onSegment(p2, p1, q2))
591
+ return true;
592
+ if (o4 === 0 && onSegment(p2, q1, q2))
593
+ return true;
594
+ return false;
595
+ }
596
+ function onSegment(p, q, r) {
597
+ return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
598
+ }
599
+ function sign(num) {
600
+ return num > 0 ? 1 : num < 0 ? -1 : 0;
601
+ }
602
+ function intersectsPolygon(a, b) {
603
+ let p = a;
604
+ do {
605
+ if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b))
606
+ return true;
607
+ p = p.next;
608
+ } while (p !== a);
609
+ return false;
610
+ }
611
+ function locallyInside(a, b) {
612
+ return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
613
+ }
614
+ function middleInside(a, b) {
615
+ let p = a;
616
+ let inside = false;
617
+ const px = (a.x + b.x) / 2;
618
+ const py = (a.y + b.y) / 2;
619
+ do {
620
+ 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)
621
+ inside = !inside;
622
+ p = p.next;
623
+ } while (p !== a);
624
+ return inside;
625
+ }
626
+ function splitPolygon(a, b) {
627
+ const a2 = new Vertex(a.i, a.x, a.y);
628
+ const b2 = new Vertex(b.i, b.x, b.y);
629
+ const an = a.next;
630
+ const bp = b.prev;
631
+ a.next = b;
632
+ b.prev = a;
633
+ a2.next = an;
634
+ an.prev = a2;
635
+ b2.next = a2;
636
+ a2.prev = b2;
637
+ bp.next = b2;
638
+ b2.prev = bp;
639
+ return b2;
640
+ }
641
+ function insertNode(i, x, y, last) {
642
+ const p = new Vertex(i, x, y);
643
+ if (!last) {
644
+ p.prev = p;
645
+ p.next = p;
646
+ } else {
647
+ p.next = last.next;
648
+ p.prev = last;
649
+ last.next.prev = p;
650
+ last.next = p;
651
+ }
652
+ return p;
653
+ }
654
+ function removeNode(p) {
655
+ p.next.prev = p.prev;
656
+ p.prev.next = p.next;
657
+ if (p.prevZ)
658
+ p.prevZ.nextZ = p.nextZ;
659
+ if (p.nextZ)
660
+ p.nextZ.prevZ = p.prevZ;
661
+ }
662
+ var Vertex = class {
663
+ constructor(i, x, y) {
664
+ this.prev = null;
665
+ this.next = null;
666
+ this.z = 0;
667
+ this.prevZ = null;
668
+ this.nextZ = null;
669
+ this.steiner = false;
670
+ this.i = i;
671
+ this.x = x;
672
+ this.y = y;
673
+ }
674
+ };
675
+
676
+ // src/utils.ts
677
+ function push(target, source) {
678
+ const size = source.length;
679
+ const startIndex = target.length;
680
+ if (startIndex > 0) {
681
+ let isDuplicate = true;
682
+ for (let i = 0; i < size; i++) {
683
+ if (target[startIndex - size + i] !== source[i]) {
684
+ isDuplicate = false;
685
+ break;
686
+ }
687
+ }
688
+ if (isDuplicate) {
689
+ return false;
690
+ }
691
+ }
692
+ for (let i = 0; i < size; i++) {
693
+ target[startIndex + i] = source[i];
694
+ }
695
+ return true;
696
+ }
697
+ function copy(target, source) {
698
+ const size = source.length;
699
+ for (let i = 0; i < size; i++) {
700
+ target[i] = source[i];
701
+ }
702
+ }
703
+ function getPointAtIndex(positions, index, size, offset, out = []) {
704
+ const startI = offset + index * size;
705
+ for (let i = 0; i < size; i++) {
706
+ out[i] = positions[startI + i];
707
+ }
708
+ return out;
709
+ }
710
+
711
+ // src/lineclip.ts
712
+ function clipPolyline(positions, bbox, options) {
713
+ const { size = 2, startIndex = 0, endIndex = positions.length } = options || {};
714
+ const numPoints = (endIndex - startIndex) / size;
715
+ const result = [];
716
+ let part = [];
717
+ let a;
718
+ let b;
719
+ let codeA = -1;
720
+ let codeB;
721
+ let lastCode;
722
+ for (let i = 1; i < numPoints; i++) {
723
+ a = getPointAtIndex(positions, i - 1, size, startIndex, a);
724
+ b = getPointAtIndex(positions, i, size, startIndex, b);
725
+ if (codeA < 0) {
726
+ codeA = bitCode(a, bbox);
727
+ }
728
+ codeB = lastCode = bitCode(b, bbox);
729
+ while (true) {
730
+ if (!(codeA | codeB)) {
731
+ push(part, a);
732
+ if (codeB !== lastCode) {
733
+ push(part, b);
734
+ if (i < numPoints - 1) {
735
+ result.push(part);
736
+ part = [];
737
+ }
738
+ } else if (i === numPoints - 1) {
739
+ push(part, b);
740
+ }
741
+ break;
742
+ } else if (codeA & codeB) {
743
+ break;
744
+ } else if (codeA) {
745
+ intersect(a, b, codeA, bbox, a);
746
+ codeA = bitCode(a, bbox);
747
+ } else {
748
+ intersect(a, b, codeB, bbox, b);
749
+ codeB = bitCode(b, bbox);
750
+ }
751
+ }
752
+ codeA = lastCode;
753
+ }
754
+ if (part.length)
755
+ result.push(part);
756
+ return result;
757
+ }
758
+ function clipPolygon(positions, bbox, options) {
759
+ const { size = 2, endIndex = positions.length } = options || {};
760
+ let { startIndex = 0 } = options || {};
761
+ let numPoints = (endIndex - startIndex) / size;
762
+ let result;
763
+ let p;
764
+ let prev;
765
+ let inside;
766
+ let prevInside;
767
+ for (let edge = 1; edge <= 8; edge *= 2) {
768
+ result = [];
769
+ prev = getPointAtIndex(positions, numPoints - 1, size, startIndex, prev);
770
+ prevInside = !(bitCode(prev, bbox) & edge);
771
+ for (let i = 0; i < numPoints; i++) {
772
+ p = getPointAtIndex(positions, i, size, startIndex, p);
773
+ inside = !(bitCode(p, bbox) & edge);
774
+ if (inside !== prevInside)
775
+ push(result, intersect(prev, p, edge, bbox));
776
+ if (inside)
777
+ push(result, p);
778
+ copy(prev, p);
779
+ prevInside = inside;
780
+ }
781
+ positions = result;
782
+ startIndex = 0;
783
+ numPoints = result.length / size;
784
+ if (!numPoints)
785
+ break;
786
+ }
787
+ return result;
788
+ }
789
+ function intersect(a, b, edge, bbox, out = []) {
790
+ let t;
791
+ let snap;
792
+ if (edge & 8) {
793
+ t = (bbox[3] - a[1]) / (b[1] - a[1]);
794
+ snap = 3;
795
+ } else if (edge & 4) {
796
+ t = (bbox[1] - a[1]) / (b[1] - a[1]);
797
+ snap = 1;
798
+ } else if (edge & 2) {
799
+ t = (bbox[2] - a[0]) / (b[0] - a[0]);
800
+ snap = 2;
801
+ } else if (edge & 1) {
802
+ t = (bbox[0] - a[0]) / (b[0] - a[0]);
803
+ snap = 0;
804
+ } else {
805
+ return null;
806
+ }
807
+ for (let i = 0; i < a.length; i++) {
808
+ out[i] = (snap & 1) === i ? bbox[snap] : t * (b[i] - a[i]) + a[i];
809
+ }
810
+ return out;
811
+ }
812
+ function bitCode(p, bbox) {
813
+ let code = 0;
814
+ if (p[0] < bbox[0])
815
+ code |= 1;
816
+ else if (p[0] > bbox[2])
817
+ code |= 2;
818
+ if (p[1] < bbox[1])
819
+ code |= 4;
820
+ else if (p[1] > bbox[3])
821
+ code |= 8;
822
+ return code;
823
+ }
824
+
825
+ // src/cut-by-grid.ts
826
+ function cutPolylineByGrid(positions, options) {
827
+ const {
828
+ size = 2,
829
+ broken = false,
830
+ gridResolution = 10,
831
+ gridOffset = [0, 0],
832
+ startIndex = 0,
833
+ endIndex = positions.length
834
+ } = options || {};
835
+ const numPoints = (endIndex - startIndex) / size;
836
+ let part = [];
837
+ const result = [part];
838
+ const a = getPointAtIndex(positions, 0, size, startIndex);
839
+ let b;
840
+ let codeB;
841
+ const cell = getGridCell(a, gridResolution, gridOffset, []);
842
+ const scratchPoint = [];
843
+ push(part, a);
844
+ for (let i = 1; i < numPoints; i++) {
845
+ b = getPointAtIndex(positions, i, size, startIndex, b);
846
+ codeB = bitCode(b, cell);
847
+ while (codeB) {
848
+ intersect(a, b, codeB, cell, scratchPoint);
849
+ const codeAlt = bitCode(scratchPoint, cell);
850
+ if (codeAlt) {
851
+ intersect(a, scratchPoint, codeAlt, cell, scratchPoint);
852
+ codeB = codeAlt;
853
+ }
854
+ push(part, scratchPoint);
855
+ copy(a, scratchPoint);
856
+ moveToNeighborCell(cell, gridResolution, codeB);
857
+ if (broken && part.length > size) {
858
+ part = [];
859
+ result.push(part);
860
+ push(part, a);
861
+ }
862
+ codeB = bitCode(b, cell);
863
+ }
864
+ push(part, b);
865
+ copy(a, b);
866
+ }
867
+ return broken ? result : result[0];
868
+ }
869
+ var TYPE_INSIDE = 0;
870
+ var TYPE_BORDER = 1;
871
+ function cutPolygonByGrid(positions, holeIndices = null, options) {
872
+ if (!positions.length) {
873
+ return [];
874
+ }
875
+ const { size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false } = options || {};
876
+ const result = [];
877
+ const queue = [
878
+ {
879
+ pos: positions,
880
+ types: edgeTypes ? new Array(positions.length / size).fill(TYPE_BORDER) : null,
881
+ holes: holeIndices || []
882
+ }
883
+ ];
884
+ const bbox = [[], []];
885
+ let cell = [];
886
+ while (queue.length) {
887
+ const { pos, types, holes } = queue.shift();
888
+ getBoundingBox(pos, size, holes[0] || pos.length, bbox);
889
+ cell = getGridCell(bbox[0], gridResolution, gridOffset, cell);
890
+ const code = bitCode(bbox[1], cell);
891
+ if (code) {
892
+ let parts = bisectPolygon(pos, types, size, 0, holes[0] || pos.length, cell, code);
893
+ const polygonLow = { pos: parts[0].pos, types: parts[0].types, holes: [] };
894
+ const polygonHigh = { pos: parts[1].pos, types: parts[1].types, holes: [] };
895
+ queue.push(polygonLow, polygonHigh);
896
+ for (let i = 0; i < holes.length; i++) {
897
+ parts = bisectPolygon(pos, types, size, holes[i], holes[i + 1] || pos.length, cell, code);
898
+ if (parts[0]) {
899
+ polygonLow.holes.push(polygonLow.pos.length);
900
+ polygonLow.pos = concatInPlace(polygonLow.pos, parts[0].pos);
901
+ if (edgeTypes) {
902
+ polygonLow.types = concatInPlace(polygonLow.types, parts[0].types);
903
+ }
904
+ }
905
+ if (parts[1]) {
906
+ polygonHigh.holes.push(polygonHigh.pos.length);
907
+ polygonHigh.pos = concatInPlace(polygonHigh.pos, parts[1].pos);
908
+ if (edgeTypes) {
909
+ polygonHigh.types = concatInPlace(polygonHigh.types, parts[1].types);
910
+ }
911
+ }
912
+ }
913
+ } else {
914
+ const polygon = { positions: pos };
915
+ if (edgeTypes) {
916
+ polygon.edgeTypes = types;
917
+ }
918
+ if (holes.length) {
919
+ polygon.holeIndices = holes;
920
+ }
921
+ result.push(polygon);
922
+ }
923
+ }
924
+ return result;
925
+ }
926
+ function bisectPolygon(positions, edgeTypes, size, startIndex, endIndex, bbox, edge) {
927
+ const numPoints = (endIndex - startIndex) / size;
928
+ const resultLow = [];
929
+ const resultHigh = [];
930
+ const typesLow = [];
931
+ const typesHigh = [];
932
+ const scratchPoint = [];
933
+ let p;
934
+ let side;
935
+ let type;
936
+ const prev = getPointAtIndex(positions, numPoints - 1, size, startIndex);
937
+ let prevSide = Math.sign(edge & 8 ? prev[1] - bbox[3] : prev[0] - bbox[2]);
938
+ let prevType = edgeTypes && edgeTypes[numPoints - 1];
939
+ let lowPointCount = 0;
940
+ let highPointCount = 0;
941
+ for (let i = 0; i < numPoints; i++) {
942
+ p = getPointAtIndex(positions, i, size, startIndex, p);
943
+ side = Math.sign(edge & 8 ? p[1] - bbox[3] : p[0] - bbox[2]);
944
+ type = edgeTypes && edgeTypes[startIndex / size + i];
945
+ if (side && prevSide && prevSide !== side) {
946
+ intersect(prev, p, edge, bbox, scratchPoint);
947
+ push(resultLow, scratchPoint) && typesLow.push(prevType);
948
+ push(resultHigh, scratchPoint) && typesHigh.push(prevType);
949
+ }
950
+ if (side <= 0) {
951
+ push(resultLow, p) && typesLow.push(type);
952
+ lowPointCount -= side;
953
+ } else if (typesLow.length) {
954
+ typesLow[typesLow.length - 1] = TYPE_INSIDE;
955
+ }
956
+ if (side >= 0) {
957
+ push(resultHigh, p) && typesHigh.push(type);
958
+ highPointCount += side;
959
+ } else if (typesHigh.length) {
960
+ typesHigh[typesHigh.length - 1] = TYPE_INSIDE;
961
+ }
962
+ copy(prev, p);
963
+ prevSide = side;
964
+ prevType = type;
965
+ }
966
+ return [
967
+ lowPointCount ? { pos: resultLow, types: edgeTypes && typesLow } : null,
968
+ highPointCount ? { pos: resultHigh, types: edgeTypes && typesHigh } : null
969
+ ];
970
+ }
971
+ function getGridCell(p, gridResolution, gridOffset, out) {
972
+ const left = Math.floor((p[0] - gridOffset[0]) / gridResolution) * gridResolution + gridOffset[0];
973
+ const bottom = Math.floor((p[1] - gridOffset[1]) / gridResolution) * gridResolution + gridOffset[1];
974
+ out[0] = left;
975
+ out[1] = bottom;
976
+ out[2] = left + gridResolution;
977
+ out[3] = bottom + gridResolution;
978
+ return out;
979
+ }
980
+ function moveToNeighborCell(cell, gridResolution, edge) {
981
+ if (edge & 8) {
982
+ cell[1] += gridResolution;
983
+ cell[3] += gridResolution;
984
+ } else if (edge & 4) {
985
+ cell[1] -= gridResolution;
986
+ cell[3] -= gridResolution;
987
+ } else if (edge & 2) {
988
+ cell[0] += gridResolution;
989
+ cell[2] += gridResolution;
990
+ } else if (edge & 1) {
991
+ cell[0] -= gridResolution;
992
+ cell[2] -= gridResolution;
993
+ }
994
+ }
995
+ function getBoundingBox(positions, size, endIndex, out) {
996
+ let minX = Infinity;
997
+ let maxX = -Infinity;
998
+ let minY = Infinity;
999
+ let maxY = -Infinity;
1000
+ for (let i = 0; i < endIndex; i += size) {
1001
+ const x = positions[i];
1002
+ const y = positions[i + 1];
1003
+ minX = x < minX ? x : minX;
1004
+ maxX = x > maxX ? x : maxX;
1005
+ minY = y < minY ? y : minY;
1006
+ maxY = y > maxY ? y : maxY;
1007
+ }
1008
+ out[0][0] = minX;
1009
+ out[0][1] = minY;
1010
+ out[1][0] = maxX;
1011
+ out[1][1] = maxY;
1012
+ return out;
1013
+ }
1014
+ function concatInPlace(arr1, arr2) {
1015
+ for (let i = 0; i < arr2.length; i++) {
1016
+ arr1.push(arr2[i]);
1017
+ }
1018
+ return arr1;
1019
+ }
1020
+
1021
+ // src/cut-by-mercator-bounds.ts
1022
+ var DEFAULT_MAX_LATITUDE = 85.051129;
1023
+ function cutPolylineByMercatorBounds(positions, options) {
1024
+ const { size = 2, startIndex = 0, endIndex = positions.length, normalize = true } = options || {};
1025
+ const newPositions = positions.slice(startIndex, endIndex);
1026
+ wrapLongitudesForShortestPath(newPositions, size, 0, endIndex - startIndex);
1027
+ const parts = cutPolylineByGrid(newPositions, {
1028
+ size,
1029
+ broken: true,
1030
+ gridResolution: 360,
1031
+ gridOffset: [-180, -180]
1032
+ });
1033
+ if (normalize) {
1034
+ for (const part of parts) {
1035
+ shiftLongitudesIntoRange(part, size);
1036
+ }
1037
+ }
1038
+ return parts;
1039
+ }
1040
+ function cutPolygonByMercatorBounds(positions, holeIndices = null, options) {
1041
+ const { size = 2, normalize = true, edgeTypes = false } = options || {};
1042
+ holeIndices = holeIndices || [];
1043
+ const newPositions = [];
1044
+ const newHoleIndices = [];
1045
+ let srcStartIndex = 0;
1046
+ let targetIndex = 0;
1047
+ for (let ringIndex = 0; ringIndex <= holeIndices.length; ringIndex++) {
1048
+ const srcEndIndex = holeIndices[ringIndex] || positions.length;
1049
+ const targetStartIndex = targetIndex;
1050
+ const splitIndex = findSplitIndex(positions, size, srcStartIndex, srcEndIndex);
1051
+ for (let i = splitIndex; i < srcEndIndex; i++) {
1052
+ newPositions[targetIndex++] = positions[i];
1053
+ }
1054
+ for (let i = srcStartIndex; i < splitIndex; i++) {
1055
+ newPositions[targetIndex++] = positions[i];
1056
+ }
1057
+ wrapLongitudesForShortestPath(newPositions, size, targetStartIndex, targetIndex);
1058
+ insertPoleVertices(newPositions, size, targetStartIndex, targetIndex, options == null ? void 0 : options.maxLatitude);
1059
+ srcStartIndex = srcEndIndex;
1060
+ newHoleIndices[ringIndex] = targetIndex;
1061
+ }
1062
+ newHoleIndices.pop();
1063
+ const parts = cutPolygonByGrid(newPositions, newHoleIndices, {
1064
+ size,
1065
+ gridResolution: 360,
1066
+ gridOffset: [-180, -180],
1067
+ edgeTypes
1068
+ });
1069
+ if (normalize) {
1070
+ for (const part of parts) {
1071
+ shiftLongitudesIntoRange(part.positions, size);
1072
+ }
1073
+ }
1074
+ return parts;
1075
+ }
1076
+ function findSplitIndex(positions, size, startIndex, endIndex) {
1077
+ let maxLat = -1;
1078
+ let pointIndex = -1;
1079
+ for (let i = startIndex + 1; i < endIndex; i += size) {
1080
+ const lat = Math.abs(positions[i]);
1081
+ if (lat > maxLat) {
1082
+ maxLat = lat;
1083
+ pointIndex = i - 1;
1084
+ }
1085
+ }
1086
+ return pointIndex;
1087
+ }
1088
+ function insertPoleVertices(positions, size, startIndex, endIndex, maxLatitude = DEFAULT_MAX_LATITUDE) {
1089
+ const firstLng = positions[startIndex];
1090
+ const lastLng = positions[endIndex - size];
1091
+ if (Math.abs(firstLng - lastLng) > 180) {
1092
+ const p = getPointAtIndex(positions, 0, size, startIndex);
1093
+ p[0] += Math.round((lastLng - firstLng) / 360) * 360;
1094
+ push(positions, p);
1095
+ p[1] = Math.sign(p[1]) * maxLatitude;
1096
+ push(positions, p);
1097
+ p[0] = firstLng;
1098
+ push(positions, p);
1099
+ }
1100
+ }
1101
+ function wrapLongitudesForShortestPath(positions, size, startIndex, endIndex) {
1102
+ let prevLng = positions[0];
1103
+ let lng;
1104
+ for (let i = startIndex; i < endIndex; i += size) {
1105
+ lng = positions[i];
1106
+ const delta = lng - prevLng;
1107
+ if (delta > 180 || delta < -180) {
1108
+ lng -= Math.round(delta / 360) * 360;
1109
+ }
1110
+ positions[i] = prevLng = lng;
1111
+ }
1112
+ }
1113
+ function shiftLongitudesIntoRange(positions, size) {
1114
+ let refLng;
1115
+ const pointCount = positions.length / size;
1116
+ for (let i = 0; i < pointCount; i++) {
1117
+ refLng = positions[i * size];
1118
+ if ((refLng + 180) % 360 !== 0) {
1119
+ break;
1120
+ }
1121
+ }
1122
+ const delta = -Math.round(refLng / 360) * 360;
1123
+ if (delta === 0) {
1124
+ return;
1125
+ }
1126
+ for (let i = 0; i < pointCount; i++) {
1127
+ positions[i * size] += delta;
1128
+ }
1129
+ }