baselode 0.1.18 → 0.1.19

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.
@@ -0,0 +1,2252 @@
1
+ import * as f from "three";
2
+ import { OrbitControls as rt } from "three/examples/jsm/controls/OrbitControls";
3
+ import { FlyControls as ot } from "three/examples/jsm/controls/FlyControls";
4
+ import { ViewportGizmo as it } from "three-viewport-gizmo";
5
+ import { EffectComposer as st } from "three/examples/jsm/postprocessing/EffectComposer.js";
6
+ import { RenderPass as at } from "three/examples/jsm/postprocessing/RenderPass.js";
7
+ import { OutlinePass as lt } from "three/examples/jsm/postprocessing/OutlinePass.js";
8
+ import ct from "papaparse";
9
+ const H = "hole_id", Ne = "latitude", ke = "longitude", Oe = "elevation", Z = "azimuth", W = "dip", te = "from", J = "to", ce = "mid", Le = "project_id", De = "easting", Ae = "northing", we = "crs", ue = "depth", xe = "alpha", Se = "beta", ut = "strike", ve = "geology_code", Fe = "geology_description", Qn = {
10
+ // A unique hole identifier across the entire dataset and all future data sets
11
+ [H]: "string",
12
+ // The hole ID from the original collar source
13
+ datasource_hole_id: "string",
14
+ // The project ID or project code from the original collar source, if available
15
+ [Le]: "string",
16
+ // The latitude of the collar, in decimal degrees (WGS84)
17
+ [Ne]: "number",
18
+ // The longitude of the collar, in decimal degrees (WGS84)
19
+ [ke]: "number",
20
+ // The elevation of the collar, in meters above sea level (WGS84)
21
+ [Oe]: "number",
22
+ // The easting coordinate of the collar, in meters (projected CRS)
23
+ [De]: "number",
24
+ // The northing coordinate of the collar, in meters (projected CRS)
25
+ [Ae]: "number",
26
+ // The coordinate reference system of the collar coordinates for easting/northing, as an EPSG code or proj string
27
+ [we]: "string"
28
+ }, er = {
29
+ // The unique hole id that maps to the collar and any other data tables
30
+ [H]: "string",
31
+ // The depth along the hole where the survey measurement was taken / started
32
+ [ue]: "number",
33
+ // The depth along the hole where the survey measurement ended, if applicable (some surveys are point measurements and may not have a 'to' depth)
34
+ [J]: "number",
35
+ // The azimuth of the hole at the survey depth, in degrees from north
36
+ [Z]: "number",
37
+ // The dip of the hole at the survey depth, in degrees from horizontal (negative values indicate downward inclination)
38
+ [W]: "number"
39
+ }, tr = {
40
+ // The unique hole id that maps to the collar and any other data tables
41
+ [H]: "string",
42
+ // The depth along the hole where the assay interval starts
43
+ [te]: "number",
44
+ // The depth along the hole where the assay interval ends
45
+ [J]: "number",
46
+ // The midpoint depth of the assay interval
47
+ [ce]: "number"
48
+ // assay value columns are variable and not standardized here.
49
+ // Assays may be flattened (one column per assay type) or long (one row per assay type with an additional 'assay_type' column)
50
+ }, nr = {
51
+ [H]: "string",
52
+ [te]: "number",
53
+ [J]: "number",
54
+ [ce]: "number",
55
+ [ve]: "string",
56
+ [Fe]: "string"
57
+ }, rr = {
58
+ [H]: "string",
59
+ [ue]: "number",
60
+ [W]: "number",
61
+ [Z]: "number",
62
+ [xe]: "number",
63
+ [Se]: "number",
64
+ comments: "string"
65
+ }, or = {
66
+ [H]: "string",
67
+ [te]: "number",
68
+ [J]: "number",
69
+ [ce]: "number"
70
+ // value columns are variable — not standardized here
71
+ }, ir = -999.25, mt = {
72
+ [H]: ["hole_id", "holeid", "hole id", "hole-id"],
73
+ datasource_hole_id: ["datasource_hole_id", "datasourceholeid", "datasource hole id", "datasource-hole-id", "company_hole_id", "companyholeid", "company hole id", "company-hole-id"],
74
+ [Le]: ["project_id", "projectid", "project id", "project-id", "project_code", "projectcode", "project code", "project-code", "companyId", "company_id", "companyid", "company id", "company-id", "dataset", "project"],
75
+ [Ne]: ["latitude", "lat"],
76
+ [ke]: ["longitude", "lon"],
77
+ [Oe]: ["elevation", "rl", "elev", "z"],
78
+ [De]: ["easting", "x"],
79
+ [Ae]: ["northing", "y"],
80
+ [we]: ["crs", "epsg", "projection"],
81
+ [te]: ["from", "depth_from", "from_depth", "samp_from", "sample_from", "sampfrom", "fromdepth"],
82
+ [J]: ["to", "depth_to", "to_depth", "samp_to", "sample_to", "sampto", "todepth"],
83
+ [ve]: [
84
+ "geology_code",
85
+ "geologycode",
86
+ "lith1",
87
+ "lith1code",
88
+ "lith1_code",
89
+ "lithology",
90
+ "plot_lithology",
91
+ "rock1"
92
+ ],
93
+ [Fe]: [
94
+ "geology_description",
95
+ "geologydescription",
96
+ "geology_comment",
97
+ "geologycomment",
98
+ "geology comment",
99
+ "lithology_comment",
100
+ "lithology comment",
101
+ "description",
102
+ "comments"
103
+ ],
104
+ [Z]: ["azimuth", "az", "dip_direction", "dipdir", "dip direction", "dipdrn", "dipdirection", "dip_dir", "computed_plane_azimuth", "calc_dipdir", "calc_dipdir_deg", "dipdir_calc", "dipdirect_calc"],
105
+ [W]: ["dip", "computed_plane_dip", "calc_dip", "calc_dip_deg", "dip_calc"],
106
+ [xe]: ["alpha", "alpha_angle", "alpha_angle_deg", "alpha_2"],
107
+ [Se]: ["beta", "beta_angle", "beta_angle_deg", "beta_2"],
108
+ declination: ["declination", "dec"],
109
+ [ue]: ["depth", "survey_depth", "surveydepth", "md", "measured_depth", "dept"],
110
+ [ut]: ["strike", "str"]
111
+ }, dt = {};
112
+ for (const [e, t] of Object.entries(mt))
113
+ for (const n of t) {
114
+ const r = n.toLowerCase().trim();
115
+ dt[r] = e;
116
+ }
117
+ const oe = "[baselode:data]";
118
+ function ft(e, t = "Unknown error") {
119
+ if (e instanceof Error) return e;
120
+ const n = typeof e == "string" && e.trim() ? e : t;
121
+ return new Error(n);
122
+ }
123
+ function ie(e, t, n = "Operation failed") {
124
+ const r = ft(t, n), o = new Error(`${e}: ${r.message}`);
125
+ return o.cause = r, o;
126
+ }
127
+ function sr(e, t) {
128
+ if (t !== void 0) {
129
+ console.warn(`${oe} ${e}`, t);
130
+ return;
131
+ }
132
+ console.warn(`${oe} ${e}`);
133
+ }
134
+ function ar(e) {
135
+ console.info(`${oe} ${e}`);
136
+ }
137
+ const K = "numeric", se = "categorical", ae = "comment", Q = "hidden", ht = "tadpole", be = {
138
+ [K]: [
139
+ { value: "bar", label: "Bars" },
140
+ { value: "markers", label: "Markers" },
141
+ { value: "markers+line", label: "Markers + Line" },
142
+ { value: "line", label: "Line only" }
143
+ ],
144
+ [se]: [
145
+ { value: "categorical", label: "Categorical bands" }
146
+ ],
147
+ [ae]: [
148
+ { value: "comment", label: "Comments" }
149
+ ],
150
+ [ht]: [
151
+ { value: "tadpole", label: "Tadpole" }
152
+ ],
153
+ [Q]: []
154
+ }, ge = /* @__PURE__ */ new Set([
155
+ // Hole identifiers
156
+ "hole_id",
157
+ "holeid",
158
+ "id",
159
+ "holetype",
160
+ "datasource_hole_id",
161
+ "anumber",
162
+ "collarid",
163
+ "companyholeid",
164
+ "company_hole_id",
165
+ "company_id",
166
+ // Project codes
167
+ "project_id",
168
+ "project_code",
169
+ "project",
170
+ "projectcode",
171
+ "projectid",
172
+ // Geographic coordinates
173
+ "latitude",
174
+ "longitude",
175
+ "lat",
176
+ "lon",
177
+ "lng",
178
+ "easting",
179
+ "northing",
180
+ "x",
181
+ "y",
182
+ "z",
183
+ "elevation",
184
+ "elev",
185
+ "rl",
186
+ // Depth / interval columns
187
+ "from",
188
+ "to",
189
+ "mid",
190
+ "depth",
191
+ "md",
192
+ "samp_from",
193
+ "samp_to",
194
+ "sample_from",
195
+ "sample_to",
196
+ "depth_from",
197
+ "depth_to",
198
+ "fromdepth",
199
+ "todepth",
200
+ // Geometry / CRS
201
+ "shape",
202
+ "geometry",
203
+ "crs",
204
+ "epsg",
205
+ // Internal / synthetic columns
206
+ "data_source",
207
+ "_hole_key",
208
+ "_hole_id_key"
209
+ ]), bt = /* @__PURE__ */ new Set([
210
+ "comments",
211
+ "comment",
212
+ "notes",
213
+ "note",
214
+ "description",
215
+ "remarks",
216
+ "remark",
217
+ "log_description",
218
+ "struct_comment",
219
+ "structcomment",
220
+ "geology_description"
221
+ ]);
222
+ function lr(e) {
223
+ if (!(e != null && e.length))
224
+ return { byType: {}, numericCols: [], categoricalCols: [], commentCols: [] };
225
+ const t = new Set(e.flatMap((r) => Object.keys(r || {}))), n = {};
226
+ for (const r of t) {
227
+ const o = r.toLowerCase().trim();
228
+ if (ge.has(o) || ge.has(r)) {
229
+ n[r] = Q;
230
+ continue;
231
+ }
232
+ if (bt.has(o)) {
233
+ const c = e.some((l) => {
234
+ const s = l[r];
235
+ return s != null && String(s).trim() !== "" && String(s) !== "null";
236
+ });
237
+ n[r] = c ? ae : Q;
238
+ continue;
239
+ }
240
+ let i = !1, a = !1;
241
+ for (const c of e) {
242
+ const l = c[r];
243
+ if (!(l == null || typeof l == "string" && l.trim() === "") && (a = !0, typeof l == "number" && Number.isFinite(l))) {
244
+ i = !0;
245
+ break;
246
+ }
247
+ }
248
+ a ? i ? n[r] = K : n[r] = se : n[r] = Q;
249
+ }
250
+ return {
251
+ byType: n,
252
+ numericCols: Object.entries(n).filter(([, r]) => r === K).map(([r]) => r),
253
+ categoricalCols: Object.entries(n).filter(([, r]) => r === se).map(([r]) => r),
254
+ commentCols: Object.entries(n).filter(([, r]) => r === ae).map(([r]) => r)
255
+ };
256
+ }
257
+ function gt(e) {
258
+ return be[e] ?? be[K];
259
+ }
260
+ function cr(e) {
261
+ const t = gt(e);
262
+ return t.length ? e === K ? "line" : t[0].value : "markers+line";
263
+ }
264
+ const Ie = ["x", "y", "z", "dx", "dy", "dz"], pt = {
265
+ x: ["x", "easting", "center_x", "xc", "xcentre", "xcenter", "x_centre", "x_center", "cx"],
266
+ y: ["y", "northing", "center_y", "yc", "ycentre", "ycenter", "y_centre", "y_center", "cy"],
267
+ z: ["z", "elevation", "center_z", "zc", "zcentre", "zcenter", "z_centre", "z_center", "cz"],
268
+ dx: ["dx", "size_x", "sx", "sizex", "dim_x", "block_size_x"],
269
+ dy: ["dy", "size_y", "sy", "sizey", "dim_y", "block_size_y"],
270
+ dz: ["dz", "size_z", "sz", "sizez", "dim_z", "block_size_z"]
271
+ }, Ce = {};
272
+ Object.entries(pt).forEach(([e, t]) => {
273
+ t.forEach((n) => {
274
+ Ce[n.toLowerCase()] = e;
275
+ });
276
+ });
277
+ function yt(e) {
278
+ const t = {};
279
+ return Object.entries(e).forEach(([n, r]) => {
280
+ const o = Ce[n.toLowerCase().trim()] || n;
281
+ t[o] = r;
282
+ }), t;
283
+ }
284
+ function ur(e) {
285
+ return new Promise((t, n) => {
286
+ ct.parse(e, {
287
+ header: !0,
288
+ dynamicTyping: !0,
289
+ skipEmptyLines: !0,
290
+ complete: (r) => {
291
+ const i = (r.data || []).map(yt).filter(
292
+ (c) => c.x !== null && c.y !== null && c.z !== null
293
+ ), a = Object.keys(i[0] || {}).filter(
294
+ (c) => !Ie.includes(c)
295
+ );
296
+ t({ data: i, properties: a });
297
+ },
298
+ error: (r) => {
299
+ n(ie("parseBlockModelCSV", r));
300
+ }
301
+ });
302
+ });
303
+ }
304
+ function mr(e) {
305
+ if (typeof e == "string")
306
+ try {
307
+ return JSON.parse(e);
308
+ } catch (t) {
309
+ throw ie("loadBlockModelMetadata", t);
310
+ }
311
+ if (e && typeof e == "object") return e;
312
+ throw ie("loadBlockModelMetadata", new Error("Invalid metadata source"));
313
+ }
314
+ function _t(e, t) {
315
+ const n = e.map((i) => i[t]).filter((i) => i != null);
316
+ if (n.length > 0 && n.every((i) => typeof i == "number")) {
317
+ const i = Math.min(...n), a = Math.max(...n);
318
+ return { type: "numeric", min: i, max: a, values: n };
319
+ }
320
+ return { type: "categorical", categories: [...new Set(n)], values: n };
321
+ }
322
+ function dr(e) {
323
+ if (!e || e.length === 0) return {};
324
+ const t = Object.keys(e[0]).filter(
325
+ (r) => !Ie.includes(r)
326
+ ), n = {};
327
+ return t.forEach((r) => {
328
+ n[r] = _t(e, r);
329
+ }), n;
330
+ }
331
+ function Mt(e, t) {
332
+ return !t || typeof t != "object" ? e : e.filter(
333
+ (n) => Object.entries(t).every(([r, o]) => {
334
+ const i = n[r];
335
+ return o == null ? !0 : typeof o != "object" || Array.isArray(o) ? i === o : !("gt" in o && !(i > o.gt) || "gte" in o && !(i >= o.gte) || "lt" in o && !(i < o.lt) || "lte" in o && !(i <= o.lte) || "eq" in o && i !== o.eq || "ne" in o && i === o.ne || "in" in o && !o.in.includes(i));
336
+ })
337
+ );
338
+ }
339
+ function fr(e, t = null) {
340
+ return (t ? Mt(e, t) : e).reduce((r, o) => {
341
+ const i = Number(o.dx) || 0, a = Number(o.dy) || 0, c = Number(o.dz) || 0;
342
+ return r + i * a * c;
343
+ }, 0);
344
+ }
345
+ function zt(e, t, n) {
346
+ if (!t) return new n.Color("#888888");
347
+ if (t.type === "numeric") {
348
+ const i = t.max - t.min, c = (1 - (i === 0 ? 0.5 : (e - t.min) / i)) * 240;
349
+ return new n.Color().setHSL(c / 360, 0.8, 0.5);
350
+ }
351
+ const o = t.categories.indexOf(e) / Math.max(t.categories.length, 1) * 360;
352
+ return new n.Color().setHSL(o / 360, 0.7, 0.5);
353
+ }
354
+ function Et(e, t) {
355
+ if (!e || e.length === 0 || !Number.isFinite(t)) return null;
356
+ const n = e.length;
357
+ if (n === 1) {
358
+ const b = e[0];
359
+ return { x: Number(b.x), y: Number(b.y), z: Number(b.z), dx: 0, dy: 0, dz: -1 };
360
+ }
361
+ let r = -1;
362
+ for (let b = 0; b < n - 1; b++) {
363
+ const L = Number(e[b].md), y = Number(e[b + 1].md);
364
+ if (t >= L && t <= y) {
365
+ r = b;
366
+ break;
367
+ }
368
+ }
369
+ let o, i, a;
370
+ if (r === -1) {
371
+ t < Number(e[0].md) ? (o = e[0], i = e[1]) : (o = e[n - 2], i = e[n - 1]);
372
+ const b = Number(o.md), y = Number(i.md) - b;
373
+ a = y > 0 ? (t - b) / y : t < b ? 0 : 1;
374
+ } else {
375
+ o = e[r], i = e[r + 1];
376
+ const b = Number(o.md), y = Number(i.md) - b;
377
+ a = y > 0 ? (t - b) / y : 0;
378
+ }
379
+ const c = Number(o.x) + a * (Number(i.x) - Number(o.x)), l = Number(o.y) + a * (Number(i.y) - Number(o.y)), s = Number(o.z) + a * (Number(i.z) - Number(o.z));
380
+ let u, g, m;
381
+ const h = Number(o.azimuth), d = Number(o.dip), p = Number(i.azimuth), N = Number(i.dip);
382
+ if (Number.isFinite(h) && Number.isFinite(d)) {
383
+ const b = Number.isFinite(p) && Number.isFinite(N) ? h + a * (p - h) : h, L = Number.isFinite(p) && Number.isFinite(N) ? d + a * (N - d) : d, y = b * Math.PI / 180, z = L * Math.PI / 180;
384
+ u = Math.cos(z) * Math.sin(y), g = Math.cos(z) * Math.cos(y), m = -Math.sin(z);
385
+ } else {
386
+ const b = Number(i.x) - Number(o.x), L = Number(i.y) - Number(o.y), y = Number(i.z) - Number(o.z), z = Math.sqrt(b * b + L * L + y * y);
387
+ if (z < 1e-10) return { x: c, y: l, z: s, dx: 0, dy: 0, dz: -1 };
388
+ u = b / z, g = L / z, m = y / z;
389
+ }
390
+ const k = Math.sqrt(u * u + g * g + m * m);
391
+ return k < 1e-10 ? { x: c, y: l, z: s, dx: 0, dy: 0, dz: -1 } : { x: c, y: l, z: s, dx: u / k, dy: g / k, dz: m / k };
392
+ }
393
+ function Nt(e, t, n, r = {}) {
394
+ const { betaZeroAxis: o = "B", betaHandedness: i = 1 } = r, { dx: a, dy: c, dz: l } = n, s = [a, c, l];
395
+ let u = [0, 0, 1];
396
+ const g = s[0] * u[0] + s[1] * u[1] + s[2] * u[2];
397
+ Math.abs(g) > 0.99 && (u = [0, 1, 0]);
398
+ const m = [
399
+ u[1] * s[2] - u[2] * s[1],
400
+ u[2] * s[0] - u[0] * s[2],
401
+ u[0] * s[1] - u[1] * s[0]
402
+ ], h = Math.sqrt(m[0] ** 2 + m[1] ** 2 + m[2] ** 2), d = h > 1e-10 ? [m[0] / h, m[1] / h, m[2] / h] : [1, 0, 0], p = [
403
+ s[1] * d[2] - s[2] * d[1],
404
+ s[2] * d[0] - s[0] * d[2],
405
+ s[0] * d[1] - s[1] * d[0]
406
+ ], N = Math.sqrt(p[0] ** 2 + p[1] ** 2 + p[2] ** 2), k = N > 1e-10 ? [p[0] / N, p[1] / N, p[2] / N] : [0, 1, 0], b = o === "R" ? d : k, L = t * Math.PI / 180 * i, y = Math.cos(L), z = Math.sin(L), O = b[0] * s[0] + b[1] * s[1] + b[2] * s[2], A = [
407
+ s[1] * b[2] - s[2] * b[1],
408
+ s[2] * b[0] - s[0] * b[2],
409
+ s[0] * b[1] - s[1] * b[0]
410
+ ], x = [
411
+ b[0] * y + A[0] * z + s[0] * O * (1 - y),
412
+ b[1] * y + A[1] * z + s[1] * O * (1 - y),
413
+ b[2] * y + A[2] * z + s[2] * O * (1 - y)
414
+ ], D = (90 - e) * Math.PI / 180, S = Math.cos(D), w = Math.sin(D), F = S * x[0] + w * s[0], C = S * x[1] + w * s[1], I = S * x[2] + w * s[2], T = Math.sqrt(F * F + C * C + I * I);
415
+ return T < 1e-10 ? { nx: 0, ny: 0, nz: 1 } : { nx: F / T, ny: C / T, nz: I / T };
416
+ }
417
+ function kt(e, t, n = {}) {
418
+ if (!(e != null && e.length) || !(t != null && t.length)) return [];
419
+ const r = /* @__PURE__ */ new Map();
420
+ for (const i of t) {
421
+ const a = i.hole_id != null ? `${i.hole_id}`.trim().toLowerCase() : "";
422
+ a && (r.has(a) || r.set(a, []), r.get(a).push(i));
423
+ }
424
+ for (const [, i] of r)
425
+ i.sort((a, c) => Number(a.md) - Number(c.md));
426
+ const o = [];
427
+ for (const i of e) {
428
+ const a = i.hole_id != null ? `${i.hole_id}`.trim().toLowerCase() : "";
429
+ if (!a) continue;
430
+ const c = r.get(a);
431
+ if (!c || c.length === 0) continue;
432
+ const l = i.depth != null ? Number(i.depth) : i.mid != null ? Number(i.mid) : null;
433
+ if (!Number.isFinite(l)) continue;
434
+ const s = Et(c, l);
435
+ if (!s) continue;
436
+ const { x: u, y: g, z: m, dx: h, dy: d, dz: p } = s;
437
+ let N, k, b;
438
+ const L = i.alpha != null ? Number(i.alpha) : null, y = i.beta != null ? Number(i.beta) : null;
439
+ if (Number.isFinite(L)) {
440
+ const z = Number.isFinite(y) ? y : 0, O = Nt(L, z, { dx: h, dy: d, dz: p }, n);
441
+ N = O.nx, k = O.ny, b = O.nz;
442
+ } else {
443
+ const z = i.dip != null ? Number(i.dip) : null, O = i.azimuth != null ? Number(i.azimuth) : null;
444
+ if (!Number.isFinite(z) || !Number.isFinite(O)) continue;
445
+ const A = z * Math.PI / 180, x = O * Math.PI / 180;
446
+ N = Math.sin(x) * Math.sin(A), k = Math.cos(x) * Math.sin(A), b = Math.cos(A);
447
+ }
448
+ o.push({ ...i, x: u, y: g, z: m, nx: N, ny: k, nz: b });
449
+ }
450
+ return o;
451
+ }
452
+ const Ot = "baselode", hr = Ot, Lt = [
453
+ "#8b1e3f",
454
+ "#2563eb",
455
+ "#16a34a",
456
+ "#f59e0b",
457
+ "#7c3aed",
458
+ "#0ea5e9",
459
+ "#ef4444",
460
+ "#10b981",
461
+ "#f97316",
462
+ "#8b5cf6"
463
+ ], M = {
464
+ bg: "#ffffff",
465
+ panel: "#f8fafc",
466
+ ink: "#1e293b",
467
+ ink_soft: "#64748b",
468
+ grid: "#e8e8e8",
469
+ line: "#d0d0d0",
470
+ accent: "#f59e0b",
471
+ accent_2: "#fcd34d",
472
+ muted_1: "#94a3b8",
473
+ muted_2: "#cbd5e1",
474
+ muted_3: "#e2e8f0",
475
+ primary: "#8b1e3f",
476
+ primary_2: "#a8324f"
477
+ }, me = {
478
+ layout: {
479
+ paper_bgcolor: M.bg,
480
+ plot_bgcolor: M.bg,
481
+ colorway: Lt,
482
+ font: {
483
+ family: "Inter, system-ui, sans-serif",
484
+ size: 12,
485
+ color: M.ink
486
+ },
487
+ title: {
488
+ font: { size: 14, color: M.ink },
489
+ x: 0.05
490
+ },
491
+ hovermode: "x unified",
492
+ hoverlabel: {
493
+ bgcolor: M.bg,
494
+ bordercolor: M.line,
495
+ font: { size: 12, color: M.ink }
496
+ },
497
+ legend: {
498
+ bgcolor: "rgba(255,255,255,0.9)",
499
+ bordercolor: M.muted_3,
500
+ borderwidth: 1,
501
+ font: { size: 11, color: M.ink },
502
+ orientation: "h",
503
+ yanchor: "bottom",
504
+ y: 1.02,
505
+ xanchor: "left",
506
+ x: 0
507
+ },
508
+ xaxis: {
509
+ showline: !0,
510
+ linewidth: 1,
511
+ linecolor: M.line,
512
+ mirror: !1,
513
+ ticks: "outside",
514
+ tickwidth: 1,
515
+ tickcolor: M.line,
516
+ ticklen: 4,
517
+ showgrid: !0,
518
+ gridcolor: M.grid,
519
+ gridwidth: 1,
520
+ zeroline: !1,
521
+ title_font: { color: M.ink, size: 12 },
522
+ tickfont: { color: M.ink_soft, size: 10 }
523
+ },
524
+ yaxis: {
525
+ showline: !0,
526
+ linewidth: 1,
527
+ linecolor: M.line,
528
+ mirror: !1,
529
+ ticks: "outside",
530
+ tickwidth: 1,
531
+ tickcolor: M.line,
532
+ ticklen: 4,
533
+ showgrid: !0,
534
+ gridcolor: M.grid,
535
+ gridwidth: 1,
536
+ zeroline: !1,
537
+ title_font: { color: M.ink, size: 12 },
538
+ tickfont: { color: M.ink_soft, size: 10 }
539
+ },
540
+ modebar: {
541
+ remove: ["select2d", "lasso2d", "autoScale2d"]
542
+ },
543
+ bargap: 0.18,
544
+ bargroupgap: 0.08
545
+ },
546
+ data: {
547
+ scatter: [{
548
+ mode: "lines+markers",
549
+ line: { width: 2, color: M.primary },
550
+ marker: {
551
+ size: 7,
552
+ color: M.primary_2,
553
+ line: { width: 1.5, color: M.bg }
554
+ }
555
+ }],
556
+ bar: [{
557
+ marker: {
558
+ color: M.primary,
559
+ line: { color: M.bg, width: 0 }
560
+ }
561
+ }],
562
+ histogram: [{
563
+ marker: {
564
+ color: M.primary,
565
+ line: { color: M.bg, width: 0 }
566
+ }
567
+ }],
568
+ box: [{
569
+ fillcolor: M.accent,
570
+ line: { color: M.ink, width: 1.5 },
571
+ marker: { color: M.ink }
572
+ }],
573
+ violin: [{
574
+ fillcolor: M.accent,
575
+ line: { color: M.ink, width: 1.5 },
576
+ marker: { color: M.ink }
577
+ }],
578
+ heatmap: [{
579
+ colorscale: [
580
+ [0, "#ffffff"],
581
+ [0.2, "#f1f5f9"],
582
+ [0.4, "#cbd5e1"],
583
+ [0.6, "#94a3b8"],
584
+ [0.8, "#475569"],
585
+ [1, "#1e293b"]
586
+ ],
587
+ colorbar: {
588
+ outlinecolor: M.line,
589
+ tickcolor: M.line,
590
+ tickfont: { color: M.ink_soft }
591
+ }
592
+ }],
593
+ contour: [{
594
+ colorscale: [
595
+ [0, "#ffffff"],
596
+ [0.25, "#fef3c7"],
597
+ [0.5, "#f59e0b"],
598
+ [0.75, "#92400e"],
599
+ [1, "#1e293b"]
600
+ ],
601
+ colorbar: {
602
+ outlinecolor: M.line,
603
+ tickcolor: M.line,
604
+ tickfont: { color: M.ink_soft }
605
+ }
606
+ }]
607
+ }
608
+ }, br = me, _ = {
609
+ bg: "#1b1b1f",
610
+ panel: "#25252a",
611
+ ink: "#f0f0e4",
612
+ ink_soft: "#c8c8b8",
613
+ grid: "#2a2a26",
614
+ line: "#3a3a34",
615
+ accent: "#ffffbb",
616
+ accent_2: "#f3ef9b",
617
+ muted_1: "#8a8a80",
618
+ muted_2: "#5e5e56",
619
+ muted_3: "#3a3a34"
620
+ }, gr = "baselode-dark", pr = {
621
+ layout: {
622
+ font: {
623
+ family: "Inter, Arial, sans-serif",
624
+ color: _.ink,
625
+ size: 14
626
+ },
627
+ title: {
628
+ x: 0.02,
629
+ xanchor: "left",
630
+ font: {
631
+ family: "Inter, Arial, sans-serif",
632
+ size: 22,
633
+ color: _.ink
634
+ }
635
+ },
636
+ paper_bgcolor: _.bg,
637
+ plot_bgcolor: _.bg,
638
+ colorway: [
639
+ _.ink,
640
+ _.accent,
641
+ _.muted_1,
642
+ _.accent_2,
643
+ _.muted_2,
644
+ _.muted_3
645
+ ],
646
+ margin: { l: 70, r: 30, t: 70, b: 60 },
647
+ hovermode: "x unified",
648
+ hoverlabel: {
649
+ bgcolor: _.panel,
650
+ bordercolor: _.accent,
651
+ font: {
652
+ family: "Inter, Arial, sans-serif",
653
+ color: _.ink,
654
+ size: 13
655
+ }
656
+ },
657
+ legend: {
658
+ bgcolor: "rgba(37,37,42,0.88)",
659
+ bordercolor: _.line,
660
+ borderwidth: 1,
661
+ font: {
662
+ family: "Inter, Arial, sans-serif",
663
+ color: _.ink,
664
+ size: 12
665
+ },
666
+ orientation: "h",
667
+ yanchor: "bottom",
668
+ y: 1.02,
669
+ xanchor: "left",
670
+ x: 0
671
+ },
672
+ xaxis: {
673
+ showline: !1,
674
+ ticks: "outside",
675
+ tickwidth: 1,
676
+ tickcolor: _.muted_1,
677
+ ticklen: 6,
678
+ showgrid: !0,
679
+ gridcolor: _.grid,
680
+ gridwidth: 1,
681
+ zeroline: !1,
682
+ title_font: { color: _.ink },
683
+ tickfont: { color: _.ink_soft }
684
+ },
685
+ yaxis: {
686
+ showline: !1,
687
+ ticks: "outside",
688
+ tickwidth: 1,
689
+ tickcolor: _.muted_1,
690
+ ticklen: 6,
691
+ showgrid: !0,
692
+ gridcolor: _.grid,
693
+ gridwidth: 1,
694
+ zeroline: !1,
695
+ title_font: { color: _.ink },
696
+ tickfont: { color: _.ink_soft }
697
+ },
698
+ bargap: 0.18,
699
+ bargroupgap: 0.08
700
+ },
701
+ data: {
702
+ scatter: [{
703
+ mode: "lines+markers",
704
+ line: { width: 2.5, color: _.ink },
705
+ marker: {
706
+ size: 7,
707
+ color: _.ink,
708
+ line: { width: 1.5, color: _.bg }
709
+ }
710
+ }],
711
+ bar: [{
712
+ marker: {
713
+ color: _.ink,
714
+ line: { color: _.bg, width: 0 }
715
+ }
716
+ }],
717
+ histogram: [{
718
+ marker: {
719
+ color: _.ink,
720
+ line: { color: _.bg, width: 0 }
721
+ }
722
+ }],
723
+ box: [{
724
+ fillcolor: _.accent,
725
+ line: { color: _.ink, width: 1.5 },
726
+ marker: { color: _.ink }
727
+ }],
728
+ violin: [{
729
+ fillcolor: _.accent,
730
+ line: { color: _.ink, width: 1.5 },
731
+ marker: { color: _.ink }
732
+ }],
733
+ heatmap: [{
734
+ colorscale: [
735
+ [0, "#1b1b1f"],
736
+ [0.2, "#2e2e28"],
737
+ [0.4, "#5e5e50"],
738
+ [0.6, "#c8c89a"],
739
+ [0.8, "#f3ef9b"],
740
+ [1, "#ffffbb"]
741
+ ],
742
+ colorbar: {
743
+ outlinecolor: _.ink,
744
+ tickcolor: _.ink,
745
+ tickfont: { color: _.ink_soft }
746
+ }
747
+ }],
748
+ contour: [{
749
+ colorscale: [
750
+ [0, "#1b1b1f"],
751
+ [0.25, "#2e2e28"],
752
+ [0.5, "#6b6b50"],
753
+ [0.75, "#f3ef9b"],
754
+ [1, "#ffffbb"]
755
+ ],
756
+ colorbar: {
757
+ outlinecolor: _.ink,
758
+ tickcolor: _.ink,
759
+ tickfont: { color: _.ink_soft }
760
+ }
761
+ }]
762
+ }
763
+ }, Dt = "#7f7f7f", ee = {
764
+ Au: "#FFD700",
765
+ // gold
766
+ Ag: "#C0C0C0",
767
+ // silver
768
+ Cu: "#B87333",
769
+ // copper / orange-brown
770
+ Fe: "#8B4513",
771
+ // iron / rusty brown
772
+ Ni: "#4CAF50",
773
+ // nickel / green
774
+ Zn: "#78909C",
775
+ // zinc / blue-grey
776
+ Pb: "#607D8B",
777
+ // lead / slate
778
+ Mo: "#9C27B0",
779
+ // molybdenite / purple
780
+ Co: "#2196F3",
781
+ // cobalt / blue
782
+ Li: "#FF5722",
783
+ // lithium / deep orange
784
+ Mn: "#795548",
785
+ // manganese / brown
786
+ Cr: "#009688",
787
+ // chromium / teal
788
+ V: "#673AB7",
789
+ // vanadium / deep purple
790
+ W: "#FF9800",
791
+ // tungsten / amber
792
+ Sn: "#9E9E9E",
793
+ // tin / medium grey
794
+ Ti: "#00BCD4",
795
+ // titanium / cyan
796
+ Al: "#FFEB3B",
797
+ // aluminium / yellow
798
+ U: "#8BC34A"
799
+ // uranium / lime green
800
+ }, At = {
801
+ // Sedimentary
802
+ shale: "#607D8B",
803
+ mudstone: "#78909C",
804
+ siltstone: "#90A4AE",
805
+ sandstone: "#F5CBA7",
806
+ limestone: "#B0BEC5",
807
+ dolomite: "#CFD8DC",
808
+ conglomerate: "#D7CCC8",
809
+ coal: "#212121",
810
+ // Iron-formation
811
+ BIF: "#8B4513",
812
+ ironstone: "#A0522D",
813
+ // Igneous – intrusive
814
+ granite: "#EF9A9A",
815
+ granodiorite: "#F48FB1",
816
+ diorite: "#CE93D8",
817
+ gabbro: "#546E7A",
818
+ peridotite: "#33691E",
819
+ pegmatite: "#FFF9C4",
820
+ // Igneous – extrusive / volcanic
821
+ basalt: "#37474F",
822
+ andesite: "#78909C",
823
+ rhyolite: "#FFCCBC",
824
+ dacite: "#FFAB91",
825
+ tuff: "#D7CCC8",
826
+ breccia: "#BCAAA4",
827
+ // Metamorphic
828
+ schist: "#80CBC4",
829
+ gneiss: "#4DB6AC",
830
+ quartzite: "#E0F7FA",
831
+ marble: "#F5F5F5",
832
+ slate: "#455A64",
833
+ phyllite: "#80DEEA",
834
+ // Other
835
+ quartz: "#ECEFF1",
836
+ calcite: "#F9FBE7",
837
+ vein: "#FFFFFF",
838
+ unknown: "#9E9E9E"
839
+ }, ne = {
840
+ commodity: ee,
841
+ lithology: At
842
+ };
843
+ function wt(e, t, n = Dt) {
844
+ if (!t || e == null) return n;
845
+ const r = String(e).trim();
846
+ if (Object.prototype.hasOwnProperty.call(t, r)) return t[r];
847
+ const o = r.toLowerCase();
848
+ for (const [i, a] of Object.entries(t))
849
+ if (String(i).trim().toLowerCase() === o) return a;
850
+ return n;
851
+ }
852
+ function xt(e) {
853
+ if (e == null) return {};
854
+ if (typeof e == "string") {
855
+ const t = e.trim().toLowerCase();
856
+ if (Object.prototype.hasOwnProperty.call(ne, t))
857
+ return ne[t];
858
+ const n = Object.keys(ne).sort().join(", ");
859
+ throw new RangeError(
860
+ `Unknown built-in colour map '${e}'. Available maps: ${n}`
861
+ );
862
+ }
863
+ if (typeof e == "object" && Object.getPrototypeOf(e) === Object.prototype) return e;
864
+ throw new TypeError(
865
+ `colourMap must be null, a string, or a plain object; got ${Array.isArray(e) ? "Array" : Object.prototype.toString.call(e)}`
866
+ );
867
+ }
868
+ const St = "#8b1e3f", vt = "#a8324f";
869
+ function Ft(e) {
870
+ if (!e) return null;
871
+ const t = e.split(/[_\-/\s]+/);
872
+ for (const n of t) {
873
+ if (Object.prototype.hasOwnProperty.call(ee, n))
874
+ return ee[n];
875
+ const r = n.toLowerCase();
876
+ for (const [o, i] of Object.entries(ee))
877
+ if (o.toLowerCase() === r) return i;
878
+ }
879
+ return null;
880
+ }
881
+ const It = "#6b7280", Ct = { l: 42, r: 4, t: 4, b: 30 }, pe = 10, ye = 12;
882
+ function _e(e) {
883
+ return e ? typeof e == "string" ? { text: e } : e : {};
884
+ }
885
+ function Be(e = {}) {
886
+ const t = _e(e.xaxis && e.xaxis.title), n = _e(e.yaxis && e.yaxis.title);
887
+ return {
888
+ ...e,
889
+ margin: Ct,
890
+ autosize: !0,
891
+ width: void 0,
892
+ xaxis: {
893
+ ...e.xaxis || {},
894
+ tickfont: {
895
+ ...e.xaxis && e.xaxis.tickfont || {},
896
+ size: pe
897
+ },
898
+ title: {
899
+ ...t,
900
+ font: { ...t.font || {}, size: ye }
901
+ }
902
+ },
903
+ yaxis: {
904
+ ...e.yaxis || {},
905
+ automargin: !0,
906
+ tickfont: {
907
+ ...e.yaxis && e.yaxis.tickfont || {},
908
+ size: pe
909
+ },
910
+ title: {
911
+ ...n,
912
+ font: { ...n.font || {}, size: ye }
913
+ }
914
+ }
915
+ };
916
+ }
917
+ function yr(e, t) {
918
+ var r;
919
+ if (!e || !t) return !1;
920
+ const n = e.points || [];
921
+ for (let o = 0; o < n.length; o += 1) {
922
+ const i = (r = n[o]) == null ? void 0 : r[t];
923
+ if (i != null && (typeof i == "number" && Number.isFinite(i) || typeof i == "string" && i.trim() !== ""))
924
+ return !0;
925
+ }
926
+ return !1;
927
+ }
928
+ function _r(e, t, n) {
929
+ if (!e || !t) return [];
930
+ const r = (e == null ? void 0 : e.points) || [], o = [], i = /* @__PURE__ */ new Set();
931
+ return r.forEach((a) => {
932
+ let c = Number(
933
+ a.from ?? a.samp_from ?? a.sample_from ?? a.fromdepth ?? a.from_depth ?? a.depth_from
934
+ ), l = Number(
935
+ a.to ?? a.samp_to ?? a.sample_to ?? a.todepth ?? a.to_depth ?? a.depth_to
936
+ );
937
+ if (!Number.isFinite(c) || !Number.isFinite(l)) {
938
+ const h = Number(a.depth ?? a.md);
939
+ Number.isFinite(h) && (c = h, l = h);
940
+ }
941
+ const s = a == null ? void 0 : a[t];
942
+ if (!Number.isFinite(c) || !Number.isFinite(l) || l < c || s == null || s === "" || n && typeof s == "string" && /^(nan|null|none)$/i.test(s.trim())) return;
943
+ const u = `${t}:${c}-${l}:${String(s)}`;
944
+ if (i.has(u)) return;
945
+ i.add(u);
946
+ const g = (c + l) / 2, m = n ? s : Number(s);
947
+ !n && !Number.isFinite(m) || o.push({
948
+ z: g,
949
+ val: m,
950
+ from: c,
951
+ to: l,
952
+ errorPlus: l - g,
953
+ errorMinus: g - c
954
+ });
955
+ }), o.sort((a, c) => c.z - a.z);
956
+ }
957
+ function Bt(e, t, n, r) {
958
+ if (!e.length) return { data: [], layout: {} };
959
+ const o = e.filter((m) => Number.isFinite(m == null ? void 0 : m.from) && Number.isFinite(m == null ? void 0 : m.to) && m.to > m.from).map((m) => ({ ...m, category: `${(m == null ? void 0 : m.val) ?? ""}`.trim() })).filter((m) => m.category !== "" && !/^(nan|null|none)$/i.test(m.category)).sort((m, h) => m.from - h.from || m.to - h.to);
960
+ if (!o.length) return { data: [], layout: {} };
961
+ const i = xt(n), a = [
962
+ "#1f77b4",
963
+ // blue
964
+ "#ff7f0e",
965
+ // orange
966
+ "#2ca02c",
967
+ // green
968
+ "#d62728",
969
+ // red
970
+ "#9467bd",
971
+ // purple
972
+ "#17becf",
973
+ // cyan
974
+ "#bcbd22",
975
+ // olive
976
+ "#e377c2",
977
+ // pink
978
+ "#8c564b",
979
+ // brown
980
+ "#393b79",
981
+ // indigo
982
+ "#e6550d",
983
+ // deep orange
984
+ "#31a354",
985
+ // deep green
986
+ "#756bb1",
987
+ // violet
988
+ "#636363"
989
+ // dark gray
990
+ ], c = [...new Set(o.map((m) => m.category))];
991
+ function l(m, h) {
992
+ if (i && Object.keys(i).length > 0) {
993
+ const d = wt(m, i, null);
994
+ if (d !== null) return d;
995
+ }
996
+ return a[h % a.length];
997
+ }
998
+ const s = new Map(
999
+ c.map((m, h) => [m, l(m, h)])
1000
+ );
1001
+ return { data: c.map((m) => {
1002
+ const h = o.filter((d) => d.category === m);
1003
+ return {
1004
+ type: "bar",
1005
+ x: h.map(() => 0.5),
1006
+ y: h.map((d) => d.to - d.from),
1007
+ base: h.map((d) => d.from),
1008
+ width: 1,
1009
+ marker: { color: s.get(m), line: { width: 0 } },
1010
+ name: m,
1011
+ showlegend: !1,
1012
+ customdata: h.map((d) => [d.from, d.to]),
1013
+ hovertemplate: `${t}: ${m}<br>from: %{customdata[0]:.3f} to: %{customdata[1]:.3f}<extra></extra>`
1014
+ };
1015
+ }), layout: Be({
1016
+ barmode: "overlay",
1017
+ bargap: 0,
1018
+ xaxis: { range: [0, 1], visible: !1, fixedrange: !0 },
1019
+ yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
1020
+ showlegend: !1,
1021
+ title: t || void 0,
1022
+ template: r !== void 0 ? r : me
1023
+ }) };
1024
+ }
1025
+ function Tt(e, t, n, r, o) {
1026
+ if (!e.length) return { data: [], layout: {} };
1027
+ const i = n === "bar", a = n === "markers", c = n === "line", l = r || St, s = r || vt, u = {
1028
+ x: e.map((d) => d.val),
1029
+ y: e.map((d) => d.z),
1030
+ hovertemplate: `${t}: %{x}<br>from: %{customdata[0]:.3f} to: %{customdata[1]:.3f}<extra></extra>`,
1031
+ customdata: e.map((d) => [Math.min(d.from, d.to), Math.max(d.from, d.to)])
1032
+ }, g = {
1033
+ type: "data",
1034
+ symmetric: !1,
1035
+ array: e.map((d) => d.errorPlus),
1036
+ arrayminus: e.map((d) => d.errorMinus),
1037
+ thickness: 1.5,
1038
+ width: 2,
1039
+ color: It
1040
+ };
1041
+ return { data: [i ? {
1042
+ ...u,
1043
+ type: "bar",
1044
+ orientation: "h",
1045
+ marker: { color: l },
1046
+ error_y: g
1047
+ } : {
1048
+ ...u,
1049
+ type: "scatter",
1050
+ mode: a ? "markers" : c ? "lines" : "lines+markers",
1051
+ line: { color: l, width: 2 },
1052
+ marker: { size: 7, color: s },
1053
+ error_y: c ? void 0 : g
1054
+ }], layout: Be({
1055
+ xaxis: { title: t, zeroline: !1 },
1056
+ yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
1057
+ barmode: "overlay",
1058
+ showlegend: !1,
1059
+ template: o !== void 0 ? o : me
1060
+ }) };
1061
+ }
1062
+ function Pt({ points: e, isCategorical: t, property: n, chartType: r, colourMap: o, template: i }) {
1063
+ if (!e || !e.length || !n) return { data: [], layout: {} };
1064
+ if (t || r === "categorical")
1065
+ return Bt(e, n, o, i);
1066
+ const a = Ft(n);
1067
+ return Tt(e, n, r, a, i);
1068
+ }
1069
+ function Mr(e = [], {
1070
+ fromCol: t = "from",
1071
+ toCol: n = "to",
1072
+ categoryCol: r = "geology_code",
1073
+ colourMap: o = null,
1074
+ template: i = void 0
1075
+ } = {}) {
1076
+ const a = [];
1077
+ return e.forEach((c) => {
1078
+ const l = Number(c == null ? void 0 : c[t]), s = Number(c == null ? void 0 : c[n]), u = c == null ? void 0 : c[r];
1079
+ if (!Number.isFinite(l) || !Number.isFinite(s) || s <= l || u == null || `${u}`.trim() === "") return;
1080
+ const g = (l + s) / 2;
1081
+ a.push({
1082
+ z: g,
1083
+ val: `${u}`,
1084
+ from: l,
1085
+ to: s,
1086
+ errorPlus: s - g,
1087
+ errorMinus: g - l
1088
+ });
1089
+ }), a.sort((c, l) => l.z - c.z), Pt({
1090
+ points: a,
1091
+ isCategorical: !0,
1092
+ property: r,
1093
+ chartType: "categorical",
1094
+ colourMap: o,
1095
+ template: i
1096
+ });
1097
+ }
1098
+ const Rt = [
1099
+ "#313695",
1100
+ "#4575b4",
1101
+ "#74add1",
1102
+ "#abd9e9",
1103
+ "#e0f3f8",
1104
+ "#fee090",
1105
+ "#fdae61",
1106
+ "#f46d43",
1107
+ "#d73027",
1108
+ "#a50026"
1109
+ ];
1110
+ function Vt(e = [], t = Rt) {
1111
+ const n = e.filter((s) => Number.isFinite(s));
1112
+ if (!n.length)
1113
+ return {
1114
+ min: null,
1115
+ max: null,
1116
+ step: null,
1117
+ bins: [],
1118
+ colors: t
1119
+ };
1120
+ const r = n.slice().sort((s, u) => s - u), o = r[0], i = r[r.length - 1], a = t.length;
1121
+ if (i === o) {
1122
+ const s = t.map((u, g) => ({
1123
+ index: g,
1124
+ min: o,
1125
+ max: i,
1126
+ label: `${o}`
1127
+ }));
1128
+ return {
1129
+ min: o,
1130
+ max: i,
1131
+ step: 0,
1132
+ bins: s,
1133
+ colors: t
1134
+ };
1135
+ }
1136
+ const c = t.map((s, u) => {
1137
+ const g = u / a, m = (u + 1) / a, h = Math.floor(g * r.length), d = Math.min(r.length - 1, Math.floor(m * r.length)), p = r[h], N = u === a - 1 ? i : r[d];
1138
+ return {
1139
+ index: u,
1140
+ min: p,
1141
+ max: N,
1142
+ label: Ht(p, N)
1143
+ };
1144
+ }), l = (i - o) / a;
1145
+ return {
1146
+ min: o,
1147
+ max: i,
1148
+ step: l,
1149
+ bins: c,
1150
+ colors: t
1151
+ };
1152
+ }
1153
+ function Ht(e, t) {
1154
+ const n = (r) => Number.isFinite(r) ? Math.abs(r) >= 1e3 ? r.toFixed(0) : Math.abs(r) >= 10 ? r.toFixed(1) : Math.abs(r) >= 0.1 ? r.toFixed(2) : r.toFixed(3) : "n/a";
1155
+ return `${n(e)} – ${n(t)}`;
1156
+ }
1157
+ function Te(e, t) {
1158
+ if (!Number.isFinite(e) || !t || !Array.isArray(t.bins) || !t.bins.length)
1159
+ return -1;
1160
+ if (t.max === t.min)
1161
+ return e === t.min ? 0 : -1;
1162
+ for (let n = 0; n < t.bins.length; n += 1) {
1163
+ const r = t.bins[n];
1164
+ if (e >= r.min && (e <= r.max || n === t.bins.length - 1))
1165
+ return n;
1166
+ }
1167
+ return -1;
1168
+ }
1169
+ function Gt(e, t, n = "#8b1e3f") {
1170
+ const r = Te(e, t);
1171
+ return r < 0 ? n : t.colors[r] || n;
1172
+ }
1173
+ function G(e) {
1174
+ e.selectables = [
1175
+ ...e.blocks,
1176
+ ...e.drillMeshes,
1177
+ ...e.structuralMeshes
1178
+ ];
1179
+ }
1180
+ const jt = {
1181
+ bedding: "#2563eb",
1182
+ foliation: "#16a34a",
1183
+ joint: "#9333ea",
1184
+ fault: "#dc2626",
1185
+ vein: "#f59e0b",
1186
+ "shear zone": "#0ea5e9",
1187
+ "fault zone": "#ef4444"
1188
+ };
1189
+ function Yt(e, t) {
1190
+ const n = t || jt, r = (e || "").toLowerCase().trim(), o = n[r] || "#888888";
1191
+ return new f.Color(o).getHex();
1192
+ }
1193
+ function Ut(e, t) {
1194
+ const n = e * Math.PI / 180, r = t * Math.PI / 180;
1195
+ return new f.Vector3(
1196
+ Math.sin(r) * Math.sin(n),
1197
+ // East component
1198
+ Math.cos(r) * Math.sin(n),
1199
+ // North component
1200
+ Math.cos(n)
1201
+ // Up component
1202
+ ).normalize();
1203
+ }
1204
+ function $t(e, t = {}) {
1205
+ const {
1206
+ radius: n = 5,
1207
+ discThickness: r = 0.2,
1208
+ opacity: o = 0.7,
1209
+ segments: i = 32,
1210
+ colorMap: a = null
1211
+ } = t, c = new f.Group(), l = new f.Vector3(0, 1, 0);
1212
+ for (const s of e) {
1213
+ const u = s.x != null ? s.x : s.easting != null ? s.easting : null, g = s.y != null ? s.y : s.northing != null ? s.northing : null, m = s.z != null ? s.z : s.elevation != null ? s.elevation : null;
1214
+ if (u == null || g == null || m == null || !Number.isFinite(u) || !Number.isFinite(g) || !Number.isFinite(m)) continue;
1215
+ const h = s[W] != null ? Number(s[W]) : null, d = s[Z] != null ? Number(s[Z]) : null;
1216
+ let p;
1217
+ if (s.nx != null && Number.isFinite(s.nx) && s.ny != null && Number.isFinite(s.ny) && s.nz != null && Number.isFinite(s.nz))
1218
+ p = new f.Vector3(s.nx, s.ny, s.nz).normalize();
1219
+ else {
1220
+ if (h == null || d == null || !Number.isFinite(h) || !Number.isFinite(d)) continue;
1221
+ p = Ut(h, d);
1222
+ }
1223
+ const N = new f.CylinderGeometry(n, n, r, i, 1, !1), k = new f.MeshStandardMaterial({
1224
+ color: Yt(s.structure_type, a),
1225
+ transparent: !0,
1226
+ opacity: o,
1227
+ side: f.DoubleSide
1228
+ }), b = new f.Mesh(N, k);
1229
+ b.position.set(u, g, m), b.quaternion.setFromUnitVectors(l, p), b.userData = {
1230
+ type: "structure",
1231
+ hole_id: s.hole_id,
1232
+ depth: s.depth ?? s.mid,
1233
+ structure_type: s.structure_type,
1234
+ dip: h,
1235
+ azimuth: d,
1236
+ comments: s.comments
1237
+ }, c.add(b);
1238
+ }
1239
+ return c;
1240
+ }
1241
+ function Xt(e, t, n, r = {}) {
1242
+ if (!e.scene || (Pe(e), !(t != null && t.length) || !(n != null && n.length))) return;
1243
+ const { maxDiscs: o = 3e3 } = r;
1244
+ let i = t;
1245
+ if (i.length > o) {
1246
+ const l = i.length / o, s = [];
1247
+ for (let u = 0; u < o; u++)
1248
+ s.push(i[Math.floor(u * l)]);
1249
+ i = s;
1250
+ }
1251
+ const a = n.flatMap((l) => (l.points || []).map((s) => ({ ...s, hole_id: l.id }))), c = kt(i, a, r);
1252
+ c.length && (e.structuralGroup = $t(c, r), e.scene.add(e.structuralGroup), e.structuralGroup.traverse((l) => {
1253
+ l.isMesh && e.structuralMeshes.push(l);
1254
+ }), G(e));
1255
+ }
1256
+ function Pe(e) {
1257
+ e.structuralGroup && (e.scene.remove(e.structuralGroup), e.structuralGroup.traverse((t) => {
1258
+ t.isMesh && (t.geometry.dispose(), t.material.dispose());
1259
+ }), e.structuralGroup = null), e.structuralMeshes = [], G(e);
1260
+ }
1261
+ function qt(e, t) {
1262
+ e.structuralGroup && (e.structuralGroup.visible = !!t);
1263
+ }
1264
+ let Zt = 0;
1265
+ function Wt(e) {
1266
+ let t, n, r, o;
1267
+ if ("width" in e || "height" in e || "x" in e && !("maxX" in e)) {
1268
+ const i = Number(e.x ?? 0), a = Number(e.y ?? 0), c = Number(e.width ?? 0), l = Number(e.height ?? 0);
1269
+ t = i, n = a, r = i + c, o = a + l;
1270
+ } else
1271
+ t = Number(e.minX), n = Number(e.minY), r = Number(e.maxX), o = Number(e.maxY);
1272
+ if (r - t <= 0)
1273
+ throw new Error(
1274
+ `Invalid raster bounds: width must be positive (got minX=${t}, maxX=${r})`
1275
+ );
1276
+ if (o - n <= 0)
1277
+ throw new Error(
1278
+ `Invalid raster bounds: height must be positive (got minY=${n}, maxY=${o})`
1279
+ );
1280
+ return { minX: t, minY: n, maxX: r, maxY: o };
1281
+ }
1282
+ function Kt(e) {
1283
+ if (e.type === "texture")
1284
+ return Promise.resolve(e.texture);
1285
+ let t, n = !1;
1286
+ if (e.type === "url")
1287
+ t = e.url;
1288
+ else if (e.type === "file")
1289
+ t = URL.createObjectURL(e.file), n = !0;
1290
+ else
1291
+ return Promise.reject(
1292
+ new Error(`Unsupported raster source type: "${e.type}"`)
1293
+ );
1294
+ return new Promise((r, o) => {
1295
+ new f.TextureLoader().load(
1296
+ t,
1297
+ (a) => {
1298
+ n && URL.revokeObjectURL(t), r(a);
1299
+ },
1300
+ void 0,
1301
+ (a) => {
1302
+ n && URL.revokeObjectURL(t), o(
1303
+ new Error(
1304
+ `Failed to load raster texture from "${t}": ${(a == null ? void 0 : a.message) ?? a}`
1305
+ )
1306
+ );
1307
+ }
1308
+ );
1309
+ });
1310
+ }
1311
+ async function zr(e) {
1312
+ const { source: t, bounds: n, elevation: r = 0, visible: o = !0, renderOrder: i = 0 } = e, a = e.id ?? `raster-overlay-${++Zt}`, c = e.name ?? a;
1313
+ let l = e.opacity ?? 1;
1314
+ if ((l < 0 || l > 1) && (console.warn(
1315
+ `[baselode] raster overlay "${a}": opacity ${l} is outside [0, 1] — clamped`
1316
+ ), l = Math.max(0, Math.min(1, l))), !t) throw new Error("raster overlay: options.source is required");
1317
+ if (!n) throw new Error("raster overlay: options.bounds is required");
1318
+ const s = Wt(n), { minX: u, minY: g, maxX: m, maxY: h } = s, d = m - u, p = h - g, N = (u + m) / 2, k = (g + h) / 2, b = await Kt(t), L = new f.PlaneGeometry(d, p), y = new f.MeshBasicMaterial({
1319
+ map: b,
1320
+ transparent: !0,
1321
+ opacity: l,
1322
+ side: f.DoubleSide,
1323
+ depthWrite: !1
1324
+ }), z = new f.Mesh(L, y);
1325
+ return z.position.set(N, k, r), z.renderOrder = i, z.visible = o, { id: a, name: c, mesh: z, texture: b, bounds: s, elevation: r, opacity: l, visible: o };
1326
+ }
1327
+ function Jt(e, t) {
1328
+ e.scene && (e.rasterOverlays.has(t.id) && de(e, t.id), e.rasterOverlays.set(t.id, t), e.scene.add(t.mesh));
1329
+ }
1330
+ function de(e, t) {
1331
+ var r;
1332
+ const n = e.rasterOverlays.get(t);
1333
+ n && ((r = e.scene) == null || r.remove(n.mesh), n.mesh.geometry.dispose(), n.mesh.material.dispose(), n.texture && n.texture.dispose(), e.rasterOverlays.delete(t));
1334
+ }
1335
+ function Qt(e, t, n) {
1336
+ const r = e.rasterOverlays.get(t);
1337
+ if (!r) return;
1338
+ const o = Math.max(0, Math.min(1, Number(n)));
1339
+ r.opacity = o, r.mesh.material.opacity = o, r.mesh.material.needsUpdate = !0;
1340
+ }
1341
+ function en(e, t, n) {
1342
+ const r = e.rasterOverlays.get(t);
1343
+ r && (r.visible = !!n, r.mesh.visible = r.visible);
1344
+ }
1345
+ function tn(e, t, n) {
1346
+ const r = e.rasterOverlays.get(t);
1347
+ r && (r.elevation = Number(n), r.mesh.position.setZ(r.elevation));
1348
+ }
1349
+ function nn(e, t) {
1350
+ return e.rasterOverlays.get(t);
1351
+ }
1352
+ function rn(e) {
1353
+ return Array.from(e.rasterOverlays.values());
1354
+ }
1355
+ function on(e) {
1356
+ for (const t of [...e.rasterOverlays.keys()])
1357
+ de(e, t);
1358
+ }
1359
+ function fe(e) {
1360
+ var n, r, o, i, a, c, l, s, u;
1361
+ if (!e) return "";
1362
+ const t = (g) => Number.isFinite(g) ? g.toFixed(3) : "nan";
1363
+ return [
1364
+ t((n = e.camera) == null ? void 0 : n.x),
1365
+ t((r = e.camera) == null ? void 0 : r.y),
1366
+ t((o = e.camera) == null ? void 0 : o.z),
1367
+ t((i = e.target) == null ? void 0 : i.x),
1368
+ t((a = e.target) == null ? void 0 : a.y),
1369
+ t((c = e.target) == null ? void 0 : c.z),
1370
+ t((l = e.up) == null ? void 0 : l.x),
1371
+ t((s = e.up) == null ? void 0 : s.y),
1372
+ t((u = e.up) == null ? void 0 : u.z)
1373
+ ].join("|");
1374
+ }
1375
+ function Re(e) {
1376
+ return !e.camera || !e.controls ? null : {
1377
+ camera: {
1378
+ x: e.camera.position.x,
1379
+ y: e.camera.position.y,
1380
+ z: e.camera.position.z
1381
+ },
1382
+ target: {
1383
+ x: e.controls.target.x,
1384
+ y: e.controls.target.y,
1385
+ z: e.controls.target.z
1386
+ },
1387
+ up: {
1388
+ x: e.camera.up.x,
1389
+ y: e.camera.up.y,
1390
+ z: e.camera.up.z
1391
+ }
1392
+ };
1393
+ }
1394
+ function sn(e, t) {
1395
+ if (!e.camera || !e.controls || !t) return !1;
1396
+ const n = t.camera || {}, r = t.target || {}, o = t.up || {};
1397
+ return [n.x, n.y, n.z, r.x, r.y, r.z, o.x, o.y, o.z].every(Number.isFinite) ? (e.camera.position.set(n.x, n.y, n.z), e.controls.target.set(r.x, r.y, r.z), e.camera.up.set(o.x, o.y, o.z), e.camera.lookAt(r.x, r.y, r.z), e.controls.update(), e._lastViewSignature = fe(t), !0) : !1;
1398
+ }
1399
+ function an(e) {
1400
+ if (!e.viewChangeHandler) return;
1401
+ const t = Date.now();
1402
+ if (t - e._lastViewEmitMs < 250) return;
1403
+ const n = Re(e);
1404
+ if (!n) return;
1405
+ const r = fe(n);
1406
+ r !== e._lastViewSignature && (e._lastViewSignature = r, e._lastViewEmitMs = t, e.viewChangeHandler(n));
1407
+ }
1408
+ function he(e, { minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: a }) {
1409
+ const c = (t + n) / 2, l = (r + o) / 2, s = (i + a) / 2, u = n - t, g = o - r, m = a - i, d = Math.max(u, g, m, 1) * 2;
1410
+ e.controls.target.set(c, l, s), e.camera.position.set(c + d, l + d, s + d), e.camera.lookAt(c, l, s), e.controls.update();
1411
+ }
1412
+ function ln(e, t = 1e3) {
1413
+ !e.camera || !e.controls || (e.controls.target.set(0, 0, 0), e.camera.position.set(t, t, t), e.camera.lookAt(0, 0, 0), e.controls.update());
1414
+ }
1415
+ function cn(e, t = 2e3) {
1416
+ !e.camera || !e.controls || (e.controls.target.set(0, 0, 0), e.camera.position.set(0, 0, t), e.camera.up.set(0, 1, 0), e.camera.lookAt(0, 0, 0), e.controls.update());
1417
+ }
1418
+ function un(e, t = 0, n = 0) {
1419
+ e.controls && typeof e.controls.pan == "function" && (e.controls.pan(t, n), e.controls.update());
1420
+ }
1421
+ function mn(e, t = 1.1) {
1422
+ !e.controls || typeof e.controls.dollyIn != "function" || typeof e.controls.dollyOut != "function" || (t > 1 ? e.controls.dollyOut(t) : e.controls.dollyIn(1 / t), e.controls.update());
1423
+ }
1424
+ function dn(e, t = 1.2) {
1425
+ if (!e.lastBounds) return;
1426
+ const {
1427
+ minX: n,
1428
+ maxX: r,
1429
+ minY: o,
1430
+ maxY: i,
1431
+ minZ: a,
1432
+ maxZ: c
1433
+ } = e.lastBounds, l = (r - n) * t, s = (i - o) * t, u = (c - a) * t, g = (n + r) / 2, m = (o + i) / 2, h = (a + c) / 2, p = Math.max(l, s, u, 1) * 2;
1434
+ e.controls.target.set(g, m, h), e.camera.position.set(g + p, m + p, h + p), e.camera.lookAt(g, m, h), e.controls.update();
1435
+ }
1436
+ const fn = 1, hn = 120;
1437
+ function bn(e, t) {
1438
+ if (!e.camera || !e.controls || !Number.isFinite(t)) return !1;
1439
+ const n = Math.min(hn, Math.max(fn, t)), r = e.controls.target, o = e.camera.position.distanceTo(r), i = e.camera.fov * Math.PI / 180, a = 2 * o * Math.tan(i / 2), c = n * Math.PI / 180, l = a / (2 * Math.tan(c / 2)), s = e.camera.position.clone().sub(r).normalize();
1440
+ return e.camera.position.copy(r).addScaledVector(s, l), e.camera.fov = n, e.camera.updateProjectionMatrix(), e.controls.update(), !0;
1441
+ }
1442
+ function gn(e, t = "orbit") {
1443
+ if (e.controlMode = t === "fly" ? "fly" : "orbit", e.controlMode === "fly")
1444
+ e.controls && (e.controls.enabled = !1), e.flyControls && (e.flyControls.enabled = !0);
1445
+ else if (e.flyControls && (e.flyControls.enabled = !1), e.controls) {
1446
+ e.controls.enabled = !0, e.camera.getWorldDirection(e._tmpDir);
1447
+ const n = e.camera.position.clone().addScaledVector(e._tmpDir, 10);
1448
+ e.controls.target.copy(n), e.controls.update();
1449
+ }
1450
+ }
1451
+ const B = "#9ca3af";
1452
+ function Me(e, t) {
1453
+ const n = Number(e == null ? void 0 : e.md), r = Number(t == null ? void 0 : t.md);
1454
+ if (!Number.isFinite(n) || !Number.isFinite(r)) return null;
1455
+ const o = Math.min(n, r), i = Math.max(n, r);
1456
+ return i <= o ? null : { segStart: o, segEnd: i };
1457
+ }
1458
+ function pn(e, t, n) {
1459
+ let r = 0, o = 0;
1460
+ for (let a = 0; a < e.length; a += 1) {
1461
+ const c = e[a], l = Number(c == null ? void 0 : c.from), s = Number(c == null ? void 0 : c.to), u = Number(c == null ? void 0 : c.value);
1462
+ if (!Number.isFinite(l) || !Number.isFinite(s) || !Number.isFinite(u) || s <= l) continue;
1463
+ const g = Math.max(t, l), h = Math.min(n, s) - g;
1464
+ h <= 0 || (r += u * h, o += h);
1465
+ }
1466
+ if (o <= 0) return null;
1467
+ const i = r / o;
1468
+ return Number.isFinite(i) ? i : null;
1469
+ }
1470
+ function yn(e, t) {
1471
+ if (!Number.isFinite(e)) return new f.Color(B);
1472
+ if (Te(e, t) < 0) return new f.Color(B);
1473
+ const r = Gt(e, t, B);
1474
+ return new f.Color(r);
1475
+ }
1476
+ function _n(e) {
1477
+ if (!e || !String(e).trim()) return B;
1478
+ const t = Ve(String(e).toLowerCase().trim());
1479
+ return "#" + new f.Color().setHSL(t, 0.7, 0.5).getHexString();
1480
+ }
1481
+ function Mn(e = {}) {
1482
+ return {
1483
+ preserveView: !!e.preserveView,
1484
+ assayIntervalsByHole: e.assayIntervalsByHole || null,
1485
+ selectedAssayVariable: e.selectedAssayVariable || "",
1486
+ isCategoricalVariable: !!e.isCategoricalVariable
1487
+ };
1488
+ }
1489
+ function zn(e, t) {
1490
+ if (!e || !t) return [];
1491
+ const n = [];
1492
+ return Object.values(e).forEach((r) => {
1493
+ (r || []).forEach((o) => {
1494
+ const i = Number(o == null ? void 0 : o.value);
1495
+ Number.isFinite(i) && n.push(i);
1496
+ });
1497
+ }), n;
1498
+ }
1499
+ function re(e) {
1500
+ return {
1501
+ holeId: e.id,
1502
+ project: e.project
1503
+ };
1504
+ }
1505
+ function En(e) {
1506
+ return `${e ?? ""}`.trim().toLowerCase();
1507
+ }
1508
+ function Nn(e, t) {
1509
+ const n = `${e ?? ""}:${t ?? 0}`, r = Ve(n), o = (t ?? 0) % 14 / 14, i = (r * 0.15 + o * 0.85) % 1, a = new f.Color();
1510
+ return a.setHSL(i, 1, 0.5), a;
1511
+ }
1512
+ function Ve(e) {
1513
+ const t = `${e ?? ""}`;
1514
+ let n = 2166136261;
1515
+ for (let r = 0; r < t.length; r += 1)
1516
+ n ^= t.charCodeAt(r), n = Math.imul(n, 16777619);
1517
+ return (n >>> 0) / 4294967295;
1518
+ }
1519
+ function kn(e, t, n) {
1520
+ let r = null, o = 0;
1521
+ for (const i of e) {
1522
+ const a = Number(i == null ? void 0 : i.from), c = Number(i == null ? void 0 : i.to);
1523
+ if (!Number.isFinite(a) || !Number.isFinite(c)) continue;
1524
+ const l = Math.min(n, c) - Math.max(t, a);
1525
+ l > o && (o = l, r = i == null ? void 0 : i.value);
1526
+ }
1527
+ return r;
1528
+ }
1529
+ function On(e, t) {
1530
+ if (!t || !e) return [];
1531
+ const n = e.id || e.holeId;
1532
+ if (!n) return [];
1533
+ const r = t[n];
1534
+ if (Array.isArray(r) && r.length) return r;
1535
+ const o = En(n);
1536
+ if (o) {
1537
+ const i = t[o];
1538
+ if (Array.isArray(i) && i.length) return i;
1539
+ }
1540
+ return [];
1541
+ }
1542
+ function Ln({ selectedAssayVariable: e, assayIntervals: t, assayScale: n, holeId: r, segmentIndex: o, p1: i, p2: a, isCategorical: c }) {
1543
+ if (!e)
1544
+ return Nn(r, o);
1545
+ if (e === "__HAS_ASSAY__") {
1546
+ if (!(t != null && t.length)) return new f.Color(B);
1547
+ const u = Me(i, a);
1548
+ return u ? t.some((m) => {
1549
+ const h = Number(m == null ? void 0 : m.from), d = Number(m == null ? void 0 : m.to);
1550
+ if (!Number.isFinite(h) || !Number.isFinite(d)) return !1;
1551
+ const p = Math.max(u.segStart, h);
1552
+ return Math.min(u.segEnd, d) > p;
1553
+ }) ? new f.Color("#ff8c42") : new f.Color(B) : new f.Color(B);
1554
+ }
1555
+ if (!(t != null && t.length)) return new f.Color(B);
1556
+ const l = Me(i, a);
1557
+ if (!l) return new f.Color(B);
1558
+ if (c) {
1559
+ const u = kn(t, l.segStart, l.segEnd);
1560
+ return new f.Color(_n(u));
1561
+ }
1562
+ const s = pn(t, l.segStart, l.segEnd);
1563
+ return yn(s, n);
1564
+ }
1565
+ function Dn(e, t, n = {}) {
1566
+ if (!e.scene || (He(e), !t || t.length === 0)) return;
1567
+ const { preserveView: r, assayIntervalsByHole: o, selectedAssayVariable: i, isCategoricalVariable: a } = Mn(n), c = a ? [] : zn(o, i), l = Vt(c);
1568
+ let s = 1 / 0, u = -1 / 0, g = 1 / 0, m = -1 / 0, h = 1 / 0, d = -1 / 0;
1569
+ const p = new f.Vector3(), N = new f.Vector3(0, 1, 0);
1570
+ t.forEach((k, b) => {
1571
+ const y = b * 137.5 % 360 / 360, z = new f.Color().setHSL(y, 0.75, 0.55), O = (k.points || []).map((D) => {
1572
+ s = Math.min(s, D.x), u = Math.max(u, D.x), g = Math.min(g, D.y), m = Math.max(m, D.y), h = Math.min(h, D.z), d = Math.max(d, D.z);
1573
+ const S = new f.Vector3(D.x, D.y, D.z);
1574
+ return S.md = D.md, S;
1575
+ });
1576
+ if (O.length < 2) {
1577
+ if (O.length === 1) {
1578
+ const D = new f.SphereGeometry(5, 12, 12), S = new f.MeshLambertMaterial({
1579
+ color: z,
1580
+ emissive: z,
1581
+ emissiveIntensity: 0.2
1582
+ }), w = new f.Mesh(D, S);
1583
+ w.position.copy(O[0]), w.userData = re(k), e.scene.add(w), e.drillLines.push(w), e.drillMeshes.push(w);
1584
+ }
1585
+ return;
1586
+ }
1587
+ const A = new f.Group();
1588
+ A.userData = re(k);
1589
+ const x = i ? On(k, o) : [];
1590
+ for (let D = 0; D < O.length - 1; D += 1) {
1591
+ const S = O[D], w = O[D + 1], F = p.subVectors(w, S), C = F.length();
1592
+ if (C <= 1e-3) continue;
1593
+ const I = 2.2, T = new f.CylinderGeometry(I, I, C, 6, 1, !0), P = Ln({
1594
+ selectedAssayVariable: i,
1595
+ assayIntervals: x,
1596
+ assayScale: l,
1597
+ holeId: k.id,
1598
+ segmentIndex: D,
1599
+ p1: S,
1600
+ p2: w,
1601
+ isCategorical: a
1602
+ }), E = new f.MeshLambertMaterial({
1603
+ color: P,
1604
+ flatShading: !0,
1605
+ emissive: P,
1606
+ emissiveIntensity: 0.15
1607
+ }), v = new f.Mesh(T, E);
1608
+ v.position.copy(S.clone().addScaledVector(F, 0.5)), v.quaternion.setFromUnitVectors(N, F.clone().normalize()), v.userData = re(k), A.add(v), e.drillMeshes.push(v);
1609
+ }
1610
+ e.scene.add(A), e.drillLines.push(A);
1611
+ }), e.camera && e.controls && (e.lastBounds = { minX: s, maxX: u, minY: g, maxY: m, minZ: h, maxZ: d }, r || he(e, { minX: s, maxX: u, minY: g, maxY: m, minZ: h, maxZ: d })), G(e);
1612
+ }
1613
+ function He(e) {
1614
+ e.drillLines.forEach((t) => {
1615
+ e.scene.remove(t), t.isGroup ? t.traverse((n) => {
1616
+ n.isMesh && (n.geometry.dispose(), n.material.dispose());
1617
+ }) : t.isMesh && (t.geometry.dispose(), t.material.dispose());
1618
+ }), e.drillLines = [], e.drillMeshes = [], G(e);
1619
+ }
1620
+ const An = 20, wn = 15, xn = "#00bcd4";
1621
+ function Sn(e = {}) {
1622
+ return {
1623
+ panelWidth: e.panelWidth != null ? Number(e.panelWidth) : An,
1624
+ lateralOffset: e.lateralOffset != null ? Number(e.lateralOffset) : wn,
1625
+ color: e.color || xn,
1626
+ valueMin: e.valueMin != null ? Number(e.valueMin) : null,
1627
+ valueMax: e.valueMax != null ? Number(e.valueMax) : null
1628
+ };
1629
+ }
1630
+ function Er(e) {
1631
+ if (!e || e.length < 2) return null;
1632
+ let t = -1 / 0, n = 1 / 0;
1633
+ for (const o of e)
1634
+ o.z > t && (t = o.z), o.z < n && (n = o.z);
1635
+ const r = t - n;
1636
+ return r < 1e-3 ? null : { topZ: t, botZ: n, height: r };
1637
+ }
1638
+ function vn(e, t, n, r, o, i, a) {
1639
+ if (!Array.isArray(e) || !Array.isArray(t)) return [];
1640
+ const c = Math.min(e.length, t.length), l = [];
1641
+ for (let b = 0; b < c; b++)
1642
+ Number.isFinite(e[b]) && Number.isFinite(t[b]) && l.push({ d: e[b], v: t[b] });
1643
+ if (l.length < 2) return [];
1644
+ const s = a != null && a > 0 ? a : null, u = s != null ? 0 : Math.min(...l.map((b) => b.d)), m = (s ?? Math.max(...l.map((b) => b.d))) - u || 1, h = Math.min(...l.map((b) => b.v)), d = Math.max(...l.map((b) => b.v)), p = o ?? h, k = (i ?? d) - p || 1;
1645
+ return l.map(({ d: b, v: L }) => {
1646
+ const y = (b - u) / m, z = Math.max(0, Math.min(1, (L - p) / k)), O = -n / 2 + z * n, A = y * r;
1647
+ return new f.Vector3(O, A, 0.01);
1648
+ });
1649
+ }
1650
+ function Fn(e, t) {
1651
+ const n = e.length;
1652
+ if (n < 2) return null;
1653
+ const r = [], o = [];
1654
+ let i = 0;
1655
+ for (let c = 0; c < n - 1; c++) {
1656
+ const l = e[c], s = e[c + 1], u = s.x - l.x, g = s.y - l.y, m = Math.sqrt(u * u + g * g);
1657
+ if (m < 1e-6) continue;
1658
+ const h = -g / m * t, d = u / m * t, p = 0.01;
1659
+ r.push(
1660
+ l.x + h,
1661
+ l.y + d,
1662
+ p,
1663
+ l.x - h,
1664
+ l.y - d,
1665
+ p,
1666
+ s.x + h,
1667
+ s.y + d,
1668
+ p,
1669
+ s.x - h,
1670
+ s.y - d,
1671
+ p
1672
+ ), o.push(i, i + 1, i + 2, i + 1, i + 3, i + 2), i += 4;
1673
+ }
1674
+ if (r.length === 0) return null;
1675
+ const a = new f.BufferGeometry();
1676
+ return a.setAttribute("position", new f.Float32BufferAttribute(r, 3)), a.setIndex(o), a;
1677
+ }
1678
+ function In(e, t) {
1679
+ const n = e.points || [];
1680
+ if (n.length < 2) return null;
1681
+ const r = n[0], o = n[n.length - 1], i = new f.Vector3(
1682
+ o.x - r.x,
1683
+ o.y - r.y,
1684
+ o.z - r.z
1685
+ ), a = i.length();
1686
+ if (a < 1e-3) return null;
1687
+ const c = i.clone().normalize(), l = Sn(t.options), { panelWidth: s, lateralOffset: u, color: g, valueMin: m, valueMax: h } = l, d = new f.Vector3(0, 0, 1);
1688
+ let p = new f.Vector3().crossVectors(c, d);
1689
+ p.lengthSq() < 1e-6 ? p.set(1, 0, 0) : p.normalize();
1690
+ const N = new f.Vector3().crossVectors(p, c).normalize(), k = new f.Vector3(r.x, r.y, r.z).addScaledVector(p, u), b = new f.Matrix4().makeBasis(p, c, N), L = new f.Quaternion().setFromRotationMatrix(b), y = n.map((F) => F.md).filter(Number.isFinite), z = y.length > 0 ? Math.max(...y) : a, O = vn(
1691
+ t.depths,
1692
+ t.values,
1693
+ s,
1694
+ a,
1695
+ m,
1696
+ h,
1697
+ z
1698
+ );
1699
+ if (O.length < 2) return null;
1700
+ const A = new f.Group();
1701
+ A.userData = { holeId: e.id, isStripLog: !0 };
1702
+ const x = s * 0.025, D = Fn(O, x);
1703
+ if (!D) return null;
1704
+ const S = new f.MeshBasicMaterial({
1705
+ color: new f.Color(g),
1706
+ side: f.DoubleSide
1707
+ }), w = new f.Mesh(D, S);
1708
+ return w.position.copy(k), w.quaternion.copy(L), A.add(w), A;
1709
+ }
1710
+ function Cn(e, t, n) {
1711
+ if (!e.scene || (le(e), !n || n.length === 0) || !t || t.length === 0) return;
1712
+ const r = /* @__PURE__ */ new Map();
1713
+ t.forEach((o) => {
1714
+ o.id != null && r.set(o.id, o);
1715
+ }), n.forEach((o) => {
1716
+ const i = r.get(o.holeId);
1717
+ if (!i) return;
1718
+ const a = In(i, o);
1719
+ a && (e.scene.add(a), e.stripLogGroups.push(a));
1720
+ });
1721
+ }
1722
+ function le(e) {
1723
+ e.stripLogGroups && (e.stripLogGroups.forEach((t) => {
1724
+ e.scene && e.scene.remove(t), t.traverse((n) => {
1725
+ n.geometry && n.geometry.dispose(), n.material && n.material.dispose();
1726
+ });
1727
+ }), e.stripLogGroups = []);
1728
+ }
1729
+ const ze = "#ffffbb", Bn = 2, Tn = 1.5, Pn = 1;
1730
+ function Rn(e) {
1731
+ const { renderer: t, scene: n, camera: r, container: o } = e;
1732
+ if (!t || !n || !r) return;
1733
+ const i = (o == null ? void 0 : o.clientWidth) || t.domElement.clientWidth || 1, a = (o == null ? void 0 : o.clientHeight) || t.domElement.clientHeight || 1, c = new st(t), l = new at(n, r);
1734
+ c.addPass(l);
1735
+ const s = new f.Vector2(i, a), u = new lt(s, n, r);
1736
+ u.visibleEdgeColor.set(ze), u.hiddenEdgeColor.set(ze), u.edgeStrength = Bn, u.edgeThickness = Tn, u.edgeGlow = Pn, u.pulsePeriod = 0, u.selectedObjects = [], c.addPass(u), c.setSize(i, a), e._composer = c, e._outlinePass = u;
1737
+ }
1738
+ function Vn(e, t, n) {
1739
+ !e._composer || !e._outlinePass || (e._composer.setSize(t, n), e._outlinePass.resolution.set(t, n));
1740
+ }
1741
+ function q(e, t) {
1742
+ e._outlinePass && (e._outlinePass.selectedObjects = t ? [t] : [], e._selectedObject = t || null);
1743
+ }
1744
+ function Ee(e) {
1745
+ e._composer && (e._composer.dispose(), e._composer = null), e._outlinePass = null, e._selectedObject = null, e.selectables = [];
1746
+ }
1747
+ const Hn = [
1748
+ { normal: [1, 0, 0], neibDir: [1, 0, 0], verts: [[1, -1, -1], [1, 1, -1], [1, 1, 1], [1, -1, 1]] },
1749
+ { normal: [-1, 0, 0], neibDir: [-1, 0, 0], verts: [[-1, -1, 1], [-1, 1, 1], [-1, 1, -1], [-1, -1, -1]] },
1750
+ { normal: [0, 1, 0], neibDir: [0, 1, 0], verts: [[-1, 1, 1], [1, 1, 1], [1, 1, -1], [-1, 1, -1]] },
1751
+ { normal: [0, -1, 0], neibDir: [0, -1, 0], verts: [[1, -1, 1], [-1, -1, 1], [-1, -1, -1], [1, -1, -1]] },
1752
+ { normal: [0, 0, 1], neibDir: [0, 0, 1], verts: [[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]] },
1753
+ { normal: [0, 0, -1], neibDir: [0, 0, -1], verts: [[1, -1, -1], [-1, -1, -1], [-1, 1, -1], [1, 1, -1]] }
1754
+ ];
1755
+ function Gn(e, t, n, r, o = {}) {
1756
+ if (!e.scene || (Ge(e), !t || !n || !r)) return;
1757
+ const { autoCenter: i = !0, opacity: a = 1 } = o;
1758
+ let c = 1 / 0, l = -1 / 0, s = 1 / 0, u = -1 / 0, g = 1 / 0, m = -1 / 0;
1759
+ t.forEach((E) => {
1760
+ const v = Number(E.x ?? E.center_x ?? 0), R = Number(E.y ?? E.center_y ?? 0), Y = Number(E.z ?? E.center_z ?? 0), U = Number(E.dx ?? E.size_x ?? 1), $ = Number(E.dy ?? E.size_y ?? 1), X = Number(E.dz ?? E.size_z ?? 1);
1761
+ c = Math.min(c, v - U / 2), l = Math.max(l, v + U / 2), s = Math.min(s, R - $ / 2), u = Math.max(u, R + $ / 2), g = Math.min(g, Y - X / 2), m = Math.max(m, Y + X / 2);
1762
+ });
1763
+ let h = 0, d = 0, p = 0;
1764
+ o.offset ? (h = Number(o.offset.x ?? 0), d = Number(o.offset.y ?? 0), p = Number(o.offset.z ?? 0)) : i && (h = -((c + l) / 2), d = -((s + u) / 2), p = -((g + m) / 2));
1765
+ const N = c + h, k = l + h, b = s + d, L = u + d, y = g + p, z = m + p, O = (E, v, R) => `${Math.round(E)},${Math.round(v)},${Math.round(R)}`, A = new Set(
1766
+ t.map((E) => O(Number(E.x ?? 0), Number(E.y ?? 0), Number(E.z ?? 0)))
1767
+ ), x = [], D = [], S = [], w = [], F = [];
1768
+ let C = 0;
1769
+ if (t.forEach((E) => {
1770
+ const v = Number(E.x ?? E.center_x ?? 0), R = Number(E.y ?? E.center_y ?? 0), Y = Number(E.z ?? E.center_z ?? 0), U = Number(E.dx ?? E.size_x ?? 1), $ = Number(E.dy ?? E.size_y ?? 1), X = Number(E.dz ?? E.size_z ?? 1), Ye = v + h, Ue = R + d, $e = Y + p, Xe = zt(E[n], r, f), { r: qe, g: Ze, b: We } = Xe;
1771
+ Hn.forEach((V) => {
1772
+ const Ke = v + V.neibDir[0] * U, Je = R + V.neibDir[1] * $, Qe = Y + V.neibDir[2] * X;
1773
+ if (A.has(O(Ke, Je, Qe))) return;
1774
+ const j = C;
1775
+ V.verts.forEach(([et, tt, nt]) => {
1776
+ x.push(Ye + et * U / 2, Ue + tt * $ / 2, $e + nt * X / 2), D.push(V.normal[0], V.normal[1], V.normal[2]), S.push(qe, Ze, We), C++;
1777
+ }), w.push(j, j + 1, j + 2, j, j + 2, j + 3), F.push(E);
1778
+ });
1779
+ }), x.length === 0) return;
1780
+ const I = new f.BufferGeometry();
1781
+ I.setAttribute("position", new f.Float32BufferAttribute(x, 3)), I.setAttribute("normal", new f.Float32BufferAttribute(D, 3)), I.setAttribute("color", new f.Float32BufferAttribute(S, 3)), I.setIndex(w);
1782
+ const T = new f.MeshLambertMaterial({
1783
+ vertexColors: !0,
1784
+ transparent: a < 1,
1785
+ opacity: a,
1786
+ side: f.DoubleSide
1787
+ }), P = new f.Mesh(I, T);
1788
+ P.userData._isMergedBlocks = !0, P.userData._quadToBlock = F, P.userData._offset = { x: h, y: d, z: p }, e.scene.add(P), e.blocks.push(P), G(e), e.camera && e.controls && (e.lastBounds = { minX: N, maxX: k, minY: b, maxY: L, minZ: y, maxZ: z }, he(e, { minX: N, maxX: k, minY: b, maxY: L, minZ: y, maxZ: z }));
1789
+ }
1790
+ function Ge(e) {
1791
+ var t;
1792
+ e.blocks.forEach((n) => {
1793
+ e.scene.remove(n), n.geometry.dispose(), n.material.dispose();
1794
+ }), e.blocks = [], e._blockHighlightMesh && ((t = e.scene) == null || t.remove(e._blockHighlightMesh), e._blockHighlightMesh.geometry.dispose(), e._blockHighlightMesh.material.dispose(), e._blockHighlightMesh = null), G(e);
1795
+ }
1796
+ function jn(e, t) {
1797
+ const n = Math.max(0, Math.min(1, Number(t)));
1798
+ e.blocks.forEach((r) => {
1799
+ r.material && (r.material.opacity = n, r.material.transparent = n < 1, r.material.needsUpdate = !0);
1800
+ });
1801
+ }
1802
+ function Yn(e, t, n) {
1803
+ const r = (n == null ? void 0 : n.x) ?? 0, o = (n == null ? void 0 : n.y) ?? 0, i = (n == null ? void 0 : n.z) ?? 0, a = Number(t.x ?? t.center_x ?? 0) + r, c = Number(t.y ?? t.center_y ?? 0) + o, l = Number(t.z ?? t.center_z ?? 0) + i, s = Number(t.dx ?? t.size_x ?? 1), u = Number(t.dy ?? t.size_y ?? 1), g = Number(t.dz ?? t.size_z ?? 1);
1804
+ if (!e._blockHighlightMesh) {
1805
+ const m = new f.BoxGeometry(1, 1, 1), h = new f.MeshBasicMaterial({ transparent: !0, opacity: 0, depthWrite: !1 });
1806
+ e._blockHighlightMesh = new f.Mesh(m, h), e.scene.add(e._blockHighlightMesh);
1807
+ }
1808
+ return e._blockHighlightMesh.position.set(a, c, l), e._blockHighlightMesh.scale.set(s, u, g), e._blockHighlightMesh;
1809
+ }
1810
+ function je(e) {
1811
+ var o, i;
1812
+ if (!e._outlinePass || e.selectables.length === 0) {
1813
+ e._outlinePass && q(e, null);
1814
+ return;
1815
+ }
1816
+ const t = e.raycaster.intersectObjects(e.selectables, !0);
1817
+ if (t.length === 0) {
1818
+ q(e, null);
1819
+ return;
1820
+ }
1821
+ const n = t[0], r = n.object;
1822
+ if ((o = r == null ? void 0 : r.userData) != null && o._isMergedBlocks) {
1823
+ const a = Math.floor(n.faceIndex / 2), c = (i = r.userData._quadToBlock) == null ? void 0 : i[a];
1824
+ if (c) {
1825
+ q(e, Yn(e, c, r.userData._offset));
1826
+ return;
1827
+ }
1828
+ }
1829
+ q(e, r);
1830
+ }
1831
+ function Un(e) {
1832
+ const t = e.renderer;
1833
+ t && (e.handleCanvasClick = (n) => {
1834
+ var h, d, p, N, k, b, L;
1835
+ if (n.button !== 0) return;
1836
+ if ((h = e.gizmo) != null && h.domElement) {
1837
+ const y = e.gizmo.domElement.getBoundingClientRect();
1838
+ if (n.clientX >= y.left && n.clientX <= y.right && n.clientY >= y.top && n.clientY <= y.bottom)
1839
+ return;
1840
+ }
1841
+ const r = t.domElement.getBoundingClientRect(), o = n.clientX - r.left, i = n.clientY - r.top;
1842
+ if (e.pointer.x = o / r.width * 2 - 1, e.pointer.y = -(i / r.height * 2) + 1, e.raycaster.setFromCamera(e.pointer, e.camera), je(e), e.blocks.length > 0) {
1843
+ const y = e.raycaster.intersectObjects(e.blocks, !1);
1844
+ if (y.length > 0) {
1845
+ const z = y[0], O = z.object;
1846
+ if ((d = O == null ? void 0 : O.userData) != null && d._isMergedBlocks && e.blockClickHandler) {
1847
+ const A = Math.floor(z.faceIndex / 2), x = O.userData._quadToBlock[A];
1848
+ x && e.blockClickHandler(x);
1849
+ }
1850
+ return;
1851
+ }
1852
+ }
1853
+ const a = e.raycaster.intersectObjects(e.drillMeshes, !0), c = e.raycaster.intersectObjects(e.structuralMeshes, !0), l = ((p = a[0]) == null ? void 0 : p.distance) ?? 1 / 0;
1854
+ if ((((N = c[0]) == null ? void 0 : N.distance) ?? 1 / 0) < l && c.length > 0) {
1855
+ const y = c[0].object;
1856
+ e.drillholeClickHandler && e.drillholeClickHandler({ type: "structure", ...y.userData });
1857
+ return;
1858
+ }
1859
+ if (a.length === 0) return;
1860
+ let u = a[0].object;
1861
+ for (; u && u.parent && !((k = u.userData) != null && k.holeId); )
1862
+ u = u.parent;
1863
+ const g = (b = u == null ? void 0 : u.userData) == null ? void 0 : b.holeId, m = (L = u == null ? void 0 : u.userData) == null ? void 0 : L.project;
1864
+ g && e.drillholeClickHandler && e.drillholeClickHandler({ holeId: g, project: m });
1865
+ }, t.domElement.addEventListener("click", e.handleCanvasClick));
1866
+ }
1867
+ class Nr {
1868
+ constructor() {
1869
+ this.container = null, this.scene = null, this.camera = null, this.renderer = null, this.controls = null, this.flyControls = null, this.gizmo = null, this.blocks = [], this.drillLines = [], this.drillMeshes = [], this.structuralGroup = null, this.structuralMeshes = [], this.stripLogGroups = [], this.frameId = null, this.clock = new f.Clock(), this.handleCanvasClick = null, this.raycaster = new f.Raycaster(), this.pointer = new f.Vector2(), this.drillholeClickHandler = null, this.blockClickHandler = null, this.controlMode = "orbit", this._tmpDir = new f.Vector3(), this.viewChangeHandler = null, this._lastViewSignature = "", this._lastViewEmitMs = 0, this.selectables = [], this._selectedObject = null, this._composer = null, this._blockHighlightMesh = null, this._outlinePass = null, this.rasterOverlays = /* @__PURE__ */ new Map();
1870
+ }
1871
+ init(t) {
1872
+ if (!t) return;
1873
+ this.container = t;
1874
+ const n = t.clientWidth, r = t.clientHeight;
1875
+ this.scene = new f.Scene(), this.scene.background = new f.Color(16777215), this.camera = new f.PerspectiveCamera(28, n / r, 1e-3, 1e7), this.camera.up.set(0, 0, 1), this.camera.position.set(50, 50, 50), this.camera.lookAt(0, 0, 0), this.renderer = new f.WebGLRenderer({ antialias: !0 }), this.renderer.setSize(n, r), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.autoClear = !1, t.appendChild(this.renderer.domElement);
1876
+ const o = new f.AmbientLight(16777215, 1.2);
1877
+ this.scene.add(o);
1878
+ const i = new f.DirectionalLight(16777215, 1.5);
1879
+ i.position.set(10, 10, 5), this.scene.add(i);
1880
+ const a = new f.AxesHelper(20);
1881
+ this.scene.add(a), this.controls = new rt(this.camera, this.renderer.domElement), this.controls.enableDamping = !1, this.controls.screenSpacePanning = !0, this.controls.enableZoom = !0, this.controls.zoomSpeed = 10, this.controls.minDistance = 1e-4, this.controls.maxDistance = 5e6, this.controls.mouseButtons = {
1882
+ LEFT: f.MOUSE.PAN,
1883
+ MIDDLE: f.MOUSE.DOLLY,
1884
+ RIGHT: f.MOUSE.ROTATE
1885
+ }, this.controls.touches = {
1886
+ ONE: f.TOUCH.ROTATE,
1887
+ TWO: f.TOUCH.DOLLY_PAN
1888
+ }, this.controls.maxPolarAngle = Math.PI, this.flyControls = new ot(this.camera, this.renderer.domElement), this.flyControls.movementSpeed = 2e3, this.flyControls.rollSpeed = Math.PI / 12, this.flyControls.dragToLook = !0, this.flyControls.enabled = !1, this.gizmo = new it(this.camera, this.renderer, {
1889
+ container: this.container,
1890
+ placement: "top-right",
1891
+ size: 110,
1892
+ offset: { top: 12, right: 12 },
1893
+ animated: !0,
1894
+ speed: 1.5
1895
+ }), this.gizmo.attachControls(this.controls), Un(this), this._wheelRelay = (l) => {
1896
+ l.target !== this.renderer.domElement && (l.preventDefault(), this.renderer.domElement.dispatchEvent(new WheelEvent("wheel", {
1897
+ clientX: l.clientX,
1898
+ clientY: l.clientY,
1899
+ deltaX: l.deltaX,
1900
+ deltaY: l.deltaY,
1901
+ deltaZ: l.deltaZ,
1902
+ deltaMode: l.deltaMode,
1903
+ ctrlKey: l.ctrlKey,
1904
+ shiftKey: l.shiftKey,
1905
+ altKey: l.altKey,
1906
+ bubbles: !1
1907
+ })));
1908
+ }, this.container.addEventListener("wheel", this._wheelRelay, { passive: !1 }), Rn(this);
1909
+ const c = () => {
1910
+ var s;
1911
+ this.frameId = requestAnimationFrame(c);
1912
+ const l = this.clock.getDelta();
1913
+ this.renderer.clear(), this.controlMode === "fly" && ((s = this.flyControls) != null && s.enabled) ? this.flyControls.update(l) : this.controls && this.controls.update(), this._emitViewChangeIfNeeded(), this._composer ? this._composer.render(l) : this.renderer.render(this.scene, this.camera), this.gizmo && this.gizmo.render();
1914
+ };
1915
+ c();
1916
+ }
1917
+ resize() {
1918
+ if (!this.container || !this.camera || !this.renderer) return;
1919
+ const t = this.container.clientWidth, n = this.container.clientHeight;
1920
+ this.camera.aspect = t / n, this.camera.updateProjectionMatrix(), this.renderer.setSize(t, n), this.gizmo && this.gizmo.update(), Vn(this, t, n);
1921
+ }
1922
+ dispose() {
1923
+ this.frameId && cancelAnimationFrame(this.frameId), this.renderer && this.handleCanvasClick && this.renderer.domElement.removeEventListener("click", this.handleCanvasClick), this.gizmo && (this.gizmo.dispose(), this.gizmo = null), this.viewChangeHandler = null, Ge(this), He(this), le(this), Pe(this), on(this), Ee(this), this.container && this._wheelRelay && this.container.removeEventListener("wheel", this._wheelRelay), this.controls && this.controls.dispose(), this.flyControls && this.flyControls.dispose(), this.renderer && (this.renderer.dispose(), this.container && this.renderer.domElement && this.container.removeChild(this.renderer.domElement));
1924
+ }
1925
+ // ---------------------------------------------------------------------------
1926
+ // Data renderers — delegate to domain modules
1927
+ // ---------------------------------------------------------------------------
1928
+ setDrillholes(t, n = {}) {
1929
+ Dn(this, t, n);
1930
+ }
1931
+ /**
1932
+ * Add floating 2D strip log panels beside drillholes in the 3D scene.
1933
+ * Each panel is a flat rectangle offset from the hole collar, depth-registered
1934
+ * to the hole's vertical extent and containing a line graph of numeric data.
1935
+ *
1936
+ * @param {Array<object>} holes - Hole objects (same array as passed to setDrillholes)
1937
+ * @param {Array<object>} stripLogs - Strip log definitions. Each must contain:
1938
+ * - `holeId` {string} — must match a hole id
1939
+ * - `depths` {number[]} — downhole depth positions for each sample
1940
+ * - `values` {number[]} — numeric value at each depth
1941
+ * - `options` {object} — optional: panelWidth, lateralOffset, color, valueMin, valueMax
1942
+ */
1943
+ setStripLogs(t, n) {
1944
+ Cn(this, t, n);
1945
+ }
1946
+ /**
1947
+ * Remove all strip log panels from the scene and free GPU resources.
1948
+ */
1949
+ clearStripLogs() {
1950
+ le(this);
1951
+ }
1952
+ /**
1953
+ * Render block model data as a single merged mesh of exterior faces only.
1954
+ * @param {Array<Object>} data - Block rows (canonical column names)
1955
+ * @param {string} selectedProperty - Attribute column used for colouring
1956
+ * @param {Object} stats - Property statistics
1957
+ * @param {Object} [options]
1958
+ */
1959
+ setBlocks(t, n, r, o = {}) {
1960
+ Gn(this, t, n, r, o);
1961
+ }
1962
+ /**
1963
+ * Update the opacity of all currently rendered blocks.
1964
+ * @param {number} opacity - New opacity value between 0 and 1
1965
+ */
1966
+ setBlockOpacity(t) {
1967
+ jn(this, t);
1968
+ }
1969
+ setStructuralDiscs(t, n, r = {}) {
1970
+ Xt(this, t, n, r);
1971
+ }
1972
+ setStructuralDiscsVisible(t) {
1973
+ qt(this, t);
1974
+ }
1975
+ // ---------------------------------------------------------------------------
1976
+ // Click handlers
1977
+ // ---------------------------------------------------------------------------
1978
+ setDrillholeClickHandler(t) {
1979
+ this.drillholeClickHandler = t;
1980
+ }
1981
+ /**
1982
+ * Register a click handler for block selection.
1983
+ * @param {Function|null} handler - Callback ``(blockData) => void``, or null to clear
1984
+ */
1985
+ setBlockClickHandler(t) {
1986
+ this.blockClickHandler = typeof t == "function" ? t : null;
1987
+ }
1988
+ // ---------------------------------------------------------------------------
1989
+ // Camera controls — delegate to baselode3dCameraControls
1990
+ // ---------------------------------------------------------------------------
1991
+ setViewChangeHandler(t) {
1992
+ this.viewChangeHandler = typeof t == "function" ? t : null;
1993
+ }
1994
+ getViewState() {
1995
+ return Re(this);
1996
+ }
1997
+ setViewState(t) {
1998
+ return sn(this, t);
1999
+ }
2000
+ _buildViewSignature(t) {
2001
+ return fe(t);
2002
+ }
2003
+ _emitViewChangeIfNeeded() {
2004
+ an(this);
2005
+ }
2006
+ _fitCameraToBounds({ minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: a }) {
2007
+ he(this, { minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: a });
2008
+ }
2009
+ recenterCameraToOrigin(t = 1e3) {
2010
+ ln(this, t);
2011
+ }
2012
+ lookDown(t = 2e3) {
2013
+ cn(this, t);
2014
+ }
2015
+ pan(t = 0, n = 0) {
2016
+ un(this, t, n);
2017
+ }
2018
+ dolly(t = 1.1) {
2019
+ mn(this, t);
2020
+ }
2021
+ focusOnLastBounds(t = 1.2) {
2022
+ dn(this, t);
2023
+ }
2024
+ /**
2025
+ * Change the camera field-of-view while keeping the visible scene the same apparent size.
2026
+ * @param {number} fovDeg - Desired FOV in degrees
2027
+ */
2028
+ setCameraFov(t) {
2029
+ bn(this, t);
2030
+ }
2031
+ /**
2032
+ * Set the scene background colour.
2033
+ * @param {'white'|'black'} colour
2034
+ */
2035
+ setBackground(t) {
2036
+ this.scene && (this.scene.background = new f.Color(t === "black" ? 0 : 16777215));
2037
+ }
2038
+ setControlMode(t = "orbit") {
2039
+ gn(this, t);
2040
+ }
2041
+ // ---------------------------------------------------------------------------
2042
+ // Selection glow public API
2043
+ // ---------------------------------------------------------------------------
2044
+ _syncSelectables() {
2045
+ G(this);
2046
+ }
2047
+ /**
2048
+ * Register the objects that are candidates for click-select glow.
2049
+ * @param {THREE.Object3D[]} objects
2050
+ */
2051
+ setSelectableObjects(t) {
2052
+ this.selectables = Array.isArray(t) ? t.slice() : [];
2053
+ }
2054
+ /**
2055
+ * Programmatically select an object (or pass null to clear).
2056
+ * @param {THREE.Object3D|null} object
2057
+ */
2058
+ selectObject(t) {
2059
+ q(this, t || null);
2060
+ }
2061
+ /**
2062
+ * Return the currently selected object, or null if nothing is selected.
2063
+ * @returns {THREE.Object3D|null}
2064
+ */
2065
+ getSelectedObject() {
2066
+ return this._selectedObject || null;
2067
+ }
2068
+ /**
2069
+ * Dispose the effect composer and all GPU resources used by the selection glow.
2070
+ */
2071
+ disposeGlow() {
2072
+ Ee(this);
2073
+ }
2074
+ /** @private */
2075
+ _updateSelectionFromPointer() {
2076
+ je(this);
2077
+ }
2078
+ // ---------------------------------------------------------------------------
2079
+ // Raster overlay API — delegate to rasterOverlayScene
2080
+ // ---------------------------------------------------------------------------
2081
+ /**
2082
+ * Add a raster overlay layer (created with createRasterOverlay) to the scene.
2083
+ * @param {object} layer - Layer descriptor returned by createRasterOverlay()
2084
+ */
2085
+ addRasterOverlay(t) {
2086
+ Jt(this, t);
2087
+ }
2088
+ /**
2089
+ * Remove a raster overlay from the scene and dispose its GPU resources.
2090
+ * @param {string} id - Overlay id
2091
+ */
2092
+ removeRasterOverlay(t) {
2093
+ de(this, t);
2094
+ }
2095
+ /**
2096
+ * Set the opacity of a raster overlay at runtime.
2097
+ * @param {string} id - Overlay id
2098
+ * @param {number} opacity - New opacity [0, 1]
2099
+ */
2100
+ setRasterOverlayOpacity(t, n) {
2101
+ Qt(this, t, n);
2102
+ }
2103
+ /**
2104
+ * Show or hide a raster overlay.
2105
+ * @param {string} id - Overlay id
2106
+ * @param {boolean} visible
2107
+ */
2108
+ setRasterOverlayVisibility(t, n) {
2109
+ en(this, t, n);
2110
+ }
2111
+ /**
2112
+ * Update the elevation (Z position) of a raster overlay.
2113
+ * @param {string} id - Overlay id
2114
+ * @param {number} elevation
2115
+ */
2116
+ setRasterOverlayElevation(t, n) {
2117
+ tn(this, t, n);
2118
+ }
2119
+ /**
2120
+ * Return a raster overlay by id, or undefined if not found.
2121
+ * @param {string} id
2122
+ * @returns {object|undefined}
2123
+ */
2124
+ getRasterOverlay(t) {
2125
+ return nn(this, t);
2126
+ }
2127
+ /**
2128
+ * Return all raster overlay layers in insertion order.
2129
+ * @returns {object[]}
2130
+ */
2131
+ listRasterOverlays() {
2132
+ return rn(this);
2133
+ }
2134
+ }
2135
+ export {
2136
+ hn as $,
2137
+ Z as A,
2138
+ nr as B,
2139
+ M as C,
2140
+ ue as D,
2141
+ De as E,
2142
+ te as F,
2143
+ ve as G,
2144
+ H,
2145
+ br as I,
2146
+ hr as J,
2147
+ Ot as K,
2148
+ Ne as L,
2149
+ ce as M,
2150
+ Ae as N,
2151
+ ne as O,
2152
+ Le as P,
2153
+ Nr as Q,
2154
+ be as R,
2155
+ bt as S,
2156
+ J as T,
2157
+ ee as U,
2158
+ we as V,
2159
+ mt as W,
2160
+ Q as X,
2161
+ It as Y,
2162
+ Dt as Z,
2163
+ dt as _,
2164
+ ke as a,
2165
+ fn as a0,
2166
+ ge as a1,
2167
+ At as a2,
2168
+ St as a3,
2169
+ vt as a4,
2170
+ ut as a5,
2171
+ xn as a6,
2172
+ wn as a7,
2173
+ An as a8,
2174
+ Jt as a9,
2175
+ Er as aA,
2176
+ nn as aB,
2177
+ Re as aC,
2178
+ Et as aD,
2179
+ rn as aE,
2180
+ mr as aF,
2181
+ ar as aG,
2182
+ sr as aH,
2183
+ cn as aI,
2184
+ yt as aJ,
2185
+ Wt as aK,
2186
+ Sn as aL,
2187
+ un as aM,
2188
+ ur as aN,
2189
+ ln as aO,
2190
+ de as aP,
2191
+ xt as aQ,
2192
+ gn as aR,
2193
+ bn as aS,
2194
+ tn as aT,
2195
+ Qt as aU,
2196
+ en as aV,
2197
+ Cn as aW,
2198
+ sn as aX,
2199
+ ft as aY,
2200
+ Nt as aa,
2201
+ Mr as ab,
2202
+ Vt as ac,
2203
+ In as ad,
2204
+ vn as ae,
2205
+ $t as af,
2206
+ fe as ag,
2207
+ fr as ah,
2208
+ _t as ai,
2209
+ on as aj,
2210
+ le as ak,
2211
+ kt as al,
2212
+ zr as am,
2213
+ cr as an,
2214
+ Ut as ao,
2215
+ mn as ap,
2216
+ an as aq,
2217
+ Mt as ar,
2218
+ he as as,
2219
+ dn as at,
2220
+ dr as au,
2221
+ _n as av,
2222
+ zt as aw,
2223
+ wt as ax,
2224
+ Te as ay,
2225
+ Gt as az,
2226
+ W as b,
2227
+ lr as c,
2228
+ Oe as d,
2229
+ Fe as e,
2230
+ ir as f,
2231
+ me as g,
2232
+ ae as h,
2233
+ se as i,
2234
+ K as j,
2235
+ gt as k,
2236
+ Pt as l,
2237
+ ht as m,
2238
+ yr as n,
2239
+ _r as o,
2240
+ Rt as p,
2241
+ Lt as q,
2242
+ _ as r,
2243
+ pr as s,
2244
+ gr as t,
2245
+ tr as u,
2246
+ Qn as v,
2247
+ ie as w,
2248
+ er as x,
2249
+ or as y,
2250
+ rr as z
2251
+ };
2252
+ //# sourceMappingURL=baselode3dScene-DbELmWnr.js.map