@vpmedia/phaser 1.0.1 → 1.0.3

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 (112) hide show
  1. package/README.md +20 -3
  2. package/dist/phaser.cjs +1 -1
  3. package/dist/phaser.cjs.LICENSE.txt +1 -1
  4. package/dist/phaser.cjs.map +1 -1
  5. package/dist/phaser.js +1 -1
  6. package/dist/phaser.js.LICENSE.txt +1 -1
  7. package/dist/phaser.js.map +1 -1
  8. package/package.json +23 -17
  9. package/src/index.js +142 -0
  10. package/src/phaser/core/animation.js +355 -0
  11. package/src/phaser/core/animation_manager.js +238 -0
  12. package/src/phaser/core/animation_parser.js +133 -0
  13. package/src/phaser/core/array_set.js +107 -0
  14. package/src/phaser/core/cache.js +558 -0
  15. package/src/phaser/core/const.js +106 -0
  16. package/src/phaser/core/device.js +67 -0
  17. package/src/phaser/core/device_util.js +388 -0
  18. package/src/phaser/core/dom.js +207 -0
  19. package/src/phaser/core/event_manager.js +243 -0
  20. package/src/phaser/core/factory.js +74 -0
  21. package/src/phaser/core/frame.js +75 -0
  22. package/src/phaser/core/frame_data.js +84 -0
  23. package/src/phaser/core/frame_util.js +33 -0
  24. package/src/phaser/core/game.js +412 -0
  25. package/src/phaser/core/input.js +401 -0
  26. package/src/phaser/core/input_button.js +102 -0
  27. package/src/phaser/core/input_handler.js +687 -0
  28. package/src/phaser/core/input_mouse.js +289 -0
  29. package/src/phaser/core/input_mspointer.js +197 -0
  30. package/src/phaser/core/input_pointer.js +427 -0
  31. package/src/phaser/core/input_touch.js +157 -0
  32. package/src/phaser/core/loader.js +1057 -0
  33. package/src/phaser/core/loader_parser.js +109 -0
  34. package/src/phaser/core/raf.js +46 -0
  35. package/src/phaser/core/raf_fb.js +75 -0
  36. package/src/phaser/core/raf_to.js +34 -0
  37. package/src/phaser/core/scale_manager.js +806 -0
  38. package/src/phaser/core/scene.js +65 -0
  39. package/src/phaser/core/scene_manager.js +309 -0
  40. package/src/phaser/core/signal.js +175 -0
  41. package/src/phaser/core/signal_binding.js +69 -0
  42. package/src/phaser/core/sound.js +538 -0
  43. package/src/phaser/core/sound_manager.js +364 -0
  44. package/src/phaser/core/stage.js +108 -0
  45. package/src/phaser/core/time.js +203 -0
  46. package/src/phaser/core/timer.js +276 -0
  47. package/src/phaser/core/timer_event.js +21 -0
  48. package/src/phaser/core/tween.js +329 -0
  49. package/src/phaser/core/tween_data.js +258 -0
  50. package/src/phaser/core/tween_easing.js +341 -0
  51. package/src/phaser/core/tween_manager.js +185 -0
  52. package/src/phaser/core/world.js +18 -0
  53. package/src/phaser/display/bitmap_text.js +322 -0
  54. package/src/phaser/display/button.js +194 -0
  55. package/src/phaser/display/canvas/buffer.js +36 -0
  56. package/src/phaser/display/canvas/graphics.js +227 -0
  57. package/src/phaser/display/canvas/masker.js +39 -0
  58. package/src/phaser/display/canvas/pool.js +126 -0
  59. package/src/phaser/display/canvas/renderer.js +123 -0
  60. package/src/phaser/display/canvas/tinter.js +144 -0
  61. package/src/phaser/display/canvas/util.js +159 -0
  62. package/src/phaser/display/display_object.js +597 -0
  63. package/src/phaser/display/graphics.js +723 -0
  64. package/src/phaser/display/graphics_data.js +27 -0
  65. package/src/phaser/display/graphics_data_util.js +15 -0
  66. package/src/phaser/display/group.js +227 -0
  67. package/src/phaser/display/image.js +288 -0
  68. package/src/phaser/display/sprite_batch.js +15 -0
  69. package/src/phaser/display/sprite_util.js +250 -0
  70. package/src/phaser/display/text.js +1089 -0
  71. package/src/phaser/display/webgl/abstract_filter.js +25 -0
  72. package/src/phaser/display/webgl/base_texture.js +68 -0
  73. package/src/phaser/display/webgl/blend_manager.js +35 -0
  74. package/src/phaser/display/webgl/earcut.js +662 -0
  75. package/src/phaser/display/webgl/earcut_node.js +28 -0
  76. package/src/phaser/display/webgl/fast_sprite_batch.js +242 -0
  77. package/src/phaser/display/webgl/filter_manager.js +46 -0
  78. package/src/phaser/display/webgl/filter_texture.js +61 -0
  79. package/src/phaser/display/webgl/graphics.js +624 -0
  80. package/src/phaser/display/webgl/graphics_data.js +42 -0
  81. package/src/phaser/display/webgl/mask_manager.js +36 -0
  82. package/src/phaser/display/webgl/render_texture.js +81 -0
  83. package/src/phaser/display/webgl/renderer.js +234 -0
  84. package/src/phaser/display/webgl/shader/complex.js +74 -0
  85. package/src/phaser/display/webgl/shader/fast.js +97 -0
  86. package/src/phaser/display/webgl/shader/normal.js +225 -0
  87. package/src/phaser/display/webgl/shader/primitive.js +72 -0
  88. package/src/phaser/display/webgl/shader/strip.js +77 -0
  89. package/src/phaser/display/webgl/shader_manager.js +89 -0
  90. package/src/phaser/display/webgl/sprite_batch.js +320 -0
  91. package/src/phaser/display/webgl/stencil_manager.js +170 -0
  92. package/src/phaser/display/webgl/texture.js +117 -0
  93. package/src/phaser/display/webgl/texture_util.js +34 -0
  94. package/src/phaser/display/webgl/util.js +78 -0
  95. package/src/phaser/geom/circle.js +186 -0
  96. package/src/phaser/geom/ellipse.js +65 -0
  97. package/src/phaser/geom/line.js +190 -0
  98. package/src/phaser/geom/matrix.js +147 -0
  99. package/src/phaser/geom/point.js +164 -0
  100. package/src/phaser/geom/polygon.js +140 -0
  101. package/src/phaser/geom/rectangle.js +306 -0
  102. package/src/phaser/geom/rounded_rectangle.js +36 -0
  103. package/src/phaser/geom/util/circle.js +122 -0
  104. package/src/phaser/geom/util/ellipse.js +34 -0
  105. package/src/phaser/geom/util/line.js +135 -0
  106. package/src/phaser/geom/util/matrix.js +53 -0
  107. package/src/phaser/geom/util/point.js +296 -0
  108. package/src/phaser/geom/util/polygon.js +28 -0
  109. package/src/phaser/geom/util/rectangle.js +229 -0
  110. package/src/phaser/geom/util/rounded_rectangle.js +32 -0
  111. package/src/phaser/util/math.js +297 -0
  112. package/src/phaser/util/string.js +32 -0
