mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 08:47:07 +00:00
Add DougalBinaryLoader Deck.gl loader
This commit is contained in:
146
lib/www/client/source/src/lib/deck.gl/DougalBinaryLoader.js
Normal file
146
lib/www/client/source/src/lib/deck.gl/DougalBinaryLoader.js
Normal file
@@ -0,0 +1,146 @@
|
||||
// src/lib/deck.gl/DougalBinaryLoader.js
|
||||
import { LoaderObject } from '@loaders.gl/core';
|
||||
import { DougalBinaryBundle } from '@dougal/binary';
|
||||
|
||||
async function cachedFetch(url, init, opts = {}) {
|
||||
let res; // The response
|
||||
let cache; // Potentially, a Cache API cache name
|
||||
let isCached;
|
||||
|
||||
if (opts?.cache === true) {
|
||||
opts.cache = { name: "dougal" };
|
||||
} else if (typeof opts?.cache === "string") {
|
||||
opts.cache = { name: opts.cache };
|
||||
} else if (opts?.cache) {
|
||||
if (!(opts.cache instanceof Object)) {
|
||||
opts.cache = { name: "dougal" }
|
||||
} else if (!(opts.cache.name)) {
|
||||
opts.cache.name = "dougal";
|
||||
}
|
||||
}
|
||||
|
||||
if (opts?.cache) {
|
||||
cache = await caches.open(opts.cache.name);
|
||||
res = await cache.match(url);
|
||||
isCached = !!res;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
res = await fetch(url, init);
|
||||
}
|
||||
|
||||
if (cache && !isCached) {
|
||||
cache.put(url, res.clone());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const DougalBinaryLoader = {
|
||||
name: 'DougalBinaryBundle Loader',
|
||||
extensions: ['dbb'],
|
||||
mimeTypes: ['application/vnd.aaltronav.dougal+octet-stream'],
|
||||
parse: async (input, options) => {
|
||||
let arrayBuffer;
|
||||
if (typeof input === 'string') {
|
||||
// Input is URL, fetch with caching
|
||||
const response = await cachedFetch(input, options?.fetch, options);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch: ${response.statusText}`);
|
||||
}
|
||||
arrayBuffer = await response.arrayBuffer();
|
||||
} else if (input instanceof ArrayBuffer) {
|
||||
arrayBuffer = input;
|
||||
} else {
|
||||
throw new Error('Invalid input: Expected URL string or ArrayBuffer');
|
||||
}
|
||||
|
||||
const bundle = DougalBinaryBundle.clone(arrayBuffer);
|
||||
|
||||
// Calculate total points
|
||||
const totalCount = bundle.chunks().reduce((acc, chunk) => acc + chunk.jCount, 0);
|
||||
|
||||
// Prepare positions (Float32Array: [lon1, lat1, lon2, lat2, ...])
|
||||
const positions = new Float32Array(totalCount * 2);
|
||||
|
||||
// Extract udv (assume constant across chunks)
|
||||
const udv = bundle.chunks()[0].udv;
|
||||
|
||||
// Prepare values as an array of TypedArrays
|
||||
const ΔelemCount = bundle.chunks()[0].ΔelemCount;
|
||||
const elemCount = bundle.chunks()[0].elemCount;
|
||||
const values = new Array(ΔelemCount + elemCount + 2);
|
||||
|
||||
// Initialize values arrays with correct types
|
||||
if (udv == 0) {
|
||||
for (let k = 0; k < values.length; k++) {
|
||||
values[k] = new (k === 0 ? Uint16Array : k === 1 ? Uint32Array : Uint8Array)(totalCount);
|
||||
}
|
||||
} else if (udv == 1) {
|
||||
for (let k = 0; k < values.length; k++) {
|
||||
values[k] = new (k === 0 ? Uint16Array : k === 1 ? Uint32Array : k === 2 ? Uint8Array : Uint16Array)(totalCount);
|
||||
}
|
||||
} else if (udv == 2) {
|
||||
for (let k = 0; k < values.length; k++) {
|
||||
values[k] = new (k === 0 ? Uint16Array : k === 1 ? Uint32Array : k === 2 ? BigUint64Array : Float32Array)(totalCount);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Invalid udv: Expected 0, 1, or 2; found ${udv}`);
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
for (const chunk of bundle.chunks()) {
|
||||
const λarray = chunk.elem(0);
|
||||
const φarray = chunk.elem(1);
|
||||
for (let i = 0; i < λarray.length; i++) {
|
||||
positions[offset * 2 + i * 2] = λarray[i];
|
||||
positions[offset * 2 + i * 2 + 1] = φarray[i];
|
||||
}
|
||||
|
||||
values[0].set(new Uint16Array(chunk.jCount).fill(chunk.i), offset);
|
||||
values[1].set(Uint32Array.from({ length: chunk.jCount }, (_, i) => chunk.j0 + i * chunk.Δj), offset);
|
||||
|
||||
for (let j = 0; j < ΔelemCount; j++) {
|
||||
values[2 + j].set(chunk.Δelem(j), offset);
|
||||
}
|
||||
for (let j = 2; j < elemCount; j++) {
|
||||
values[2 + ΔelemCount + j - 2].set(chunk.elem(j), offset);
|
||||
}
|
||||
|
||||
offset += chunk.jCount;
|
||||
}
|
||||
|
||||
console.log(`Parsed ${totalCount} points, ${values.length} value arrays`);
|
||||
|
||||
const attributes = {
|
||||
getPosition: {
|
||||
value: positions,
|
||||
type: 'float32',
|
||||
size: 2
|
||||
},
|
||||
udv
|
||||
};
|
||||
|
||||
values.forEach((valArray, k) => {
|
||||
let value = valArray;
|
||||
if (valArray instanceof BigUint64Array) {
|
||||
value = Float64Array.from(valArray, v => Number(v));
|
||||
}
|
||||
attributes[`value${k}`] = {
|
||||
value,
|
||||
type: value instanceof Float64Array ? 'float64' :
|
||||
value instanceof Uint16Array ? 'uint16' :
|
||||
value instanceof Uint32Array ? 'uint32' : 'float32',
|
||||
size: 1
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
length: totalCount,
|
||||
attributes
|
||||
};
|
||||
},
|
||||
options: {} // Optional: Add custom options if needed
|
||||
};
|
||||
|
||||
export default DougalBinaryLoader;
|
||||
Reference in New Issue
Block a user