@gisatcz/deckgl-geolib 2.6.0-dev.4 → 2.6.0-dev.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/cjs/index.js +261 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +2 -2
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/esm/index.js +261 -24
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +2 -2
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/types/core/CogTiles.d.ts +1 -0
- package/dist/esm/types/core/GeoImage.d.ts +4 -2
- package/dist/esm/types/core/lib/TerrainGenerator.d.ts +2 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/workers/TerrainWorkerPool.d.ts +58 -0
- package/dist/esm/types/workers/terrain.worker.d.ts +5 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -6331,7 +6331,8 @@ class ReliefCompositor {
|
|
|
6331
6331
|
}
|
|
6332
6332
|
|
|
6333
6333
|
class TerrainGenerator {
|
|
6334
|
-
static async generate(input, options, meshMaxError)
|
|
6334
|
+
static async generate(input, options, meshMaxError, workerPool, // TerrainWorkerPool (optional for flexibility)
|
|
6335
|
+
signal) {
|
|
6335
6336
|
const { width, height } = input;
|
|
6336
6337
|
const isKernel = width === 258;
|
|
6337
6338
|
// 1. Compute Terrain Data (Extract Elevation)
|
|
@@ -6339,27 +6340,47 @@ class TerrainGenerator {
|
|
|
6339
6340
|
// For kernel tiles, the mesh uses the inner 257×257 sub-grid (rows 1–257, cols 1–257)
|
|
6340
6341
|
// so that row 0 / col 0 (kernel padding) is dropped while the bottom/right stitching
|
|
6341
6342
|
// overlap is preserved.
|
|
6342
|
-
|
|
6343
|
+
let meshTerrain = isKernel ? this.extractMeshRaster(terrain) : terrain;
|
|
6343
6344
|
const meshWidth = isKernel ? 257 : width;
|
|
6344
6345
|
const meshHeight = isKernel ? 257 : height;
|
|
6345
6346
|
// 2. Tesselate (Generate Mesh)
|
|
6346
6347
|
const { terrainSkirtHeight, verticalExaggeration = 1.0 } = options;
|
|
6347
6348
|
let mesh;
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6349
|
+
let meshTerrainForAttributes; // ← Will hold terrain for getMeshAttributes()
|
|
6350
|
+
if (workerPool) {
|
|
6351
|
+
// ✅ NEW: Offload to Web Worker with ZERO-COPY ROUNDTRIP
|
|
6352
|
+
// Transfer meshTerrain to worker; worker transfers it back alongside mesh
|
|
6353
|
+
// This avoids meshTerrain.slice() allocation on main thread
|
|
6354
|
+
const result = await workerPool.computeMesh({
|
|
6355
|
+
terrain: meshTerrain, // ← Transferred to worker (detached here)
|
|
6356
|
+
meshMaxError,
|
|
6357
|
+
tesselator: options.tesselator || 'martini',
|
|
6358
|
+
width: meshWidth,
|
|
6359
|
+
height: meshHeight,
|
|
6360
|
+
signal, // ← Thread cancellation signal to worker
|
|
6361
|
+
});
|
|
6362
|
+
mesh = { vertices: result.vertices, triangles: result.triangles };
|
|
6363
|
+
meshTerrainForAttributes = result.terrain; // ← Transferred back from worker
|
|
6364
|
+
meshTerrain = result.terrain; // ← Reassign for downstream use (tileResult.raw, etc.)
|
|
6365
|
+
}
|
|
6366
|
+
else {
|
|
6367
|
+
// ❌ FALLBACK: Synchronous (old behavior, kept for safety)
|
|
6368
|
+
switch (options.tesselator) {
|
|
6369
|
+
case 'martini':
|
|
6370
|
+
mesh = this.getMartiniTileMesh(meshMaxError, meshWidth, meshTerrain);
|
|
6371
|
+
break;
|
|
6372
|
+
case 'delatin':
|
|
6373
|
+
mesh = this.getDelatinTileMesh(meshMaxError, meshWidth, meshHeight, meshTerrain);
|
|
6374
|
+
break;
|
|
6375
|
+
default:
|
|
6376
|
+
mesh = this.getMartiniTileMesh(meshMaxError, meshWidth, meshTerrain);
|
|
6377
|
+
break;
|
|
6378
|
+
}
|
|
6379
|
+
meshTerrainForAttributes = meshTerrain; // ← Use original
|
|
6359
6380
|
}
|
|
6360
6381
|
const { vertices } = mesh;
|
|
6361
6382
|
let { triangles } = mesh;
|
|
6362
|
-
let attributes = this.getMeshAttributes(vertices,
|
|
6383
|
+
let attributes = this.getMeshAttributes(vertices, meshTerrainForAttributes, meshWidth, meshHeight, input.bounds, verticalExaggeration);
|
|
6363
6384
|
// Compute bounding box before adding skirt so that z values are not skewed
|
|
6364
6385
|
const boundingBox = schema.getMeshBoundingBox(attributes);
|
|
6365
6386
|
if (terrainSkirtHeight) {
|
|
@@ -6626,13 +6647,14 @@ class GeoImage {
|
|
|
6626
6647
|
const data = await tiff.getImage(0);
|
|
6627
6648
|
this.data = data;
|
|
6628
6649
|
}
|
|
6629
|
-
async getMap(input, options, meshMaxError)
|
|
6650
|
+
async getMap(input, options, meshMaxError, workerPool, // TerrainWorkerPool (optional)
|
|
6651
|
+
signal) {
|
|
6630
6652
|
const mergedOptions = GeoImage.resolveVisualizationMode({ ...DefaultGeoImageOptions, ...options }, options);
|
|
6631
6653
|
switch (mergedOptions.type) {
|
|
6632
6654
|
case 'image':
|
|
6633
6655
|
return this.getBitmap(input, mergedOptions);
|
|
6634
6656
|
case 'terrain':
|
|
6635
|
-
return this.getHeightmap(input, mergedOptions, meshMaxError);
|
|
6657
|
+
return this.getHeightmap(input, mergedOptions, meshMaxError, workerPool, signal);
|
|
6636
6658
|
default:
|
|
6637
6659
|
return null;
|
|
6638
6660
|
}
|
|
@@ -6689,7 +6711,8 @@ class GeoImage {
|
|
|
6689
6711
|
return resolved;
|
|
6690
6712
|
}
|
|
6691
6713
|
// GetHeightmap uses only "useChannel" and "multiplier" options
|
|
6692
|
-
async getHeightmap(input, options, meshMaxError)
|
|
6714
|
+
async getHeightmap(input, options, meshMaxError, workerPool, // TerrainWorkerPool (optional)
|
|
6715
|
+
signal) {
|
|
6693
6716
|
let rasters = [];
|
|
6694
6717
|
let width;
|
|
6695
6718
|
let height;
|
|
@@ -6711,8 +6734,8 @@ class GeoImage {
|
|
|
6711
6734
|
bounds = input.bounds;
|
|
6712
6735
|
cellSizeMeters = input.cellSizeMeters;
|
|
6713
6736
|
}
|
|
6714
|
-
// Delegate to TerrainGenerator
|
|
6715
|
-
return await TerrainGenerator.generate({ width, height, rasters, bounds, cellSizeMeters }, options, meshMaxError);
|
|
6737
|
+
// Delegate to TerrainGenerator with worker pool and cancellation signal
|
|
6738
|
+
return await TerrainGenerator.generate({ width, height, rasters, bounds, cellSizeMeters }, options, meshMaxError, workerPool, signal);
|
|
6716
6739
|
}
|
|
6717
6740
|
async getBitmap(input, options) {
|
|
6718
6741
|
let rasters = [];
|
|
@@ -6736,6 +6759,214 @@ class GeoImage {
|
|
|
6736
6759
|
}
|
|
6737
6760
|
}
|
|
6738
6761
|
|
|
6762
|
+
function decodeBase64(base64, enableUnicode) {
|
|
6763
|
+
var binaryString = atob(base64);
|
|
6764
|
+
return binaryString;
|
|
6765
|
+
}
|
|
6766
|
+
|
|
6767
|
+
function createURL(base64, sourcemapArg, enableUnicodeArg) {
|
|
6768
|
+
var source = decodeBase64(base64);
|
|
6769
|
+
var start = source.indexOf('\n', 10) + 1;
|
|
6770
|
+
var body = source.substring(start) + ('');
|
|
6771
|
+
var blob = new Blob([body], { type: 'application/javascript' });
|
|
6772
|
+
return URL.createObjectURL(blob);
|
|
6773
|
+
}
|
|
6774
|
+
|
|
6775
|
+
function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
|
|
6776
|
+
var url;
|
|
6777
|
+
return function WorkerFactory(options) {
|
|
6778
|
+
url = url || createURL(base64);
|
|
6779
|
+
return new Worker(url, options);
|
|
6780
|
+
};
|
|
6781
|
+
}
|
|
6782
|
+
|
|
6783
|
+
var WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNsYXNzIE1hcnRpbmkgewogICAgICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgICAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgICAgICAgIGlmICh0aWxlU2l6ZSAmICh0aWxlU2l6ZSAtIDEpKSB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICAgICBgRXhwZWN0ZWQgZ3JpZCBzaXplIHRvIGJlIDJebisxLCBnb3QgJHtncmlkU2l6ZX0uYCk7CgogICAgICAgICAgICB0aGlzLm51bVRyaWFuZ2xlcyA9IHRpbGVTaXplICogdGlsZVNpemUgKiAyIC0gMjsKICAgICAgICAgICAgdGhpcy5udW1QYXJlbnRUcmlhbmdsZXMgPSB0aGlzLm51bVRyaWFuZ2xlcyAtIHRpbGVTaXplICogdGlsZVNpemU7CgogICAgICAgICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOwoKICAgICAgICAgICAgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7CgogICAgICAgICAgICAvLyBnZXQgdHJpYW5nbGUgY29vcmRpbmF0ZXMgZnJvbSBpdHMgaW5kZXggaW4gYW4gaW1wbGljaXQgYmluYXJ5IHRyZWUKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgaWQgPSBpICsgMjsKICAgICAgICAgICAgICAgIGxldCBheCA9IDAsIGF5ID0gMCwgYnggPSAwLCBieSA9IDAsIGN4ID0gMCwgY3kgPSAwOwogICAgICAgICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG15ID0gKGF5ICsgYnkpID4+IDE7CgogICAgICAgICAgICAgICAgICAgIGlmIChpZCAmIDEpIHsgLy8gbGVmdCBoYWxmCiAgICAgICAgICAgICAgICAgICAgICAgIGJ4ID0gYXg7IGJ5ID0gYXk7CiAgICAgICAgICAgICAgICAgICAgICAgIGF4ID0gY3g7IGF5ID0gY3k7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gcmlnaHQgaGFsZgogICAgICAgICAgICAgICAgICAgICAgICBheCA9IGJ4OyBheSA9IGJ5OwogICAgICAgICAgICAgICAgICAgICAgICBieCA9IGN4OyBieSA9IGN5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjeCA9IG14OyBjeSA9IG15OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDBdID0gYXg7CiAgICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICAgICAgICAgIHRoaXMuY29vcmRzW2sgKyAyXSA9IGJ4OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDNdID0gYnk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICAgICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFRpbGUgewogICAgICAgIGNvbnN0cnVjdG9yKHRlcnJhaW4sIG1hcnRpbmkpIHsKICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IG1hcnRpbmkuZ3JpZFNpemU7CiAgICAgICAgICAgIGlmICh0ZXJyYWluLmxlbmd0aCAhPT0gc2l6ZSAqIHNpemUpIHRocm93IG5ldyBFcnJvcigKICAgICAgICAgICAgICAgIGBFeHBlY3RlZCB0ZXJyYWluIGRhdGEgb2YgbGVuZ3RoICR7c2l6ZSAqIHNpemV9ICgke3NpemV9IHggJHtzaXplfSksIGdvdCAke3RlcnJhaW4ubGVuZ3RofS5gKTsKCiAgICAgICAgICAgIHRoaXMudGVycmFpbiA9IHRlcnJhaW47CiAgICAgICAgICAgIHRoaXMubWFydGluaSA9IG1hcnRpbmk7CiAgICAgICAgICAgIHRoaXMuZXJyb3JzID0gbmV3IEZsb2F0MzJBcnJheSh0ZXJyYWluLmxlbmd0aCk7CiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGUoKSB7CiAgICAgICAgICAgIGNvbnN0IHtudW1UcmlhbmdsZXMsIG51bVBhcmVudFRyaWFuZ2xlcywgY29vcmRzLCBncmlkU2l6ZTogc2l6ZX0gPSB0aGlzLm1hcnRpbmk7CiAgICAgICAgICAgIGNvbnN0IHt0ZXJyYWluLCBlcnJvcnN9ID0gdGhpczsKCiAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciBhbGwgcG9zc2libGUgdHJpYW5nbGVzLCBzdGFydGluZyBmcm9tIHRoZSBzbWFsbGVzdCBsZXZlbAogICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICAgICAgICAgIGNvbnN0IGF4ID0gY29vcmRzW2sgKyAwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ4ID0gY29vcmRzW2sgKyAyXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ5ID0gY29vcmRzW2sgKyAzXTsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgY3ggPSBteCArIG15IC0gYXk7CiAgICAgICAgICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsKCiAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQogICAgICAgICAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkSGVpZ2h0ID0gKHRlcnJhaW5bYXkgKiBzaXplICsgYXhdICsgdGVycmFpbltieSAqIHNpemUgKyBieF0pIC8gMjsKICAgICAgICAgICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgICAgICAgICBjb25zdCBtaWRkbGVFcnJvciA9IE1hdGguYWJzKGludGVycG9sYXRlZEhlaWdodCAtIHRlcnJhaW5bbWlkZGxlSW5kZXhdKTsKCiAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgbWlkZGxlRXJyb3IpOwoKICAgICAgICAgICAgICAgIGlmIChpIDwgbnVtUGFyZW50VHJpYW5nbGVzKSB7IC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRDaGlsZEluZGV4ID0gKChheSArIGN5KSA+PiAxKSAqIHNpemUgKyAoKGF4ICsgY3gpID4+IDEpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9ICgoYnkgKyBjeSkgPj4gMSkgKiBzaXplICsgKChieCArIGN4KSA+PiAxKTsKICAgICAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgZXJyb3JzW2xlZnRDaGlsZEluZGV4XSwgZXJyb3JzW3JpZ2h0Q2hpbGRJbmRleF0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBnZXRNZXNoKG1heEVycm9yID0gMCkgewogICAgICAgICAgICBjb25zdCB7Z3JpZFNpemU6IHNpemUsIGluZGljZXN9ID0gdGhpcy5tYXJ0aW5pOwogICAgICAgICAgICBjb25zdCB7ZXJyb3JzfSA9IHRoaXM7CiAgICAgICAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgICAgICAgIGxldCBudW1UcmlhbmdsZXMgPSAwOwogICAgICAgICAgICBjb25zdCBtYXggPSBzaXplIC0gMTsKCiAgICAgICAgICAgIC8vIHVzZSBhbiBpbmRleCBncmlkIHRvIGtlZXAgdHJhY2sgb2YgdmVydGljZXMgdGhhdCB3ZXJlIGFscmVhZHkgdXNlZCB0byBhdm9pZCBkdXBsaWNhdGlvbgogICAgICAgICAgICBpbmRpY2VzLmZpbGwoMCk7CgogICAgICAgICAgICAvLyByZXRyaWV2ZSBtZXNoIGluIHR3byBzdGFnZXMgdGhhdCBib3RoIHRyYXZlcnNlIHRoZSBlcnJvciBtYXA6CiAgICAgICAgICAgIC8vIC0gY291bnRFbGVtZW50czogZmluZCB1c2VkIHZlcnRpY2VzIChhbmQgYXNzaWduIGVhY2ggYW4gaW5kZXgpLCBhbmQgY291bnQgdHJpYW5nbGVzIChmb3IgbWluaW11bSBhbGxvY2F0aW9uKQogICAgICAgICAgICAvLyAtIHByb2Nlc3NUcmlhbmdsZTogZmlsbCB0aGUgYWxsb2NhdGVkIHZlcnRpY2VzICYgdHJpYW5nbGVzIHR5cGVkIGFycmF5cwoKICAgICAgICAgICAgZnVuY3Rpb24gY291bnRFbGVtZW50cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgbXkgPSAoYXkgKyBieSkgPj4gMTsKCiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KSA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgY291bnRFbGVtZW50cyhjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgICAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICAgICAgICAgICAgaW5kaWNlc1tieSAqIHNpemUgKyBieF0gPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgICAgICAgICAgICBudW1UcmlhbmdsZXMrKzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjb3VudEVsZW1lbnRzKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBjb3VudEVsZW1lbnRzKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwoKICAgICAgICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICAgICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAvLyB0cmlhbmdsZSBkb2Vzbid0IGFwcHJveGltYXRlIHRoZSBzdXJmYWNlIHdlbGwgZW5vdWdoOyBkcmlsbCBkb3duIGZ1cnRoZXIKICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwoKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgICAgICAgICAgICBjb25zdCBhID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gLSAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSAtIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKCiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGEgKyAxXSA9IGF5OwoKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CgogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjXSA9IGN4OwogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKCiAgICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgICAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBiOwogICAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CgogICAgICAgICAgICByZXR1cm4ge3ZlcnRpY2VzLCB0cmlhbmdsZXN9OwogICAgICAgIH0KICAgIH0KCiAgICAvLyBsb2FkZXJzLmdsCiAgICAvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUCiAgICAvLyBDb3B5cmlnaHQgKGMpIHZpcy5nbCBjb250cmlidXRvcnMKICAgIC8vIElTQyBMaWNlbnNlCiAgICAvLyBDb3B5cmlnaHQoYykgMjAxOSwgTWljaGFlbCBGb2dsZW1hbiwgVmxhZGltaXIgQWdhZm9ua2luCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnQgKi8KICAgIC8vIEB0cy1ub2NoZWNrCiAgICAvKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudCAqLwogICAgZnVuY3Rpb24gb3JpZW50KGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICByZXR1cm4gKGJ4IC0gY3gpICogKGF5IC0gY3kpIC0gKGJ5IC0gY3kpICogKGF4IC0gY3gpOwogICAgfQogICAgY2xhc3MgRGVsYXRpbiB7CiAgICAgICAgY29uc3RydWN0b3IoZGF0YSwgd2lkdGgsIGhlaWdodCA9IHdpZHRoKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7IC8vIGhlaWdodCBkYXRhCiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gW107IC8vIHZlcnRleCBjb29yZGluYXRlcyAoeCwgeSkKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXMgPSBbXTsgLy8gbWVzaCB0cmlhbmdsZSBpbmRpY2VzCiAgICAgICAgICAgIC8vIGFkZGl0aW9uYWwgdHJpYW5nbGUgZGF0YQogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fY2FuZGlkYXRlcyA9IFtdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcXVldWUgPSBbXTsgLy8gcXVldWUgb2YgYWRkZWQgdHJpYW5nbGVzCiAgICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IFtdOwogICAgICAgICAgICB0aGlzLl9ybXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcGVuZGluZyA9IFtdOyAvLyB0cmlhbmdsZXMgcGVuZGluZyBhZGRpdGlvbiB0byBxdWV1ZQogICAgICAgICAgICB0aGlzLl9wZW5kaW5nTGVuID0gMDsKICAgICAgICAgICAgdGhpcy5fcm1zU3VtID0gMDsKICAgICAgICAgICAgY29uc3QgeDEgPSB3aWR0aCAtIDE7CiAgICAgICAgICAgIGNvbnN0IHkxID0gaGVpZ2h0IC0gMTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLl9hZGRQb2ludCgwLCAwKTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLl9hZGRQb2ludCh4MSwgMCk7CiAgICAgICAgICAgIGNvbnN0IHAyID0gdGhpcy5fYWRkUG9pbnQoMCwgeTEpOwogICAgICAgICAgICBjb25zdCBwMyA9IHRoaXMuX2FkZFBvaW50KHgxLCB5MSk7CiAgICAgICAgICAgIC8vIGFkZCBpbml0aWFsIHR3byB0cmlhbmdsZXMKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMywgcDAsIHAyLCAtMSwgLTEsIC0xKTsKICAgICAgICAgICAgdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAzLCBwMSwgdDAsIC0xLCAtMSk7CiAgICAgICAgICAgIHRoaXMuX2ZsdXNoKCk7CiAgICAgICAgfQogICAgICAgIC8vIHJlZmluZSB0aGUgbWVzaCB1bnRpbCBpdHMgbWF4aW11bSBlcnJvciBnZXRzIGJlbG93IHRoZSBnaXZlbiBvbmUKICAgICAgICBydW4obWF4RXJyb3IgPSAxKSB7CiAgICAgICAgICAgIHdoaWxlICh0aGlzLmdldE1heEVycm9yKCkgPiBtYXhFcnJvcikgewogICAgICAgICAgICAgICAgdGhpcy5yZWZpbmUoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyByZWZpbmUgdGhlIG1lc2ggd2l0aCBhIHNpbmdsZSBwb2ludAogICAgICAgIHJlZmluZSgpIHsKICAgICAgICAgICAgdGhpcy5fc3RlcCgpOwogICAgICAgICAgICB0aGlzLl9mbHVzaCgpOwogICAgICAgIH0KICAgICAgICAvLyBtYXggZXJyb3Igb2YgdGhlIGN1cnJlbnQgbWVzaAogICAgICAgIGdldE1heEVycm9yKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzWzBdOwogICAgICAgIH0KICAgICAgICAvLyByb290LW1lYW4tc3F1YXJlIGRldmlhdGlvbiBvZiB0aGUgY3VycmVudCBtZXNoCiAgICAgICAgZ2V0Uk1TRCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Jtc1N1bSA+IDAgPyBNYXRoLnNxcnQodGhpcy5fcm1zU3VtIC8gKHRoaXMud2lkdGggKiB0aGlzLmhlaWdodCkpIDogMDsKICAgICAgICB9CiAgICAgICAgLy8gaGVpZ2h0IHZhbHVlIGF0IGEgZ2l2ZW4gcG9zaXRpb24KICAgICAgICBoZWlnaHRBdCh4LCB5KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy53aWR0aCAqIHkgKyB4XTsKICAgICAgICB9CiAgICAgICAgLy8gcmFzdGVyaXplIGFuZCBxdWV1ZSBhbGwgdHJpYW5nbGVzIHRoYXQgZ290IGFkZGVkIG9yIHVwZGF0ZWQgaW4gX3N0ZXAKICAgICAgICBfZmx1c2goKSB7CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3BlbmRpbmdMZW47IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3BlbmRpbmdbaV07CiAgICAgICAgICAgICAgICAvLyByYXN0ZXJpemUgdHJpYW5nbGUgdG8gZmluZCBtYXhpbXVtIHBpeGVsIGVycm9yCiAgICAgICAgICAgICAgICBjb25zdCBhID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMF07CiAgICAgICAgICAgICAgICBjb25zdCBiID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMV07CiAgICAgICAgICAgICAgICBjb25zdCBjID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMl07CiAgICAgICAgICAgICAgICB0aGlzLl9maW5kQ2FuZGlkYXRlKGNvb3Jkc1thXSwgY29vcmRzW2EgKyAxXSwgY29vcmRzW2JdLCBjb29yZHNbYiArIDFdLCBjb29yZHNbY10sIGNvb3Jkc1tjICsgMV0sIHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdMZW4gPSAwOwogICAgICAgIH0KICAgICAgICAvLyByYXN0ZXJpemUgYSB0cmlhbmdsZSwgZmluZCBpdHMgbWF4IGVycm9yLCBhbmQgcXVldWUgaXQgZm9yIHByb2Nlc3NpbmcKICAgICAgICBfZmluZENhbmRpZGF0ZShwMHgsIHAweSwgcDF4LCBwMXksIHAyeCwgcDJ5LCB0KSB7CiAgICAgICAgICAgIC8vIHRyaWFuZ2xlIGJvdW5kaW5nIGJveAogICAgICAgICAgICBjb25zdCBtaW5YID0gTWF0aC5taW4ocDB4LCBwMXgsIHAyeCk7CiAgICAgICAgICAgIGNvbnN0IG1pblkgPSBNYXRoLm1pbihwMHksIHAxeSwgcDJ5KTsKICAgICAgICAgICAgY29uc3QgbWF4WCA9IE1hdGgubWF4KHAweCwgcDF4LCBwMngpOwogICAgICAgICAgICBjb25zdCBtYXhZID0gTWF0aC5tYXgocDB5LCBwMXksIHAyeSk7CiAgICAgICAgICAgIC8vIGZvcndhcmQgZGlmZmVyZW5jaW5nIHZhcmlhYmxlcwogICAgICAgICAgICBsZXQgdzAwID0gb3JpZW50KHAxeCwgcDF5LCBwMngsIHAyeSwgbWluWCwgbWluWSk7CiAgICAgICAgICAgIGxldCB3MDEgPSBvcmllbnQocDJ4LCBwMnksIHAweCwgcDB5LCBtaW5YLCBtaW5ZKTsKICAgICAgICAgICAgbGV0IHcwMiA9IG9yaWVudChwMHgsIHAweSwgcDF4LCBwMXksIG1pblgsIG1pblkpOwogICAgICAgICAgICBjb25zdCBhMDEgPSBwMXkgLSBwMHk7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IHAweCAtIHAxeDsKICAgICAgICAgICAgY29uc3QgYTEyID0gcDJ5IC0gcDF5OwogICAgICAgICAgICBjb25zdCBiMTIgPSBwMXggLSBwMng7CiAgICAgICAgICAgIGNvbnN0IGEyMCA9IHAweSAtIHAyeTsKICAgICAgICAgICAgY29uc3QgYjIwID0gcDJ4IC0gcDB4OwogICAgICAgICAgICAvLyBwcmUtbXVsdGlwbGllZCB6IHZhbHVlcyBhdCB2ZXJ0aWNlcwogICAgICAgICAgICBjb25zdCBhID0gb3JpZW50KHAweCwgcDB5LCBwMXgsIHAxeSwgcDJ4LCBwMnkpOwogICAgICAgICAgICBjb25zdCB6MCA9IHRoaXMuaGVpZ2h0QXQocDB4LCBwMHkpIC8gYTsKICAgICAgICAgICAgY29uc3QgejEgPSB0aGlzLmhlaWdodEF0KHAxeCwgcDF5KSAvIGE7CiAgICAgICAgICAgIGNvbnN0IHoyID0gdGhpcy5oZWlnaHRBdChwMngsIHAyeSkgLyBhOwogICAgICAgICAgICAvLyBpdGVyYXRlIG92ZXIgcGl4ZWxzIGluIGJvdW5kaW5nIGJveAogICAgICAgICAgICBsZXQgbWF4RXJyb3IgPSAwOwogICAgICAgICAgICBsZXQgbXggPSAwOwogICAgICAgICAgICBsZXQgbXkgPSAwOwogICAgICAgICAgICBsZXQgcm1zID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgeSA9IG1pblk7IHkgPD0gbWF4WTsgeSsrKSB7CiAgICAgICAgICAgICAgICAvLyBjb21wdXRlIHN0YXJ0aW5nIG9mZnNldAogICAgICAgICAgICAgICAgbGV0IGR4ID0gMDsKICAgICAgICAgICAgICAgIGlmICh3MDAgPCAwICYmIGExMiAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgIGR4ID0gTWF0aC5tYXgoZHgsIE1hdGguZmxvb3IoLXcwMCAvIGExMikpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHcwMSA8IDAgJiYgYTIwICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgZHggPSBNYXRoLm1heChkeCwgTWF0aC5mbG9vcigtdzAxIC8gYTIwKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodzAyIDwgMCAmJiBhMDEgIT09IDApIHsKICAgICAgICAgICAgICAgICAgICBkeCA9IE1hdGgubWF4KGR4LCBNYXRoLmZsb29yKC13MDIgLyBhMDEpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxldCB3MCA9IHcwMCArIGExMiAqIGR4OwogICAgICAgICAgICAgICAgbGV0IHcxID0gdzAxICsgYTIwICogZHg7CiAgICAgICAgICAgICAgICBsZXQgdzIgPSB3MDIgKyBhMDEgKiBkeDsKICAgICAgICAgICAgICAgIGxldCB3YXNJbnNpZGUgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBtaW5YICsgZHg7IHggPD0gbWF4WDsgeCsrKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgaWYgaW5zaWRlIHRyaWFuZ2xlCiAgICAgICAgICAgICAgICAgICAgaWYgKHcwID49IDAgJiYgdzEgPj0gMCAmJiB3MiA+PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0luc2lkZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgeiB1c2luZyBiYXJ5Y2VudHJpYyBjb29yZGluYXRlcwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB6ID0gejAgKiB3MCArIHoxICogdzEgKyB6MiAqIHcyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkeiA9IE1hdGguYWJzKHogLSB0aGlzLmhlaWdodEF0KHgsIHkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcm1zICs9IGR6ICogZHo7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkeiA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhFcnJvciA9IGR6OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSB4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXkgPSB5OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHdhc0luc2lkZSkgewogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdzAgKz0gYTEyOwogICAgICAgICAgICAgICAgICAgIHcxICs9IGEyMDsKICAgICAgICAgICAgICAgICAgICB3MiArPSBhMDE7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3MDAgKz0gYjEyOwogICAgICAgICAgICAgICAgdzAxICs9IGIyMDsKICAgICAgICAgICAgICAgIHcwMiArPSBiMDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKChteCA9PT0gcDB4ICYmIG15ID09PSBwMHkpIHx8IChteCA9PT0gcDF4ICYmIG15ID09PSBwMXkpIHx8IChteCA9PT0gcDJ4ICYmIG15ID09PSBwMnkpKSB7CiAgICAgICAgICAgICAgICBtYXhFcnJvciA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gdXBkYXRlIHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHRdID0gbXg7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IG15OwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSBybXM7CiAgICAgICAgICAgIC8vIGFkZCB0cmlhbmdsZSB0byBwcmlvcml0eSBxdWV1ZQogICAgICAgICAgICB0aGlzLl9xdWV1ZVB1c2godCwgbWF4RXJyb3IsIHJtcyk7CiAgICAgICAgfQogICAgICAgIC8vIHByb2Nlc3MgdGhlIG5leHQgdHJpYW5nbGUgaW4gdGhlIHF1ZXVlLCBzcGxpdHRpbmcgaXQgd2l0aCBhIG5ldyBwb2ludAogICAgICAgIF9zdGVwKCkgewogICAgICAgICAgICAvLyBwb3AgdHJpYW5nbGUgd2l0aCBoaWdoZXN0IGVycm9yIGZyb20gcHJpb3JpdHkgcXVldWUKICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3F1ZXVlUG9wKCk7CiAgICAgICAgICAgIGNvbnN0IGUwID0gdCAqIDMgKyAwOwogICAgICAgICAgICBjb25zdCBlMSA9IHQgKiAzICsgMTsKICAgICAgICAgICAgY29uc3QgZTIgPSB0ICogMyArIDI7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbZTBdOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2UxXTsKICAgICAgICAgICAgY29uc3QgcDIgPSB0aGlzLnRyaWFuZ2xlc1tlMl07CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy5jb29yZHNbMiAqIHAwXTsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLmNvb3Jkc1syICogcDAgKyAxXTsKICAgICAgICAgICAgY29uc3QgYnggPSB0aGlzLmNvb3Jkc1syICogcDFdOwogICAgICAgICAgICBjb25zdCBieSA9IHRoaXMuY29vcmRzWzIgKiBwMSArIDFdOwogICAgICAgICAgICBjb25zdCBjeCA9IHRoaXMuY29vcmRzWzIgKiBwMl07CiAgICAgICAgICAgIGNvbnN0IGN5ID0gdGhpcy5jb29yZHNbMiAqIHAyICsgMV07CiAgICAgICAgICAgIGNvbnN0IHB4ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdF07CiAgICAgICAgICAgIGNvbnN0IHB5ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdCArIDFdOwogICAgICAgICAgICBjb25zdCBwbiA9IHRoaXMuX2FkZFBvaW50KHB4LCBweSk7CiAgICAgICAgICAgIGlmIChvcmllbnQoYXgsIGF5LCBieCwgYnksIHB4LCBweSkgPT09IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUNvbGxpbmVhcihwbiwgZTApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKG9yaWVudChieCwgYnksIGN4LCBjeSwgcHgsIHB5KSA9PT0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlQ29sbGluZWFyKHBuLCBlMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAob3JpZW50KGN4LCBjeSwgYXgsIGF5LCBweCwgcHkpID09PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVDb2xsaW5lYXIocG4sIGUyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnN0IGgwID0gdGhpcy5faGFsZmVkZ2VzW2UwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgxID0gdGhpcy5faGFsZmVkZ2VzW2UxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgyID0gdGhpcy5faGFsZmVkZ2VzW2UyXTsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAxLCBwbiwgaDAsIC0xLCAtMSwgZTApOwogICAgICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDIsIHBuLCBoMSwgLTEsIHQwICsgMSk7CiAgICAgICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAyLCBwMCwgcG4sIGgyLCB0MCArIDIsIHQxICsgMSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MCk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gYWRkIGNvb3JkaW5hdGVzIGZvciBhIG5ldyB2ZXJ0ZXgKICAgICAgICBfYWRkUG9pbnQoeCwgeSkgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5jb29yZHMubGVuZ3RoID4+IDE7CiAgICAgICAgICAgIHRoaXMuY29vcmRzLnB1c2goeCwgeSk7CiAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgIH0KICAgICAgICAvLyBhZGQgb3IgdXBkYXRlIGEgdHJpYW5nbGUgaW4gdGhlIG1lc2gKICAgICAgICBfYWRkVHJpYW5nbGUoYSwgYiwgYywgYWIsIGJjLCBjYSwgZSA9IHRoaXMudHJpYW5nbGVzLmxlbmd0aCkgewogICAgICAgICAgICBjb25zdCB0ID0gZSAvIDM7IC8vIG5ldyB0cmlhbmdsZSBpbmRleAogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdmVydGljZXMKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDBdID0gYTsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDFdID0gYjsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDJdID0gYzsKICAgICAgICAgICAgLy8gYWRkIHRyaWFuZ2xlIGhhbGZlZGdlcwogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbZSArIDBdID0gYWI7CiAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tlICsgMV0gPSBiYzsKICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2UgKyAyXSA9IGNhOwogICAgICAgICAgICAvLyBsaW5rIG5laWdoYm9yaW5nIGhhbGZlZGdlcwogICAgICAgICAgICBpZiAoYWIgPj0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2FiXSA9IGUgKyAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChiYyA+PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbYmNdID0gZSArIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNhID49IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tjYV0gPSBlICsgMjsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBpbml0IHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAwXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1t0XSA9IC0xOwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSAwOwogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdG8gcGVuZGluZyBxdWV1ZSBmb3IgbGF0ZXIgcmFzdGVyaXphdGlvbgogICAgICAgICAgICB0aGlzLl9wZW5kaW5nW3RoaXMuX3BlbmRpbmdMZW4rK10gPSB0OwogICAgICAgICAgICAvLyByZXR1cm4gZmlyc3QgaGFsZmVkZ2UgaW5kZXgKICAgICAgICAgICAgcmV0dXJuIGU7CiAgICAgICAgfQogICAgICAgIF9sZWdhbGl6ZShhKSB7CiAgICAgICAgICAgIC8vIGlmIHRoZSBwYWlyIG9mIHRyaWFuZ2xlcyBkb2Vzbid0IHNhdGlzZnkgdGhlIERlbGF1bmF5IGNvbmRpdGlvbgogICAgICAgICAgICAvLyAocDEgaXMgaW5zaWRlIHRoZSBjaXJjdW1jaXJjbGUgb2YgW3AwLCBwbCwgcHJdKSwgZmxpcCB0aGVtLAogICAgICAgICAgICAvLyB0aGVuIGRvIHRoZSBzYW1lIGNoZWNrL2ZsaXAgcmVjdXJzaXZlbHkgZm9yIHRoZSBuZXcgcGFpciBvZiB0cmlhbmdsZXMKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gICAgICAgICAgIHBsICAgICAgICAgICAgICAgICAgICBwbAogICAgICAgICAgICAvLyAgICAgICAgICAvfHxcICAgICAgICAgICAgICAgICAgLyAgXAogICAgICAgICAgICAvLyAgICAgICBhbC8gfHwgXGJsICAgICAgICAgICAgYWwvICAgIFxhCiAgICAgICAgICAgIC8vICAgICAgICAvICB8fCAgXCAgICAgICAgICAgICAgLyAgICAgIFwKICAgICAgICAgICAgLy8gICAgICAgLyAgYXx8YiAgXCAgICBmbGlwICAgIC9fX19hcl9fX1wKICAgICAgICAgICAgLy8gICAgIHAwXCAgIHx8ICAgL3AxICAgPT4gICBwMFwtLS1ibC0tLS9wMQogICAgICAgICAgICAvLyAgICAgICAgXCAgfHwgIC8gICAgICAgICAgICAgIFwgICAgICAvCiAgICAgICAgICAgIC8vICAgICAgIGFyXCB8fCAvYnIgICAgICAgICAgICAgYlwgICAgL2JyCiAgICAgICAgICAgIC8vICAgICAgICAgIFx8fC8gICAgICAgICAgICAgICAgICBcICAvCiAgICAgICAgICAgIC8vICAgICAgICAgICBwciAgICAgICAgICAgICAgICAgICAgcHIKICAgICAgICAgICAgY29uc3QgYiA9IHRoaXMuX2hhbGZlZGdlc1thXTsKICAgICAgICAgICAgaWYgKGIgPCAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYTAgPSBhIC0gKGEgJSAzKTsKICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYWwgPSBhMCArICgoYSArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFyID0gYTAgKyAoKGEgKyAyKSAlIDMpOwogICAgICAgICAgICBjb25zdCBibCA9IGIwICsgKChiICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgYnIgPSBiMCArICgoYiArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbYXJdOwogICAgICAgICAgICBjb25zdCBwciA9IHRoaXMudHJpYW5nbGVzW2FdOwogICAgICAgICAgICBjb25zdCBwbCA9IHRoaXMudHJpYW5nbGVzW2FsXTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLnRyaWFuZ2xlc1tibF07CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBpZiAoIWluQ2lyY2xlKGNvb3Jkc1syICogcDBdLCBjb29yZHNbMiAqIHAwICsgMV0sIGNvb3Jkc1syICogcHJdLCBjb29yZHNbMiAqIHByICsgMV0sIGNvb3Jkc1syICogcGxdLCBjb29yZHNbMiAqIHBsICsgMV0sIGNvb3Jkc1syICogcDFdLCBjb29yZHNbMiAqIHAxICsgMV0pKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgaGFsID0gdGhpcy5faGFsZmVkZ2VzW2FsXTsKICAgICAgICAgICAgY29uc3QgaGFyID0gdGhpcy5faGFsZmVkZ2VzW2FyXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYTAgLyAzKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcDEsIHBsLCAtMSwgaGJsLCBoYWwsIGEwKTsKICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDAsIHByLCB0MCwgaGFyLCBoYnIsIGIwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEgKyAyKTsKICAgICAgICB9CiAgICAgICAgLy8gaGFuZGxlIGEgY2FzZSB3aGVyZSBuZXcgdmVydGV4IGlzIG9uIHRoZSBlZGdlIG9mIGEgdHJpYW5nbGUKICAgICAgICBfaGFuZGxlQ29sbGluZWFyKHBuLCBhKSB7CiAgICAgICAgICAgIGNvbnN0IGEwID0gYSAtIChhICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFsID0gYTAgKyAoKGEgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBhciA9IGEwICsgKChhICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLnRyaWFuZ2xlc1thcl07CiAgICAgICAgICAgIGNvbnN0IHByID0gdGhpcy50cmlhbmdsZXNbYV07CiAgICAgICAgICAgIGNvbnN0IHBsID0gdGhpcy50cmlhbmdsZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYWwgPSB0aGlzLl9oYWxmZWRnZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYXIgPSB0aGlzLl9oYWxmZWRnZXNbYXJdOwogICAgICAgICAgICBjb25zdCBiID0gdGhpcy5faGFsZmVkZ2VzW2FdOwogICAgICAgICAgICBpZiAoYiA8IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocG4sIHAwLCBwciwgLTEsIGhhciwgLTEsIGEwKTsKICAgICAgICAgICAgICAgIGNvbnN0IHQxID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHBuLCBwbCwgdDAsIC0xLCBoYWwpOwogICAgICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQxICsgMik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYmwgPSBiMCArICgoYiArIDIpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGJyID0gYjAgKyAoKGIgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcHIsIHBuLCBoYXIsIC0xLCAtMSwgYTApOwogICAgICAgICAgICBjb25zdCB0MSA9IHRoaXMuX2FkZFRyaWFuZ2xlKHByLCBwMSwgcG4sIGhiciwgLTEsIHQwICsgMSwgYjApOwogICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAxLCBwbCwgcG4sIGhibCwgLTEsIHQxICsgMSk7CiAgICAgICAgICAgIGNvbnN0IHQzID0gdGhpcy5fYWRkVHJpYW5nbGUocGwsIHAwLCBwbiwgaGFsLCB0MCArIDIsIHQyICsgMSk7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEpOwogICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQzKTsKICAgICAgICB9CiAgICAgICAgLy8gcHJpb3JpdHkgcXVldWUgbWV0aG9kcwogICAgICAgIF9xdWV1ZVB1c2godCwgZXJyb3IsIHJtcykgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5fcXVldWUubGVuZ3RoOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSBpOwogICAgICAgICAgICB0aGlzLl9xdWV1ZS5wdXNoKHQpOwogICAgICAgICAgICB0aGlzLl9lcnJvcnMucHVzaChlcnJvcik7CiAgICAgICAgICAgIHRoaXMuX3Jtc1N1bSArPSBybXM7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcCgpIHsKICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlU3dhcCgwLCBuKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVEb3duKDAsIG4pOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcEJhY2soKSB7CiAgICAgICAgICAgIGNvbnN0IHQgPSB0aGlzLl9xdWV1ZS5wb3AoKTsKICAgICAgICAgICAgdGhpcy5fZXJyb3JzLnBvcCgpOwogICAgICAgICAgICB0aGlzLl9ybXNTdW0gLT0gdGhpcy5fcm1zW3RdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSAtMTsKICAgICAgICAgICAgcmV0dXJuIHQ7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVJlbW92ZSh0KSB7CiAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLl9xdWV1ZUluZGljZXNbdF07CiAgICAgICAgICAgIGlmIChpIDwgMCkgewogICAgICAgICAgICAgICAgY29uc3QgaXQgPSB0aGlzLl9wZW5kaW5nLmluZGV4T2YodCk7CiAgICAgICAgICAgICAgICBpZiAoaXQgIT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGVuZGluZ1tpdF0gPSB0aGlzLl9wZW5kaW5nWy0tdGhpcy5fcGVuZGluZ0xlbl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Jyb2tlbiB0cmlhbmd1bGF0aW9uIChzb21ldGhpbmcgd2VudCB3cm9uZykuJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIGlmIChuICE9PSBpKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZVN3YXAoaSwgbik7CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlRG93bihpLCBuKSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZUxlc3MoaSwgaikgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzW2ldID4gdGhpcy5fZXJyb3JzW2pdOwogICAgICAgIH0KICAgICAgICBfcXVldWVTd2FwKGksIGopIHsKICAgICAgICAgICAgY29uc3QgcGkgPSB0aGlzLl9xdWV1ZVtpXTsKICAgICAgICAgICAgY29uc3QgcGogPSB0aGlzLl9xdWV1ZVtqXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVbaV0gPSBwajsKICAgICAgICAgICAgdGhpcy5fcXVldWVbal0gPSBwaTsKICAgICAgICAgICAgdGhpcy5fcXVldWVJbmRpY2VzW3BpXSA9IGo7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1twal0gPSBpOwogICAgICAgICAgICBjb25zdCBlID0gdGhpcy5fZXJyb3JzW2ldOwogICAgICAgICAgICB0aGlzLl9lcnJvcnNbaV0gPSB0aGlzLl9lcnJvcnNbal07CiAgICAgICAgICAgIHRoaXMuX2Vycm9yc1tqXSA9IGU7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVVwKGowKSB7CiAgICAgICAgICAgIGxldCBqID0gajA7CiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpID0gKGogLSAxKSA+PiAxOwogICAgICAgICAgICAgICAgaWYgKGkgPT09IGogfHwgIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaiA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgX3F1ZXVlRG93bihpMCwgbikgewogICAgICAgICAgICBsZXQgaSA9IGkwOwogICAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICAgICAgY29uc3QgajEgPSAyICogaSArIDE7CiAgICAgICAgICAgICAgICBpZiAoajEgPj0gbiB8fCBqMSA8IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IGoyID0gajEgKyAxOwogICAgICAgICAgICAgICAgbGV0IGogPSBqMTsKICAgICAgICAgICAgICAgIGlmIChqMiA8IG4gJiYgdGhpcy5fcXVldWVMZXNzKGoyLCBqMSkpIHsKICAgICAgICAgICAgICAgICAgICBqID0gajI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaSA9IGo7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGkgPiBpMDsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbkNpcmNsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBweCwgcHkpIHsKICAgICAgICBjb25zdCBkeCA9IGF4IC0gcHg7CiAgICAgICAgY29uc3QgZHkgPSBheSAtIHB5OwogICAgICAgIGNvbnN0IGV4ID0gYnggLSBweDsKICAgICAgICBjb25zdCBleSA9IGJ5IC0gcHk7CiAgICAgICAgY29uc3QgZnggPSBjeCAtIHB4OwogICAgICAgIGNvbnN0IGZ5ID0gY3kgLSBweTsKICAgICAgICBjb25zdCBhcCA9IGR4ICogZHggKyBkeSAqIGR5OwogICAgICAgIGNvbnN0IGJwID0gZXggKiBleCArIGV5ICogZXk7CiAgICAgICAgY29uc3QgY3AgPSBmeCAqIGZ4ICsgZnkgKiBmeTsKICAgICAgICByZXR1cm4gZHggKiAoZXkgKiBjcCAtIGJwICogZnkpIC0gZHkgKiAoZXggKiBjcCAtIGJwICogZngpICsgYXAgKiAoZXggKiBmeSAtIGV5ICogZngpIDwgMDsKICAgIH0KCiAgICAvKioKICAgICAqIFdlYiBXb3JrZXIgZm9yIHRlcnJhaW4gbWVzaCB0ZXNzZWxsYXRpb24uCiAgICAgKiBSdW5zIE1hcnRpbmkvRGVsYXRpbiBhbGdvcml0aG1zIG9uIGEgYmFja2dyb3VuZCB0aHJlYWQgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIG1haW4gdGhyZWFkLgogICAgICovCiAgICAvLyBUcmFjayBhYm9ydGVkIHRhc2tzIHRvIGF2b2lkIHNlbmRpbmcgcmVzdWx0cyBmb3IgY2FuY2VsbGVkIHdvcmsKICAgIGNvbnN0IGFib3J0ZWRUYXNrcyA9IG5ldyBNYXAoKTsKICAgIHNlbGYub25tZXNzYWdlID0gKGUpID0+IHsKICAgICAgICBjb25zdCBkYXRhID0gZS5kYXRhOwogICAgICAgIGlmIChkYXRhLnR5cGUgPT09ICdhYm9ydCcpIHsKICAgICAgICAgICAgLy8gTWFyayB0YXNrIGFzIGFib3J0ZWQ7IGlmIGl0J3Mgc3RpbGwgY29tcHV0aW5nLCB3ZSdsbCBza2lwIHRoZSByZXNwb25zZQogICAgICAgICAgICBhYm9ydGVkVGFza3Muc2V0KGRhdGEudGFza0lkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBpZiAoZGF0YS50eXBlID09PSAnY29tcHV0ZU1lc2gnKSB7CiAgICAgICAgICAgIGNvbnN0IHsgdGFza0lkLCB0ZXJyYWluLCBtZXNoTWF4RXJyb3IsIHRlc3NlbGF0b3IsIHdpZHRoLCBoZWlnaHQgfSA9IGRhdGE7CiAgICAgICAgICAgIGxldCBtZXNoOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgaWYgKHRlc3NlbGF0b3IgPT09ICdkZWxhdGluJykgewogICAgICAgICAgICAgICAgICAgIC8vIERlbGF0aW4gdGVzc2VsbGF0aW9uCiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGluID0gbmV3IERlbGF0aW4odGVycmFpbiwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgdGluLnJ1bihtZXNoTWF4RXJyb3IpOwogICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3I6IERlbGF0aW4gaW5zdGFuY2UgcHJvcGVydGllcyAnY29vcmRzJyBhbmQgJ3RyaWFuZ2xlcycgYXJlIG5vdCBleHBsaWNpdGx5IHR5cGVkIGluIHRoZSBsaWJyYXJ5IHBvcnQKICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGNvb3JkcywgdHJpYW5nbGVzIH0gPSB0aW47CiAgICAgICAgICAgICAgICAgICAgLy8gY29vcmRzIGlzIGEgcGxhaW4gYXJyYXkg4oCUIGNvbnZlcnQgdG8gRmxvYXQ2NEFycmF5IHNvIGl0IGhhcyAuYnVmZmVyIGZvciB0cmFuc2ZlcgogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRpY2VzVHlwZWQgPSBGbG9hdDY0QXJyYXkuZnJvbShjb29yZHMpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyaWFuZ2xlc1R5cGVkID0gVWludDMyQXJyYXkuZnJvbSh0cmlhbmdsZXMpOwogICAgICAgICAgICAgICAgICAgIG1lc2ggPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzOiB2ZXJ0aWNlc1R5cGVkLAogICAgICAgICAgICAgICAgICAgICAgICB0cmlhbmdsZXM6IHRyaWFuZ2xlc1R5cGVkLAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyBNYXJ0aW5pIHRlc3NlbGxhdGlvbiAoZGVmYXVsdCkKICAgICAgICAgICAgICAgICAgICBjb25zdCBncmlkU2l6ZSA9IHdpZHRoID09PSAyNTcgPyAyNTcgOiB3aWR0aCArIDE7IC8vIE9ubHkgYWRkIDEgaWYgd2lkdGggaXMgbm90IGFscmVhZHkgMl5uKzEKICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXJ0aW5pID0gbmV3IE1hcnRpbmkoZ3JpZFNpemUpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbGUgPSBtYXJ0aW5pLmNyZWF0ZVRpbGUodGVycmFpbik7CiAgICAgICAgICAgICAgICAgICAgbWVzaCA9IHRpbGUuZ2V0TWVzaChtZXNoTWF4RXJyb3IpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gT25seSBzZW5kIHJlc3VsdCBpZiBub3QgYWJvcnRlZAogICAgICAgICAgICAgICAgaWYgKCFhYm9ydGVkVGFza3MuZ2V0KHRhc2tJZCkpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ21lc2hSZXN1bHQnLAogICAgICAgICAgICAgICAgICAgICAgICB0YXNrSWQsCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogbWVzaCwKICAgICAgICAgICAgICAgICAgICAgICAgdGVycmFpbiwgLy8g4oaQIENSSVRJQ0FMOiBSZXR1cm4gdGVycmFpbiBidWZmZXIgdG8gbWFpbiB0aHJlYWQKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIC8vIFRyYW5zZmVyIG93bmVyc2hpcCBvZiBBTEwgYnVmZmVycyBiYWNrIHRvIG1haW4gdGhyZWFkICh6ZXJvLWNvcHkgcm91bmR0cmlwKQogICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgYXZvaWRzIG1lc2hUZXJyYWluLnNsaWNlKCkgYWxsb2NhdGlvbiBvbiBtYWluIHRocmVhZAogICAgICAgICAgICAgICAgICAgIHNlbGYucG9zdE1lc3NhZ2UocmVzcG9uc2UsIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmZXI6IFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc2gudmVydGljZXMuYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzaC50cmlhbmdsZXMuYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi5idWZmZXIsIC8vIOKGkCBUcmFuc2ZlciB0ZXJyYWluIGJhY2sKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVwb3J0IGVycm9ycyBmb3Igbm9uLWFib3J0ZWQgdGFza3MKICAgICAgICAgICAgICAgIGlmICghYWJvcnRlZFRhc2tzLmdldCh0YXNrSWQpKSB7CiAgICAgICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdlcnJvcicsCiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2tJZCwKICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmaW5hbGx5IHsKICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIGFib3J0IHRyYWNraW5nCiAgICAgICAgICAgICAgICBhYm9ydGVkVGFza3MuZGVsZXRlKHRhc2tJZCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9OwogICAgLy8gU2lnbmFsIHRoYXQgd29ya2VyIGlzIHJlYWR5CiAgICBzZWxmLnBvc3RNZXNzYWdlKHsgdHlwZTogJ3JlYWR5JyB9KTsKCn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPXRlcnJhaW4ud29ya2VyLmpzLm1hcAoK');
|
|
6784
|
+
/* eslint-enable */
|
|
6785
|
+
|
|
6786
|
+
/**
|
|
6787
|
+
* Pool of Web Workers for parallel terrain tessellation.
|
|
6788
|
+
* Distributes work across multiple workers based on CPU core count.
|
|
6789
|
+
*
|
|
6790
|
+
* SINGLETON PATTERN: One global pool is shared across all CogTiles instances
|
|
6791
|
+
* to avoid expensive worker creation/destruction during deck.gl layer recreations.
|
|
6792
|
+
*/
|
|
6793
|
+
// @ts-expect-error - The import statement will be handled by both Rollup (web-worker: prefix)
|
|
6794
|
+
// and our Vite plugin (web-worker: → ?worker conversion)
|
|
6795
|
+
/**
|
|
6796
|
+
* Manages a pool of terrain tessellation workers.
|
|
6797
|
+
* Automatically scales to CPU core count (capped at 8 for memory safety).
|
|
6798
|
+
*/
|
|
6799
|
+
class TerrainWorkerPool {
|
|
6800
|
+
workers = [];
|
|
6801
|
+
pendingTasks = new Map();
|
|
6802
|
+
taskCounter = 0;
|
|
6803
|
+
roundRobinIndex = 0;
|
|
6804
|
+
constructor(poolSize) {
|
|
6805
|
+
// Default to CPU core count, fallback to 4, cap at 8 to prevent memory exhaustion
|
|
6806
|
+
const defaultSize = Math.min(navigator.hardwareConcurrency || 4, 8);
|
|
6807
|
+
// On low-memory devices (<4GB), use only 2 workers to avoid OOM
|
|
6808
|
+
const memoryAdjustedSize = navigator.deviceMemory && navigator.deviceMemory < 4
|
|
6809
|
+
? 2
|
|
6810
|
+
: defaultSize;
|
|
6811
|
+
const size = poolSize ?? memoryAdjustedSize;
|
|
6812
|
+
for (let i = 0; i < size; i++) {
|
|
6813
|
+
const worker = new WorkerFactory();
|
|
6814
|
+
worker.onmessage = this.handleWorkerMessage.bind(this);
|
|
6815
|
+
worker.onerror = this.handleWorkerError.bind(this);
|
|
6816
|
+
this.workers.push(worker);
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
/**
|
|
6820
|
+
* Compute terrain mesh using the worker pool.
|
|
6821
|
+
* Returns a Promise that resolves with the mesh data.
|
|
6822
|
+
* Supports cancellation via AbortSignal.
|
|
6823
|
+
*/
|
|
6824
|
+
async computeMesh(options) {
|
|
6825
|
+
const { terrain, meshMaxError, tesselator, width, height, signal } = options;
|
|
6826
|
+
// Check if already aborted
|
|
6827
|
+
if (signal?.aborted) {
|
|
6828
|
+
throw new DOMException('Aborted', 'AbortError');
|
|
6829
|
+
}
|
|
6830
|
+
const taskId = `task_${++this.taskCounter}`;
|
|
6831
|
+
return new Promise((resolve, reject) => {
|
|
6832
|
+
// Pick worker once — used for both dispatch and abort to ensure correct routing
|
|
6833
|
+
const worker = this.getNextWorker();
|
|
6834
|
+
const task = { resolve, reject, aborted: false, worker };
|
|
6835
|
+
this.pendingTasks.set(taskId, task);
|
|
6836
|
+
// Handle abort signal
|
|
6837
|
+
if (signal) {
|
|
6838
|
+
signal.addEventListener('abort', () => {
|
|
6839
|
+
// Guard against late aborts: only process if task still exists
|
|
6840
|
+
if (!this.pendingTasks.has(taskId)) {
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6843
|
+
task.aborted = true;
|
|
6844
|
+
this.pendingTasks.delete(taskId);
|
|
6845
|
+
// Send abort to the same worker that owns this task
|
|
6846
|
+
worker.postMessage({ type: 'abort', taskId });
|
|
6847
|
+
reject(new DOMException('Aborted', 'AbortError'));
|
|
6848
|
+
}, { once: true });
|
|
6849
|
+
}
|
|
6850
|
+
// Transfer terrain buffer ownership to avoid copy
|
|
6851
|
+
// NOTE: After this, `terrain` becomes detached on main thread
|
|
6852
|
+
worker.postMessage({
|
|
6853
|
+
type: 'computeMesh',
|
|
6854
|
+
taskId,
|
|
6855
|
+
terrain,
|
|
6856
|
+
meshMaxError,
|
|
6857
|
+
tesselator,
|
|
6858
|
+
width,
|
|
6859
|
+
height,
|
|
6860
|
+
}, [terrain.buffer] // ← Transferable
|
|
6861
|
+
);
|
|
6862
|
+
});
|
|
6863
|
+
}
|
|
6864
|
+
getNextWorker() {
|
|
6865
|
+
const worker = this.workers[this.roundRobinIndex];
|
|
6866
|
+
this.roundRobinIndex = (this.roundRobinIndex + 1) % this.workers.length;
|
|
6867
|
+
return worker;
|
|
6868
|
+
}
|
|
6869
|
+
handleWorkerMessage(e) {
|
|
6870
|
+
const { type, taskId, result, terrain, error } = e.data;
|
|
6871
|
+
if (type === 'ready') {
|
|
6872
|
+
// Worker initialization complete (can be ignored)
|
|
6873
|
+
return;
|
|
6874
|
+
}
|
|
6875
|
+
const task = this.pendingTasks.get(taskId);
|
|
6876
|
+
if (!task) {
|
|
6877
|
+
// Task was aborted or already resolved
|
|
6878
|
+
return;
|
|
6879
|
+
}
|
|
6880
|
+
this.pendingTasks.delete(taskId);
|
|
6881
|
+
if (task.aborted) {
|
|
6882
|
+
// Ignore result for aborted task
|
|
6883
|
+
return;
|
|
6884
|
+
}
|
|
6885
|
+
if (type === 'meshResult') {
|
|
6886
|
+
// Combine result with terrain that was transferred back
|
|
6887
|
+
task.resolve({
|
|
6888
|
+
vertices: result.vertices,
|
|
6889
|
+
triangles: result.triangles,
|
|
6890
|
+
terrain, // ← Include terrain from message
|
|
6891
|
+
});
|
|
6892
|
+
}
|
|
6893
|
+
else if (type === 'error') {
|
|
6894
|
+
task.reject(new Error(`Worker error: ${error}`));
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
handleWorkerError(e) {
|
|
6898
|
+
// Find which worker failed (e.target is the Worker instance)
|
|
6899
|
+
const failedWorker = e.target;
|
|
6900
|
+
// Find all pending tasks assigned to this worker
|
|
6901
|
+
const failedTaskIds = [];
|
|
6902
|
+
this.pendingTasks.forEach((task, taskId) => {
|
|
6903
|
+
if (task.worker === failedWorker) {
|
|
6904
|
+
failedTaskIds.push(taskId);
|
|
6905
|
+
}
|
|
6906
|
+
});
|
|
6907
|
+
// Reject all tasks for the failed worker
|
|
6908
|
+
for (const taskId of failedTaskIds) {
|
|
6909
|
+
const task = this.pendingTasks.get(taskId);
|
|
6910
|
+
if (task) {
|
|
6911
|
+
this.pendingTasks.delete(taskId);
|
|
6912
|
+
task.reject(new Error(`Worker crashed: ${e.message || 'Unknown error'}`));
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
// Respawn the failed worker to maintain pool capacity
|
|
6916
|
+
const workerIndex = this.workers.indexOf(failedWorker);
|
|
6917
|
+
if (workerIndex !== -1) {
|
|
6918
|
+
try {
|
|
6919
|
+
const newWorker = new WorkerFactory();
|
|
6920
|
+
newWorker.onmessage = this.handleWorkerMessage.bind(this);
|
|
6921
|
+
newWorker.onerror = this.handleWorkerError.bind(this);
|
|
6922
|
+
this.workers[workerIndex] = newWorker;
|
|
6923
|
+
}
|
|
6924
|
+
catch (spawnError) {
|
|
6925
|
+
// eslint-disable-next-line no-console
|
|
6926
|
+
console.error('[TerrainWorkerPool] Failed to respawn worker:', spawnError);
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
}
|
|
6930
|
+
/**
|
|
6931
|
+
* Terminate all workers.
|
|
6932
|
+
* ⚠️ NOTE: Because this is a singleton, terminate() should only be called
|
|
6933
|
+
* on app shutdown, not on individual layer unmount.
|
|
6934
|
+
*/
|
|
6935
|
+
terminate() {
|
|
6936
|
+
// Reject all pending tasks before terminating workers
|
|
6937
|
+
this.pendingTasks.forEach(task => {
|
|
6938
|
+
task.reject(new DOMException('Worker pool terminated', 'AbortError'));
|
|
6939
|
+
});
|
|
6940
|
+
this.pendingTasks.clear();
|
|
6941
|
+
this.workers.forEach(w => w.terminate());
|
|
6942
|
+
this.workers = [];
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6945
|
+
// ─── SINGLETON INSTANCE ───
|
|
6946
|
+
// Lazily initialized on first use; shared across all CogTiles instances
|
|
6947
|
+
let globalWorkerPool = null;
|
|
6948
|
+
/**
|
|
6949
|
+
* Gets the global terrain worker pool, creating it on first use.
|
|
6950
|
+
* All CogTiles instances share this pool to avoid expensive worker churn
|
|
6951
|
+
* during deck.gl layer recreations.
|
|
6952
|
+
*/
|
|
6953
|
+
function getGlobalTerrainWorkerPool() {
|
|
6954
|
+
if (!globalWorkerPool) {
|
|
6955
|
+
globalWorkerPool = new TerrainWorkerPool();
|
|
6956
|
+
}
|
|
6957
|
+
return globalWorkerPool;
|
|
6958
|
+
}
|
|
6959
|
+
/**
|
|
6960
|
+
* Terminates the global worker pool.
|
|
6961
|
+
* Only call this on app shutdown, not on layer unmount.
|
|
6962
|
+
*/
|
|
6963
|
+
function terminateGlobalTerrainWorkerPool() {
|
|
6964
|
+
if (globalWorkerPool) {
|
|
6965
|
+
globalWorkerPool.terminate();
|
|
6966
|
+
globalWorkerPool = null;
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
|
|
6739
6970
|
const EARTH_CIRCUMFERENCE = 2 * Math.PI * 6378137;
|
|
6740
6971
|
const EARTH_HALF_CIRCUMFERENCE = EARTH_CIRCUMFERENCE / 2;
|
|
6741
6972
|
const webMercatorOrigin = [-20037508.342789244, 20037508.342789244];
|
|
@@ -7089,12 +7320,18 @@ class CogTiles {
|
|
|
7089
7320
|
// future cache hits just await the already-resolved promise directly.
|
|
7090
7321
|
cache = new TileCacheManager();
|
|
7091
7322
|
tileReader;
|
|
7323
|
+
workerPool; // TerrainWorkerPool (for terrain tiles)
|
|
7092
7324
|
// Store initialization promise to prevent concurrent duplicate initializations
|
|
7093
7325
|
initializePromise;
|
|
7094
7326
|
// Track the last successfully initialized URL to detect URL changes
|
|
7095
7327
|
lastInitializedUrl;
|
|
7096
7328
|
constructor(options) {
|
|
7097
7329
|
this.options = { ...CogTilesGeoImageOptionsDefaults, ...options };
|
|
7330
|
+
// Get reference to global worker pool for terrain tiles
|
|
7331
|
+
// Do NOT create a new pool per instance — reuse the singleton
|
|
7332
|
+
if (options.type === 'terrain') {
|
|
7333
|
+
this.workerPool = getGlobalTerrainWorkerPool();
|
|
7334
|
+
}
|
|
7098
7335
|
}
|
|
7099
7336
|
async initializeCog(url) {
|
|
7100
7337
|
// Reuse existing initialization while it is in progress, or when the same URL
|
|
@@ -7626,7 +7863,7 @@ class CogTiles {
|
|
|
7626
7863
|
height: requiredSize,
|
|
7627
7864
|
bounds: bounds ?? [0, 0, 0, 0],
|
|
7628
7865
|
cellSizeMeters,
|
|
7629
|
-
}, generatorOptions, resolvedMeshMaxError);
|
|
7866
|
+
}, generatorOptions, resolvedMeshMaxError, this.workerPool, controller.signal);
|
|
7630
7867
|
})();
|
|
7631
7868
|
const entry = {
|
|
7632
7869
|
promise: pipeline,
|
|
@@ -7680,7 +7917,7 @@ class CogTiles {
|
|
|
7680
7917
|
height: this.tileSize,
|
|
7681
7918
|
bounds: bounds ?? [0, 0, 0, 0],
|
|
7682
7919
|
cellSizeMeters,
|
|
7683
|
-
}, this.options, meshMaxError ?? 4.0);
|
|
7920
|
+
}, this.options, meshMaxError ?? 4.0, this.workerPool, signal);
|
|
7684
7921
|
}
|
|
7685
7922
|
async getBitmapTile(x, y, z, bounds, cellSizeMeters, meshMaxError, signal) {
|
|
7686
7923
|
const rasterKey = this.cache.getTileCacheKey(x, y, z);
|
|
@@ -7702,7 +7939,7 @@ class CogTiles {
|
|
|
7702
7939
|
height: this.tileSize,
|
|
7703
7940
|
bounds: bounds ?? [0, 0, 0, 0],
|
|
7704
7941
|
cellSizeMeters,
|
|
7705
|
-
}, this.options, meshMaxError ?? 4.0);
|
|
7942
|
+
}, this.options, meshMaxError ?? 4.0, this.workerPool);
|
|
7706
7943
|
}
|
|
7707
7944
|
async getTileAllBands(x, y, z, meshMaxError, signal, bounds) {
|
|
7708
7945
|
if (!this.cog) {
|
|
@@ -7799,7 +8036,7 @@ class CogTiles {
|
|
|
7799
8036
|
height: FETCH_SIZE,
|
|
7800
8037
|
bounds: bounds ?? [0, 0, 0, 0],
|
|
7801
8038
|
cellSizeMeters,
|
|
7802
|
-
}, generatorOptions, resolvedMeshMaxError);
|
|
8039
|
+
}, generatorOptions, resolvedMeshMaxError, this.workerPool, signal);
|
|
7803
8040
|
if (tileResult)
|
|
7804
8041
|
results.push(tileResult);
|
|
7805
8042
|
}
|
|
@@ -15679,4 +15916,5 @@ exports.GeoImage = GeoImage;
|
|
|
15679
15916
|
exports.extractTerrainCoordinate = extractTerrainCoordinate;
|
|
15680
15917
|
exports.sampleTerrainTileCoordinates = sampleTerrainTileCoordinates;
|
|
15681
15918
|
exports.suppressGlobalAbortErrors = suppressGlobalAbortErrors;
|
|
15919
|
+
exports.terminateGlobalTerrainWorkerPool = terminateGlobalTerrainWorkerPool;
|
|
15682
15920
|
//# sourceMappingURL=index.js.map
|