@loaders.gl/json 4.0.0 → 4.0.2
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/dist.dev.js +4 -4
- package/dist/geojson-worker.js +1287 -1279
- package/package.json +5 -5
package/dist/geojson-worker.js
CHANGED
|
@@ -36,61 +36,69 @@
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// ../worker-utils/src/lib/worker-farm/worker-body.ts
|
|
39
|
-
function getParentPort() {
|
|
39
|
+
async function getParentPort() {
|
|
40
40
|
let parentPort;
|
|
41
41
|
try {
|
|
42
42
|
eval("globalThis.parentPort = require('worker_threads').parentPort");
|
|
43
43
|
parentPort = globalThis.parentPort;
|
|
44
44
|
} catch {
|
|
45
|
+
try {
|
|
46
|
+
eval("globalThis.workerThreadsPromise = import('worker_threads')");
|
|
47
|
+
const workerThreads = await globalThis.workerThreadsPromise;
|
|
48
|
+
parentPort = workerThreads.parentPort;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(error.message);
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
return parentPort;
|
|
47
54
|
}
|
|
48
55
|
var onMessageWrapperMap = /* @__PURE__ */ new Map();
|
|
49
56
|
var WorkerBody = class {
|
|
50
57
|
/** Check that we are actually in a worker thread */
|
|
51
|
-
static inWorkerThread() {
|
|
52
|
-
return typeof self !== "undefined" || Boolean(getParentPort());
|
|
58
|
+
static async inWorkerThread() {
|
|
59
|
+
return typeof self !== "undefined" || Boolean(await getParentPort());
|
|
53
60
|
}
|
|
54
61
|
/*
|
|
55
62
|
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any
|
|
56
63
|
*/
|
|
57
64
|
static set onmessage(onMessage) {
|
|
58
|
-
function handleMessage(message) {
|
|
59
|
-
const
|
|
60
|
-
const { type, payload } =
|
|
65
|
+
async function handleMessage(message) {
|
|
66
|
+
const parentPort2 = await getParentPort();
|
|
67
|
+
const { type, payload } = parentPort2 ? message : message.data;
|
|
61
68
|
onMessage(type, payload);
|
|
62
69
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
getParentPort().then((parentPort2) => {
|
|
71
|
+
if (parentPort2) {
|
|
72
|
+
parentPort2.on("message", handleMessage);
|
|
73
|
+
parentPort2.on("exit", () => console.debug("Node worker closing"));
|
|
74
|
+
} else {
|
|
75
|
+
globalThis.onmessage = handleMessage;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
70
78
|
}
|
|
71
|
-
static addEventListener(onMessage) {
|
|
79
|
+
static async addEventListener(onMessage) {
|
|
72
80
|
let onMessageWrapper = onMessageWrapperMap.get(onMessage);
|
|
73
81
|
if (!onMessageWrapper) {
|
|
74
|
-
onMessageWrapper = (message) => {
|
|
82
|
+
onMessageWrapper = async (message) => {
|
|
75
83
|
if (!isKnownMessage(message)) {
|
|
76
84
|
return;
|
|
77
85
|
}
|
|
78
|
-
const parentPort3 = getParentPort();
|
|
86
|
+
const parentPort3 = await getParentPort();
|
|
79
87
|
const { type, payload } = parentPort3 ? message : message.data;
|
|
80
88
|
onMessage(type, payload);
|
|
81
89
|
};
|
|
82
90
|
}
|
|
83
|
-
const parentPort2 = getParentPort();
|
|
91
|
+
const parentPort2 = await getParentPort();
|
|
84
92
|
if (parentPort2) {
|
|
85
93
|
console.error("not implemented");
|
|
86
94
|
} else {
|
|
87
95
|
globalThis.addEventListener("message", onMessageWrapper);
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
|
-
static removeEventListener(onMessage) {
|
|
98
|
+
static async removeEventListener(onMessage) {
|
|
91
99
|
const onMessageWrapper = onMessageWrapperMap.get(onMessage);
|
|
92
100
|
onMessageWrapperMap.delete(onMessage);
|
|
93
|
-
const parentPort2 = getParentPort();
|
|
101
|
+
const parentPort2 = await getParentPort();
|
|
94
102
|
if (parentPort2) {
|
|
95
103
|
console.error("not implemented");
|
|
96
104
|
} else {
|
|
@@ -102,10 +110,10 @@
|
|
|
102
110
|
* @param type
|
|
103
111
|
* @param payload
|
|
104
112
|
*/
|
|
105
|
-
static postMessage(type, payload) {
|
|
113
|
+
static async postMessage(type, payload) {
|
|
106
114
|
const data = { source: "loaders.gl", type, payload };
|
|
107
115
|
const transferList = getTransferList(payload);
|
|
108
|
-
const parentPort2 = getParentPort();
|
|
116
|
+
const parentPort2 = await getParentPort();
|
|
109
117
|
if (parentPort2) {
|
|
110
118
|
parentPort2.postMessage(data, transferList);
|
|
111
119
|
} else {
|
|
@@ -120,8 +128,8 @@
|
|
|
120
128
|
|
|
121
129
|
// ../loader-utils/src/lib/worker-loader-utils/create-loader-worker.ts
|
|
122
130
|
var requestId = 0;
|
|
123
|
-
function createLoaderWorker(loader) {
|
|
124
|
-
if (!WorkerBody.inWorkerThread()) {
|
|
131
|
+
async function createLoaderWorker(loader) {
|
|
132
|
+
if (!await WorkerBody.inWorkerThread()) {
|
|
125
133
|
return;
|
|
126
134
|
}
|
|
127
135
|
WorkerBody.onmessage = async (type, payload) => {
|
|
@@ -253,1356 +261,1356 @@
|
|
|
253
261
|
return obj;
|
|
254
262
|
}
|
|
255
263
|
|
|
256
|
-
//
|
|
257
|
-
var
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
273
|
-
area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
|
|
274
|
-
j = i;
|
|
264
|
+
// ../schema/src/lib/table/batches/base-table-batch-aggregator.ts
|
|
265
|
+
var DEFAULT_ROW_COUNT = 100;
|
|
266
|
+
var BaseTableBatchAggregator = class {
|
|
267
|
+
constructor(schema, options) {
|
|
268
|
+
this.length = 0;
|
|
269
|
+
this.rows = null;
|
|
270
|
+
this.cursor = 0;
|
|
271
|
+
this._headers = [];
|
|
272
|
+
this.options = options;
|
|
273
|
+
this.schema = schema;
|
|
274
|
+
if (!Array.isArray(schema)) {
|
|
275
|
+
this._headers = [];
|
|
276
|
+
for (const key in schema) {
|
|
277
|
+
this._headers[schema[key].index] = schema[key].name;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
275
280
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
|
|
283
|
-
let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
|
|
284
|
-
const triangles = [];
|
|
285
|
-
if (!outerNode || outerNode.next === outerNode.prev)
|
|
286
|
-
return triangles;
|
|
287
|
-
let invSize;
|
|
288
|
-
let maxX;
|
|
289
|
-
let maxY;
|
|
290
|
-
let minX;
|
|
291
|
-
let minY;
|
|
292
|
-
let x;
|
|
293
|
-
let y;
|
|
294
|
-
if (hasHoles)
|
|
295
|
-
outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
|
|
296
|
-
if (positions.length > 80 * dim) {
|
|
297
|
-
minX = maxX = positions[0];
|
|
298
|
-
minY = maxY = positions[1];
|
|
299
|
-
for (let i = dim; i < outerLen; i += dim) {
|
|
300
|
-
x = positions[i];
|
|
301
|
-
y = positions[i + 1];
|
|
302
|
-
if (x < minX)
|
|
303
|
-
minX = x;
|
|
304
|
-
if (y < minY)
|
|
305
|
-
minY = y;
|
|
306
|
-
if (x > maxX)
|
|
307
|
-
maxX = x;
|
|
308
|
-
if (y > maxY)
|
|
309
|
-
maxY = y;
|
|
281
|
+
rowCount() {
|
|
282
|
+
return this.length;
|
|
283
|
+
}
|
|
284
|
+
addArrayRow(row, cursor) {
|
|
285
|
+
if (Number.isFinite(cursor)) {
|
|
286
|
+
this.cursor = cursor;
|
|
310
287
|
}
|
|
311
|
-
|
|
312
|
-
|
|
288
|
+
this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
|
|
289
|
+
this.rows[this.length] = row;
|
|
290
|
+
this.length++;
|
|
313
291
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
area2 = getPolygonSignedArea(data, {
|
|
322
|
-
start,
|
|
323
|
-
end,
|
|
324
|
-
size: dim,
|
|
325
|
-
plane
|
|
326
|
-
});
|
|
292
|
+
addObjectRow(row, cursor) {
|
|
293
|
+
if (Number.isFinite(cursor)) {
|
|
294
|
+
this.cursor = cursor;
|
|
295
|
+
}
|
|
296
|
+
this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
|
|
297
|
+
this.rows[this.length] = row;
|
|
298
|
+
this.length++;
|
|
327
299
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
300
|
+
getBatch() {
|
|
301
|
+
let rows = this.rows;
|
|
302
|
+
if (!rows) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
rows = rows.slice(0, this.length);
|
|
306
|
+
this.rows = null;
|
|
307
|
+
const batch = {
|
|
308
|
+
shape: this.options.shape,
|
|
309
|
+
batchType: "data",
|
|
310
|
+
data: rows,
|
|
311
|
+
length: this.length,
|
|
312
|
+
schema: this.schema,
|
|
313
|
+
cursor: this.cursor
|
|
314
|
+
};
|
|
315
|
+
return batch;
|
|
336
316
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// ../schema/src/lib/table/simple-table/row-utils.ts
|
|
320
|
+
function convertToObjectRow(arrayRow, headers) {
|
|
321
|
+
if (!arrayRow) {
|
|
322
|
+
throw new Error("null row");
|
|
340
323
|
}
|
|
341
|
-
|
|
324
|
+
if (!headers) {
|
|
325
|
+
throw new Error("no headers");
|
|
326
|
+
}
|
|
327
|
+
const objectRow = {};
|
|
328
|
+
for (let i = 0; i < headers.length; i++) {
|
|
329
|
+
objectRow[headers[i]] = arrayRow[i];
|
|
330
|
+
}
|
|
331
|
+
return objectRow;
|
|
342
332
|
}
|
|
343
|
-
function
|
|
344
|
-
if (!
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (p === p.next)
|
|
356
|
-
break;
|
|
357
|
-
again = true;
|
|
358
|
-
} else {
|
|
359
|
-
p = p.next;
|
|
360
|
-
}
|
|
361
|
-
} while (again || p !== end);
|
|
362
|
-
return end;
|
|
333
|
+
function convertToArrayRow(objectRow, headers) {
|
|
334
|
+
if (!objectRow) {
|
|
335
|
+
throw new Error("null row");
|
|
336
|
+
}
|
|
337
|
+
if (!headers) {
|
|
338
|
+
throw new Error("no headers");
|
|
339
|
+
}
|
|
340
|
+
const arrayRow = new Array(headers.length);
|
|
341
|
+
for (let i = 0; i < headers.length; i++) {
|
|
342
|
+
arrayRow[i] = objectRow[headers[i]];
|
|
343
|
+
}
|
|
344
|
+
return arrayRow;
|
|
363
345
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
ear = next.next;
|
|
381
|
-
stop = next.next;
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
ear = next;
|
|
385
|
-
if (ear === stop) {
|
|
386
|
-
if (!pass) {
|
|
387
|
-
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
388
|
-
} else if (pass === 1) {
|
|
389
|
-
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
390
|
-
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
391
|
-
} else if (pass === 2) {
|
|
392
|
-
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
346
|
+
|
|
347
|
+
// ../schema/src/lib/table/batches/row-table-batch-aggregator.ts
|
|
348
|
+
var DEFAULT_ROW_COUNT2 = 100;
|
|
349
|
+
var RowTableBatchAggregator = class {
|
|
350
|
+
constructor(schema, options) {
|
|
351
|
+
this.length = 0;
|
|
352
|
+
this.objectRows = null;
|
|
353
|
+
this.arrayRows = null;
|
|
354
|
+
this.cursor = 0;
|
|
355
|
+
this._headers = [];
|
|
356
|
+
this.options = options;
|
|
357
|
+
this.schema = schema;
|
|
358
|
+
if (!Array.isArray(schema)) {
|
|
359
|
+
this._headers = [];
|
|
360
|
+
for (const key in schema) {
|
|
361
|
+
this._headers[schema[key].index] = schema[key].name;
|
|
393
362
|
}
|
|
394
|
-
break;
|
|
395
363
|
}
|
|
396
364
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const a = ear.prev;
|
|
400
|
-
const b = ear;
|
|
401
|
-
const c = ear.next;
|
|
402
|
-
if (area(a, b, c) >= 0)
|
|
403
|
-
return false;
|
|
404
|
-
const ax = a.x;
|
|
405
|
-
const bx = b.x;
|
|
406
|
-
const cx = c.x;
|
|
407
|
-
const ay = a.y;
|
|
408
|
-
const by = b.y;
|
|
409
|
-
const cy = c.y;
|
|
410
|
-
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
|
|
411
|
-
const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
|
|
412
|
-
const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
|
|
413
|
-
const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
414
|
-
let p = c.next;
|
|
415
|
-
while (p !== a) {
|
|
416
|
-
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
417
|
-
return false;
|
|
418
|
-
p = p.next;
|
|
365
|
+
rowCount() {
|
|
366
|
+
return this.length;
|
|
419
367
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
|
|
436
|
-
const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
|
|
437
|
-
const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
438
|
-
const minZ = zOrder(x0, y0, minX, minY, invSize);
|
|
439
|
-
const maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
440
|
-
let p = ear.prevZ;
|
|
441
|
-
let n = ear.nextZ;
|
|
442
|
-
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
443
|
-
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
444
|
-
return false;
|
|
445
|
-
p = p.prevZ;
|
|
446
|
-
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
447
|
-
return false;
|
|
448
|
-
n = n.nextZ;
|
|
449
|
-
}
|
|
450
|
-
while (p && p.z >= minZ) {
|
|
451
|
-
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
452
|
-
return false;
|
|
453
|
-
p = p.prevZ;
|
|
454
|
-
}
|
|
455
|
-
while (n && n.z <= maxZ) {
|
|
456
|
-
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
457
|
-
return false;
|
|
458
|
-
n = n.nextZ;
|
|
368
|
+
addArrayRow(row, cursor) {
|
|
369
|
+
if (Number.isFinite(cursor)) {
|
|
370
|
+
this.cursor = cursor;
|
|
371
|
+
}
|
|
372
|
+
switch (this.options.shape) {
|
|
373
|
+
case "object-row-table":
|
|
374
|
+
const rowObject = convertToObjectRow(row, this._headers);
|
|
375
|
+
this.addObjectRow(rowObject, cursor);
|
|
376
|
+
break;
|
|
377
|
+
case "array-row-table":
|
|
378
|
+
this.arrayRows = this.arrayRows || new Array(DEFAULT_ROW_COUNT2);
|
|
379
|
+
this.arrayRows[this.length] = row;
|
|
380
|
+
this.length++;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
459
383
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
let p = start;
|
|
464
|
-
do {
|
|
465
|
-
const a = p.prev;
|
|
466
|
-
const b = p.next.next;
|
|
467
|
-
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
468
|
-
triangles.push(a.i / dim | 0);
|
|
469
|
-
triangles.push(p.i / dim | 0);
|
|
470
|
-
triangles.push(b.i / dim | 0);
|
|
471
|
-
removeNode(p);
|
|
472
|
-
removeNode(p.next);
|
|
473
|
-
p = start = b;
|
|
384
|
+
addObjectRow(row, cursor) {
|
|
385
|
+
if (Number.isFinite(cursor)) {
|
|
386
|
+
this.cursor = cursor;
|
|
474
387
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
let c = splitPolygon(a, b);
|
|
486
|
-
a = filterPoints(a, a.next);
|
|
487
|
-
c = filterPoints(c, c.next);
|
|
488
|
-
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
489
|
-
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
b = b.next;
|
|
388
|
+
switch (this.options.shape) {
|
|
389
|
+
case "array-row-table":
|
|
390
|
+
const rowArray = convertToArrayRow(row, this._headers);
|
|
391
|
+
this.addArrayRow(rowArray, cursor);
|
|
392
|
+
break;
|
|
393
|
+
case "object-row-table":
|
|
394
|
+
this.objectRows = this.objectRows || new Array(DEFAULT_ROW_COUNT2);
|
|
395
|
+
this.objectRows[this.length] = row;
|
|
396
|
+
this.length++;
|
|
397
|
+
break;
|
|
493
398
|
}
|
|
494
|
-
a = a.next;
|
|
495
|
-
} while (a !== start);
|
|
496
|
-
}
|
|
497
|
-
function eliminateHoles(data, holeIndices, outerNode, dim, areas, plane) {
|
|
498
|
-
const queue = [];
|
|
499
|
-
let i;
|
|
500
|
-
let len;
|
|
501
|
-
let start;
|
|
502
|
-
let end;
|
|
503
|
-
let list;
|
|
504
|
-
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
505
|
-
start = holeIndices[i] * dim;
|
|
506
|
-
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
507
|
-
list = linkedList(data, start, end, dim, false, areas && areas[i + 1], plane);
|
|
508
|
-
if (list === list.next)
|
|
509
|
-
list.steiner = true;
|
|
510
|
-
queue.push(getLeftmost(list));
|
|
511
399
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
400
|
+
getBatch() {
|
|
401
|
+
let rows = this.arrayRows || this.objectRows;
|
|
402
|
+
if (!rows) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
rows = rows.slice(0, this.length);
|
|
406
|
+
this.arrayRows = null;
|
|
407
|
+
this.objectRows = null;
|
|
408
|
+
return {
|
|
409
|
+
shape: this.options.shape,
|
|
410
|
+
batchType: "data",
|
|
411
|
+
data: rows,
|
|
412
|
+
length: this.length,
|
|
413
|
+
schema: this.schema,
|
|
414
|
+
cursor: this.cursor
|
|
415
|
+
};
|
|
515
416
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// ../schema/src/lib/table/batches/columnar-table-batch-aggregator.ts
|
|
420
|
+
var DEFAULT_ROW_COUNT3 = 100;
|
|
421
|
+
var ColumnarTableBatchAggregator = class {
|
|
422
|
+
constructor(schema, options) {
|
|
423
|
+
this.length = 0;
|
|
424
|
+
this.allocated = 0;
|
|
425
|
+
this.columns = {};
|
|
426
|
+
this.schema = schema;
|
|
427
|
+
this._reallocateColumns();
|
|
525
428
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
429
|
+
rowCount() {
|
|
430
|
+
return this.length;
|
|
431
|
+
}
|
|
432
|
+
addArrayRow(row) {
|
|
433
|
+
this._reallocateColumns();
|
|
434
|
+
let i = 0;
|
|
435
|
+
for (const fieldName in this.columns) {
|
|
436
|
+
this.columns[fieldName][this.length] = row[i++];
|
|
437
|
+
}
|
|
438
|
+
this.length++;
|
|
439
|
+
}
|
|
440
|
+
addObjectRow(row) {
|
|
441
|
+
this._reallocateColumns();
|
|
442
|
+
for (const fieldName in row) {
|
|
443
|
+
this.columns[fieldName][this.length] = row[fieldName];
|
|
444
|
+
}
|
|
445
|
+
this.length++;
|
|
446
|
+
}
|
|
447
|
+
getBatch() {
|
|
448
|
+
this._pruneColumns();
|
|
449
|
+
const columns = Array.isArray(this.schema) ? this.columns : {};
|
|
450
|
+
if (!Array.isArray(this.schema)) {
|
|
451
|
+
for (const fieldName in this.schema) {
|
|
452
|
+
const field = this.schema[fieldName];
|
|
453
|
+
columns[field.name] = this.columns[field.index];
|
|
544
454
|
}
|
|
545
455
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
456
|
+
this.columns = {};
|
|
457
|
+
const batch = {
|
|
458
|
+
shape: "columnar-table",
|
|
459
|
+
batchType: "data",
|
|
460
|
+
data: columns,
|
|
461
|
+
schema: this.schema,
|
|
462
|
+
length: this.length
|
|
463
|
+
};
|
|
464
|
+
return batch;
|
|
465
|
+
}
|
|
466
|
+
// HELPERS
|
|
467
|
+
_reallocateColumns() {
|
|
468
|
+
if (this.length < this.allocated) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
this.allocated = this.allocated > 0 ? this.allocated *= 2 : DEFAULT_ROW_COUNT3;
|
|
472
|
+
this.columns = {};
|
|
473
|
+
for (const fieldName in this.schema) {
|
|
474
|
+
const field = this.schema[fieldName];
|
|
475
|
+
const ArrayType = field.type || Float32Array;
|
|
476
|
+
const oldColumn = this.columns[field.index];
|
|
477
|
+
if (oldColumn && ArrayBuffer.isView(oldColumn)) {
|
|
478
|
+
const typedArray = new ArrayType(this.allocated);
|
|
479
|
+
typedArray.set(oldColumn);
|
|
480
|
+
this.columns[field.index] = typedArray;
|
|
481
|
+
} else if (oldColumn) {
|
|
482
|
+
oldColumn.length = this.allocated;
|
|
483
|
+
this.columns[field.index] = oldColumn;
|
|
484
|
+
} else {
|
|
485
|
+
this.columns[field.index] = new ArrayType(this.allocated);
|
|
562
486
|
}
|
|
563
487
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
488
|
+
}
|
|
489
|
+
_pruneColumns() {
|
|
490
|
+
for (const [columnName, column] of Object.entries(this.columns)) {
|
|
491
|
+
this.columns[columnName] = column.slice(0, this.length);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// ../schema/src/lib/table/batches/table-batch-builder.ts
|
|
497
|
+
var DEFAULT_OPTIONS = {
|
|
498
|
+
shape: "array-row-table",
|
|
499
|
+
batchSize: "auto",
|
|
500
|
+
batchDebounceMs: 0,
|
|
501
|
+
limit: 0,
|
|
502
|
+
_limitMB: 0
|
|
503
|
+
};
|
|
504
|
+
var ERR_MESSAGE = "TableBatchBuilder";
|
|
505
|
+
var TableBatchBuilder = class {
|
|
506
|
+
constructor(schema, options) {
|
|
507
|
+
this.aggregator = null;
|
|
508
|
+
this.batchCount = 0;
|
|
509
|
+
this.bytesUsed = 0;
|
|
510
|
+
this.isChunkComplete = false;
|
|
511
|
+
this.lastBatchEmittedMs = Date.now();
|
|
512
|
+
this.totalLength = 0;
|
|
513
|
+
this.totalBytes = 0;
|
|
514
|
+
this.rowBytes = 0;
|
|
515
|
+
this.schema = schema;
|
|
516
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
517
|
+
}
|
|
518
|
+
limitReached() {
|
|
519
|
+
if (Boolean(this.options?.limit) && this.totalLength >= this.options.limit) {
|
|
520
|
+
return true;
|
|
521
|
+
}
|
|
522
|
+
if (Boolean(this.options?._limitMB) && this.totalBytes / 1e6 >= this.options._limitMB) {
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
/** @deprecated Use addArrayRow or addObjectRow */
|
|
528
|
+
addRow(row) {
|
|
529
|
+
if (this.limitReached()) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
this.totalLength++;
|
|
533
|
+
this.rowBytes = this.rowBytes || this._estimateRowMB(row);
|
|
534
|
+
this.totalBytes += this.rowBytes;
|
|
535
|
+
if (Array.isArray(row)) {
|
|
536
|
+
this.addArrayRow(row);
|
|
537
|
+
} else {
|
|
538
|
+
this.addObjectRow(row);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/** Add one row to the batch */
|
|
542
|
+
addArrayRow(row) {
|
|
543
|
+
if (!this.aggregator) {
|
|
544
|
+
const TableBatchType = this._getTableBatchType();
|
|
545
|
+
this.aggregator = new TableBatchType(this.schema, this.options);
|
|
546
|
+
}
|
|
547
|
+
this.aggregator.addArrayRow(row);
|
|
548
|
+
}
|
|
549
|
+
/** Add one row to the batch */
|
|
550
|
+
addObjectRow(row) {
|
|
551
|
+
if (!this.aggregator) {
|
|
552
|
+
const TableBatchType = this._getTableBatchType();
|
|
553
|
+
this.aggregator = new TableBatchType(this.schema, this.options);
|
|
554
|
+
}
|
|
555
|
+
this.aggregator.addObjectRow(row);
|
|
556
|
+
}
|
|
557
|
+
/** Mark an incoming raw memory chunk has completed */
|
|
558
|
+
chunkComplete(chunk) {
|
|
559
|
+
if (chunk instanceof ArrayBuffer) {
|
|
560
|
+
this.bytesUsed += chunk.byteLength;
|
|
561
|
+
}
|
|
562
|
+
if (typeof chunk === "string") {
|
|
563
|
+
this.bytesUsed += chunk.length;
|
|
564
|
+
}
|
|
565
|
+
this.isChunkComplete = true;
|
|
566
|
+
}
|
|
567
|
+
getFullBatch(options) {
|
|
568
|
+
return this._isFull() ? this._getBatch(options) : null;
|
|
569
|
+
}
|
|
570
|
+
getFinalBatch(options) {
|
|
571
|
+
return this._getBatch(options);
|
|
572
|
+
}
|
|
573
|
+
// INTERNAL
|
|
574
|
+
_estimateRowMB(row) {
|
|
575
|
+
return Array.isArray(row) ? row.length * 8 : Object.keys(row).length * 8;
|
|
576
|
+
}
|
|
577
|
+
_isFull() {
|
|
578
|
+
if (!this.aggregator || this.aggregator.rowCount() === 0) {
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
if (this.options.batchSize === "auto") {
|
|
582
|
+
if (!this.isChunkComplete) {
|
|
583
|
+
return false;
|
|
626
584
|
}
|
|
627
|
-
|
|
585
|
+
} else if (this.options.batchSize > this.aggregator.rowCount()) {
|
|
586
|
+
return false;
|
|
628
587
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
function zOrder(x, y, minX, minY, invSize) {
|
|
635
|
-
x = (x - minX) * invSize | 0;
|
|
636
|
-
y = (y - minY) * invSize | 0;
|
|
637
|
-
x = (x | x << 8) & 16711935;
|
|
638
|
-
x = (x | x << 4) & 252645135;
|
|
639
|
-
x = (x | x << 2) & 858993459;
|
|
640
|
-
x = (x | x << 1) & 1431655765;
|
|
641
|
-
y = (y | y << 8) & 16711935;
|
|
642
|
-
y = (y | y << 4) & 252645135;
|
|
643
|
-
y = (y | y << 2) & 858993459;
|
|
644
|
-
y = (y | y << 1) & 1431655765;
|
|
645
|
-
return x | y << 1;
|
|
646
|
-
}
|
|
647
|
-
function getLeftmost(start) {
|
|
648
|
-
let p = start;
|
|
649
|
-
let leftmost = start;
|
|
650
|
-
do {
|
|
651
|
-
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
|
|
652
|
-
leftmost = p;
|
|
653
|
-
p = p.next;
|
|
654
|
-
} while (p !== start);
|
|
655
|
-
return leftmost;
|
|
656
|
-
}
|
|
657
|
-
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
658
|
-
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
|
659
|
-
}
|
|
660
|
-
function isValidDiagonal(a, b) {
|
|
661
|
-
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);
|
|
662
|
-
}
|
|
663
|
-
function area(p, q, r) {
|
|
664
|
-
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
665
|
-
}
|
|
666
|
-
function equals(p1, p2) {
|
|
667
|
-
return p1.x === p2.x && p1.y === p2.y;
|
|
668
|
-
}
|
|
669
|
-
function intersects(p1, q1, p2, q2) {
|
|
670
|
-
const o1 = sign(area(p1, q1, p2));
|
|
671
|
-
const o2 = sign(area(p1, q1, q2));
|
|
672
|
-
const o3 = sign(area(p2, q2, p1));
|
|
673
|
-
const o4 = sign(area(p2, q2, q1));
|
|
674
|
-
if (o1 !== o2 && o3 !== o4)
|
|
675
|
-
return true;
|
|
676
|
-
if (o1 === 0 && onSegment(p1, p2, q1))
|
|
677
|
-
return true;
|
|
678
|
-
if (o2 === 0 && onSegment(p1, q2, q1))
|
|
679
|
-
return true;
|
|
680
|
-
if (o3 === 0 && onSegment(p2, p1, q2))
|
|
681
|
-
return true;
|
|
682
|
-
if (o4 === 0 && onSegment(p2, q1, q2))
|
|
588
|
+
if (this.options.batchDebounceMs > Date.now() - this.lastBatchEmittedMs) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
this.isChunkComplete = false;
|
|
592
|
+
this.lastBatchEmittedMs = Date.now();
|
|
683
593
|
return true;
|
|
684
|
-
return false;
|
|
685
|
-
}
|
|
686
|
-
function onSegment(p, q, r) {
|
|
687
|
-
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);
|
|
688
|
-
}
|
|
689
|
-
function sign(num) {
|
|
690
|
-
return num > 0 ? 1 : num < 0 ? -1 : 0;
|
|
691
|
-
}
|
|
692
|
-
function intersectsPolygon(a, b) {
|
|
693
|
-
let p = a;
|
|
694
|
-
do {
|
|
695
|
-
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))
|
|
696
|
-
return true;
|
|
697
|
-
p = p.next;
|
|
698
|
-
} while (p !== a);
|
|
699
|
-
return false;
|
|
700
|
-
}
|
|
701
|
-
function locallyInside(a, b) {
|
|
702
|
-
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;
|
|
703
|
-
}
|
|
704
|
-
function middleInside(a, b) {
|
|
705
|
-
let p = a;
|
|
706
|
-
let inside = false;
|
|
707
|
-
const px = (a.x + b.x) / 2;
|
|
708
|
-
const py = (a.y + b.y) / 2;
|
|
709
|
-
do {
|
|
710
|
-
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)
|
|
711
|
-
inside = !inside;
|
|
712
|
-
p = p.next;
|
|
713
|
-
} while (p !== a);
|
|
714
|
-
return inside;
|
|
715
|
-
}
|
|
716
|
-
function splitPolygon(a, b) {
|
|
717
|
-
const a2 = new Vertex(a.i, a.x, a.y);
|
|
718
|
-
const b2 = new Vertex(b.i, b.x, b.y);
|
|
719
|
-
const an = a.next;
|
|
720
|
-
const bp = b.prev;
|
|
721
|
-
a.next = b;
|
|
722
|
-
b.prev = a;
|
|
723
|
-
a2.next = an;
|
|
724
|
-
an.prev = a2;
|
|
725
|
-
b2.next = a2;
|
|
726
|
-
a2.prev = b2;
|
|
727
|
-
bp.next = b2;
|
|
728
|
-
b2.prev = bp;
|
|
729
|
-
return b2;
|
|
730
|
-
}
|
|
731
|
-
function insertNode(i, x, y, last) {
|
|
732
|
-
const p = new Vertex(i, x, y);
|
|
733
|
-
if (!last) {
|
|
734
|
-
p.prev = p;
|
|
735
|
-
p.next = p;
|
|
736
|
-
} else {
|
|
737
|
-
p.next = last.next;
|
|
738
|
-
p.prev = last;
|
|
739
|
-
last.next.prev = p;
|
|
740
|
-
last.next = p;
|
|
741
594
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
595
|
+
/**
|
|
596
|
+
* bytesUsed can be set via chunkComplete or via getBatch*
|
|
597
|
+
*/
|
|
598
|
+
_getBatch(options) {
|
|
599
|
+
if (!this.aggregator) {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
if (options?.bytesUsed) {
|
|
603
|
+
this.bytesUsed = options.bytesUsed;
|
|
604
|
+
}
|
|
605
|
+
const normalizedBatch = this.aggregator.getBatch();
|
|
606
|
+
normalizedBatch.count = this.batchCount;
|
|
607
|
+
normalizedBatch.bytesUsed = this.bytesUsed;
|
|
608
|
+
Object.assign(normalizedBatch, options);
|
|
609
|
+
this.batchCount++;
|
|
610
|
+
this.aggregator = null;
|
|
611
|
+
return normalizedBatch;
|
|
612
|
+
}
|
|
613
|
+
_getTableBatchType() {
|
|
614
|
+
switch (this.options.shape) {
|
|
615
|
+
case "row-table":
|
|
616
|
+
return BaseTableBatchAggregator;
|
|
617
|
+
case "array-row-table":
|
|
618
|
+
case "object-row-table":
|
|
619
|
+
return RowTableBatchAggregator;
|
|
620
|
+
case "columnar-table":
|
|
621
|
+
return ColumnarTableBatchAggregator;
|
|
622
|
+
case "arrow-table":
|
|
623
|
+
if (!TableBatchBuilder.ArrowBatch) {
|
|
624
|
+
throw new Error(ERR_MESSAGE);
|
|
625
|
+
}
|
|
626
|
+
return TableBatchBuilder.ArrowBatch;
|
|
627
|
+
default:
|
|
628
|
+
throw new Error(ERR_MESSAGE);
|
|
629
|
+
}
|
|
766
630
|
}
|
|
767
631
|
};
|
|
768
632
|
|
|
769
|
-
//
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
633
|
+
// ../../node_modules/@math.gl/polygon/dist/polygon-utils.js
|
|
634
|
+
var DimIndex = {
|
|
635
|
+
x: 0,
|
|
636
|
+
y: 1,
|
|
637
|
+
z: 2
|
|
638
|
+
};
|
|
639
|
+
function getPolygonSignedArea(points, options = {}) {
|
|
640
|
+
const {
|
|
641
|
+
start = 0,
|
|
642
|
+
end = points.length,
|
|
643
|
+
plane = "xy"
|
|
644
|
+
} = options;
|
|
645
|
+
const dim = options.size || 2;
|
|
646
|
+
let area2 = 0;
|
|
647
|
+
const i0 = DimIndex[plane[0]];
|
|
648
|
+
const i1 = DimIndex[plane[1]];
|
|
649
|
+
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
650
|
+
area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
|
|
651
|
+
j = i;
|
|
652
|
+
}
|
|
653
|
+
return area2 / 2;
|
|
785
654
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
655
|
+
|
|
656
|
+
// ../../node_modules/@math.gl/polygon/dist/earcut.js
|
|
657
|
+
function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
|
|
658
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
659
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
|
|
660
|
+
let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
|
|
661
|
+
const triangles = [];
|
|
662
|
+
if (!outerNode || outerNode.next === outerNode.prev)
|
|
663
|
+
return triangles;
|
|
664
|
+
let invSize;
|
|
665
|
+
let maxX;
|
|
666
|
+
let maxY;
|
|
667
|
+
let minX;
|
|
668
|
+
let minY;
|
|
669
|
+
let x;
|
|
670
|
+
let y;
|
|
671
|
+
if (hasHoles)
|
|
672
|
+
outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
|
|
673
|
+
if (positions.length > 80 * dim) {
|
|
674
|
+
minX = maxX = positions[0];
|
|
675
|
+
minY = maxY = positions[1];
|
|
676
|
+
for (let i = dim; i < outerLen; i += dim) {
|
|
677
|
+
x = positions[i];
|
|
678
|
+
y = positions[i + 1];
|
|
679
|
+
if (x < minX)
|
|
680
|
+
minX = x;
|
|
681
|
+
if (y < minY)
|
|
682
|
+
minY = y;
|
|
683
|
+
if (x > maxX)
|
|
684
|
+
maxX = x;
|
|
685
|
+
if (y > maxY)
|
|
686
|
+
maxY = y;
|
|
794
687
|
}
|
|
688
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
689
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
|
795
690
|
}
|
|
796
|
-
|
|
691
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
|
692
|
+
return triangles;
|
|
797
693
|
}
|
|
798
|
-
function
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
positions: new PositionDataType(pointPositionsCount * coordLength),
|
|
818
|
-
globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
|
|
819
|
-
featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
|
|
820
|
-
numericProps: {},
|
|
821
|
-
properties: [],
|
|
822
|
-
fields: []
|
|
823
|
-
};
|
|
824
|
-
const lines = {
|
|
825
|
-
type: "LineString",
|
|
826
|
-
pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
|
|
827
|
-
positions: new PositionDataType(linePositionsCount * coordLength),
|
|
828
|
-
globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
|
|
829
|
-
featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
|
|
830
|
-
numericProps: {},
|
|
831
|
-
properties: [],
|
|
832
|
-
fields: []
|
|
833
|
-
};
|
|
834
|
-
const polygons = {
|
|
835
|
-
type: "Polygon",
|
|
836
|
-
polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
|
|
837
|
-
primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
|
|
838
|
-
positions: new PositionDataType(polygonPositionsCount * coordLength),
|
|
839
|
-
globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
|
|
840
|
-
featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
|
|
841
|
-
numericProps: {},
|
|
842
|
-
properties: [],
|
|
843
|
-
fields: []
|
|
844
|
-
};
|
|
845
|
-
if (triangulate) {
|
|
846
|
-
polygons.triangles = [];
|
|
694
|
+
function linkedList(data, start, end, dim, clockwise, area2, plane) {
|
|
695
|
+
let i;
|
|
696
|
+
let last;
|
|
697
|
+
if (area2 === void 0) {
|
|
698
|
+
area2 = getPolygonSignedArea(data, {
|
|
699
|
+
start,
|
|
700
|
+
end,
|
|
701
|
+
size: dim,
|
|
702
|
+
plane
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
let i0 = DimIndex[plane[0]];
|
|
706
|
+
let i1 = DimIndex[plane[1]];
|
|
707
|
+
if (clockwise === area2 < 0) {
|
|
708
|
+
for (i = start; i < end; i += dim)
|
|
709
|
+
last = insertNode(i, data[i + i0], data[i + i1], last);
|
|
710
|
+
} else {
|
|
711
|
+
for (i = end - dim; i >= start; i -= dim)
|
|
712
|
+
last = insertNode(i, data[i + i0], data[i + i1], last);
|
|
847
713
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
object.numericProps[propName] = new T(object.positions.length / coordLength);
|
|
852
|
-
}
|
|
714
|
+
if (last && equals(last, last.next)) {
|
|
715
|
+
removeNode(last);
|
|
716
|
+
last = last.next;
|
|
853
717
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
for (const feature of features) {
|
|
870
|
-
const geometry = feature.geometry;
|
|
871
|
-
const properties = feature.properties || {};
|
|
872
|
-
switch (geometry.type) {
|
|
873
|
-
case "Point":
|
|
874
|
-
handlePoint(geometry, points, indexMap, coordLength, properties);
|
|
875
|
-
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
876
|
-
if (hasGlobalId) {
|
|
877
|
-
points.fields.push({ id: feature.id });
|
|
878
|
-
}
|
|
879
|
-
indexMap.pointFeature++;
|
|
880
|
-
break;
|
|
881
|
-
case "LineString":
|
|
882
|
-
handleLineString(geometry, lines, indexMap, coordLength, properties);
|
|
883
|
-
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
884
|
-
if (hasGlobalId) {
|
|
885
|
-
lines.fields.push({ id: feature.id });
|
|
886
|
-
}
|
|
887
|
-
indexMap.lineFeature++;
|
|
888
|
-
break;
|
|
889
|
-
case "Polygon":
|
|
890
|
-
handlePolygon(geometry, polygons, indexMap, coordLength, properties);
|
|
891
|
-
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
892
|
-
if (hasGlobalId) {
|
|
893
|
-
polygons.fields.push({ id: feature.id });
|
|
894
|
-
}
|
|
895
|
-
indexMap.polygonFeature++;
|
|
718
|
+
return last;
|
|
719
|
+
}
|
|
720
|
+
function filterPoints(start, end) {
|
|
721
|
+
if (!start)
|
|
722
|
+
return start;
|
|
723
|
+
if (!end)
|
|
724
|
+
end = start;
|
|
725
|
+
let p = start;
|
|
726
|
+
let again;
|
|
727
|
+
do {
|
|
728
|
+
again = false;
|
|
729
|
+
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
730
|
+
removeNode(p);
|
|
731
|
+
p = end = p.prev;
|
|
732
|
+
if (p === p.next)
|
|
896
733
|
break;
|
|
897
|
-
|
|
898
|
-
|
|
734
|
+
again = true;
|
|
735
|
+
} else {
|
|
736
|
+
p = p.next;
|
|
737
|
+
}
|
|
738
|
+
} while (again || p !== end);
|
|
739
|
+
return end;
|
|
740
|
+
}
|
|
741
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
742
|
+
if (!ear)
|
|
743
|
+
return;
|
|
744
|
+
if (!pass && invSize)
|
|
745
|
+
indexCurve(ear, minX, minY, invSize);
|
|
746
|
+
let stop = ear;
|
|
747
|
+
let prev;
|
|
748
|
+
let next;
|
|
749
|
+
while (ear.prev !== ear.next) {
|
|
750
|
+
prev = ear.prev;
|
|
751
|
+
next = ear.next;
|
|
752
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
753
|
+
triangles.push(prev.i / dim | 0);
|
|
754
|
+
triangles.push(ear.i / dim | 0);
|
|
755
|
+
triangles.push(next.i / dim | 0);
|
|
756
|
+
removeNode(ear);
|
|
757
|
+
ear = next.next;
|
|
758
|
+
stop = next.next;
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
761
|
+
ear = next;
|
|
762
|
+
if (ear === stop) {
|
|
763
|
+
if (!pass) {
|
|
764
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
765
|
+
} else if (pass === 1) {
|
|
766
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
767
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
768
|
+
} else if (pass === 2) {
|
|
769
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
770
|
+
}
|
|
771
|
+
break;
|
|
899
772
|
}
|
|
900
|
-
indexMap.feature++;
|
|
901
773
|
}
|
|
902
|
-
return makeAccessorObjects(points, lines, polygons, coordLength);
|
|
903
774
|
}
|
|
904
|
-
function
|
|
905
|
-
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
775
|
+
function isEar(ear) {
|
|
776
|
+
const a = ear.prev;
|
|
777
|
+
const b = ear;
|
|
778
|
+
const c = ear.next;
|
|
779
|
+
if (area(a, b, c) >= 0)
|
|
780
|
+
return false;
|
|
781
|
+
const ax = a.x;
|
|
782
|
+
const bx = b.x;
|
|
783
|
+
const cx = c.x;
|
|
784
|
+
const ay = a.y;
|
|
785
|
+
const by = b.y;
|
|
786
|
+
const cy = c.y;
|
|
787
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
|
|
788
|
+
const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
|
|
789
|
+
const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
|
|
790
|
+
const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
791
|
+
let p = c.next;
|
|
792
|
+
while (p !== a) {
|
|
793
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
794
|
+
return false;
|
|
795
|
+
p = p.next;
|
|
796
|
+
}
|
|
797
|
+
return true;
|
|
919
798
|
}
|
|
920
|
-
function
|
|
921
|
-
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
799
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
800
|
+
const a = ear.prev;
|
|
801
|
+
const b = ear;
|
|
802
|
+
const c = ear.next;
|
|
803
|
+
if (area(a, b, c) >= 0)
|
|
804
|
+
return false;
|
|
805
|
+
const ax = a.x;
|
|
806
|
+
const bx = b.x;
|
|
807
|
+
const cx = c.x;
|
|
808
|
+
const ay = a.y;
|
|
809
|
+
const by = b.y;
|
|
810
|
+
const cy = c.y;
|
|
811
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
|
|
812
|
+
const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
|
|
813
|
+
const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
|
|
814
|
+
const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
815
|
+
const minZ = zOrder(x0, y0, minX, minY, invSize);
|
|
816
|
+
const maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
817
|
+
let p = ear.prevZ;
|
|
818
|
+
let n = ear.nextZ;
|
|
819
|
+
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
820
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
821
|
+
return false;
|
|
822
|
+
p = p.prevZ;
|
|
823
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
824
|
+
return false;
|
|
825
|
+
n = n.nextZ;
|
|
826
|
+
}
|
|
827
|
+
while (p && p.z >= minZ) {
|
|
828
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
829
|
+
return false;
|
|
830
|
+
p = p.prevZ;
|
|
831
|
+
}
|
|
832
|
+
while (n && n.z <= maxZ) {
|
|
833
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
834
|
+
return false;
|
|
835
|
+
n = n.nextZ;
|
|
939
836
|
}
|
|
837
|
+
return true;
|
|
940
838
|
}
|
|
941
|
-
function
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
839
|
+
function cureLocalIntersections(start, triangles, dim) {
|
|
840
|
+
let p = start;
|
|
841
|
+
do {
|
|
842
|
+
const a = p.prev;
|
|
843
|
+
const b = p.next.next;
|
|
844
|
+
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
845
|
+
triangles.push(a.i / dim | 0);
|
|
846
|
+
triangles.push(p.i / dim | 0);
|
|
847
|
+
triangles.push(b.i / dim | 0);
|
|
848
|
+
removeNode(p);
|
|
849
|
+
removeNode(p.next);
|
|
850
|
+
p = start = b;
|
|
851
|
+
}
|
|
852
|
+
p = p.next;
|
|
853
|
+
} while (p !== start);
|
|
854
|
+
return filterPoints(p);
|
|
855
|
+
}
|
|
856
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
857
|
+
let a = start;
|
|
858
|
+
do {
|
|
859
|
+
let b = a.next.next;
|
|
860
|
+
while (b !== a.prev) {
|
|
861
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
862
|
+
let c = splitPolygon(a, b);
|
|
863
|
+
a = filterPoints(a, a.next);
|
|
864
|
+
c = filterPoints(c, c.next);
|
|
865
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
866
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
b = b.next;
|
|
969
870
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
}
|
|
871
|
+
a = a.next;
|
|
872
|
+
} while (a !== start);
|
|
973
873
|
}
|
|
974
|
-
function
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
874
|
+
function eliminateHoles(data, holeIndices, outerNode, dim, areas, plane) {
|
|
875
|
+
const queue = [];
|
|
876
|
+
let i;
|
|
877
|
+
let len;
|
|
878
|
+
let start;
|
|
879
|
+
let end;
|
|
880
|
+
let list;
|
|
881
|
+
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
882
|
+
start = holeIndices[i] * dim;
|
|
883
|
+
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
884
|
+
list = linkedList(data, start, end, dim, false, areas && areas[i + 1], plane);
|
|
885
|
+
if (list === list.next)
|
|
886
|
+
list.steiner = true;
|
|
887
|
+
queue.push(getLeftmost(list));
|
|
981
888
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
const offset = indices[0];
|
|
986
|
-
const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
|
|
987
|
-
const triangles = earcut(polygonPositions, holes, coordLength, areas);
|
|
988
|
-
for (let t = 0, tl = triangles.length; t < tl; ++t) {
|
|
989
|
-
polygons.triangles.push(startPosition + triangles[t]);
|
|
889
|
+
queue.sort(compareX);
|
|
890
|
+
for (i = 0; i < queue.length; i++) {
|
|
891
|
+
outerNode = eliminateHole(queue[i], outerNode);
|
|
990
892
|
}
|
|
893
|
+
return outerNode;
|
|
991
894
|
}
|
|
992
|
-
function
|
|
993
|
-
|
|
994
|
-
for (const key in obj) {
|
|
995
|
-
returnObj[key] = { value: obj[key], size };
|
|
996
|
-
}
|
|
997
|
-
return returnObj;
|
|
895
|
+
function compareX(a, b) {
|
|
896
|
+
return a.x - b.x;
|
|
998
897
|
}
|
|
999
|
-
function
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
...points,
|
|
1004
|
-
positions: { value: points.positions, size: coordLength },
|
|
1005
|
-
globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
|
|
1006
|
-
featureIds: { value: points.featureIds, size: 1 },
|
|
1007
|
-
numericProps: wrapProps(points.numericProps, 1)
|
|
1008
|
-
},
|
|
1009
|
-
lines: {
|
|
1010
|
-
...lines,
|
|
1011
|
-
positions: { value: lines.positions, size: coordLength },
|
|
1012
|
-
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
1013
|
-
globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
|
|
1014
|
-
featureIds: { value: lines.featureIds, size: 1 },
|
|
1015
|
-
numericProps: wrapProps(lines.numericProps, 1)
|
|
1016
|
-
},
|
|
1017
|
-
polygons: {
|
|
1018
|
-
...polygons,
|
|
1019
|
-
positions: { value: polygons.positions, size: coordLength },
|
|
1020
|
-
polygonIndices: { value: polygons.polygonIndices, size: 1 },
|
|
1021
|
-
primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
|
|
1022
|
-
globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
|
|
1023
|
-
featureIds: { value: polygons.featureIds, size: 1 },
|
|
1024
|
-
numericProps: wrapProps(polygons.numericProps, 1)
|
|
1025
|
-
}
|
|
1026
|
-
// triangles not expected
|
|
1027
|
-
};
|
|
1028
|
-
if (binaryFeatures.polygons && polygons.triangles) {
|
|
1029
|
-
binaryFeatures.polygons.triangles = { value: new Uint32Array(polygons.triangles), size: 1 };
|
|
898
|
+
function eliminateHole(hole, outerNode) {
|
|
899
|
+
const bridge = findHoleBridge(hole, outerNode);
|
|
900
|
+
if (!bridge) {
|
|
901
|
+
return outerNode;
|
|
1030
902
|
}
|
|
1031
|
-
|
|
903
|
+
const bridgeReverse = splitPolygon(bridge, hole);
|
|
904
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
|
905
|
+
return filterPoints(bridge, bridge.next);
|
|
1032
906
|
}
|
|
1033
|
-
function
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
907
|
+
function findHoleBridge(hole, outerNode) {
|
|
908
|
+
let p = outerNode;
|
|
909
|
+
const hx = hole.x;
|
|
910
|
+
const hy = hole.y;
|
|
911
|
+
let qx = -Infinity;
|
|
912
|
+
let m;
|
|
913
|
+
do {
|
|
914
|
+
if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
|
|
915
|
+
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
|
|
916
|
+
if (x <= hx && x > qx) {
|
|
917
|
+
qx = x;
|
|
918
|
+
m = p.x < p.next.x ? p : p.next;
|
|
919
|
+
if (x === hx)
|
|
920
|
+
return m;
|
|
921
|
+
}
|
|
1038
922
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
923
|
+
p = p.next;
|
|
924
|
+
} while (p !== outerNode);
|
|
925
|
+
if (!m)
|
|
926
|
+
return null;
|
|
927
|
+
const stop = m;
|
|
928
|
+
const mx = m.x;
|
|
929
|
+
const my = m.y;
|
|
930
|
+
let tanMin = Infinity;
|
|
931
|
+
let tan;
|
|
932
|
+
p = m;
|
|
933
|
+
do {
|
|
934
|
+
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)) {
|
|
935
|
+
tan = Math.abs(hy - p.y) / (hx - p.x);
|
|
936
|
+
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
|
|
937
|
+
m = p;
|
|
938
|
+
tanMin = tan;
|
|
939
|
+
}
|
|
1046
940
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
941
|
+
p = p.next;
|
|
942
|
+
} while (p !== stop);
|
|
943
|
+
return m;
|
|
1049
944
|
}
|
|
1050
|
-
function
|
|
1051
|
-
|
|
1052
|
-
return Array;
|
|
1053
|
-
}
|
|
1054
|
-
return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
|
|
945
|
+
function sectorContainsSector(m, p) {
|
|
946
|
+
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
1055
947
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
polygonObjectsCount++;
|
|
1105
|
-
polygonRingsCount += geometry.coordinates.length;
|
|
1106
|
-
const flattened = geometry.coordinates.flat();
|
|
1107
|
-
polygonPositionsCount += flattened.length;
|
|
1108
|
-
for (const coord of flattened) {
|
|
1109
|
-
coordLengths.add(coord.length);
|
|
1110
|
-
}
|
|
1111
|
-
break;
|
|
1112
|
-
case "MultiPolygon":
|
|
1113
|
-
polygonFeaturesCount++;
|
|
1114
|
-
for (const polygon of geometry.coordinates) {
|
|
1115
|
-
polygonObjectsCount++;
|
|
1116
|
-
polygonRingsCount += polygon.length;
|
|
1117
|
-
const flattened2 = polygon.flat();
|
|
1118
|
-
polygonPositionsCount += flattened2.length;
|
|
1119
|
-
for (const coord of flattened2) {
|
|
1120
|
-
coordLengths.add(coord.length);
|
|
1121
|
-
}
|
|
948
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
949
|
+
let p = start;
|
|
950
|
+
do {
|
|
951
|
+
if (p.z === 0)
|
|
952
|
+
p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
953
|
+
p.prevZ = p.prev;
|
|
954
|
+
p.nextZ = p.next;
|
|
955
|
+
p = p.next;
|
|
956
|
+
} while (p !== start);
|
|
957
|
+
p.prevZ.nextZ = null;
|
|
958
|
+
p.prevZ = null;
|
|
959
|
+
sortLinked(p);
|
|
960
|
+
}
|
|
961
|
+
function sortLinked(list) {
|
|
962
|
+
let e;
|
|
963
|
+
let i;
|
|
964
|
+
let inSize = 1;
|
|
965
|
+
let numMerges;
|
|
966
|
+
let p;
|
|
967
|
+
let pSize;
|
|
968
|
+
let q;
|
|
969
|
+
let qSize;
|
|
970
|
+
let tail;
|
|
971
|
+
do {
|
|
972
|
+
p = list;
|
|
973
|
+
list = null;
|
|
974
|
+
tail = null;
|
|
975
|
+
numMerges = 0;
|
|
976
|
+
while (p) {
|
|
977
|
+
numMerges++;
|
|
978
|
+
q = p;
|
|
979
|
+
pSize = 0;
|
|
980
|
+
for (i = 0; i < inSize; i++) {
|
|
981
|
+
pSize++;
|
|
982
|
+
q = q.nextZ;
|
|
983
|
+
if (!q)
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
qSize = inSize;
|
|
987
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
988
|
+
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
|
|
989
|
+
e = p;
|
|
990
|
+
p = p.nextZ;
|
|
991
|
+
pSize--;
|
|
992
|
+
} else {
|
|
993
|
+
e = q;
|
|
994
|
+
q = q.nextZ;
|
|
995
|
+
qSize--;
|
|
1122
996
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
997
|
+
if (tail)
|
|
998
|
+
tail.nextZ = e;
|
|
999
|
+
else
|
|
1000
|
+
list = e;
|
|
1001
|
+
e.prevZ = tail;
|
|
1002
|
+
tail = e;
|
|
1003
|
+
}
|
|
1004
|
+
p = q;
|
|
1126
1005
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
pointFeaturesCount,
|
|
1132
|
-
linePositionsCount,
|
|
1133
|
-
linePathsCount,
|
|
1134
|
-
lineFeaturesCount,
|
|
1135
|
-
polygonPositionsCount,
|
|
1136
|
-
polygonObjectsCount,
|
|
1137
|
-
polygonRingsCount,
|
|
1138
|
-
polygonFeaturesCount
|
|
1139
|
-
};
|
|
1006
|
+
tail.nextZ = null;
|
|
1007
|
+
inSize *= 2;
|
|
1008
|
+
} while (numMerges > 1);
|
|
1009
|
+
return list;
|
|
1140
1010
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1011
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
1012
|
+
x = (x - minX) * invSize | 0;
|
|
1013
|
+
y = (y - minY) * invSize | 0;
|
|
1014
|
+
x = (x | x << 8) & 16711935;
|
|
1015
|
+
x = (x | x << 4) & 252645135;
|
|
1016
|
+
x = (x | x << 2) & 858993459;
|
|
1017
|
+
x = (x | x << 1) & 1431655765;
|
|
1018
|
+
y = (y | y << 8) & 16711935;
|
|
1019
|
+
y = (y | y << 4) & 252645135;
|
|
1020
|
+
y = (y | y << 2) & 858993459;
|
|
1021
|
+
y = (y | y << 1) & 1431655765;
|
|
1022
|
+
return x | y << 1;
|
|
1145
1023
|
}
|
|
1146
|
-
function
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1024
|
+
function getLeftmost(start) {
|
|
1025
|
+
let p = start;
|
|
1026
|
+
let leftmost = start;
|
|
1027
|
+
do {
|
|
1028
|
+
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
|
|
1029
|
+
leftmost = p;
|
|
1030
|
+
p = p.next;
|
|
1031
|
+
} while (p !== start);
|
|
1032
|
+
return leftmost;
|
|
1152
1033
|
}
|
|
1153
|
-
function
|
|
1154
|
-
|
|
1155
|
-
for (const c of coordinates) {
|
|
1156
|
-
data.push(...c);
|
|
1157
|
-
for (let i = c.length; i < options.coordLength; i++) {
|
|
1158
|
-
data.push(0);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1034
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
1035
|
+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
|
1161
1036
|
}
|
|
1162
|
-
function
|
|
1163
|
-
|
|
1164
|
-
const ringAreas = [];
|
|
1165
|
-
const polygons = [];
|
|
1166
|
-
for (const lineString of coordinates) {
|
|
1167
|
-
const lineString2d = lineString.map((p) => p.slice(0, 2));
|
|
1168
|
-
let area2 = getPolygonSignedArea(lineString2d.flat());
|
|
1169
|
-
const ccw = area2 < 0;
|
|
1170
|
-
if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
|
|
1171
|
-
lineString.reverse();
|
|
1172
|
-
area2 = -area2;
|
|
1173
|
-
}
|
|
1174
|
-
ringAreas.push(area2);
|
|
1175
|
-
flattenLineString(lineString, data, polygons, options);
|
|
1176
|
-
count++;
|
|
1177
|
-
}
|
|
1178
|
-
if (count > 0) {
|
|
1179
|
-
areas.push(ringAreas);
|
|
1180
|
-
indices.push(polygons);
|
|
1181
|
-
}
|
|
1037
|
+
function isValidDiagonal(a, b) {
|
|
1038
|
+
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);
|
|
1182
1039
|
}
|
|
1183
|
-
function
|
|
1184
|
-
|
|
1185
|
-
if (geometry.type === "GeometryCollection") {
|
|
1186
|
-
throw new Error("GeometryCollection type not supported");
|
|
1187
|
-
}
|
|
1188
|
-
const data = [];
|
|
1189
|
-
const indices = [];
|
|
1190
|
-
let areas;
|
|
1191
|
-
let type;
|
|
1192
|
-
switch (geometry.type) {
|
|
1193
|
-
case "Point":
|
|
1194
|
-
type = "Point";
|
|
1195
|
-
flattenPoint(geometry.coordinates, data, indices, options);
|
|
1196
|
-
break;
|
|
1197
|
-
case "MultiPoint":
|
|
1198
|
-
type = "Point";
|
|
1199
|
-
geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
|
|
1200
|
-
break;
|
|
1201
|
-
case "LineString":
|
|
1202
|
-
type = "LineString";
|
|
1203
|
-
flattenLineString(geometry.coordinates, data, indices, options);
|
|
1204
|
-
break;
|
|
1205
|
-
case "MultiLineString":
|
|
1206
|
-
type = "LineString";
|
|
1207
|
-
geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
|
|
1208
|
-
break;
|
|
1209
|
-
case "Polygon":
|
|
1210
|
-
type = "Polygon";
|
|
1211
|
-
areas = [];
|
|
1212
|
-
flattenPolygon(geometry.coordinates, data, indices, areas, options);
|
|
1213
|
-
break;
|
|
1214
|
-
case "MultiPolygon":
|
|
1215
|
-
type = "Polygon";
|
|
1216
|
-
areas = [];
|
|
1217
|
-
geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
|
|
1218
|
-
break;
|
|
1219
|
-
default:
|
|
1220
|
-
throw new Error(`Unknown type: ${type}`);
|
|
1221
|
-
}
|
|
1222
|
-
return { ...feature, geometry: { type, indices, data, areas } };
|
|
1040
|
+
function area(p, q, r) {
|
|
1041
|
+
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
1223
1042
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
function geojsonToBinary(features, options = { fixRingWinding: true, triangulate: true }) {
|
|
1227
|
-
const geometryInfo = extractGeometryInfo(features);
|
|
1228
|
-
const coordLength = geometryInfo.coordLength;
|
|
1229
|
-
const { fixRingWinding } = options;
|
|
1230
|
-
const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
|
|
1231
|
-
return flatGeojsonToBinary(flatFeatures, geometryInfo, {
|
|
1232
|
-
numericPropKeys: options.numericPropKeys,
|
|
1233
|
-
PositionDataType: options.PositionDataType || Float32Array,
|
|
1234
|
-
triangulate: options.triangulate
|
|
1235
|
-
});
|
|
1043
|
+
function equals(p1, p2) {
|
|
1044
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
1236
1045
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
this.rows[this.length] = row;
|
|
1272
|
-
this.length++;
|
|
1273
|
-
}
|
|
1274
|
-
getBatch() {
|
|
1275
|
-
let rows = this.rows;
|
|
1276
|
-
if (!rows) {
|
|
1277
|
-
return null;
|
|
1278
|
-
}
|
|
1279
|
-
rows = rows.slice(0, this.length);
|
|
1280
|
-
this.rows = null;
|
|
1281
|
-
const batch = {
|
|
1282
|
-
shape: this.options.shape,
|
|
1283
|
-
batchType: "data",
|
|
1284
|
-
data: rows,
|
|
1285
|
-
length: this.length,
|
|
1286
|
-
schema: this.schema,
|
|
1287
|
-
cursor: this.cursor
|
|
1288
|
-
};
|
|
1289
|
-
return batch;
|
|
1290
|
-
}
|
|
1291
|
-
};
|
|
1292
|
-
|
|
1293
|
-
// ../schema/src/lib/table/simple-table/row-utils.ts
|
|
1294
|
-
function convertToObjectRow(arrayRow, headers) {
|
|
1295
|
-
if (!arrayRow) {
|
|
1296
|
-
throw new Error("null row");
|
|
1297
|
-
}
|
|
1298
|
-
if (!headers) {
|
|
1299
|
-
throw new Error("no headers");
|
|
1300
|
-
}
|
|
1301
|
-
const objectRow = {};
|
|
1302
|
-
for (let i = 0; i < headers.length; i++) {
|
|
1303
|
-
objectRow[headers[i]] = arrayRow[i];
|
|
1304
|
-
}
|
|
1305
|
-
return objectRow;
|
|
1046
|
+
function intersects(p1, q1, p2, q2) {
|
|
1047
|
+
const o1 = sign(area(p1, q1, p2));
|
|
1048
|
+
const o2 = sign(area(p1, q1, q2));
|
|
1049
|
+
const o3 = sign(area(p2, q2, p1));
|
|
1050
|
+
const o4 = sign(area(p2, q2, q1));
|
|
1051
|
+
if (o1 !== o2 && o3 !== o4)
|
|
1052
|
+
return true;
|
|
1053
|
+
if (o1 === 0 && onSegment(p1, p2, q1))
|
|
1054
|
+
return true;
|
|
1055
|
+
if (o2 === 0 && onSegment(p1, q2, q1))
|
|
1056
|
+
return true;
|
|
1057
|
+
if (o3 === 0 && onSegment(p2, p1, q2))
|
|
1058
|
+
return true;
|
|
1059
|
+
if (o4 === 0 && onSegment(p2, q1, q2))
|
|
1060
|
+
return true;
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
function onSegment(p, q, r) {
|
|
1064
|
+
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);
|
|
1065
|
+
}
|
|
1066
|
+
function sign(num) {
|
|
1067
|
+
return num > 0 ? 1 : num < 0 ? -1 : 0;
|
|
1068
|
+
}
|
|
1069
|
+
function intersectsPolygon(a, b) {
|
|
1070
|
+
let p = a;
|
|
1071
|
+
do {
|
|
1072
|
+
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))
|
|
1073
|
+
return true;
|
|
1074
|
+
p = p.next;
|
|
1075
|
+
} while (p !== a);
|
|
1076
|
+
return false;
|
|
1077
|
+
}
|
|
1078
|
+
function locallyInside(a, b) {
|
|
1079
|
+
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;
|
|
1306
1080
|
}
|
|
1307
|
-
function
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
return arrayRow;
|
|
1081
|
+
function middleInside(a, b) {
|
|
1082
|
+
let p = a;
|
|
1083
|
+
let inside = false;
|
|
1084
|
+
const px = (a.x + b.x) / 2;
|
|
1085
|
+
const py = (a.y + b.y) / 2;
|
|
1086
|
+
do {
|
|
1087
|
+
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)
|
|
1088
|
+
inside = !inside;
|
|
1089
|
+
p = p.next;
|
|
1090
|
+
} while (p !== a);
|
|
1091
|
+
return inside;
|
|
1319
1092
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
}
|
|
1346
|
-
switch (this.options.shape) {
|
|
1347
|
-
case "object-row-table":
|
|
1348
|
-
const rowObject = convertToObjectRow(row, this._headers);
|
|
1349
|
-
this.addObjectRow(rowObject, cursor);
|
|
1350
|
-
break;
|
|
1351
|
-
case "array-row-table":
|
|
1352
|
-
this.arrayRows = this.arrayRows || new Array(DEFAULT_ROW_COUNT2);
|
|
1353
|
-
this.arrayRows[this.length] = row;
|
|
1354
|
-
this.length++;
|
|
1355
|
-
break;
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
addObjectRow(row, cursor) {
|
|
1359
|
-
if (Number.isFinite(cursor)) {
|
|
1360
|
-
this.cursor = cursor;
|
|
1361
|
-
}
|
|
1362
|
-
switch (this.options.shape) {
|
|
1363
|
-
case "array-row-table":
|
|
1364
|
-
const rowArray = convertToArrayRow(row, this._headers);
|
|
1365
|
-
this.addArrayRow(rowArray, cursor);
|
|
1366
|
-
break;
|
|
1367
|
-
case "object-row-table":
|
|
1368
|
-
this.objectRows = this.objectRows || new Array(DEFAULT_ROW_COUNT2);
|
|
1369
|
-
this.objectRows[this.length] = row;
|
|
1370
|
-
this.length++;
|
|
1371
|
-
break;
|
|
1372
|
-
}
|
|
1093
|
+
function splitPolygon(a, b) {
|
|
1094
|
+
const a2 = new Vertex(a.i, a.x, a.y);
|
|
1095
|
+
const b2 = new Vertex(b.i, b.x, b.y);
|
|
1096
|
+
const an = a.next;
|
|
1097
|
+
const bp = b.prev;
|
|
1098
|
+
a.next = b;
|
|
1099
|
+
b.prev = a;
|
|
1100
|
+
a2.next = an;
|
|
1101
|
+
an.prev = a2;
|
|
1102
|
+
b2.next = a2;
|
|
1103
|
+
a2.prev = b2;
|
|
1104
|
+
bp.next = b2;
|
|
1105
|
+
b2.prev = bp;
|
|
1106
|
+
return b2;
|
|
1107
|
+
}
|
|
1108
|
+
function insertNode(i, x, y, last) {
|
|
1109
|
+
const p = new Vertex(i, x, y);
|
|
1110
|
+
if (!last) {
|
|
1111
|
+
p.prev = p;
|
|
1112
|
+
p.next = p;
|
|
1113
|
+
} else {
|
|
1114
|
+
p.next = last.next;
|
|
1115
|
+
p.prev = last;
|
|
1116
|
+
last.next.prev = p;
|
|
1117
|
+
last.next = p;
|
|
1373
1118
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1119
|
+
return p;
|
|
1120
|
+
}
|
|
1121
|
+
function removeNode(p) {
|
|
1122
|
+
p.next.prev = p.prev;
|
|
1123
|
+
p.prev.next = p.next;
|
|
1124
|
+
if (p.prevZ)
|
|
1125
|
+
p.prevZ.nextZ = p.nextZ;
|
|
1126
|
+
if (p.nextZ)
|
|
1127
|
+
p.nextZ.prevZ = p.prevZ;
|
|
1128
|
+
}
|
|
1129
|
+
var Vertex = class {
|
|
1130
|
+
constructor(i, x, y) {
|
|
1131
|
+
_defineProperty(this, "i", void 0);
|
|
1132
|
+
_defineProperty(this, "x", void 0);
|
|
1133
|
+
_defineProperty(this, "y", void 0);
|
|
1134
|
+
_defineProperty(this, "prev", null);
|
|
1135
|
+
_defineProperty(this, "next", null);
|
|
1136
|
+
_defineProperty(this, "z", 0);
|
|
1137
|
+
_defineProperty(this, "prevZ", null);
|
|
1138
|
+
_defineProperty(this, "nextZ", null);
|
|
1139
|
+
_defineProperty(this, "steiner", false);
|
|
1140
|
+
this.i = i;
|
|
1141
|
+
this.x = x;
|
|
1142
|
+
this.y = y;
|
|
1390
1143
|
}
|
|
1391
1144
|
};
|
|
1392
1145
|
|
|
1393
|
-
// ../
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
this._reallocateColumns();
|
|
1408
|
-
let i = 0;
|
|
1409
|
-
for (const fieldName in this.columns) {
|
|
1410
|
-
this.columns[fieldName][this.length] = row[i++];
|
|
1411
|
-
}
|
|
1412
|
-
this.length++;
|
|
1413
|
-
}
|
|
1414
|
-
addObjectRow(row) {
|
|
1415
|
-
this._reallocateColumns();
|
|
1416
|
-
for (const fieldName in row) {
|
|
1417
|
-
this.columns[fieldName][this.length] = row[fieldName];
|
|
1146
|
+
// ../gis/src/lib/binary-features/flat-geojson-to-binary.ts
|
|
1147
|
+
function flatGeojsonToBinary(features, geometryInfo, options) {
|
|
1148
|
+
const propArrayTypes = extractNumericPropTypes(features);
|
|
1149
|
+
const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
|
|
1150
|
+
return fillArrays(
|
|
1151
|
+
features,
|
|
1152
|
+
{
|
|
1153
|
+
propArrayTypes,
|
|
1154
|
+
...geometryInfo
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
numericPropKeys: options && options.numericPropKeys || numericPropKeys,
|
|
1158
|
+
PositionDataType: options ? options.PositionDataType : Float32Array,
|
|
1159
|
+
triangulate: options ? options.triangulate : true
|
|
1418
1160
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
if (
|
|
1425
|
-
for (const
|
|
1426
|
-
const
|
|
1427
|
-
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
function extractNumericPropTypes(features) {
|
|
1164
|
+
const propArrayTypes = {};
|
|
1165
|
+
for (const feature of features) {
|
|
1166
|
+
if (feature.properties) {
|
|
1167
|
+
for (const key in feature.properties) {
|
|
1168
|
+
const val = feature.properties[key];
|
|
1169
|
+
propArrayTypes[key] = deduceArrayType(val, propArrayTypes[key]);
|
|
1428
1170
|
}
|
|
1429
1171
|
}
|
|
1430
|
-
this.columns = {};
|
|
1431
|
-
const batch = {
|
|
1432
|
-
shape: "columnar-table",
|
|
1433
|
-
batchType: "data",
|
|
1434
|
-
data: columns,
|
|
1435
|
-
schema: this.schema,
|
|
1436
|
-
length: this.length
|
|
1437
|
-
};
|
|
1438
|
-
return batch;
|
|
1439
1172
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1173
|
+
return propArrayTypes;
|
|
1174
|
+
}
|
|
1175
|
+
function fillArrays(features, geometryInfo, options) {
|
|
1176
|
+
const {
|
|
1177
|
+
pointPositionsCount,
|
|
1178
|
+
pointFeaturesCount,
|
|
1179
|
+
linePositionsCount,
|
|
1180
|
+
linePathsCount,
|
|
1181
|
+
lineFeaturesCount,
|
|
1182
|
+
polygonPositionsCount,
|
|
1183
|
+
polygonObjectsCount,
|
|
1184
|
+
polygonRingsCount,
|
|
1185
|
+
polygonFeaturesCount,
|
|
1186
|
+
propArrayTypes,
|
|
1187
|
+
coordLength
|
|
1188
|
+
} = geometryInfo;
|
|
1189
|
+
const { numericPropKeys = [], PositionDataType = Float32Array, triangulate = true } = options;
|
|
1190
|
+
const hasGlobalId = features[0] && "id" in features[0];
|
|
1191
|
+
const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
|
|
1192
|
+
const points = {
|
|
1193
|
+
type: "Point",
|
|
1194
|
+
positions: new PositionDataType(pointPositionsCount * coordLength),
|
|
1195
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
|
|
1196
|
+
featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
|
|
1197
|
+
numericProps: {},
|
|
1198
|
+
properties: [],
|
|
1199
|
+
fields: []
|
|
1200
|
+
};
|
|
1201
|
+
const lines = {
|
|
1202
|
+
type: "LineString",
|
|
1203
|
+
pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
|
|
1204
|
+
positions: new PositionDataType(linePositionsCount * coordLength),
|
|
1205
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
|
|
1206
|
+
featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
|
|
1207
|
+
numericProps: {},
|
|
1208
|
+
properties: [],
|
|
1209
|
+
fields: []
|
|
1210
|
+
};
|
|
1211
|
+
const polygons = {
|
|
1212
|
+
type: "Polygon",
|
|
1213
|
+
polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
|
|
1214
|
+
primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
|
|
1215
|
+
positions: new PositionDataType(polygonPositionsCount * coordLength),
|
|
1216
|
+
globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
|
|
1217
|
+
featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
|
|
1218
|
+
numericProps: {},
|
|
1219
|
+
properties: [],
|
|
1220
|
+
fields: []
|
|
1221
|
+
};
|
|
1222
|
+
if (triangulate) {
|
|
1223
|
+
polygons.triangles = [];
|
|
1224
|
+
}
|
|
1225
|
+
for (const object of [points, lines, polygons]) {
|
|
1226
|
+
for (const propName of numericPropKeys) {
|
|
1227
|
+
const T = propArrayTypes[propName];
|
|
1228
|
+
object.numericProps[propName] = new T(object.positions.length / coordLength);
|
|
1461
1229
|
}
|
|
1462
1230
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1231
|
+
lines.pathIndices[linePathsCount] = linePositionsCount;
|
|
1232
|
+
polygons.polygonIndices[polygonObjectsCount] = polygonPositionsCount;
|
|
1233
|
+
polygons.primitivePolygonIndices[polygonRingsCount] = polygonPositionsCount;
|
|
1234
|
+
const indexMap = {
|
|
1235
|
+
pointPosition: 0,
|
|
1236
|
+
pointFeature: 0,
|
|
1237
|
+
linePosition: 0,
|
|
1238
|
+
linePath: 0,
|
|
1239
|
+
lineFeature: 0,
|
|
1240
|
+
polygonPosition: 0,
|
|
1241
|
+
polygonObject: 0,
|
|
1242
|
+
polygonRing: 0,
|
|
1243
|
+
polygonFeature: 0,
|
|
1244
|
+
feature: 0
|
|
1245
|
+
};
|
|
1246
|
+
for (const feature of features) {
|
|
1247
|
+
const geometry = feature.geometry;
|
|
1248
|
+
const properties = feature.properties || {};
|
|
1249
|
+
switch (geometry.type) {
|
|
1250
|
+
case "Point":
|
|
1251
|
+
handlePoint(geometry, points, indexMap, coordLength, properties);
|
|
1252
|
+
points.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
1253
|
+
if (hasGlobalId) {
|
|
1254
|
+
points.fields.push({ id: feature.id });
|
|
1255
|
+
}
|
|
1256
|
+
indexMap.pointFeature++;
|
|
1257
|
+
break;
|
|
1258
|
+
case "LineString":
|
|
1259
|
+
handleLineString(geometry, lines, indexMap, coordLength, properties);
|
|
1260
|
+
lines.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
1261
|
+
if (hasGlobalId) {
|
|
1262
|
+
lines.fields.push({ id: feature.id });
|
|
1263
|
+
}
|
|
1264
|
+
indexMap.lineFeature++;
|
|
1265
|
+
break;
|
|
1266
|
+
case "Polygon":
|
|
1267
|
+
handlePolygon(geometry, polygons, indexMap, coordLength, properties);
|
|
1268
|
+
polygons.properties.push(keepStringProperties(properties, numericPropKeys));
|
|
1269
|
+
if (hasGlobalId) {
|
|
1270
|
+
polygons.fields.push({ id: feature.id });
|
|
1271
|
+
}
|
|
1272
|
+
indexMap.polygonFeature++;
|
|
1273
|
+
break;
|
|
1274
|
+
default:
|
|
1275
|
+
throw new Error("Invalid geometry type");
|
|
1466
1276
|
}
|
|
1277
|
+
indexMap.feature++;
|
|
1467
1278
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1279
|
+
return makeAccessorObjects(points, lines, polygons, coordLength);
|
|
1280
|
+
}
|
|
1281
|
+
function handlePoint(geometry, points, indexMap, coordLength, properties) {
|
|
1282
|
+
points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
|
|
1283
|
+
const nPositions = geometry.data.length / coordLength;
|
|
1284
|
+
fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
|
|
1285
|
+
points.globalFeatureIds.fill(
|
|
1286
|
+
indexMap.feature,
|
|
1287
|
+
indexMap.pointPosition,
|
|
1288
|
+
indexMap.pointPosition + nPositions
|
|
1289
|
+
);
|
|
1290
|
+
points.featureIds.fill(
|
|
1291
|
+
indexMap.pointFeature,
|
|
1292
|
+
indexMap.pointPosition,
|
|
1293
|
+
indexMap.pointPosition + nPositions
|
|
1294
|
+
);
|
|
1295
|
+
indexMap.pointPosition += nPositions;
|
|
1296
|
+
}
|
|
1297
|
+
function handleLineString(geometry, lines, indexMap, coordLength, properties) {
|
|
1298
|
+
lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
|
|
1299
|
+
const nPositions = geometry.data.length / coordLength;
|
|
1300
|
+
fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
|
|
1301
|
+
lines.globalFeatureIds.fill(
|
|
1302
|
+
indexMap.feature,
|
|
1303
|
+
indexMap.linePosition,
|
|
1304
|
+
indexMap.linePosition + nPositions
|
|
1305
|
+
);
|
|
1306
|
+
lines.featureIds.fill(
|
|
1307
|
+
indexMap.lineFeature,
|
|
1308
|
+
indexMap.linePosition,
|
|
1309
|
+
indexMap.linePosition + nPositions
|
|
1310
|
+
);
|
|
1311
|
+
for (let i = 0, il = geometry.indices.length; i < il; ++i) {
|
|
1312
|
+
const start = geometry.indices[i];
|
|
1313
|
+
const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
|
|
1314
|
+
lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
|
|
1315
|
+
indexMap.linePosition += (end - start) / coordLength;
|
|
1491
1316
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1317
|
+
}
|
|
1318
|
+
function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
|
|
1319
|
+
polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
|
|
1320
|
+
const nPositions = geometry.data.length / coordLength;
|
|
1321
|
+
fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
|
|
1322
|
+
polygons.globalFeatureIds.fill(
|
|
1323
|
+
indexMap.feature,
|
|
1324
|
+
indexMap.polygonPosition,
|
|
1325
|
+
indexMap.polygonPosition + nPositions
|
|
1326
|
+
);
|
|
1327
|
+
polygons.featureIds.fill(
|
|
1328
|
+
indexMap.polygonFeature,
|
|
1329
|
+
indexMap.polygonPosition,
|
|
1330
|
+
indexMap.polygonPosition + nPositions
|
|
1331
|
+
);
|
|
1332
|
+
for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
|
|
1333
|
+
const startPosition = indexMap.polygonPosition;
|
|
1334
|
+
polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
|
|
1335
|
+
const areas = geometry.areas[l];
|
|
1336
|
+
const indices = geometry.indices[l];
|
|
1337
|
+
const nextIndices = geometry.indices[l + 1];
|
|
1338
|
+
for (let i = 0, il = indices.length; i < il; ++i) {
|
|
1339
|
+
const start = indices[i];
|
|
1340
|
+
const end = i === il - 1 ? (
|
|
1341
|
+
// last line, so either read to:
|
|
1342
|
+
nextIndices === void 0 ? geometry.data.length : nextIndices[0]
|
|
1343
|
+
) : indices[i + 1];
|
|
1344
|
+
polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
|
|
1345
|
+
indexMap.polygonPosition += (end - start) / coordLength;
|
|
1498
1346
|
}
|
|
1499
|
-
|
|
1347
|
+
const endPosition = indexMap.polygonPosition;
|
|
1348
|
+
triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
|
|
1500
1349
|
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
if (Array.isArray(row)) {
|
|
1510
|
-
this.addArrayRow(row);
|
|
1511
|
-
} else {
|
|
1512
|
-
this.addObjectRow(row);
|
|
1513
|
-
}
|
|
1350
|
+
}
|
|
1351
|
+
function triangulatePolygon(polygons, areas, indices, {
|
|
1352
|
+
startPosition,
|
|
1353
|
+
endPosition,
|
|
1354
|
+
coordLength
|
|
1355
|
+
}) {
|
|
1356
|
+
if (!polygons.triangles) {
|
|
1357
|
+
return;
|
|
1514
1358
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1359
|
+
const start = startPosition * coordLength;
|
|
1360
|
+
const end = endPosition * coordLength;
|
|
1361
|
+
const polygonPositions = polygons.positions.subarray(start, end);
|
|
1362
|
+
const offset = indices[0];
|
|
1363
|
+
const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
|
|
1364
|
+
const triangles = earcut(polygonPositions, holes, coordLength, areas);
|
|
1365
|
+
for (let t = 0, tl = triangles.length; t < tl; ++t) {
|
|
1366
|
+
polygons.triangles.push(startPosition + triangles[t]);
|
|
1522
1367
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1368
|
+
}
|
|
1369
|
+
function wrapProps(obj, size) {
|
|
1370
|
+
const returnObj = {};
|
|
1371
|
+
for (const key in obj) {
|
|
1372
|
+
returnObj[key] = { value: obj[key], size };
|
|
1373
|
+
}
|
|
1374
|
+
return returnObj;
|
|
1375
|
+
}
|
|
1376
|
+
function makeAccessorObjects(points, lines, polygons, coordLength) {
|
|
1377
|
+
const binaryFeatures = {
|
|
1378
|
+
shape: "binary-feature-collection",
|
|
1379
|
+
points: {
|
|
1380
|
+
...points,
|
|
1381
|
+
positions: { value: points.positions, size: coordLength },
|
|
1382
|
+
globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
|
|
1383
|
+
featureIds: { value: points.featureIds, size: 1 },
|
|
1384
|
+
numericProps: wrapProps(points.numericProps, 1)
|
|
1385
|
+
},
|
|
1386
|
+
lines: {
|
|
1387
|
+
...lines,
|
|
1388
|
+
positions: { value: lines.positions, size: coordLength },
|
|
1389
|
+
pathIndices: { value: lines.pathIndices, size: 1 },
|
|
1390
|
+
globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
|
|
1391
|
+
featureIds: { value: lines.featureIds, size: 1 },
|
|
1392
|
+
numericProps: wrapProps(lines.numericProps, 1)
|
|
1393
|
+
},
|
|
1394
|
+
polygons: {
|
|
1395
|
+
...polygons,
|
|
1396
|
+
positions: { value: polygons.positions, size: coordLength },
|
|
1397
|
+
polygonIndices: { value: polygons.polygonIndices, size: 1 },
|
|
1398
|
+
primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
|
|
1399
|
+
globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
|
|
1400
|
+
featureIds: { value: polygons.featureIds, size: 1 },
|
|
1401
|
+
numericProps: wrapProps(polygons.numericProps, 1)
|
|
1528
1402
|
}
|
|
1529
|
-
|
|
1403
|
+
// triangles not expected
|
|
1404
|
+
};
|
|
1405
|
+
if (binaryFeatures.polygons && polygons.triangles) {
|
|
1406
|
+
binaryFeatures.polygons.triangles = { value: new Uint32Array(polygons.triangles), size: 1 };
|
|
1530
1407
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1408
|
+
return binaryFeatures;
|
|
1409
|
+
}
|
|
1410
|
+
function fillNumericProperties(object, properties, index, length) {
|
|
1411
|
+
for (const numericPropName in object.numericProps) {
|
|
1412
|
+
if (numericPropName in properties) {
|
|
1413
|
+
const value = properties[numericPropName];
|
|
1414
|
+
object.numericProps[numericPropName].fill(value, index, index + length);
|
|
1535
1415
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
function keepStringProperties(properties, numericKeys) {
|
|
1419
|
+
const props = {};
|
|
1420
|
+
for (const key in properties) {
|
|
1421
|
+
if (!numericKeys.includes(key)) {
|
|
1422
|
+
props[key] = properties[key];
|
|
1538
1423
|
}
|
|
1539
|
-
this.isChunkComplete = true;
|
|
1540
1424
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1425
|
+
return props;
|
|
1426
|
+
}
|
|
1427
|
+
function deduceArrayType(x, constructor) {
|
|
1428
|
+
if (constructor === Array || !Number.isFinite(x)) {
|
|
1429
|
+
return Array;
|
|
1543
1430
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1431
|
+
return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
// ../gis/src/lib/binary-features/extract-geometry-info.ts
|
|
1435
|
+
function extractGeometryInfo(features) {
|
|
1436
|
+
let pointPositionsCount = 0;
|
|
1437
|
+
let pointFeaturesCount = 0;
|
|
1438
|
+
let linePositionsCount = 0;
|
|
1439
|
+
let linePathsCount = 0;
|
|
1440
|
+
let lineFeaturesCount = 0;
|
|
1441
|
+
let polygonPositionsCount = 0;
|
|
1442
|
+
let polygonObjectsCount = 0;
|
|
1443
|
+
let polygonRingsCount = 0;
|
|
1444
|
+
let polygonFeaturesCount = 0;
|
|
1445
|
+
const coordLengths = /* @__PURE__ */ new Set();
|
|
1446
|
+
for (const feature of features) {
|
|
1447
|
+
const geometry = feature.geometry;
|
|
1448
|
+
switch (geometry.type) {
|
|
1449
|
+
case "Point":
|
|
1450
|
+
pointFeaturesCount++;
|
|
1451
|
+
pointPositionsCount++;
|
|
1452
|
+
coordLengths.add(geometry.coordinates.length);
|
|
1453
|
+
break;
|
|
1454
|
+
case "MultiPoint":
|
|
1455
|
+
pointFeaturesCount++;
|
|
1456
|
+
pointPositionsCount += geometry.coordinates.length;
|
|
1457
|
+
for (const point of geometry.coordinates) {
|
|
1458
|
+
coordLengths.add(point.length);
|
|
1459
|
+
}
|
|
1460
|
+
break;
|
|
1461
|
+
case "LineString":
|
|
1462
|
+
lineFeaturesCount++;
|
|
1463
|
+
linePositionsCount += geometry.coordinates.length;
|
|
1464
|
+
linePathsCount++;
|
|
1465
|
+
for (const coord of geometry.coordinates) {
|
|
1466
|
+
coordLengths.add(coord.length);
|
|
1467
|
+
}
|
|
1468
|
+
break;
|
|
1469
|
+
case "MultiLineString":
|
|
1470
|
+
lineFeaturesCount++;
|
|
1471
|
+
for (const line of geometry.coordinates) {
|
|
1472
|
+
linePositionsCount += line.length;
|
|
1473
|
+
linePathsCount++;
|
|
1474
|
+
for (const coord of line) {
|
|
1475
|
+
coordLengths.add(coord.length);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
break;
|
|
1479
|
+
case "Polygon":
|
|
1480
|
+
polygonFeaturesCount++;
|
|
1481
|
+
polygonObjectsCount++;
|
|
1482
|
+
polygonRingsCount += geometry.coordinates.length;
|
|
1483
|
+
const flattened = geometry.coordinates.flat();
|
|
1484
|
+
polygonPositionsCount += flattened.length;
|
|
1485
|
+
for (const coord of flattened) {
|
|
1486
|
+
coordLengths.add(coord.length);
|
|
1487
|
+
}
|
|
1488
|
+
break;
|
|
1489
|
+
case "MultiPolygon":
|
|
1490
|
+
polygonFeaturesCount++;
|
|
1491
|
+
for (const polygon of geometry.coordinates) {
|
|
1492
|
+
polygonObjectsCount++;
|
|
1493
|
+
polygonRingsCount += polygon.length;
|
|
1494
|
+
const flattened2 = polygon.flat();
|
|
1495
|
+
polygonPositionsCount += flattened2.length;
|
|
1496
|
+
for (const coord of flattened2) {
|
|
1497
|
+
coordLengths.add(coord.length);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
break;
|
|
1501
|
+
default:
|
|
1502
|
+
throw new Error(`Unsupported geometry type: ${geometry.type}`);
|
|
1503
|
+
}
|
|
1546
1504
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1505
|
+
return {
|
|
1506
|
+
coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
|
|
1507
|
+
pointPositionsCount,
|
|
1508
|
+
pointFeaturesCount,
|
|
1509
|
+
linePositionsCount,
|
|
1510
|
+
linePathsCount,
|
|
1511
|
+
lineFeaturesCount,
|
|
1512
|
+
polygonPositionsCount,
|
|
1513
|
+
polygonObjectsCount,
|
|
1514
|
+
polygonRingsCount,
|
|
1515
|
+
polygonFeaturesCount
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// ../gis/src/lib/binary-features/geojson-to-flat-geojson.ts
|
|
1520
|
+
function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
|
|
1521
|
+
return features.map((feature) => flattenFeature(feature, options));
|
|
1522
|
+
}
|
|
1523
|
+
function flattenPoint(coordinates, data, indices, options) {
|
|
1524
|
+
indices.push(data.length);
|
|
1525
|
+
data.push(...coordinates);
|
|
1526
|
+
for (let i = coordinates.length; i < options.coordLength; i++) {
|
|
1527
|
+
data.push(0);
|
|
1550
1528
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
}
|
|
1559
|
-
} else if (this.options.batchSize > this.aggregator.rowCount()) {
|
|
1560
|
-
return false;
|
|
1561
|
-
}
|
|
1562
|
-
if (this.options.batchDebounceMs > Date.now() - this.lastBatchEmittedMs) {
|
|
1563
|
-
return false;
|
|
1529
|
+
}
|
|
1530
|
+
function flattenLineString(coordinates, data, indices, options) {
|
|
1531
|
+
indices.push(data.length);
|
|
1532
|
+
for (const c of coordinates) {
|
|
1533
|
+
data.push(...c);
|
|
1534
|
+
for (let i = c.length; i < options.coordLength; i++) {
|
|
1535
|
+
data.push(0);
|
|
1564
1536
|
}
|
|
1565
|
-
this.isChunkComplete = false;
|
|
1566
|
-
this.lastBatchEmittedMs = Date.now();
|
|
1567
|
-
return true;
|
|
1568
1537
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1538
|
+
}
|
|
1539
|
+
function flattenPolygon(coordinates, data, indices, areas, options) {
|
|
1540
|
+
let count = 0;
|
|
1541
|
+
const ringAreas = [];
|
|
1542
|
+
const polygons = [];
|
|
1543
|
+
for (const lineString of coordinates) {
|
|
1544
|
+
const lineString2d = lineString.map((p) => p.slice(0, 2));
|
|
1545
|
+
let area2 = getPolygonSignedArea(lineString2d.flat());
|
|
1546
|
+
const ccw = area2 < 0;
|
|
1547
|
+
if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
|
|
1548
|
+
lineString.reverse();
|
|
1549
|
+
area2 = -area2;
|
|
1578
1550
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
Object.assign(normalizedBatch, options);
|
|
1583
|
-
this.batchCount++;
|
|
1584
|
-
this.aggregator = null;
|
|
1585
|
-
return normalizedBatch;
|
|
1551
|
+
ringAreas.push(area2);
|
|
1552
|
+
flattenLineString(lineString, data, polygons, options);
|
|
1553
|
+
count++;
|
|
1586
1554
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
return BaseTableBatchAggregator;
|
|
1591
|
-
case "array-row-table":
|
|
1592
|
-
case "object-row-table":
|
|
1593
|
-
return RowTableBatchAggregator;
|
|
1594
|
-
case "columnar-table":
|
|
1595
|
-
return ColumnarTableBatchAggregator;
|
|
1596
|
-
case "arrow-table":
|
|
1597
|
-
if (!TableBatchBuilder.ArrowBatch) {
|
|
1598
|
-
throw new Error(ERR_MESSAGE);
|
|
1599
|
-
}
|
|
1600
|
-
return TableBatchBuilder.ArrowBatch;
|
|
1601
|
-
default:
|
|
1602
|
-
throw new Error(ERR_MESSAGE);
|
|
1603
|
-
}
|
|
1555
|
+
if (count > 0) {
|
|
1556
|
+
areas.push(ringAreas);
|
|
1557
|
+
indices.push(polygons);
|
|
1604
1558
|
}
|
|
1605
|
-
}
|
|
1559
|
+
}
|
|
1560
|
+
function flattenFeature(feature, options) {
|
|
1561
|
+
const { geometry } = feature;
|
|
1562
|
+
if (geometry.type === "GeometryCollection") {
|
|
1563
|
+
throw new Error("GeometryCollection type not supported");
|
|
1564
|
+
}
|
|
1565
|
+
const data = [];
|
|
1566
|
+
const indices = [];
|
|
1567
|
+
let areas;
|
|
1568
|
+
let type;
|
|
1569
|
+
switch (geometry.type) {
|
|
1570
|
+
case "Point":
|
|
1571
|
+
type = "Point";
|
|
1572
|
+
flattenPoint(geometry.coordinates, data, indices, options);
|
|
1573
|
+
break;
|
|
1574
|
+
case "MultiPoint":
|
|
1575
|
+
type = "Point";
|
|
1576
|
+
geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
|
|
1577
|
+
break;
|
|
1578
|
+
case "LineString":
|
|
1579
|
+
type = "LineString";
|
|
1580
|
+
flattenLineString(geometry.coordinates, data, indices, options);
|
|
1581
|
+
break;
|
|
1582
|
+
case "MultiLineString":
|
|
1583
|
+
type = "LineString";
|
|
1584
|
+
geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
|
|
1585
|
+
break;
|
|
1586
|
+
case "Polygon":
|
|
1587
|
+
type = "Polygon";
|
|
1588
|
+
areas = [];
|
|
1589
|
+
flattenPolygon(geometry.coordinates, data, indices, areas, options);
|
|
1590
|
+
break;
|
|
1591
|
+
case "MultiPolygon":
|
|
1592
|
+
type = "Polygon";
|
|
1593
|
+
areas = [];
|
|
1594
|
+
geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
|
|
1595
|
+
break;
|
|
1596
|
+
default:
|
|
1597
|
+
throw new Error(`Unknown type: ${type}`);
|
|
1598
|
+
}
|
|
1599
|
+
return { ...feature, geometry: { type, indices, data, areas } };
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
// ../gis/src/lib/binary-features/geojson-to-binary.ts
|
|
1603
|
+
function geojsonToBinary(features, options = { fixRingWinding: true, triangulate: true }) {
|
|
1604
|
+
const geometryInfo = extractGeometryInfo(features);
|
|
1605
|
+
const coordLength = geometryInfo.coordLength;
|
|
1606
|
+
const { fixRingWinding } = options;
|
|
1607
|
+
const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
|
|
1608
|
+
return flatGeojsonToBinary(flatFeatures, geometryInfo, {
|
|
1609
|
+
numericPropKeys: options.numericPropKeys,
|
|
1610
|
+
PositionDataType: options.PositionDataType || Float32Array,
|
|
1611
|
+
triangulate: options.triangulate
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1606
1614
|
|
|
1607
1615
|
// src/lib/clarinet/clarinet.ts
|
|
1608
1616
|
var MAX_BUFFER_LENGTH = Number.MAX_SAFE_INTEGER;
|
|
@@ -2417,7 +2425,7 @@ Char: ${this.c}`;
|
|
|
2417
2425
|
}
|
|
2418
2426
|
|
|
2419
2427
|
// src/geojson-loader.ts
|
|
2420
|
-
var VERSION = true ? "4.0.
|
|
2428
|
+
var VERSION = true ? "4.0.2" : "latest";
|
|
2421
2429
|
var GeoJSONWorkerLoader = {
|
|
2422
2430
|
name: "GeoJSON",
|
|
2423
2431
|
id: "geojson",
|