@loaders.gl/json 3.1.0 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.js +5 -1873
- package/dist/dist.min.js +2543 -0
- package/dist/es5/geojson-loader.js +1 -1
- package/dist/es5/json-loader.js +1 -1
- package/dist/es5/ndjson-loader.js +1 -1
- package/dist/esm/geojson-loader.js +1 -1
- package/dist/esm/json-loader.js +1 -1
- package/dist/esm/ndjson-loader.js +1 -1
- package/dist/geojson-worker.js +778 -183
- package/package.json +7 -7
package/dist/geojson-worker.js
CHANGED
|
@@ -159,83 +159,509 @@
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
//
|
|
163
|
-
function
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
162
|
+
// ../../node_modules/@math.gl/polygon/dist/esm/polygon-utils.js
|
|
163
|
+
function getPolygonSignedArea(points, options = {}) {
|
|
164
|
+
const {
|
|
165
|
+
start = 0,
|
|
166
|
+
end = points.length
|
|
167
|
+
} = options;
|
|
168
|
+
const dim = options.size || 2;
|
|
169
|
+
let area2 = 0;
|
|
170
|
+
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
171
|
+
area2 += (points[i] - points[j]) * (points[i + 1] + points[j + 1]);
|
|
172
|
+
j = i;
|
|
173
|
+
}
|
|
174
|
+
return area2 / 2;
|
|
170
175
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
let
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
176
|
+
|
|
177
|
+
// ../../node_modules/@math.gl/polygon/dist/esm/earcut.js
|
|
178
|
+
function earcut(data, holeIndices, dim, areas) {
|
|
179
|
+
dim = dim || 2;
|
|
180
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
181
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
182
|
+
let outerNode = linkedList(data, 0, outerLen, dim, true, areas && areas[0]);
|
|
183
|
+
const triangles = [];
|
|
184
|
+
if (!outerNode || outerNode.next === outerNode.prev)
|
|
185
|
+
return triangles;
|
|
186
|
+
let invSize;
|
|
187
|
+
let maxX;
|
|
188
|
+
let maxY;
|
|
189
|
+
let minX;
|
|
190
|
+
let minY;
|
|
191
|
+
let x;
|
|
192
|
+
let y;
|
|
193
|
+
if (hasHoles)
|
|
194
|
+
outerNode = eliminateHoles(data, holeIndices, outerNode, dim, areas);
|
|
195
|
+
if (data.length > 80 * dim) {
|
|
196
|
+
minX = maxX = data[0];
|
|
197
|
+
minY = maxY = data[1];
|
|
198
|
+
for (let i = dim; i < outerLen; i += dim) {
|
|
199
|
+
x = data[i];
|
|
200
|
+
y = data[i + 1];
|
|
201
|
+
if (x < minX)
|
|
202
|
+
minX = x;
|
|
203
|
+
if (y < minY)
|
|
204
|
+
minY = y;
|
|
205
|
+
if (x > maxX)
|
|
206
|
+
maxX = x;
|
|
207
|
+
if (y > maxY)
|
|
208
|
+
maxY = y;
|
|
209
|
+
}
|
|
210
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
211
|
+
invSize = invSize !== 0 ? 1 / invSize : 0;
|
|
212
|
+
}
|
|
213
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
|
|
214
|
+
return triangles;
|
|
215
|
+
}
|
|
216
|
+
function linkedList(data, start, end, dim, clockwise, area2) {
|
|
217
|
+
let i;
|
|
218
|
+
let last;
|
|
219
|
+
if (area2 === void 0) {
|
|
220
|
+
area2 = getPolygonSignedArea(data, {
|
|
221
|
+
start,
|
|
222
|
+
end,
|
|
223
|
+
size: dim
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (clockwise === area2 < 0) {
|
|
227
|
+
for (i = start; i < end; i += dim)
|
|
228
|
+
last = insertNode(i, data[i], data[i + 1], last);
|
|
229
|
+
} else {
|
|
230
|
+
for (i = end - dim; i >= start; i -= dim)
|
|
231
|
+
last = insertNode(i, data[i], data[i + 1], last);
|
|
232
|
+
}
|
|
233
|
+
if (last && equals(last, last.next)) {
|
|
234
|
+
removeNode(last);
|
|
235
|
+
last = last.next;
|
|
236
|
+
}
|
|
237
|
+
return last;
|
|
238
|
+
}
|
|
239
|
+
function filterPoints(start, end) {
|
|
240
|
+
if (!start)
|
|
241
|
+
return start;
|
|
242
|
+
if (!end)
|
|
243
|
+
end = start;
|
|
244
|
+
let p = start;
|
|
245
|
+
let again;
|
|
246
|
+
do {
|
|
247
|
+
again = false;
|
|
248
|
+
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
249
|
+
removeNode(p);
|
|
250
|
+
p = end = p.prev;
|
|
251
|
+
if (p === p.next)
|
|
215
252
|
break;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
253
|
+
again = true;
|
|
254
|
+
} else {
|
|
255
|
+
p = p.next;
|
|
256
|
+
}
|
|
257
|
+
} while (again || p !== end);
|
|
258
|
+
return end;
|
|
259
|
+
}
|
|
260
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
261
|
+
if (!ear)
|
|
262
|
+
return;
|
|
263
|
+
if (!pass && invSize)
|
|
264
|
+
indexCurve(ear, minX, minY, invSize);
|
|
265
|
+
let stop = ear;
|
|
266
|
+
let prev;
|
|
267
|
+
let next;
|
|
268
|
+
while (ear.prev !== ear.next) {
|
|
269
|
+
prev = ear.prev;
|
|
270
|
+
next = ear.next;
|
|
271
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
272
|
+
triangles.push(prev.i / dim);
|
|
273
|
+
triangles.push(ear.i / dim);
|
|
274
|
+
triangles.push(next.i / dim);
|
|
275
|
+
removeNode(ear);
|
|
276
|
+
ear = next.next;
|
|
277
|
+
stop = next.next;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
ear = next;
|
|
281
|
+
if (ear === stop) {
|
|
282
|
+
if (!pass) {
|
|
283
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
284
|
+
} else if (pass === 1) {
|
|
285
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
286
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
287
|
+
} else if (pass === 2) {
|
|
288
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function isEar(ear) {
|
|
295
|
+
const a = ear.prev;
|
|
296
|
+
const b = ear;
|
|
297
|
+
const c = ear.next;
|
|
298
|
+
if (area(a, b, c) >= 0)
|
|
299
|
+
return false;
|
|
300
|
+
let p = ear.next.next;
|
|
301
|
+
while (p !== ear.prev) {
|
|
302
|
+
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)
|
|
303
|
+
return false;
|
|
304
|
+
p = p.next;
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
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 minTX = a.x < b.x ? a.x < c.x ? a.x : c.x : b.x < c.x ? b.x : c.x;
|
|
315
|
+
const minTY = a.y < b.y ? a.y < c.y ? a.y : c.y : b.y < c.y ? b.y : c.y;
|
|
316
|
+
const maxTX = a.x > b.x ? a.x > c.x ? a.x : c.x : b.x > c.x ? b.x : c.x;
|
|
317
|
+
const maxTY = a.y > b.y ? a.y > c.y ? a.y : c.y : b.y > c.y ? b.y : c.y;
|
|
318
|
+
const minZ = zOrder(minTX, minTY, minX, minY, invSize);
|
|
319
|
+
const maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
|
|
320
|
+
let p = ear.prevZ;
|
|
321
|
+
let n = ear.nextZ;
|
|
322
|
+
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
323
|
+
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)
|
|
324
|
+
return false;
|
|
325
|
+
p = p.prevZ;
|
|
326
|
+
if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
327
|
+
return false;
|
|
328
|
+
n = n.nextZ;
|
|
329
|
+
}
|
|
330
|
+
while (p && p.z >= minZ) {
|
|
331
|
+
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)
|
|
332
|
+
return false;
|
|
333
|
+
p = p.prevZ;
|
|
334
|
+
}
|
|
335
|
+
while (n && n.z <= maxZ) {
|
|
336
|
+
if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
337
|
+
return false;
|
|
338
|
+
n = n.nextZ;
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
function cureLocalIntersections(start, triangles, dim) {
|
|
343
|
+
let p = start;
|
|
344
|
+
do {
|
|
345
|
+
const a = p.prev;
|
|
346
|
+
const b = p.next.next;
|
|
347
|
+
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
348
|
+
triangles.push(a.i / dim);
|
|
349
|
+
triangles.push(p.i / dim);
|
|
350
|
+
triangles.push(b.i / dim);
|
|
351
|
+
removeNode(p);
|
|
352
|
+
removeNode(p.next);
|
|
353
|
+
p = start = b;
|
|
354
|
+
}
|
|
355
|
+
p = p.next;
|
|
356
|
+
} while (p !== start);
|
|
357
|
+
return filterPoints(p);
|
|
358
|
+
}
|
|
359
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
360
|
+
let a = start;
|
|
361
|
+
do {
|
|
362
|
+
let b = a.next.next;
|
|
363
|
+
while (b !== a.prev) {
|
|
364
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
365
|
+
let c = splitPolygon(a, b);
|
|
366
|
+
a = filterPoints(a, a.next);
|
|
367
|
+
c = filterPoints(c, c.next);
|
|
368
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize);
|
|
369
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
b = b.next;
|
|
373
|
+
}
|
|
374
|
+
a = a.next;
|
|
375
|
+
} while (a !== start);
|
|
376
|
+
}
|
|
377
|
+
function eliminateHoles(data, holeIndices, outerNode, dim, areas) {
|
|
378
|
+
const queue = [];
|
|
379
|
+
let i;
|
|
380
|
+
let len;
|
|
381
|
+
let start;
|
|
382
|
+
let end;
|
|
383
|
+
let list;
|
|
384
|
+
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
385
|
+
start = holeIndices[i] * dim;
|
|
386
|
+
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
387
|
+
list = linkedList(data, start, end, dim, false, areas && areas[i + 1]);
|
|
388
|
+
if (list === list.next)
|
|
389
|
+
list.steiner = true;
|
|
390
|
+
queue.push(getLeftmost(list));
|
|
391
|
+
}
|
|
392
|
+
queue.sort(compareX);
|
|
393
|
+
for (i = 0; i < queue.length; i++) {
|
|
394
|
+
eliminateHole(queue[i], outerNode);
|
|
395
|
+
outerNode = filterPoints(outerNode, outerNode.next);
|
|
396
|
+
}
|
|
397
|
+
return outerNode;
|
|
398
|
+
}
|
|
399
|
+
function compareX(a, b) {
|
|
400
|
+
return a.x - b.x;
|
|
401
|
+
}
|
|
402
|
+
function eliminateHole(hole, outerNode) {
|
|
403
|
+
outerNode = findHoleBridge(hole, outerNode);
|
|
404
|
+
if (outerNode) {
|
|
405
|
+
const b = splitPolygon(outerNode, hole);
|
|
406
|
+
filterPoints(outerNode, outerNode.next);
|
|
407
|
+
filterPoints(b, b.next);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function findHoleBridge(hole, outerNode) {
|
|
411
|
+
let p = outerNode;
|
|
412
|
+
const hx = hole.x;
|
|
413
|
+
const hy = hole.y;
|
|
414
|
+
let qx = -Infinity;
|
|
415
|
+
let m;
|
|
416
|
+
do {
|
|
417
|
+
if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
|
|
418
|
+
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
|
|
419
|
+
if (x <= hx && x > qx) {
|
|
420
|
+
qx = x;
|
|
421
|
+
if (x === hx) {
|
|
422
|
+
if (hy === p.y)
|
|
423
|
+
return p;
|
|
424
|
+
if (hy === p.next.y)
|
|
425
|
+
return p.next;
|
|
223
426
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
427
|
+
m = p.x < p.next.x ? p : p.next;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
p = p.next;
|
|
431
|
+
} while (p !== outerNode);
|
|
432
|
+
if (!m)
|
|
433
|
+
return null;
|
|
434
|
+
if (hx === qx)
|
|
435
|
+
return m;
|
|
436
|
+
const stop = m;
|
|
437
|
+
const mx = m.x;
|
|
438
|
+
const my = m.y;
|
|
439
|
+
let tanMin = Infinity;
|
|
440
|
+
let tan;
|
|
441
|
+
p = m;
|
|
442
|
+
do {
|
|
443
|
+
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)) {
|
|
444
|
+
tan = Math.abs(hy - p.y) / (hx - p.x);
|
|
445
|
+
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
|
|
446
|
+
m = p;
|
|
447
|
+
tanMin = tan;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
p = p.next;
|
|
451
|
+
} while (p !== stop);
|
|
452
|
+
return m;
|
|
453
|
+
}
|
|
454
|
+
function sectorContainsSector(m, p) {
|
|
455
|
+
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
456
|
+
}
|
|
457
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
458
|
+
let p = start;
|
|
459
|
+
do {
|
|
460
|
+
if (p.z === null)
|
|
461
|
+
p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
462
|
+
p.prevZ = p.prev;
|
|
463
|
+
p.nextZ = p.next;
|
|
464
|
+
p = p.next;
|
|
465
|
+
} while (p !== start);
|
|
466
|
+
p.prevZ.nextZ = null;
|
|
467
|
+
p.prevZ = null;
|
|
468
|
+
sortLinked(p);
|
|
469
|
+
}
|
|
470
|
+
function sortLinked(list) {
|
|
471
|
+
let e;
|
|
472
|
+
let i;
|
|
473
|
+
let inSize = 1;
|
|
474
|
+
let numMerges;
|
|
475
|
+
let p;
|
|
476
|
+
let pSize;
|
|
477
|
+
let q;
|
|
478
|
+
let qSize;
|
|
479
|
+
let tail;
|
|
480
|
+
do {
|
|
481
|
+
p = list;
|
|
482
|
+
list = null;
|
|
483
|
+
tail = null;
|
|
484
|
+
numMerges = 0;
|
|
485
|
+
while (p) {
|
|
486
|
+
numMerges++;
|
|
487
|
+
q = p;
|
|
488
|
+
pSize = 0;
|
|
489
|
+
for (i = 0; i < inSize; i++) {
|
|
490
|
+
pSize++;
|
|
491
|
+
q = q.nextZ;
|
|
492
|
+
if (!q)
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
qSize = inSize;
|
|
496
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
497
|
+
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
|
|
498
|
+
e = p;
|
|
499
|
+
p = p.nextZ;
|
|
500
|
+
pSize--;
|
|
501
|
+
} else {
|
|
502
|
+
e = q;
|
|
503
|
+
q = q.nextZ;
|
|
504
|
+
qSize--;
|
|
234
505
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
506
|
+
if (tail)
|
|
507
|
+
tail.nextZ = e;
|
|
508
|
+
else
|
|
509
|
+
list = e;
|
|
510
|
+
e.prevZ = tail;
|
|
511
|
+
tail = e;
|
|
512
|
+
}
|
|
513
|
+
p = q;
|
|
238
514
|
}
|
|
515
|
+
tail.nextZ = null;
|
|
516
|
+
inSize *= 2;
|
|
517
|
+
} while (numMerges > 1);
|
|
518
|
+
return list;
|
|
519
|
+
}
|
|
520
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
521
|
+
x = 32767 * (x - minX) * invSize;
|
|
522
|
+
y = 32767 * (y - minY) * invSize;
|
|
523
|
+
x = (x | x << 8) & 16711935;
|
|
524
|
+
x = (x | x << 4) & 252645135;
|
|
525
|
+
x = (x | x << 2) & 858993459;
|
|
526
|
+
x = (x | x << 1) & 1431655765;
|
|
527
|
+
y = (y | y << 8) & 16711935;
|
|
528
|
+
y = (y | y << 4) & 252645135;
|
|
529
|
+
y = (y | y << 2) & 858993459;
|
|
530
|
+
y = (y | y << 1) & 1431655765;
|
|
531
|
+
return x | y << 1;
|
|
532
|
+
}
|
|
533
|
+
function getLeftmost(start) {
|
|
534
|
+
let p = start;
|
|
535
|
+
let leftmost = start;
|
|
536
|
+
do {
|
|
537
|
+
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
|
|
538
|
+
leftmost = p;
|
|
539
|
+
p = p.next;
|
|
540
|
+
} while (p !== start);
|
|
541
|
+
return leftmost;
|
|
542
|
+
}
|
|
543
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
544
|
+
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;
|
|
545
|
+
}
|
|
546
|
+
function isValidDiagonal(a, b) {
|
|
547
|
+
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)) || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
|
|
548
|
+
}
|
|
549
|
+
function area(p, q, r) {
|
|
550
|
+
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
551
|
+
}
|
|
552
|
+
function equals(p1, p2) {
|
|
553
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
554
|
+
}
|
|
555
|
+
function intersects(p1, q1, p2, q2) {
|
|
556
|
+
const o1 = sign(area(p1, q1, p2));
|
|
557
|
+
const o2 = sign(area(p1, q1, q2));
|
|
558
|
+
const o3 = sign(area(p2, q2, p1));
|
|
559
|
+
const o4 = sign(area(p2, q2, q1));
|
|
560
|
+
if (o1 !== o2 && o3 !== o4)
|
|
561
|
+
return true;
|
|
562
|
+
if (o1 === 0 && onSegment(p1, p2, q1))
|
|
563
|
+
return true;
|
|
564
|
+
if (o2 === 0 && onSegment(p1, q2, q1))
|
|
565
|
+
return true;
|
|
566
|
+
if (o3 === 0 && onSegment(p2, p1, q2))
|
|
567
|
+
return true;
|
|
568
|
+
if (o4 === 0 && onSegment(p2, q1, q2))
|
|
569
|
+
return true;
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
function onSegment(p, q, r) {
|
|
573
|
+
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);
|
|
574
|
+
}
|
|
575
|
+
function sign(num) {
|
|
576
|
+
return num > 0 ? 1 : num < 0 ? -1 : 0;
|
|
577
|
+
}
|
|
578
|
+
function intersectsPolygon(a, b) {
|
|
579
|
+
let p = a;
|
|
580
|
+
do {
|
|
581
|
+
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))
|
|
582
|
+
return true;
|
|
583
|
+
p = p.next;
|
|
584
|
+
} while (p !== a);
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
function locallyInside(a, b) {
|
|
588
|
+
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;
|
|
589
|
+
}
|
|
590
|
+
function middleInside(a, b) {
|
|
591
|
+
let p = a;
|
|
592
|
+
let inside = false;
|
|
593
|
+
const px = (a.x + b.x) / 2;
|
|
594
|
+
const py = (a.y + b.y) / 2;
|
|
595
|
+
do {
|
|
596
|
+
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)
|
|
597
|
+
inside = !inside;
|
|
598
|
+
p = p.next;
|
|
599
|
+
} while (p !== a);
|
|
600
|
+
return inside;
|
|
601
|
+
}
|
|
602
|
+
function splitPolygon(a, b) {
|
|
603
|
+
const a2 = new Node(a.i, a.x, a.y);
|
|
604
|
+
const b2 = new Node(b.i, b.x, b.y);
|
|
605
|
+
const an = a.next;
|
|
606
|
+
const bp = b.prev;
|
|
607
|
+
a.next = b;
|
|
608
|
+
b.prev = a;
|
|
609
|
+
a2.next = an;
|
|
610
|
+
an.prev = a2;
|
|
611
|
+
b2.next = a2;
|
|
612
|
+
a2.prev = b2;
|
|
613
|
+
bp.next = b2;
|
|
614
|
+
b2.prev = bp;
|
|
615
|
+
return b2;
|
|
616
|
+
}
|
|
617
|
+
function insertNode(i, x, y, last) {
|
|
618
|
+
const p = new Node(i, x, y);
|
|
619
|
+
if (!last) {
|
|
620
|
+
p.prev = p;
|
|
621
|
+
p.next = p;
|
|
622
|
+
} else {
|
|
623
|
+
p.next = last.next;
|
|
624
|
+
p.prev = last;
|
|
625
|
+
last.next.prev = p;
|
|
626
|
+
last.next = p;
|
|
627
|
+
}
|
|
628
|
+
return p;
|
|
629
|
+
}
|
|
630
|
+
function removeNode(p) {
|
|
631
|
+
p.next.prev = p.prev;
|
|
632
|
+
p.prev.next = p.next;
|
|
633
|
+
if (p.prevZ)
|
|
634
|
+
p.prevZ.nextZ = p.nextZ;
|
|
635
|
+
if (p.nextZ)
|
|
636
|
+
p.nextZ.prevZ = p.prevZ;
|
|
637
|
+
}
|
|
638
|
+
function Node(i, x, y) {
|
|
639
|
+
this.i = i;
|
|
640
|
+
this.x = x;
|
|
641
|
+
this.y = y;
|
|
642
|
+
this.prev = null;
|
|
643
|
+
this.next = null;
|
|
644
|
+
this.z = null;
|
|
645
|
+
this.prevZ = null;
|
|
646
|
+
this.nextZ = null;
|
|
647
|
+
this.steiner = false;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// ../gis/src/lib/flat-geojson-to-binary.ts
|
|
651
|
+
function flatGeojsonToBinary(features, geometryInfo, options) {
|
|
652
|
+
const propArrayTypes = extractNumericPropTypes(features);
|
|
653
|
+
const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
|
|
654
|
+
return fillArrays(features, {
|
|
655
|
+
propArrayTypes,
|
|
656
|
+
...geometryInfo
|
|
657
|
+
}, {
|
|
658
|
+
numericPropKeys: options && options.numericPropKeys || numericPropKeys,
|
|
659
|
+
PositionDataType: options ? options.PositionDataType : Float32Array
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
function extractNumericPropTypes(features) {
|
|
663
|
+
const propArrayTypes = {};
|
|
664
|
+
for (const feature of features) {
|
|
239
665
|
if (feature.properties) {
|
|
240
666
|
for (const key in feature.properties) {
|
|
241
667
|
const val = feature.properties[key];
|
|
@@ -243,22 +669,9 @@
|
|
|
243
669
|
}
|
|
244
670
|
}
|
|
245
671
|
}
|
|
246
|
-
return
|
|
247
|
-
coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
|
|
248
|
-
pointPositionsCount,
|
|
249
|
-
pointFeaturesCount,
|
|
250
|
-
linePositionsCount,
|
|
251
|
-
linePathsCount,
|
|
252
|
-
lineFeaturesCount,
|
|
253
|
-
polygonPositionsCount,
|
|
254
|
-
polygonObjectsCount,
|
|
255
|
-
polygonRingsCount,
|
|
256
|
-
polygonFeaturesCount,
|
|
257
|
-
numericPropKeys: Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array),
|
|
258
|
-
propArrayTypes
|
|
259
|
-
};
|
|
672
|
+
return propArrayTypes;
|
|
260
673
|
}
|
|
261
|
-
function
|
|
674
|
+
function fillArrays(features, geometryInfo, options) {
|
|
262
675
|
const {
|
|
263
676
|
pointPositionsCount,
|
|
264
677
|
pointFeaturesCount,
|
|
@@ -268,42 +681,48 @@
|
|
|
268
681
|
polygonPositionsCount,
|
|
269
682
|
polygonObjectsCount,
|
|
270
683
|
polygonRingsCount,
|
|
684
|
+
polygonFeaturesCount,
|
|
271
685
|
propArrayTypes,
|
|
272
|
-
|
|
273
|
-
} =
|
|
274
|
-
const {
|
|
686
|
+
coordLength
|
|
687
|
+
} = geometryInfo;
|
|
688
|
+
const { numericPropKeys = [], PositionDataType = Float32Array } = options;
|
|
689
|
+
const hasGlobalId = features[0] && "id" in features[0];
|
|
275
690
|
const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
|
|
276
691
|
const points = {
|
|
692
|
+
type: "Point",
|
|
277
693
|
positions: new PositionDataType(pointPositionsCount * coordLength),
|
|
278
694
|
globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
|
|
279
695
|
featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
|
|
280
696
|
numericProps: {},
|
|
281
|
-
properties:
|
|
282
|
-
fields:
|
|
697
|
+
properties: [],
|
|
698
|
+
fields: []
|
|
283
699
|
};
|
|
284
700
|
const lines = {
|
|
285
|
-
|
|
701
|
+
type: "LineString",
|
|
286
702
|
pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
|
|
703
|
+
positions: new PositionDataType(linePositionsCount * coordLength),
|
|
287
704
|
globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
|
|
288
705
|
featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
|
|
289
706
|
numericProps: {},
|
|
290
|
-
properties:
|
|
291
|
-
fields:
|
|
707
|
+
properties: [],
|
|
708
|
+
fields: []
|
|
292
709
|
};
|
|
293
710
|
const polygons = {
|
|
294
|
-
|
|
711
|
+
type: "Polygon",
|
|
295
712
|
polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
|
|
296
713
|
primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
|
|
714
|
+
positions: new PositionDataType(polygonPositionsCount * coordLength),
|
|
715
|
+
triangles: [],
|
|
297
716
|
globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
|
|
298
717
|
featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
|
|
299
718
|
numericProps: {},
|
|
300
|
-
properties:
|
|
301
|
-
fields:
|
|
719
|
+
properties: [],
|
|
720
|
+
fields: []
|
|
302
721
|
};
|
|
303
722
|
for (const object of [points, lines, polygons]) {
|
|
304
|
-
for (const propName of numericPropKeys
|
|
305
|
-
const
|
|
306
|
-
object.numericProps[propName] = new
|
|
723
|
+
for (const propName of numericPropKeys) {
|
|
724
|
+
const T = propArrayTypes[propName];
|
|
725
|
+
object.numericProps[propName] = new T(object.positions.length / coordLength);
|
|
307
726
|
}
|
|
308
727
|
}
|
|
309
728
|
lines.pathIndices[linePathsCount] = linePositionsCount;
|
|
@@ -326,33 +745,27 @@
|
|
|
326
745
|
const properties = feature.properties || {};
|
|
327
746
|
switch (geometry.type) {
|
|
328
747
|
case "Point":
|
|
329
|
-
handlePoint(geometry
|
|
330
|
-
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
331
|
-
indexMap.pointFeature++;
|
|
332
|
-
break;
|
|
333
|
-
case "MultiPoint":
|
|
334
|
-
handleMultiPoint(geometry.coordinates, points, indexMap, coordLength, properties);
|
|
748
|
+
handlePoint(geometry, points, indexMap, coordLength, properties);
|
|
335
749
|
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
750
|
+
if (hasGlobalId) {
|
|
751
|
+
points.fields.push({ id: feature.id });
|
|
752
|
+
}
|
|
336
753
|
indexMap.pointFeature++;
|
|
337
754
|
break;
|
|
338
755
|
case "LineString":
|
|
339
|
-
handleLineString(geometry
|
|
340
|
-
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
341
|
-
indexMap.lineFeature++;
|
|
342
|
-
break;
|
|
343
|
-
case "MultiLineString":
|
|
344
|
-
handleMultiLineString(geometry.coordinates, lines, indexMap, coordLength, properties);
|
|
756
|
+
handleLineString(geometry, lines, indexMap, coordLength, properties);
|
|
345
757
|
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
758
|
+
if (hasGlobalId) {
|
|
759
|
+
lines.fields.push({ id: feature.id });
|
|
760
|
+
}
|
|
346
761
|
indexMap.lineFeature++;
|
|
347
762
|
break;
|
|
348
763
|
case "Polygon":
|
|
349
|
-
handlePolygon(geometry
|
|
350
|
-
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
351
|
-
indexMap.polygonFeature++;
|
|
352
|
-
break;
|
|
353
|
-
case "MultiPolygon":
|
|
354
|
-
handleMultiPolygon(geometry.coordinates, polygons, indexMap, coordLength, properties);
|
|
764
|
+
handlePolygon(geometry, polygons, indexMap, coordLength, properties);
|
|
355
765
|
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
766
|
+
if (hasGlobalId) {
|
|
767
|
+
polygons.fields.push({ id: feature.id });
|
|
768
|
+
}
|
|
356
769
|
indexMap.polygonFeature++;
|
|
357
770
|
break;
|
|
358
771
|
default:
|
|
@@ -362,93 +775,105 @@
|
|
|
362
775
|
}
|
|
363
776
|
return makeAccessorObjects(points, lines, polygons, coordLength);
|
|
364
777
|
}
|
|
365
|
-
function handlePoint(
|
|
366
|
-
points.positions.set(
|
|
367
|
-
|
|
368
|
-
points
|
|
369
|
-
|
|
370
|
-
indexMap.pointPosition
|
|
371
|
-
|
|
372
|
-
function handleMultiPoint(coords, points, indexMap, coordLength, properties) {
|
|
373
|
-
for (const point of coords) {
|
|
374
|
-
handlePoint(point, points, indexMap, coordLength, properties);
|
|
375
|
-
}
|
|
778
|
+
function handlePoint(geometry, points, indexMap, coordLength, properties) {
|
|
779
|
+
points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
|
|
780
|
+
const nPositions = geometry.data.length / coordLength;
|
|
781
|
+
fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
|
|
782
|
+
points.globalFeatureIds.fill(indexMap.feature, indexMap.pointPosition, indexMap.pointPosition + nPositions);
|
|
783
|
+
points.featureIds.fill(indexMap.pointFeature, indexMap.pointPosition, indexMap.pointPosition + nPositions);
|
|
784
|
+
indexMap.pointPosition += nPositions;
|
|
376
785
|
}
|
|
377
|
-
function handleLineString(
|
|
378
|
-
lines.
|
|
379
|
-
|
|
380
|
-
fillCoords(lines.positions, coords, indexMap.linePosition, coordLength);
|
|
381
|
-
const nPositions = coords.length;
|
|
786
|
+
function handleLineString(geometry, lines, indexMap, coordLength, properties) {
|
|
787
|
+
lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
|
|
788
|
+
const nPositions = geometry.data.length / coordLength;
|
|
382
789
|
fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
|
|
383
|
-
lines.globalFeatureIds.
|
|
384
|
-
lines.featureIds.
|
|
385
|
-
|
|
790
|
+
lines.globalFeatureIds.fill(indexMap.feature, indexMap.linePosition, indexMap.linePosition + nPositions);
|
|
791
|
+
lines.featureIds.fill(indexMap.lineFeature, indexMap.linePosition, indexMap.linePosition + nPositions);
|
|
792
|
+
for (let i = 0, il = geometry.indices.length; i < il; ++i) {
|
|
793
|
+
const start = geometry.indices[i];
|
|
794
|
+
const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
|
|
795
|
+
lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
|
|
796
|
+
indexMap.linePosition += (end - start) / coordLength;
|
|
797
|
+
}
|
|
386
798
|
}
|
|
387
|
-
function
|
|
388
|
-
|
|
389
|
-
|
|
799
|
+
function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
|
|
800
|
+
polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
|
|
801
|
+
const nPositions = geometry.data.length / coordLength;
|
|
802
|
+
fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
|
|
803
|
+
polygons.globalFeatureIds.fill(indexMap.feature, indexMap.polygonPosition, indexMap.polygonPosition + nPositions);
|
|
804
|
+
polygons.featureIds.fill(indexMap.polygonFeature, indexMap.polygonPosition, indexMap.polygonPosition + nPositions);
|
|
805
|
+
for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
|
|
806
|
+
const startPosition = indexMap.polygonPosition;
|
|
807
|
+
polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
|
|
808
|
+
const areas = geometry.areas[l];
|
|
809
|
+
const indices = geometry.indices[l];
|
|
810
|
+
const nextIndices = geometry.indices[l + 1];
|
|
811
|
+
for (let i = 0, il = indices.length; i < il; ++i) {
|
|
812
|
+
const start = indices[i];
|
|
813
|
+
const end = i === il - 1 ? nextIndices === void 0 ? geometry.data.length : nextIndices[0] : indices[i + 1];
|
|
814
|
+
polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
|
|
815
|
+
indexMap.polygonPosition += (end - start) / coordLength;
|
|
816
|
+
}
|
|
817
|
+
const endPosition = indexMap.polygonPosition;
|
|
818
|
+
triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
|
|
390
819
|
}
|
|
391
820
|
}
|
|
392
|
-
function
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
821
|
+
function triangulatePolygon(polygons, areas, indices, {
|
|
822
|
+
startPosition,
|
|
823
|
+
endPosition,
|
|
824
|
+
coordLength
|
|
825
|
+
}) {
|
|
826
|
+
const start = startPosition * coordLength;
|
|
827
|
+
const end = endPosition * coordLength;
|
|
828
|
+
const polygonPositions = polygons.positions.subarray(start, end);
|
|
829
|
+
const offset = indices[0];
|
|
830
|
+
const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
|
|
831
|
+
const triangles = earcut(polygonPositions, holes, coordLength, areas);
|
|
832
|
+
for (let t = 0, tl = triangles.length; t < tl; ++t) {
|
|
833
|
+
polygons.triangles.push(startPosition + triangles[t]);
|
|
404
834
|
}
|
|
405
835
|
}
|
|
406
|
-
function
|
|
407
|
-
|
|
408
|
-
|
|
836
|
+
function wrapProps(obj, size) {
|
|
837
|
+
const returnObj = {};
|
|
838
|
+
for (const key in obj) {
|
|
839
|
+
returnObj[key] = { value: obj[key], size };
|
|
409
840
|
}
|
|
841
|
+
return returnObj;
|
|
410
842
|
}
|
|
411
843
|
function makeAccessorObjects(points, lines, polygons, coordLength) {
|
|
412
|
-
|
|
844
|
+
return {
|
|
413
845
|
points: {
|
|
414
846
|
...points,
|
|
415
847
|
positions: { value: points.positions, size: coordLength },
|
|
416
848
|
globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
|
|
417
849
|
featureIds: { value: points.featureIds, size: 1 },
|
|
418
|
-
|
|
850
|
+
numericProps: wrapProps(points.numericProps, 1)
|
|
419
851
|
},
|
|
420
852
|
lines: {
|
|
421
853
|
...lines,
|
|
422
|
-
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
423
854
|
positions: { value: lines.positions, size: coordLength },
|
|
855
|
+
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
424
856
|
globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
|
|
425
857
|
featureIds: { value: lines.featureIds, size: 1 },
|
|
426
|
-
|
|
858
|
+
numericProps: wrapProps(lines.numericProps, 1)
|
|
427
859
|
},
|
|
428
860
|
polygons: {
|
|
429
861
|
...polygons,
|
|
862
|
+
positions: { value: polygons.positions, size: coordLength },
|
|
430
863
|
polygonIndices: { value: polygons.polygonIndices, size: 1 },
|
|
431
864
|
primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
|
|
432
|
-
|
|
865
|
+
triangles: { value: new Uint32Array(polygons.triangles), size: 1 },
|
|
433
866
|
globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
|
|
434
867
|
featureIds: { value: polygons.featureIds, size: 1 },
|
|
435
|
-
|
|
868
|
+
numericProps: wrapProps(polygons.numericProps, 1)
|
|
436
869
|
}
|
|
437
870
|
};
|
|
438
|
-
for (const geomType in returnObj) {
|
|
439
|
-
for (const numericProp in returnObj[geomType].numericProps) {
|
|
440
|
-
returnObj[geomType].numericProps[numericProp] = {
|
|
441
|
-
value: returnObj[geomType].numericProps[numericProp],
|
|
442
|
-
size: 1
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
return returnObj;
|
|
447
871
|
}
|
|
448
872
|
function fillNumericProperties(object, properties, index, length) {
|
|
449
873
|
for (const numericPropName in object.numericProps) {
|
|
450
874
|
if (numericPropName in properties) {
|
|
451
|
-
|
|
875
|
+
const value = properties[numericPropName];
|
|
876
|
+
object.numericProps[numericPropName].fill(value, index, index + length);
|
|
452
877
|
}
|
|
453
878
|
}
|
|
454
879
|
}
|
|
@@ -461,16 +886,6 @@
|
|
|
461
886
|
}
|
|
462
887
|
return props;
|
|
463
888
|
}
|
|
464
|
-
function fillCoords(array, coords, startVertex, coordLength) {
|
|
465
|
-
let index = startVertex * coordLength;
|
|
466
|
-
for (const coord of coords) {
|
|
467
|
-
array.set(coord, index);
|
|
468
|
-
index += coordLength;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
function flatten(arrays) {
|
|
472
|
-
return [].concat(...arrays);
|
|
473
|
-
}
|
|
474
889
|
function deduceArrayType(x, constructor) {
|
|
475
890
|
if (constructor === Array || !Number.isFinite(x)) {
|
|
476
891
|
return Array;
|
|
@@ -478,6 +893,186 @@
|
|
|
478
893
|
return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
|
|
479
894
|
}
|
|
480
895
|
|
|
896
|
+
// ../gis/src/lib/extract-geometry-info.ts
|
|
897
|
+
function extractGeometryInfo(features) {
|
|
898
|
+
let pointPositionsCount = 0;
|
|
899
|
+
let pointFeaturesCount = 0;
|
|
900
|
+
let linePositionsCount = 0;
|
|
901
|
+
let linePathsCount = 0;
|
|
902
|
+
let lineFeaturesCount = 0;
|
|
903
|
+
let polygonPositionsCount = 0;
|
|
904
|
+
let polygonObjectsCount = 0;
|
|
905
|
+
let polygonRingsCount = 0;
|
|
906
|
+
let polygonFeaturesCount = 0;
|
|
907
|
+
const coordLengths = new Set();
|
|
908
|
+
for (const feature of features) {
|
|
909
|
+
const geometry = feature.geometry;
|
|
910
|
+
switch (geometry.type) {
|
|
911
|
+
case "Point":
|
|
912
|
+
pointFeaturesCount++;
|
|
913
|
+
pointPositionsCount++;
|
|
914
|
+
coordLengths.add(geometry.coordinates.length);
|
|
915
|
+
break;
|
|
916
|
+
case "MultiPoint":
|
|
917
|
+
pointFeaturesCount++;
|
|
918
|
+
pointPositionsCount += geometry.coordinates.length;
|
|
919
|
+
for (const point of geometry.coordinates) {
|
|
920
|
+
coordLengths.add(point.length);
|
|
921
|
+
}
|
|
922
|
+
break;
|
|
923
|
+
case "LineString":
|
|
924
|
+
lineFeaturesCount++;
|
|
925
|
+
linePositionsCount += geometry.coordinates.length;
|
|
926
|
+
linePathsCount++;
|
|
927
|
+
for (const coord of geometry.coordinates) {
|
|
928
|
+
coordLengths.add(coord.length);
|
|
929
|
+
}
|
|
930
|
+
break;
|
|
931
|
+
case "MultiLineString":
|
|
932
|
+
lineFeaturesCount++;
|
|
933
|
+
for (const line of geometry.coordinates) {
|
|
934
|
+
linePositionsCount += line.length;
|
|
935
|
+
linePathsCount++;
|
|
936
|
+
for (const coord of line) {
|
|
937
|
+
coordLengths.add(coord.length);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
break;
|
|
941
|
+
case "Polygon":
|
|
942
|
+
polygonFeaturesCount++;
|
|
943
|
+
polygonObjectsCount++;
|
|
944
|
+
polygonRingsCount += geometry.coordinates.length;
|
|
945
|
+
const flattened = geometry.coordinates.flat();
|
|
946
|
+
polygonPositionsCount += flattened.length;
|
|
947
|
+
for (const coord of flattened) {
|
|
948
|
+
coordLengths.add(coord.length);
|
|
949
|
+
}
|
|
950
|
+
break;
|
|
951
|
+
case "MultiPolygon":
|
|
952
|
+
polygonFeaturesCount++;
|
|
953
|
+
for (const polygon of geometry.coordinates) {
|
|
954
|
+
polygonObjectsCount++;
|
|
955
|
+
polygonRingsCount += polygon.length;
|
|
956
|
+
const flattened2 = polygon.flat();
|
|
957
|
+
polygonPositionsCount += flattened2.length;
|
|
958
|
+
for (const coord of flattened2) {
|
|
959
|
+
coordLengths.add(coord.length);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
break;
|
|
963
|
+
default:
|
|
964
|
+
throw new Error(`Unsupported geometry type: ${geometry.type}`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
|
|
969
|
+
pointPositionsCount,
|
|
970
|
+
pointFeaturesCount,
|
|
971
|
+
linePositionsCount,
|
|
972
|
+
linePathsCount,
|
|
973
|
+
lineFeaturesCount,
|
|
974
|
+
polygonPositionsCount,
|
|
975
|
+
polygonObjectsCount,
|
|
976
|
+
polygonRingsCount,
|
|
977
|
+
polygonFeaturesCount
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// ../gis/src/lib/geojson-to-flat-geojson.ts
|
|
982
|
+
function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
|
|
983
|
+
return features.map((feature) => flattenFeature(feature, options));
|
|
984
|
+
}
|
|
985
|
+
function flattenPoint(coordinates, data, indices, options) {
|
|
986
|
+
indices.push(data.length);
|
|
987
|
+
data.push(...coordinates);
|
|
988
|
+
for (let i = coordinates.length; i < options.coordLength; i++) {
|
|
989
|
+
data.push(0);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
function flattenLineString(coordinates, data, indices, options) {
|
|
993
|
+
indices.push(data.length);
|
|
994
|
+
for (const c of coordinates) {
|
|
995
|
+
data.push(...c);
|
|
996
|
+
for (let i = c.length; i < options.coordLength; i++) {
|
|
997
|
+
data.push(0);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
function flattenPolygon(coordinates, data, indices, areas, options) {
|
|
1002
|
+
let count = 0;
|
|
1003
|
+
const ringAreas = [];
|
|
1004
|
+
const polygons = [];
|
|
1005
|
+
for (const lineString of coordinates) {
|
|
1006
|
+
const lineString2d = lineString.map((p) => p.slice(0, 2));
|
|
1007
|
+
let area2 = getPolygonSignedArea(lineString2d.flat());
|
|
1008
|
+
const ccw = area2 < 0;
|
|
1009
|
+
if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
|
|
1010
|
+
lineString.reverse();
|
|
1011
|
+
area2 = -area2;
|
|
1012
|
+
}
|
|
1013
|
+
ringAreas.push(area2);
|
|
1014
|
+
flattenLineString(lineString, data, polygons, options);
|
|
1015
|
+
count++;
|
|
1016
|
+
}
|
|
1017
|
+
if (count > 0) {
|
|
1018
|
+
areas.push(ringAreas);
|
|
1019
|
+
indices.push(polygons);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
function flattenFeature(feature, options) {
|
|
1023
|
+
const { geometry } = feature;
|
|
1024
|
+
if (geometry.type === "GeometryCollection") {
|
|
1025
|
+
throw new Error("GeometryCollection type not supported");
|
|
1026
|
+
}
|
|
1027
|
+
const data = [];
|
|
1028
|
+
const indices = [];
|
|
1029
|
+
let areas;
|
|
1030
|
+
let type;
|
|
1031
|
+
switch (geometry.type) {
|
|
1032
|
+
case "Point":
|
|
1033
|
+
type = "Point";
|
|
1034
|
+
flattenPoint(geometry.coordinates, data, indices, options);
|
|
1035
|
+
break;
|
|
1036
|
+
case "MultiPoint":
|
|
1037
|
+
type = "Point";
|
|
1038
|
+
geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
|
|
1039
|
+
break;
|
|
1040
|
+
case "LineString":
|
|
1041
|
+
type = "LineString";
|
|
1042
|
+
flattenLineString(geometry.coordinates, data, indices, options);
|
|
1043
|
+
break;
|
|
1044
|
+
case "MultiLineString":
|
|
1045
|
+
type = "LineString";
|
|
1046
|
+
geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
|
|
1047
|
+
break;
|
|
1048
|
+
case "Polygon":
|
|
1049
|
+
type = "Polygon";
|
|
1050
|
+
areas = [];
|
|
1051
|
+
flattenPolygon(geometry.coordinates, data, indices, areas, options);
|
|
1052
|
+
break;
|
|
1053
|
+
case "MultiPolygon":
|
|
1054
|
+
type = "Polygon";
|
|
1055
|
+
areas = [];
|
|
1056
|
+
geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
|
|
1057
|
+
break;
|
|
1058
|
+
default:
|
|
1059
|
+
throw new Error(`Unknown type: ${type}`);
|
|
1060
|
+
}
|
|
1061
|
+
return { ...feature, geometry: { type, indices, data, areas } };
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// ../gis/src/lib/geojson-to-binary.ts
|
|
1065
|
+
function geojsonToBinary(features, options = { fixRingWinding: true }) {
|
|
1066
|
+
const geometryInfo = extractGeometryInfo(features);
|
|
1067
|
+
const coordLength = geometryInfo.coordLength;
|
|
1068
|
+
const { fixRingWinding } = options;
|
|
1069
|
+
const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
|
|
1070
|
+
return flatGeojsonToBinary(flatFeatures, geometryInfo, {
|
|
1071
|
+
numericPropKeys: options.numericPropKeys,
|
|
1072
|
+
PositionDataType: options.PositionDataType || Float32Array
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
|
|
481
1076
|
// src/lib/parse-json.ts
|
|
482
1077
|
function parseJSONSync(jsonText, options) {
|
|
483
1078
|
try {
|
|
@@ -1640,7 +2235,7 @@ Char: ${this.c}`;
|
|
|
1640
2235
|
}
|
|
1641
2236
|
|
|
1642
2237
|
// src/geojson-loader.ts
|
|
1643
|
-
var VERSION =
|
|
2238
|
+
var VERSION = true ? "3.1.4" : "latest";
|
|
1644
2239
|
var DEFAULT_GEOJSON_LOADER_OPTIONS = {
|
|
1645
2240
|
geojson: {
|
|
1646
2241
|
shape: "object-row-table"
|