videx-3d
Version:
React 3D component library designed for sub surface visualizations in the browser
611 lines (610 loc) • 22.1 kB
JavaScript
import { wrap as Z } from "comlink";
import $ from "p-limit";
import { x as ct, D as ft, P as ut, b as dt, a as gt, c as pt, T as wt, y as yt, z as mt, A as xt, B as bt, p as vt, d as _t, E as Mt, F as At, G as Ft, H as Lt, I as St, J as Vt, K as It, L as Bt, M as Et, e as Tt, N as Dt, o as qt, O as zt, Q as Gt, R as kt, i as Pt, S as jt, U as Nt, V as Ct, X as Qt, g as Ut, Y as Wt, Z as Ht, _ as Zt, $ as $t, h as Jt, m as Kt, a0 as Ot, a1 as Xt, a2 as Yt, n as Rt, a3 as te, f as ee, a4 as se, a5 as ie, a6 as re, a7 as ne, a8 as ae, a9 as le, aa as oe, ab as he, ac as ce, ad as fe, ae as ue, af as de, ag as ge, s as pe, ah as we, ai as ye, aj as me, u as xe, ak as be } from "./chunk-iY0wQ9Z6.js";
import { C as _e, T as Me, c as Ae, b as Fe, a as Le, d as Se, e as Ve, g as Ie, f as Be, t as Ee, h as Te, w as De } from "./chunk-CnY6Tmof.js";
import { D as ze, c as Ge, a as ke, b as Pe, t as je, d as Ne } from "./chunk-MFzFdEWm.js";
const J = 10, K = 25;
class Y {
store;
config;
cached = /* @__PURE__ */ new Map();
_activeLoaders = {};
_batchqueue = /* @__PURE__ */ new Map();
_flushScheduled = null;
constructor(t, e = {}) {
this.store = t, this.config = { ...e }, this.config.batched && (this.config.batchSize === void 0 && (this.config.batchSize = J), this.config.batchMaxDelay === void 0 && (this.config.batchMaxDelay = K)), this._flushScheduled = null;
}
async init(...t) {
if (this.config.init)
try {
const e = await this.config.init(...t);
if (Array.isArray(e))
return this.cached = new Map(e), !0;
} catch (e) {
console.warn("Init failed", e);
}
return this.clear(), !1;
}
async all() {
if (this.config.preloaded) {
if (this.config.transform) {
const t = this.config.transform;
return Array.from(this.cached.values()).map((e) => t(e));
}
return Array.from(this.cached.values());
} else
console.warn('Data Loader: "all" called on non-preloaded dataset!');
return [];
}
async _enqueueRequest(t) {
if (this._batchqueue.has(t))
return this._batchqueue.get(t).promise;
let e = null;
const i = new Promise((n) => {
e = n;
}), r = {
key: t,
promise: i,
_resolve: e
};
return this._batchqueue.set(t, r), this._flushScheduled || (this._flushScheduled = setTimeout(() => {
this._processBatchQueue();
}, this.config.batchMaxDelay)), i;
}
async _processBatch(t) {
const e = t.map((i) => i.key);
if (!this.config.batchLoad) return null;
this.config.batchLoad(e).then((i) => {
Array.isArray(i) && i.forEach(([r, n]) => {
this.set(r, n);
});
}).catch((i) => {
console.warn("Batch load failed", i);
}).finally(() => {
t.forEach((i) => {
const r = this.cached.get(i.key) || null;
i._resolve(r);
});
});
}
async _processBatchQueue() {
let t = [];
for (const e of this._batchqueue.values())
t.push(e), this._batchqueue.delete(e.key), (t.length >= this.config.batchSize || this._batchqueue.size === 0) && (this._processBatch(t), t = []);
this._batchqueue.size ? this._flushScheduled = setTimeout(() => this._processBatchQueue(), 1) : this._flushScheduled = null;
}
async get(t, e) {
if (this.cached.has(t))
return this.config.transform ? this.config.transform(this.cached.get(t)) : this.cached.get(t);
if (this.config.preloaded) return null;
if (!this.config.batched && this.config.load) {
if (this.config.noCache)
return this.config.load(t, e);
let i = this._activeLoaders[t];
if (!i) {
if (e)
throw Error(
"DataLoader: A load function with additional args may not be cached. Set noCache to true in config."
);
i = this.config.load(t).then((r) => {
r && this.cached.set(t, r);
}).catch((r) => {
console.warn("Load failed", r);
}).finally(() => {
delete this._activeLoaders[t];
}), this._activeLoaders[t] = i;
}
return await i, this.config.transform ? this.config.transform(this.cached.get(t)) : this.cached.get(t);
}
return this.config.batched && this.config.batchLoad ? this._enqueueRequest(t) : null;
}
set(t, e) {
this.cached.set(t, e);
}
clear() {
this.cached.clear();
}
}
class R {
store = null;
config;
generators = /* @__PURE__ */ new Map();
constructor(t = {}, e) {
this.config = { concurrentStoreCalls: 0, ...t }, e && this.setStore(e);
}
add(t, e) {
this.generators.set(t, e);
}
setStore(t) {
if (t && this.config.concurrentStoreCalls) {
const e = $(this.config.concurrentStoreCalls), i = {
get: (r, n, s) => e(() => t.get(r, n, s)),
all: (r) => e(() => t.all(r)),
query: (r, n) => e(() => t.query(r, n))
};
this.store = i;
} else
this.store = t;
}
async connectRemoteStore(t) {
const e = Z(t);
this.setStore(e);
}
async invoke(t, ...e) {
if (!this.store) throw Error("No available store!");
if (!this.generators.has(t))
throw Error(`Generator with key '${t}' not found!`);
return this.generators.get(t).bind(this.store)(...e);
}
}
function tt(u, t, e = 1, i = 1, r = (n) => n) {
console.time("triangulate");
const n = [], s = [], a = [], c = [], h = u.length / t;
let l, o, d, g, v, y, m, _, A, S, b, V, M, F, L, k, f, C, D, q, z, p, x, Q, H = 0, U = 0, W = 0, B = new Array(t).fill(null), P = new Array(t).fill(null);
const w = new Array(t - 1).fill(null);
function j(I, T, G) {
return n.push({ x: I * e, y: G, z: T * i, edge: null }), a.push(I / (t - 1), 1 - T / (h - 1)), H++;
}
function E(I, T, G) {
D = {
index: U++,
tail: I,
head: T,
twin: null,
prev: null,
next: null
}, q = {
index: U++,
tail: T,
head: G,
twin: null,
prev: null,
next: null
}, z = {
index: U++,
tail: G,
head: I,
twin: null,
prev: null,
next: null
}, D.next = q, q.next = z, z.next = D, D.prev = z, q.prev = D, z.prev = q, n[I].edge || (n[I].edge = D), n[T].edge || (n[T].edge = q), n[G].edge || (n[G].edge = z), s.push(D, q, z), c.push(I, T, G);
}
for (k = 1; k < h - 1; k++) {
Q = !1;
const I = B;
for (B = P, P = I.fill(null), p = null, C = k - 1, W += t, L = 1; L < t - 1; L++)
f = L - 1, S = W + L, A = S - 1, _ = S - t, m = _ - 1, b = r(u[m]), V = r(u[_]), M = r(u[A]), F = r(u[S]), b !== null && V !== null && M !== null && F !== null ? x = 1 : b !== null && V !== null && M !== null ? x = 2 : b !== null && V !== null && F !== null ? x = 3 : b !== null && M !== null && F !== null ? x = 4 : V !== null && M !== null && F !== null ? x = 5 : x = 0, d = null, g = null, x !== 0 ? (Q ? (l = B[f], d = P[f]) : (x !== 5 && (B[f] === null ? (l = j(f, C, b), B[f] = l) : l = B[f]), x !== 3 && (d = j(f, k, M)), P[f] = d), x !== 4 && (B[L] === null ? (o = j(L, C, V), B[L] = o) : o = B[L]), x !== 2 && (g = j(L, k, F)), x === 1 ? (v = Math.abs(n[l].y - n[g].y), y = Math.abs(n[o].y - n[d].y), v < y ? (E(l, d, g), p !== null && (s[s.length - 3].twin = p, p.twin = s[s.length - 3]), E(g, o, l), w[f] !== null && (s[s.length - 2].twin = w[f], w[f].twin = s[s.length - 2]), s[s.length - 4].twin = s[s.length - 1], s[s.length - 1].twin = s[s.length - 4], w[f] = s[s.length - 5], p = s[s.length - 3]) : (E(l, d, o), w[f] !== null && (s[s.length - 1].twin = w[f], w[f].twin = s[s.length - 1]), p !== null && (s[s.length - 3].twin = p, p.twin = s[s.length - 3]), E(o, d, g), s[s.length - 5].twin = s[s.length - 3], s[s.length - 3].twin = s[s.length - 5], w[f] = s[s.length - 2], p = s[s.length - 1])) : x === 2 ? (E(l, d, o), w[f] !== null && (s[s.length - 1].twin = w[f], w[f].twin = s[s.length - 1]), p !== null && (s[s.length - 3].twin = p, p.twin = s[s.length - 3]), w[f] = null, p = null) : x === 5 ? (E(o, d, g), w[f] = s[s.length - 2], p = s[s.length - 1]) : x === 3 ? (E(o, l, g), w[f] !== null && (s[s.length - 3].twin = w[f], w[f].twin = s[s.length - 3]), w[f] = null, p = s[s.length - 1]) : (E(l, d, g), p !== null && (s[s.length - 3].twin = p, p.twin = s[s.length - 3]), w[f] = s[s.length - 2], p = null)) : (w[f] = null, p = null), P[L] = g, Q = !!x;
}
return console.timeEnd("triangulate"), console.log(c.length / 3), { vertices: n, indices: c, uvs: a, edges: s };
}
const et = (u) => `#${u.toString(16).padStart(6, "0")}`;
function st() {
const u = "123456789ABCDEF";
let t = "#";
for (let e = 0; e < 6; e++)
t += u[Math.floor(Math.random() * 16)];
return t;
}
async function it(u, t = -1, e = null) {
const i = await u.arrayBuffer(), r = new DataView(i), n = {
ny: r.getInt32(8, !1),
xori: r.getFloat32(12, !1),
xmax: r.getFloat32(16, !1),
yori: r.getFloat32(20, !1),
ymax: r.getFloat32(24, !1),
xinc: r.getFloat32(28, !1),
yinc: r.getFloat32(32, !1),
nx: r.getInt32(44, !1),
rot: r.getFloat32(48, !1)
}, s = 1e30, a = 1e-30, c = new Float32Array(n.nx * n.ny);
let h, l, o, d, g, v = 0, y = 100;
for (; y < r.byteLength; ) {
l = r.getInt32(y), y += 4;
for (let m = 0; m < l; m += 4)
h = r.getFloat32(y + m, !1), o = v % n.nx, d = n.ny - Math.floor(v / n.nx), g = (d - 1) * n.nx + o, c[g] = h < a || h > s ? t : e ? e - h : h, v++;
y += l + 4;
}
return { header: n, data: c };
}
function rt(u) {
return u.map((t) => -t);
}
function nt(u, t) {
return u.map((e) => e * t);
}
function at(u, t, e) {
const i = (r) => {
if (r.userData[u] && r.userData[u] === t)
return r;
if (r.children && r.children.length)
for (let n = 0; n < r.children.length; n++) {
const s = i(r.children[n]);
if (s)
return s;
}
return null;
};
return i(e);
}
class N {
data;
columns;
rows;
stride;
_rowLength;
_lerpFn = [];
arrayConstructor;
constructor(t, e, i = 1) {
this.data = t, this.columns = e, this.stride = i, this._rowLength = e * i, this.rows = this.data.length / this._rowLength, this.arrayConstructor = (r) => new this.data.constructor(
r
);
}
static readWriteBlock(t, e, i, r, n, s, a, c, h, l, o = null) {
if (!(t instanceof N && s instanceof N))
throw Error("Source and target must be of type Typed2dArray");
if (a < 0 || a + h > s.columns || c < 0 || c + l > s.rows)
throw Error("Invalid target block dimensions!");
if (e < 0 || e + r > t.columns || i < 0 || i + n > t.rows)
throw Error("Invalid source block dimensions!");
const d = Math.max(1, h - 1), g = Math.max(1, l - 1), v = Math.max(1, r - 1), y = Math.max(1, n - 1);
for (let m = 0; m < l; m++) {
const _ = s.index(0, m + c), A = m / g * y + i;
for (let S = 0; S < h; S++) {
const b = _ + (S + a) * s.stride, V = S / d * v + e;
let M = t.valueAt(V, A);
if (o && (M = o(M)), s.stride === 1)
s.data[b] = M;
else if (Array.isArray(M))
for (let F = 0; F < M.length; F++)
s.data[b + F] = M[F];
}
}
return this;
}
// built-in interpolation methods
static logInterp(t, e, i, r, n, s) {
const a = (e * e - t * t) * n + t * t, c = (r * r - i * i) * n + i * i;
return Math.sqrt((c - a) * s + a);
}
static linearInterp(t, e, i, r, n, s) {
const a = (e - t) * n + t;
return ((r - i) * n + i - a) * s + a;
}
static nearestInterp(t, e, i, r, n, s) {
const a = n <= 0.5 ? t : e, c = n <= 0.5 ? i : r;
return s <= 0.5 ? a : c;
}
// // create a new Typed2DArray instance using an existing data array
// static from<ArrayType>(source: ArrayType, columns: number, stride = 1, copyData = false) {
// const data = source instanceof Typed2DArray ? source.data : source;
// const array = new Typed2DArray(data.constructor, columns, data.length / (columns * stride), stride, false);
// array.data = copyData ? new array.type(data) : data;
// if (source instanceof Typed2DArray) {
// array.setInterpolator(...source._lerpFn);
// }
// return array;
// }
// alias for columns
get width() {
return this.columns;
}
// alias for rows
get height() {
return this.rows;
}
// get the array index to the first component from the provided column and row indices
index(t, e) {
if (t < 0 || e < 0 || t >= this.columns || e >= this.rows)
throw Error("Index out of bounds!");
return e * this._rowLength + t * this.stride;
}
// get the column and row at the beginning of the item according to stride from an index into the data array
positionOf(t) {
if (t < 0 || t > this.data.length) return;
const e = t % this.stride, i = Math.floor((t - e) / this._rowLength), r = Math.floor((t - i * this._rowLength) / this.stride);
return { row: i, col: r };
}
// allow you to set a custom interpolation function per component, which are used when interpolating values
setInterpolator(...t) {
return this._lerpFn = t, this;
}
// get the configured interpolation function for the given component index
getInterpolator(t) {
return this._lerpFn.length > 0 ? this._lerpFn[Math.min(t, this._lerpFn.length - 1)] : N.linearInterp;
}
// convenience function for reading an entire column
col(t, e) {
return this.readBlock(
Math.floor(t),
0,
1,
this.rows,
void 0,
void 0,
e
);
}
// convenience function for reading an entire row
row(t, e) {
const i = this.index(0, Math.floor(t));
if (e) {
for (let r = 0; r < this._rowLength; r++)
e[r] = this.data[i + r];
return e;
}
return this.data.subarray(i, i + this._rowLength);
}
// set a single value into the provided column and row
setValue(t, e, ...i) {
const r = this.index(t, e);
for (let n = 0; n < Math.min(i.length, this.stride); n++)
this.data[r + n] = i[n];
return this;
}
// read all the values within the provided block dimension
readBlock(t, e, i, r, n, s, a) {
if (t < 0 || t + i > this.columns || e < 0 || e + r > this.rows)
throw Error("Invalid block dimensions!");
n = Number.isFinite(n) ? n : i, s = Number.isFinite(s) ? s : r, a = a || this.arrayConstructor(n * s * this.stride);
const c = Math.max(1, n - 1), h = Math.max(1, s - 1), l = Math.max(1, i - 1), o = Math.max(1, r - 1);
let d = 0;
for (let g = 0; g < s; g++) {
const v = g / h * o + e;
for (let y = 0; y < n; y++) {
const m = y / c * l + t, _ = this.valueAt(m, v);
if (this.stride === 1)
a[d++] = _;
else if (Array.isArray(_))
for (let A = 0; A < _.length; A++)
a[d++] = _[A];
}
}
return a;
}
// upscale grid using the current interpolation method
upscale(t, e) {
if (t < this.columns || e < this.rows)
throw Error(
"New column and row size must be equal or bigger than the current sizes!"
);
const i = this.readBlock(
0,
0,
this.columns,
this.rows,
t,
e
);
return this.columns = t, this.rows = e, this._rowLength = t * this.stride, this.data = i, this;
}
// write values into a given block dimension
writeBlock(t, e, i, r, n) {
if (n.length !== i * r * this.stride)
throw Error("Incorrect number of values");
if (t < 0 || t + i > this.columns || e < 0 || e + r > this.rows)
throw Error("Invalid block dimensions!");
let s = 0;
for (let a = e; a < e + r; a++) {
const c = this.index(t, a);
for (let h = 0; h < i; h++) {
const l = c + h * this.stride;
for (let o = 0; o < this.stride; o++)
this.data[l + o] = n[s++];
}
}
return this;
}
// fills the block with a single value
fillBlock(t, e, i, r, n) {
if (t < 0 || t + i > this.columns || e < 0 || e + r > this.rows)
throw Error("Invalid block dimensions!");
let s = (a, c, h) => {
this.data[h] = n;
};
typeof n == "function" ? s = (a, c, h) => {
const l = n(a, c, h);
if (Array.isArray(l) && l.length && l.length > 0)
for (let o = 0; o < Math.min(l.length, this.stride); o++)
this.data[h + o] = l[o];
else
this.data[h] = l;
} : this.stride > 1 && Array.isArray(n) && (s = (a, c, h) => {
for (let l = 0; l < Math.min(n.length, this.stride); l++)
this.data[h + l] = n[l];
});
for (let a = e; a < e + r; a++) {
const c = this.index(t, a);
for (let h = 0; h < i; h++) {
const l = c + h * this.stride;
s(h, a, l);
}
}
return this;
}
// get the value corresponding to the specified index according to stride
valueOf(t, e) {
const { stride: i, data: r } = this;
if (i > 1) {
t = t % i, e = e || this.arrayConstructor(i);
for (let n = 0; n < i; n++)
e[n] = r[t + n];
return e;
}
return r[t];
}
// get the calue at the requested column and row, which may be given as fractions, which in case
// bilinear filtering will be applied to interpolate values (for each component) in between columns and rows
valueAt(t, e, i) {
const { columns: r, rows: n, stride: s, data: a } = this, c = t % 1, h = e % 1;
if (c > 0 || h > 0) {
const o = (t < 0 ? 0 : t >= r ? r - 1 : t) | 0, d = (e < 0 ? 0 : e >= n ? n - 1 : e) | 0, g = o === r - 1 ? o : o + 1, v = d === n - 1 ? d : d + 1;
let y = this.index(o, d), m = this.index(g, d), _ = this.index(o, v), A = this.index(g, v);
if (s > 1) {
i = i || this.arrayConstructor(s);
for (let b = 0; b < s; b++) {
const V = this.getInterpolator(b);
i[b] = V(a[y++], a[m++], a[_++], a[A++], c, h);
}
return i;
}
return this.getInterpolator(0)(a[y], a[m], a[_], a[A], c, h);
}
const l = this.index(t, e);
if (s > 1) {
i = i || this.arrayConstructor(s);
for (let o = 0; o < s; o++)
i[o] = a[l + o];
return i;
}
return a[l];
}
// swap all values from one row with all values from another row
swapRows(t, e, i) {
i = i || this.arrayConstructor(this._rowLength), this.row(t, i);
const r = this.index(0, t), n = this.index(0, e);
for (let s = 0; s < this._rowLength; s++)
this.data[r + s] = this.data[n + s], this.data[n + s] = i[s];
return this;
}
// invert all rows (top-bottom to bottom-top)
invertRows() {
const t = Math.floor(this.rows / 2), e = this.arrayConstructor(this._rowLength);
for (let i = this.rows - 1, r = 0; i > t; i--, r++)
this.swapRows(i, r, e);
return this;
}
copyInto(t, e = 0, i = 0, r = this.columns - e, n = this.rows - i) {
if (t.length !== r * n * this.stride)
throw Error("Target is not of the correct size!");
let s = 0;
for (let a = i; a < i + n; a++) {
const c = this.index(0, a);
for (let h = e; h < e + r; h++) {
const l = c + h * this.stride;
for (let o = 0; o < this.stride; o++)
t[s++] = this.data[l + o];
}
}
return this;
}
// return a multi-dimensional javascript array of the data (main purpose for debugging)
toJsArray() {
const t = new Array(this.rows);
for (let e = 0; e < this.rows; e++) {
const i = this.index(0, e);
t[e] = new Array(this.columns);
for (let r = 0; r < this.columns; r++)
if (this.stride > 1) {
t[e][r] = new Array(this.stride);
for (let n = 0; n < this.stride; n++)
t[e][r][n] = this.data[i + r * this.stride + n];
} else
t[e][r] = this.data[i + r * this.stride];
}
return t;
}
}
function lt(u) {
const t = new Float32Array(u.length * 3);
for (let e = 0; e < u.length; e++) {
const i = e * 3;
t[i + 0] = u[e][0], t[i + 1] = u[e][1], t[i + 2] = u[e][2];
}
return t;
}
export {
_e as CRS,
ct as CameraManager,
Y as DataLoader,
ze as Delatin,
ft as DepthReadMaterial,
R as GeneratorRegistry,
ut as PI,
dt as PI2,
gt as PI4,
pt as PI8,
wt as TAU,
Me as TubeMaterial,
N as Typed2DArray,
yt as WellboreManager,
mt as addVec2,
xt as addVec3,
bt as angleVec3,
vt as calculateFrenetFrames,
Ge as calculateHashValue,
Ae as calculateWellSegments,
_t as clamp,
Mt as copyVec3,
Fe as createConfig,
Le as createElevationTexture,
ke as createFenceGeometry,
Se as createNormalTexture,
Pe as createTubeGeometry,
At as crossVec3,
Ft as degreesToRadians,
Lt as directionVec2,
St as directionVec3,
Vt as distanceVec2,
It as distanceVec3,
Bt as dotVec2,
Et as dotVec3,
Tt as edgeOfRectangle,
Ve as elevationMapNormalsToRGBA,
Dt as feetToMeters,
qt as getCurvePositions,
zt as getFormationMarkers,
at as getObjectByCustomProperty,
Gt as getProjectedTrajectory,
Ie as getProjectionDefFromUtmZone,
kt as getSplineCurve,
Pt as getTrajectory,
jt as getTypedArrayFromBuffer,
Nt as getTypedArrayType,
Be as getUtmZoneFromLatLng,
Ct as getVec2,
Qt as getVec3,
Ut as getWellboreFormations,
et as idToHexColor,
Wt as inverseLerp,
Ht as lengthVec2,
Zt as lengthVec3,
$t as lerp,
Jt as mergeFormationIntervals,
Kt as mixVec2,
Ot as mixVec3,
nt as multiply,
rt as negate,
Xt as negateVec2,
Yt as negateVec3,
Rt as normalizeVec2,
te as normalizeVec3,
ee as normalizedDeviceToScreen,
se as packAttribute,
ie as packBufferGeometries,
re as packBufferGeometry,
ne as packBufferGeometryLike,
it as parseIrapbin,
st as randomColor,
ae as readDepth,
le as remap,
oe as rotateVec3,
he as scaleVec2,
ce as scaleVec3,
fe as screenToNormalizedDevice,
ue as setVec2,
de as setVec3,
ge as simplifyCurve2D,
pe as subVec2,
we as subVec3,
je as titleCase,
lt as toFloat32Array,
ye as toRGB,
Ee as toSegments,
Te as triangleNormal,
tt as triangulateGrid,
Ne as triangulateGridDelaunay,
me as unpackBufferGeometries,
xe as unpackBufferGeometry,
be as uvMaterial,
De as wgs84Def
};