@@ -0,0 +1,662 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import Node from './earcut_node';
8
+
9
+ /**
10
+ *
11
+ * @param {object} list TBD
12
+ * @returns {object} TBD
13
+ */
14
+ export function sortLinked(list) {
15
+ let i;
16
+ let p;
17
+ let q;
18
+ let e;
19
+ let tail;
20
+ let numMerges;
21
+ let pSize;
22
+ let qSize;
23
+ let inSize = 1;
24
+ do {
25
+ p = list;
26
+ list = null;
27
+ tail = null;
28
+ numMerges = 0;
29
+ while (p) {
30
+ numMerges += 1;
31
+ q = p;
32
+ pSize = 0;
33
+ for (i = 0; i < inSize; i += 1) {
34
+ pSize += 1;
35
+ q = q.nextZ;
36
+ if (!q) {
37
+ break;
38
+ }
39
+ }
40
+ qSize = inSize;
41
+ while (pSize > 0 || (qSize > 0 && q)) {
42
+ if (pSize === 0) {
43
+ e = q;
44
+ q = q.nextZ;
45
+ qSize -= 1;
46
+ } else if (qSize === 0 || !q) {
47
+ e = p;
48
+ p = p.nextZ;
49
+ pSize -= 1;
50
+ } else if (p.z <= q.z) {
51
+ e = p;
52
+ p = p.nextZ;
53
+ pSize -= 1;
54
+ } else {
55
+ e = q;
56
+ q = q.nextZ;
57
+ qSize -= 1;
58
+ }
59
+ if (tail) {
60
+ tail.nextZ = e;
61
+ } else {
62
+ list = e;
63
+ }
64
+ e.prevZ = tail;
65
+ tail = e;
66
+ }
67
+ p = q;
68
+ }
69
+ tail.nextZ = null;
70
+ inSize *= 2;
71
+ } while (numMerges > 1);
72
+ return list;
73
+ }
74
+
75
+ /**
76
+ *
77
+ * @param {object} a TBD
78
+ * @param {object} b TBD
79
+ * @returns {number} TBD
80
+ */
81
+ export function compareX(a, b) {
82
+ return a.x - b.x;
83
+ }
84
+
85
+ /**
86
+ *
87
+ * @param {number} x TBD
88
+ * @param {number} y TBD
89
+ * @param {number} minX TBD
90
+ * @param {number} minY TBD
91
+ * @param {number} size TBD
92
+ * @returns {number} TBD
93
+ */
94
+ export function zOrder(x, y, minX, minY, size) {
95
+ // coords are transformed into non-negative 15-bit integer range
96
+ x = 32767 * (x - minX) / size;
97
+ y = 32767 * (y - minY) / size;
98
+ x = (x | (x << 8)) & 0x00FF00FF;
99
+ x = (x | (x << 4)) & 0x0F0F0F0F;
100
+ x = (x | (x << 2)) & 0x33333333;
101
+ x = (x | (x << 1)) & 0x55555555;
102
+ y = (y | (y << 8)) & 0x00FF00FF;
103
+ y = (y | (y << 4)) & 0x0F0F0F0F;
104
+ y = (y | (y << 2)) & 0x33333333;
105
+ y = (y | (y << 1)) & 0x55555555;
106
+ return x | (y << 1);
107
+ }
108
+
109
+ /**
110
+ *
111
+ * @param {object} start TBD
112
+ * @param {number} minX TBD
113
+ * @param {number} minY TBD
114
+ * @param {number} size TBD
115
+ */
116
+ export function indexCurve(start, minX, minY, size) {
117
+ let p = start;
118
+ do {
119
+ if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size);
120
+ p.prevZ = p.prev;
121
+ p.nextZ = p.next;
122
+ p = p.next;
123
+ } while (p !== start);
124
+ p.prevZ.nextZ = null;
125
+ p.prevZ = null;
126
+ sortLinked(p);
127
+ }
128
+
129
+ /**
130
+ *
131
+ * @param {object} start TBD
132
+ * @returns {object} TBD
133
+ */
134
+ export function getLeftmost(start) {
135
+ let p = start;
136
+ let leftmost = start;
137
+ do {
138
+ if (p.x < leftmost.x) leftmost = p;
139
+ p = p.next;
140
+ } while (p !== start);
141
+ return leftmost;
142
+ }
143
+
144
+ /**
145
+ *
146
+ * @param {number} ax TBD
147
+ * @param {number} ay TBD
148
+ * @param {number} bx TBD
149
+ * @param {number} by TBD
150
+ * @param {number} cx TBD
151
+ * @param {number} cy TBD
152
+ * @param {number} px TBD
153
+ * @param {number} py TBD
154
+ * @returns {object} TBD
155
+ */
156
+ export function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
157
+ return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
158
+ }
159
+
160
+ /**
161
+ *
162
+ * @param {object} p TBD
163
+ * @param {object} q TBD
164
+ * @param {object} r TBD
165
+ * @returns {number} TBD
166
+ */
167
+ export function area(p, q, r) {
168
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
169
+ }
170
+
171
+ /**
172
+ *
173
+ * @param {object} p1 TBD
174
+ * @param {object} p2 TBD
175
+ * @returns {boolean} TBD
176
+ */
177
+ export function equals(p1, p2) {
178
+ return p1.x === p2.x && p1.y === p2.y;
179
+ }
180
+
181
+ /**
182
+ *
183
+ * @param {object} p1 TBD
184
+ * @param {object} q1 TBD
185
+ * @param {object} p2 TBD
186
+ * @param {object} q2 TBD
187
+ * @returns {boolean} TBD
188
+ */
189
+ export function intersects(p1, q1, p2, q2) {
190
+ return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;
191
+ }
192
+
193
+ /**
194
+ *
195
+ * @param {object} a TBD
196
+ * @param {object} b TBD
197
+ * @returns {boolean} TBD
198
+ */
199
+ export function intersectsPolygon(a, b) {
200
+ let p = a;
201
+ do {
202
+ 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)) return true;
203
+ p = p.next;
204
+ } while (p !== a);
205
+ return false;
206
+ }
207
+
208
+ /**
209
+ *
210
+ * @param {object} a TBD
211
+ * @param {object} b TBD
212
+ * @returns {object} TBD
213
+ */
214
+ export function locallyInside(a, b) {
215
+ 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;
216
+ }
217
+
218
+ /**
219
+ *
220
+ * @param {object} a TBD
221
+ * @param {object} b TBD
222
+ * @returns {boolean} TBD
223
+ */
224
+ export function middleInside(a, b) {
225
+ let p = a;
226
+ let inside = false;
227
+ const px = (a.x + b.x) / 2;
228
+ const py = (a.y + b.y) / 2;
229
+ do {
230
+ if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) {
231
+ inside = !inside;
232
+ }
233
+ p = p.next;
234
+ } while (p !== a);
235
+ return inside;
236
+ }
237
+
238
+ /**
239
+ *
240
+ * @param {object} a TBD
241
+ * @param {object} b TBD
242
+ * @returns {boolean} TBD
243
+ */
244
+ export function isValidDiagonal(a, b) {
245
+ return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
246
+ }
247
+
248
+ /**
249
+ *
250
+ * @param {object} a TBD
251
+ * @param {object} b TBD
252
+ * @returns {object} TBD
253
+ */
254
+ export function splitPolygon(a, b) {
255
+ const a2 = new Node(a.i, a.x, a.y);
256
+ const b2 = new Node(b.i, b.x, b.y);
257
+ const an = a.next;
258
+ const bp = b.prev;
259
+ a.next = b;
260
+ b.prev = a;
261
+ a2.next = an;
262
+ an.prev = a2;
263
+ b2.next = a2;
264
+ a2.prev = b2;
265
+ bp.next = b2;
266
+ b2.prev = bp;
267
+ return b2;
268
+ }
269
+
270
+ /**
271
+ *
272
+ * @param {number} i TBD
273
+ * @param {number} x TBD
274
+ * @param {number} y TBD
275
+ * @param {object} last TBD
276
+ * @returns {object} TBD
277
+ */
278
+ export function insertNode(i, x, y, last) {
279
+ const p = new Node(i, x, y);
280
+ if (!last) {
281
+ p.prev = p;
282
+ p.next = p;
283
+ } else {
284
+ p.next = last.next;
285
+ p.prev = last;
286
+ last.next.prev = p;
287
+ last.next = p;
288
+ }
289
+ return p;
290
+ }
291
+
292
+ /**
293
+ *
294
+ * @param {object} p TBD
295
+ */
296
+ export function removeNode(p) {
297
+ p.next.prev = p.prev;
298
+ p.prev.next = p.next;
299
+ if (p.prevZ) {
300
+ p.prevZ.nextZ = p.nextZ;
301
+ }
302
+ if (p.nextZ) {
303
+ p.nextZ.prevZ = p.prevZ;
304
+ }
305
+ }
306
+
307
+ /**
308
+ *
309
+ * @param {object} ear TBD
310
+ * @returns {boolean} TBD
311
+ */
312
+ export function isEar(ear) {
313
+ const a = ear.prev;
314
+ const b = ear;
315
+ const c = ear.next;
316
+ if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
317
+ // now make sure we don't have other points inside the potential ear
318
+ let p = ear.next.next;
319
+ while (p !== ear.prev) {
320
+ if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
321
+ p = p.next;
322
+ }
323
+ return true;
324
+ }
325
+
326
+ /**
327
+ *
328
+ * @param {object} ear TBD
329
+ * @param {number} minX TBD
330
+ * @param {number} minY TBD
331
+ * @param {number} size TBD
332
+ * @returns {boolean} TBD
333
+ */
334
+ export function isEarHashed(ear, minX, minY, size) {
335
+ const a = ear.prev;
336
+ const b = ear;
337
+ const c = ear.next;
338
+ if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
339
+ // triangle bbox; min & max are calculated like this for speed
340
+ const minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x);
341
+ const minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y);
342
+ const maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x);
343
+ const maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
344
+ // z-order range for the current triangle bbox;
345
+ const minZ = zOrder(minTX, minTY, minX, minY, size);
346
+ const maxZ = zOrder(maxTX, maxTY, minX, minY, size);
347
+ // first look for points inside the triangle in increasing z-order
348
+ let p = ear.nextZ;
349
+ while (p && p.z <= maxZ) {
350
+ if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) {
351
+ return false;
352
+ }
353
+ p = p.nextZ;
354
+ }
355
+ // then look for points in decreasing z-order
356
+ p = ear.prevZ;
357
+ while (p && p.z >= minZ) {
358
+ if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) {
359
+ return false;
360
+ }
361
+ p = p.prevZ;
362
+ }
363
+ return true;
364
+ }
365
+
366
+ /**
367
+ *
368
+ * @param {object} data TBD
369
+ * @param {number} start TBD
370
+ * @param {number} end TBD
371
+ * @param {number} dim TBD
372
+ * @param {boolean} clockwise TBD
373
+ * @returns {object} TBD
374
+ */
375
+ export function linkedList(data, start, end, dim, clockwise) {
376
+ let sum = 0;
377
+ let i;
378
+ let j;
379
+ let last;
380
+ // calculate original winding order of a polygon ring
381
+ for (i = start, j = end - dim; i < end; i += dim) {
382
+ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
383
+ j = i;
384
+ }
385
+ // link points into circular doubly-linked list in the specified winding order
386
+ if (clockwise === (sum > 0)) {
387
+ for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
388
+ } else {
389
+ for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
390
+ }
391
+ return last;
392
+ }
393
+
394
+ /**
395
+ *
396
+ * @param {object} start TBD
397
+ * @param {object} end TBD
398
+ * @returns {object} TBD
399
+ */
400
+ export function filterPoints(start, end) {
401
+ if (!start) return start;
402
+ if (!end) end = start;
403
+ let p = start;
404
+ let again;
405
+ do {
406
+ again = false;
407
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
408
+ removeNode(p);
409
+ p = p.prev;
410
+ end = p;
411
+ if (p === p.next) return null;
412
+ again = true;
413
+ } else {
414
+ p = p.next;
415
+ }
416
+ } while (again || p !== end);
417
+ return end;
418
+ }
419
+
420
+ /**
421
+ *
422
+ * @param {object} hole TBD
423
+ * @param {object} outerNode TBD
424
+ * @returns {object} TBD
425
+ */
426
+ export function findHoleBridge(hole, outerNode) {
427
+ let p = outerNode;
428
+ const hx = hole.x;
429
+ const hy = hole.y;
430
+ let qx = -Infinity;
431
+ let m;
432
+ // find a segment intersected by a ray from the hole's leftmost point to the left;
433
+ // segment's endpoint with lesser x will be potential connection point
434
+ do {
435
+ if (hy <= p.y && hy >= p.next.y) {
436
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
437
+ if (x <= hx && x > qx) {
438
+ qx = x;
439
+ m = p.x < p.next.x ? p : p.next;
440
+ }
441
+ }
442
+ p = p.next;
443
+ } while (p !== outerNode);
444
+ if (!m) return null;
445
+ if (hole.x === m.x) return m.prev; // hole touches outer segment; pick lower endpoint
446
+ // look for points inside the triangle of hole point, segment intersection and endpoint;
447
+ // if there are no points found, we have a valid connection;
448
+ // otherwise choose the point of the minimum angle with the ray as connection point
449
+ const stop = m;
450
+ let tanMin = Infinity;
451
+ let tan;
452
+ p = m.next;
453
+ while (p !== stop) {
454
+ if (hx >= p.x && p.x >= m.x && pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) {
455
+ tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
456
+ if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) {
457
+ m = p;
458
+ tanMin = tan;
459
+ }
460
+ }
461
+ p = p.next;
462
+ }
463
+ return m;
464
+ }
465
+
466
+ /**
467
+ *
468
+ * @param {object} hole TBD
469
+ * @param {object} outerNode TBD
470
+ */
471
+ export function eliminateHole(hole, outerNode) {
472
+ outerNode = findHoleBridge(hole, outerNode);
473
+ if (outerNode) {
474
+ const b = splitPolygon(outerNode, hole);
475
+ filterPoints(b, b.next);
476
+ }
477
+ }
478
+
479
+ /**
480
+ *
481
+ * @param {object} data TBD
482
+ * @param {object} holeIndices TBD
483
+ * @param {object} outerNode TBD
484
+ * @param {object} dim TBD
485
+ * @returns {object} TBD
486
+ */
487
+ export function eliminateHoles(data, holeIndices, outerNode, dim) {
488
+ const queue = [];
489
+ let i;
490
+ let len;
491
+ let start;
492
+ let end;
493
+ let list;
494
+ for (i = 0, len = holeIndices.length; i < len; i += 1) {
495
+ start = holeIndices[i] * dim;
496
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
497
+ list = linkedList(data, start, end, dim, false);
498
+ if (list === list.next) list.steiner = true;
499
+ queue.push(getLeftmost(list));
500
+ }
501
+ queue.sort(compareX);
502
+ // process holes from left to right
503
+ for (i = 0; i < queue.length; i += 1) {
504
+ eliminateHole(queue[i], outerNode);
505
+ outerNode = filterPoints(outerNode, outerNode.next);
506
+ }
507
+ return outerNode;
508
+ }
509
+
510
+ /**
511
+ *
512
+ * @param {object} start TBD
513
+ * @param {object} triangles TBD
514
+ * @param {number} dim TBD
515
+ * @returns {object} TBD
516
+ */
517
+ export function cureLocalIntersections(start, triangles, dim) {
518
+ let p = start;
519
+ do {
520
+ const a = p.prev;
521
+ const b = p.next.next;
522
+ // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
523
+ if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
524
+ triangles.push(a.i / dim);
525
+ triangles.push(p.i / dim);
526
+ triangles.push(b.i / dim);
527
+ // remove two nodes involved
528
+ removeNode(p);
529
+ removeNode(p.next);
530
+ p = b;
531
+ start = p;
532
+ }
533
+ p = p.next;
534
+ } while (p !== start);
535
+ return p;
536
+ }
537
+
538
+ /**
539
+ *
540
+ * @param {object} start TBD
541
+ * @param {object} triangles TBD
542
+ * @param {number} dim TBD
543
+ * @param {number} minX TBD
544
+ * @param {number} minY TBD
545
+ * @param {number} size TBD
546
+ */
547
+ export function splitEarcut(start, triangles, dim, minX, minY, size) {
548
+ // look for a valid diagonal that divides the polygon into two
549
+ let a = start;
550
+ do {
551
+ let b = a.next.next;
552
+ while (b !== a.prev) {
553
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
554
+ // split the polygon in two by the diagonal
555
+ let c = splitPolygon(a, b);
556
+ // filter colinear points around the cuts
557
+ a = filterPoints(a, a.next);
558
+ c = filterPoints(c, c.next);
559
+ // run earcut on each half
560
+ earcutLinked(a, triangles, dim, minX, minY, size);
561
+ earcutLinked(c, triangles, dim, minX, minY, size);
562
+ return;
563
+ }
564
+ b = b.next;
565
+ }
566
+ a = a.next;
567
+ } while (a !== start);
568
+ }
569
+
570
+ /**
571
+ *
572
+ * @param {object} ear TBD
573
+ * @param {object} triangles TBD
574
+ * @param {number} dim TBD
575
+ * @param {number} minX TBD
576
+ * @param {number} minY TBD
577
+ * @param {number} size TBD
578
+ * @param {object} pass TBD
579
+ */
580
+ export function earcutLinked(ear, triangles, dim, minX, minY, size, pass) {
581
+ if (!ear) return;
582
+ // interlink polygon nodes in z-order
583
+ if (!pass && size) indexCurve(ear, minX, minY, size);
584
+ let stop = ear;
585
+ let prev;
586
+ let next;
587
+ // iterate through ears, slicing them one by one
588
+ while (ear.prev !== ear.next) {
589
+ prev = ear.prev;
590
+ next = ear.next;
591
+ if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) {
592
+ // cut off the triangle
593
+ triangles.push(prev.i / dim);
594
+ triangles.push(ear.i / dim);
595
+ triangles.push(next.i / dim);
596
+ removeNode(ear);
597
+ // skipping the next vertice leads to less sliver triangles
598
+ ear = next.next;
599
+ stop = next.next;
600
+ continue;
601
+ }
602
+ ear = next;
603
+ // if we looped through the whole remaining polygon and can't find any more ears
604
+ if (ear === stop) {
605
+ // try filtering points and slicing again
606
+ if (!pass) {
607
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1);
608
+ // if this didn't work, try curing all small self-intersections locally
609
+ } else if (pass === 1) {
610
+ ear = cureLocalIntersections(ear, triangles, dim);
611
+ earcutLinked(ear, triangles, dim, minX, minY, size, 2);
612
+ // as a last resort, try splitting the remaining polygon into two
613
+ } else if (pass === 2) {
614
+ splitEarcut(ear, triangles, dim, minX, minY, size);
615
+ }
616
+ break;
617
+ }
618
+ }
619
+ }
620
+
621
+ /**
622
+ *
623
+ * @param {object} data TBD
624
+ * @param {object} holeIndices TBD
625
+ * @param {number} dim TBD
626
+ * @returns {object} TBD
627
+ */
628
+ export function triangulate(data, holeIndices, dim) {
629
+ dim = dim || 2;
630
+ const hasHoles = holeIndices && holeIndices.length;
631
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
632
+ let outerNode = linkedList(data, 0, outerLen, dim, true);
633
+ const triangles = [];
634
+ if (!outerNode) return triangles;
635
+ let minX;
636
+ let minY;
637
+ let maxX;
638
+ let maxY;
639
+ let x;
640
+ let y;
641
+ let size;
642
+ if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
643
+ // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
644
+ if (data.length > 80 * dim) {
645
+ minX = data[0];
646
+ maxX = data[0];
647
+ minY = data[1];
648
+ maxY = data[1];
649
+ for (let i = dim; i < outerLen; i += dim) {
650
+ x = data[i];
651
+ y = data[i + 1];
652
+ if (x < minX) minX = x;
653
+ if (y < minY) minY = y;
654
+ if (x > maxX) maxX = x;
655
+ if (y > maxY) maxY = y;
656
+ }
657
+ // minX, minY and size are later used to transform coords into integers for z-order calculation
658
+ size = Math.max(maxX - minX, maxY - minY);
659
+ }
660
+ earcutLinked(outerNode, triangles, dim, minX, minY, size);
661
+ return triangles;
662
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+
8
+ export default class {
9
+
10
+ constructor(i, x, y) {
11
+ // vertice index in coordinates array
12
+ this.i = i;
13
+ // vertex coordinates
14
+ this.x = x;
15
+ this.y = y;
16
+ // previous and next vertice nodes in a polygon ring
17
+ this.prev = null;
18
+ this.next = null;
19
+ // z-order curve value
20
+ this.z = null;
21
+ // previous and next nodes in z-order
22
+ this.prevZ = null;
23
+ this.nextZ = null;
24
+ // indicates whether this is a steiner point
25
+ this.steiner = false;
26
+ }
27
+
28
+ }