@loaders.gl/json 4.0.0-alpha.4 → 4.0.0-alpha.5
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.d.ts +2 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/dist.min.js +2543 -0
- package/dist/geojson-loader.d.ts +16 -0
- package/dist/geojson-loader.d.ts.map +1 -0
- package/dist/geojson-loader.js +1 -1
- package/dist/geojson-worker.js +782 -181
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/json-loader.d.ts +14 -0
- package/dist/json-loader.d.ts.map +1 -0
- package/dist/json-loader.js +1 -1
- package/dist/jsonl-loader.d.ts +1 -0
- package/dist/jsonl-loader.d.ts.map +1 -0
- package/dist/lib/clarinet/clarinet.d.ts +74 -0
- package/dist/lib/clarinet/clarinet.d.ts.map +1 -0
- package/dist/lib/jsonpath/jsonpath.d.ts +32 -0
- package/dist/lib/jsonpath/jsonpath.d.ts.map +1 -0
- package/dist/lib/parse-json-in-batches.d.ts +5 -0
- package/dist/lib/parse-json-in-batches.d.ts.map +1 -0
- package/dist/lib/parse-json-in-batches.js +18 -1
- package/dist/lib/parse-json-in-batches.js.map +1 -1
- package/dist/lib/parse-json.d.ts +3 -0
- package/dist/lib/parse-json.d.ts.map +1 -0
- package/dist/lib/parse-ndjson-in-batches.d.ts +4 -0
- package/dist/lib/parse-ndjson-in-batches.d.ts.map +1 -0
- package/dist/lib/parse-ndjson.d.ts +2 -0
- package/dist/lib/parse-ndjson.d.ts.map +1 -0
- package/dist/lib/parser/json-parser.d.ts +22 -0
- package/dist/lib/parser/json-parser.d.ts.map +1 -0
- package/dist/lib/parser/streaming-json-parser.d.ts +37 -0
- package/dist/lib/parser/streaming-json-parser.d.ts.map +1 -0
- package/dist/ndjson-loader.d.ts +22 -0
- package/dist/ndjson-loader.d.ts.map +1 -0
- package/dist/ndjson-loader.js +1 -1
- package/dist/workers/geojson-worker.d.ts +2 -0
- package/dist/workers/geojson-worker.d.ts.map +1 -0
- package/package.json +8 -8
- package/src/index.ts +2 -0
- package/src/lib/parse-json-in-batches.ts +23 -1
package/dist/geojson-worker.js
CHANGED
|
@@ -159,105 +159,519 @@
|
|
|
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];
|
|
242
|
-
|
|
668
|
+
propArrayTypes[key] = deduceArrayType(val, propArrayTypes[key]);
|
|
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(numericPropKeys).filter((k) => numericPropKeys[k])
|
|
258
|
-
};
|
|
672
|
+
return propArrayTypes;
|
|
259
673
|
}
|
|
260
|
-
function
|
|
674
|
+
function fillArrays(features, geometryInfo, options) {
|
|
261
675
|
const {
|
|
262
676
|
pointPositionsCount,
|
|
263
677
|
pointFeaturesCount,
|
|
@@ -267,40 +681,48 @@
|
|
|
267
681
|
polygonPositionsCount,
|
|
268
682
|
polygonObjectsCount,
|
|
269
683
|
polygonRingsCount,
|
|
270
|
-
polygonFeaturesCount
|
|
271
|
-
|
|
272
|
-
|
|
684
|
+
polygonFeaturesCount,
|
|
685
|
+
propArrayTypes,
|
|
686
|
+
coordLength
|
|
687
|
+
} = geometryInfo;
|
|
688
|
+
const { numericPropKeys = [], PositionDataType = Float32Array } = options;
|
|
689
|
+
const hasGlobalId = features[0] && "id" in features[0];
|
|
273
690
|
const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
|
|
274
691
|
const points = {
|
|
692
|
+
type: "Point",
|
|
275
693
|
positions: new PositionDataType(pointPositionsCount * coordLength),
|
|
276
694
|
globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
|
|
277
695
|
featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
|
|
278
696
|
numericProps: {},
|
|
279
|
-
properties:
|
|
280
|
-
fields:
|
|
697
|
+
properties: [],
|
|
698
|
+
fields: []
|
|
281
699
|
};
|
|
282
700
|
const lines = {
|
|
283
|
-
|
|
701
|
+
type: "LineString",
|
|
284
702
|
pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
|
|
703
|
+
positions: new PositionDataType(linePositionsCount * coordLength),
|
|
285
704
|
globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
|
|
286
705
|
featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
|
|
287
706
|
numericProps: {},
|
|
288
|
-
properties:
|
|
289
|
-
fields:
|
|
707
|
+
properties: [],
|
|
708
|
+
fields: []
|
|
290
709
|
};
|
|
291
710
|
const polygons = {
|
|
292
|
-
|
|
711
|
+
type: "Polygon",
|
|
293
712
|
polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
|
|
294
713
|
primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
|
|
714
|
+
positions: new PositionDataType(polygonPositionsCount * coordLength),
|
|
715
|
+
triangles: [],
|
|
295
716
|
globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
|
|
296
717
|
featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
|
|
297
718
|
numericProps: {},
|
|
298
|
-
properties:
|
|
299
|
-
fields:
|
|
719
|
+
properties: [],
|
|
720
|
+
fields: []
|
|
300
721
|
};
|
|
301
722
|
for (const object of [points, lines, polygons]) {
|
|
302
|
-
for (const propName of numericPropKeys
|
|
303
|
-
|
|
723
|
+
for (const propName of numericPropKeys) {
|
|
724
|
+
const T = propArrayTypes[propName];
|
|
725
|
+
object.numericProps[propName] = new T(object.positions.length / coordLength);
|
|
304
726
|
}
|
|
305
727
|
}
|
|
306
728
|
lines.pathIndices[linePathsCount] = linePositionsCount;
|
|
@@ -323,33 +745,27 @@
|
|
|
323
745
|
const properties = feature.properties || {};
|
|
324
746
|
switch (geometry.type) {
|
|
325
747
|
case "Point":
|
|
326
|
-
handlePoint(geometry
|
|
327
|
-
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
328
|
-
indexMap.pointFeature++;
|
|
329
|
-
break;
|
|
330
|
-
case "MultiPoint":
|
|
331
|
-
handleMultiPoint(geometry.coordinates, points, indexMap, coordLength, properties);
|
|
748
|
+
handlePoint(geometry, points, indexMap, coordLength, properties);
|
|
332
749
|
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
750
|
+
if (hasGlobalId) {
|
|
751
|
+
points.fields.push({ id: feature.id });
|
|
752
|
+
}
|
|
333
753
|
indexMap.pointFeature++;
|
|
334
754
|
break;
|
|
335
755
|
case "LineString":
|
|
336
|
-
handleLineString(geometry
|
|
337
|
-
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
338
|
-
indexMap.lineFeature++;
|
|
339
|
-
break;
|
|
340
|
-
case "MultiLineString":
|
|
341
|
-
handleMultiLineString(geometry.coordinates, lines, indexMap, coordLength, properties);
|
|
756
|
+
handleLineString(geometry, lines, indexMap, coordLength, properties);
|
|
342
757
|
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
758
|
+
if (hasGlobalId) {
|
|
759
|
+
lines.fields.push({ id: feature.id });
|
|
760
|
+
}
|
|
343
761
|
indexMap.lineFeature++;
|
|
344
762
|
break;
|
|
345
763
|
case "Polygon":
|
|
346
|
-
handlePolygon(geometry
|
|
347
|
-
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
348
|
-
indexMap.polygonFeature++;
|
|
349
|
-
break;
|
|
350
|
-
case "MultiPolygon":
|
|
351
|
-
handleMultiPolygon(geometry.coordinates, polygons, indexMap, coordLength, properties);
|
|
764
|
+
handlePolygon(geometry, polygons, indexMap, coordLength, properties);
|
|
352
765
|
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
766
|
+
if (hasGlobalId) {
|
|
767
|
+
polygons.fields.push({ id: feature.id });
|
|
768
|
+
}
|
|
353
769
|
indexMap.polygonFeature++;
|
|
354
770
|
break;
|
|
355
771
|
default:
|
|
@@ -359,93 +775,105 @@
|
|
|
359
775
|
}
|
|
360
776
|
return makeAccessorObjects(points, lines, polygons, coordLength);
|
|
361
777
|
}
|
|
362
|
-
function handlePoint(
|
|
363
|
-
points.positions.set(
|
|
364
|
-
|
|
365
|
-
points
|
|
366
|
-
|
|
367
|
-
indexMap.pointPosition
|
|
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;
|
|
368
785
|
}
|
|
369
|
-
function
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
function handleLineString(coords, lines, indexMap, coordLength, properties) {
|
|
375
|
-
lines.pathIndices[indexMap.linePath] = indexMap.linePosition;
|
|
376
|
-
indexMap.linePath++;
|
|
377
|
-
fillCoords(lines.positions, coords, indexMap.linePosition, coordLength);
|
|
378
|
-
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;
|
|
379
789
|
fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
|
|
380
|
-
lines.globalFeatureIds.
|
|
381
|
-
lines.featureIds.
|
|
382
|
-
|
|
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
|
+
}
|
|
383
798
|
}
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
-
|
|
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 });
|
|
387
819
|
}
|
|
388
820
|
}
|
|
389
|
-
function
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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]);
|
|
401
834
|
}
|
|
402
835
|
}
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
|
|
836
|
+
function wrapProps(obj, size) {
|
|
837
|
+
const returnObj = {};
|
|
838
|
+
for (const key in obj) {
|
|
839
|
+
returnObj[key] = { value: obj[key], size };
|
|
406
840
|
}
|
|
841
|
+
return returnObj;
|
|
407
842
|
}
|
|
408
843
|
function makeAccessorObjects(points, lines, polygons, coordLength) {
|
|
409
|
-
|
|
844
|
+
return {
|
|
410
845
|
points: {
|
|
411
846
|
...points,
|
|
412
847
|
positions: { value: points.positions, size: coordLength },
|
|
413
848
|
globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
|
|
414
849
|
featureIds: { value: points.featureIds, size: 1 },
|
|
415
|
-
|
|
850
|
+
numericProps: wrapProps(points.numericProps, 1)
|
|
416
851
|
},
|
|
417
852
|
lines: {
|
|
418
853
|
...lines,
|
|
419
|
-
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
420
854
|
positions: { value: lines.positions, size: coordLength },
|
|
855
|
+
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
421
856
|
globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
|
|
422
857
|
featureIds: { value: lines.featureIds, size: 1 },
|
|
423
|
-
|
|
858
|
+
numericProps: wrapProps(lines.numericProps, 1)
|
|
424
859
|
},
|
|
425
860
|
polygons: {
|
|
426
861
|
...polygons,
|
|
862
|
+
positions: { value: polygons.positions, size: coordLength },
|
|
427
863
|
polygonIndices: { value: polygons.polygonIndices, size: 1 },
|
|
428
864
|
primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
|
|
429
|
-
|
|
865
|
+
triangles: { value: new Uint32Array(polygons.triangles), size: 1 },
|
|
430
866
|
globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
|
|
431
867
|
featureIds: { value: polygons.featureIds, size: 1 },
|
|
432
|
-
|
|
868
|
+
numericProps: wrapProps(polygons.numericProps, 1)
|
|
433
869
|
}
|
|
434
870
|
};
|
|
435
|
-
for (const geomType in returnObj) {
|
|
436
|
-
for (const numericProp in returnObj[geomType].numericProps) {
|
|
437
|
-
returnObj[geomType].numericProps[numericProp] = {
|
|
438
|
-
value: returnObj[geomType].numericProps[numericProp],
|
|
439
|
-
size: 1
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
return returnObj;
|
|
444
871
|
}
|
|
445
872
|
function fillNumericProperties(object, properties, index, length) {
|
|
446
873
|
for (const numericPropName in object.numericProps) {
|
|
447
874
|
if (numericPropName in properties) {
|
|
448
|
-
|
|
875
|
+
const value = properties[numericPropName];
|
|
876
|
+
object.numericProps[numericPropName].fill(value, index, index + length);
|
|
449
877
|
}
|
|
450
878
|
}
|
|
451
879
|
}
|
|
@@ -458,18 +886,191 @@
|
|
|
458
886
|
}
|
|
459
887
|
return props;
|
|
460
888
|
}
|
|
461
|
-
function
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
889
|
+
function deduceArrayType(x, constructor) {
|
|
890
|
+
if (constructor === Array || !Number.isFinite(x)) {
|
|
891
|
+
return Array;
|
|
892
|
+
}
|
|
893
|
+
return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
|
|
894
|
+
}
|
|
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);
|
|
466
990
|
}
|
|
467
991
|
}
|
|
468
|
-
function
|
|
469
|
-
|
|
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
|
+
}
|
|
470
1000
|
}
|
|
471
|
-
function
|
|
472
|
-
|
|
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
|
+
});
|
|
473
1074
|
}
|
|
474
1075
|
|
|
475
1076
|
// src/lib/parse-json.ts
|
|
@@ -1634,7 +2235,7 @@ Char: ${this.c}`;
|
|
|
1634
2235
|
}
|
|
1635
2236
|
|
|
1636
2237
|
// src/geojson-loader.ts
|
|
1637
|
-
var VERSION =
|
|
2238
|
+
var VERSION = true ? "4.0.0-alpha.5" : "latest";
|
|
1638
2239
|
var DEFAULT_GEOJSON_LOADER_OPTIONS = {
|
|
1639
2240
|
geojson: {
|
|
1640
2241
|
shape: "object-row-table"
|