baselode 0.1.1

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,1821 @@
1
+ import ee from "papaparse";
2
+ import { jsx as k, jsxs as ae } from "react/jsx-runtime";
3
+ import { useRef as rt, useState as W, useEffect as re, useMemo as ze } from "react";
4
+ import me from "plotly.js-dist-min";
5
+ import * as g from "three";
6
+ import { OrbitControls as ot } from "three/examples/jsm/controls/OrbitControls";
7
+ import { FlyControls as it } from "three/examples/jsm/controls/FlyControls";
8
+ import { ViewportGizmo as st } from "three-viewport-gizmo";
9
+ const x = "hole_id", q = "latitude", X = "longitude", oe = "elevation", j = "azimuth", B = "dip", $ = "from", H = "to", we = "mid", Z = "project_id", K = "easting", J = "northing", $e = "crs", V = "depth", cn = {
10
+ // A unique hole identifier across the entire dataset and all future data sets
11
+ [x]: "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
+ [Z]: "string",
16
+ // The latitude of the collar, in decimal degrees (WGS84)
17
+ [q]: "number",
18
+ // The longitude of the collar, in decimal degrees (WGS84)
19
+ [X]: "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
+ [K]: "number",
24
+ // The northing coordinate of the collar, in meters (projected CRS)
25
+ [J]: "number",
26
+ // The coordinate reference system of the collar coordinates for easting/northing, as an EPSG code or proj string
27
+ [$e]: "string"
28
+ }, un = {
29
+ // The unique hole id that maps to the collar and any other data tables
30
+ [x]: "string",
31
+ // The depth along the hole where the survey measurement was taken / started
32
+ [V]: "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
+ [H]: "number",
35
+ // The azimuth of the hole at the survey depth, in degrees from north
36
+ [j]: "number",
37
+ // The dip of the hole at the survey depth, in degrees from horizontal (negative values indicate downward inclination)
38
+ [B]: "number"
39
+ }, dn = {
40
+ // The unique hole id that maps to the collar and any other data tables
41
+ [x]: "string",
42
+ // The depth along the hole where the assay interval starts
43
+ [$]: "number",
44
+ // The depth along the hole where the assay interval ends
45
+ [H]: "number",
46
+ // The midpoint depth of the assay interval
47
+ [we]: "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
+ }, at = {
51
+ [x]: ["hole_id", "holeid", "hole id", "hole-id"],
52
+ datasource_hole_id: ["datasource_hole_id", "datasourceholeid", "datasource hole id", "datasource-hole-id", "company_hole_id", "companyholeid", "company hole id", "company-hole-id"],
53
+ [Z]: ["project_id", "projectid", "project id", "project-id", "project_code", "projectcode", "project code", "project-code", "companyId", "company_id", "companyid", "company id", "company-id", "dataset", "project"],
54
+ [q]: ["latitude", "lat"],
55
+ [X]: ["longitude", "lon"],
56
+ [oe]: ["elevation", "rl", "elev", "z"],
57
+ [K]: ["easting", "x"],
58
+ [J]: ["northing", "y"],
59
+ [$e]: ["crs", "epsg", "projection"],
60
+ [$]: ["from", "depth_from", "from_depth", "samp_from", "sample_from", "sampfrom", "fromdepth"],
61
+ [H]: ["to", "depth_to", "to_depth", "samp_to", "sample_to", "sampto", "todepth"],
62
+ [j]: ["azimuth", "az", "dipdir", "dip_direction"],
63
+ [B]: ["dip"],
64
+ declination: ["declination", "dec"],
65
+ [V]: ["depth", "survey_depth", "surveydepth"]
66
+ }, je = {};
67
+ for (const [e, t] of Object.entries(at))
68
+ for (const n of t) {
69
+ const r = n.toLowerCase().trim();
70
+ je[r] = e;
71
+ }
72
+ function fe(e) {
73
+ return (e || "").toString().trim().toLowerCase().replace(/\s+/g, "_");
74
+ }
75
+ function ce(e, t = null, n = null) {
76
+ const r = { ...je };
77
+ if (n) {
78
+ for (const [s, i] of Object.entries(n))
79
+ if (s != null && i != null) {
80
+ const a = fe(s), c = fe(i);
81
+ r[a] = c;
82
+ }
83
+ }
84
+ const o = {};
85
+ for (const [s, i] of Object.entries(e)) {
86
+ const a = fe(s), c = r[a] || a;
87
+ o[c] = i;
88
+ }
89
+ return o;
90
+ }
91
+ function mn(e, t = null, n = null) {
92
+ return e.map((r) => ce(r, t, n));
93
+ }
94
+ const Be = /* @__PURE__ */ new Set([
95
+ "hole_id",
96
+ "holeid",
97
+ "id",
98
+ "holeId",
99
+ "project_code",
100
+ "project",
101
+ "latitude",
102
+ "longitude",
103
+ "lat",
104
+ "lng",
105
+ "elevation",
106
+ "dip",
107
+ "azimuth",
108
+ "holetype",
109
+ "shape",
110
+ "anumber",
111
+ "collarid",
112
+ "companyholeid",
113
+ "company_hole_id",
114
+ "samp_from",
115
+ "samp_to",
116
+ "sample_from",
117
+ "sample_to",
118
+ "from",
119
+ "to",
120
+ "depth_from",
121
+ "depth_to",
122
+ "fromdepth",
123
+ "todepth",
124
+ "comment",
125
+ "z"
126
+ ]), Ie = "[baselode:data]";
127
+ function lt(e, t = "Unknown error") {
128
+ if (e instanceof Error) return e;
129
+ const n = typeof e == "string" && e.trim() ? e : t;
130
+ return new Error(n);
131
+ }
132
+ function P(e, t, n = "Operation failed") {
133
+ const r = lt(t, n), o = new Error(`${e}: ${r.message}`);
134
+ return o.cause = r, o;
135
+ }
136
+ function fn(e, t) {
137
+ if (t !== void 0) {
138
+ console.warn(`${Ie} ${e}`, t);
139
+ return;
140
+ }
141
+ console.warn(`${Ie} ${e}`);
142
+ }
143
+ function hn(e) {
144
+ console.info(`${Ie} ${e}`);
145
+ }
146
+ const ye = (e, t = null) => ce(e, null, t);
147
+ function ct(e) {
148
+ return { holeId: e[x] };
149
+ }
150
+ function Ue(e, t = null) {
151
+ const n = e[x], r = n !== void 0 ? `${n}`.trim() : "";
152
+ if (!r) return null;
153
+ const o = e[Z] || e.project || e.project_code, s = Number(e[$]), i = Number(e[H]);
154
+ return !Number.isFinite(s) || !Number.isFinite(i) || i <= s ? null : {
155
+ holeId: r,
156
+ project: o,
157
+ from: s,
158
+ to: i,
159
+ ...e
160
+ };
161
+ }
162
+ function Ye(e, t) {
163
+ var o;
164
+ const n = t.sort((s, i) => s.from - i.from), r = [];
165
+ return n.forEach((s) => {
166
+ const { from: i, to: a, project: c, ...l } = s, u = {
167
+ z: i,
168
+ from: i,
169
+ to: a,
170
+ [x]: e,
171
+ [Z]: c,
172
+ ...l
173
+ };
174
+ r.push(u), r.push({ ...u, z: a });
175
+ }), { id: e, project: (o = n[0]) == null ? void 0 : o.project, points: r };
176
+ }
177
+ function pn(e, t = null) {
178
+ return new Promise((n, r) => {
179
+ const o = /* @__PURE__ */ new Set();
180
+ ee.parse(e, {
181
+ header: !0,
182
+ dynamicTyping: !0,
183
+ skipEmptyLines: !0,
184
+ step: (s) => {
185
+ const a = ye(s.data, t)[x];
186
+ a !== void 0 && `${a}`.trim() !== "" && o.add(`${a}`.trim());
187
+ },
188
+ complete: () => n(Array.from(o)),
189
+ error: (s) => r(P("parseAssayHoleIds", s))
190
+ });
191
+ });
192
+ }
193
+ function ut(e) {
194
+ return Object.entries(e || {}).some(([t, n]) => !(Be.has(t) || n == null || typeof n == "string" && n.trim() === ""));
195
+ }
196
+ function dt(e, t = null) {
197
+ return new Promise((n, r) => {
198
+ const o = /* @__PURE__ */ new Map();
199
+ ee.parse(e, {
200
+ header: !0,
201
+ dynamicTyping: !0,
202
+ skipEmptyLines: !0,
203
+ step: (s) => {
204
+ const i = ye(s.data, t);
205
+ if (!ut(i)) return;
206
+ const c = ct(i).holeId;
207
+ if (c !== void 0 && `${c}`.trim() !== "") {
208
+ const l = `${c}`.trim();
209
+ o.has(l) || o.set(l, {
210
+ holeId: l
211
+ });
212
+ }
213
+ },
214
+ complete: () => n(Array.from(o.values())),
215
+ error: (s) => r(P("parseAssayHoleIdsWithAssays", s))
216
+ });
217
+ });
218
+ }
219
+ function mt(e, t, n = null, r = null) {
220
+ return new Promise((o, s) => {
221
+ const i = `${t}`.trim();
222
+ if (!i) {
223
+ s(P("parseAssayHole", new Error("Missing hole id")));
224
+ return;
225
+ }
226
+ const a = [];
227
+ ee.parse(e, {
228
+ header: !0,
229
+ dynamicTyping: !0,
230
+ skipEmptyLines: !0,
231
+ step: (c) => {
232
+ const l = ye(c.data, r), u = Ue(l, r);
233
+ u && `${u.holeId}`.trim() === i && a.push(u);
234
+ },
235
+ complete: () => {
236
+ if (!a.length) {
237
+ o(null);
238
+ return;
239
+ }
240
+ const c = Ye(i, a);
241
+ o(c);
242
+ },
243
+ error: (c) => s(P("parseAssayHole", c))
244
+ });
245
+ });
246
+ }
247
+ function ft(e, t = null, n = null) {
248
+ return new Promise((r, o) => {
249
+ ee.parse(e, {
250
+ header: !0,
251
+ dynamicTyping: !0,
252
+ skipEmptyLines: !0,
253
+ complete: (s) => {
254
+ const i = /* @__PURE__ */ new Map();
255
+ s.data.forEach((c) => {
256
+ const l = ye(c, n), u = Ue(l, n);
257
+ u && (i.has(u.holeId) || i.set(u.holeId, []), i.get(u.holeId).push(u));
258
+ });
259
+ const a = Array.from(i.entries()).map(([c, l]) => Ye(c, l));
260
+ r({ holes: a });
261
+ },
262
+ error: (s) => o(P("parseAssaysCSV", s))
263
+ });
264
+ });
265
+ }
266
+ function yn(e = {}) {
267
+ const t = {};
268
+ return Object.entries(e || {}).forEach(([n, r]) => {
269
+ n && (t[fe(n)] = r);
270
+ }), t;
271
+ }
272
+ function gn(e = {}, t = [], n) {
273
+ for (const r of t) {
274
+ const o = e[r];
275
+ if (o != null && `${o}`.trim() !== "")
276
+ return o;
277
+ }
278
+ return n;
279
+ }
280
+ const ht = 4;
281
+ function Ge(e = [], t = "") {
282
+ if (!e.length) return [];
283
+ if (!t) return e;
284
+ const n = e.findIndex((s) => s === t);
285
+ if (n === -1) return e;
286
+ const r = e[n], o = e.filter((s, i) => i !== n);
287
+ return [r, ...o];
288
+ }
289
+ function he({
290
+ property: e = "",
291
+ chartType: t = "",
292
+ categoricalProps: n = [],
293
+ numericDefaultChartType: r = "markers+line"
294
+ } = {}) {
295
+ return e ? n.includes(e) ? "categorical" : !t || t === "categorical" ? r : t : t || r;
296
+ }
297
+ function qe({
298
+ holeIds: e = [],
299
+ focusedHoleId: t = "",
300
+ plotCount: n = ht,
301
+ defaultProp: r = "",
302
+ categoricalProps: o = [],
303
+ numericDefaultChartType: s = "markers+line"
304
+ } = {}) {
305
+ const i = Ge(e, t);
306
+ return Array.from({ length: n }).map((a, c) => {
307
+ const l = i[c] || e[c] || "", u = he({
308
+ property: r,
309
+ chartType: "",
310
+ categoricalProps: o,
311
+ numericDefaultChartType: s
312
+ });
313
+ return {
314
+ holeId: l,
315
+ property: r,
316
+ chartType: u
317
+ };
318
+ });
319
+ }
320
+ function Xe(e = []) {
321
+ const t = e.flatMap((i) => i.points || []), n = /* @__PURE__ */ new Set();
322
+ t.forEach((i) => {
323
+ Object.keys(i || {}).forEach((a) => {
324
+ Be.has(a) || n.add(a);
325
+ });
326
+ });
327
+ const r = [], o = [];
328
+ n.forEach((i) => {
329
+ var l;
330
+ let a = !1, c = !1;
331
+ for (let u = 0; u < t.length; u += 1) {
332
+ const m = (l = t[u]) == null ? void 0 : l[i];
333
+ if (!(m == null || typeof m == "string" && m.trim() === "") && (c = !0, typeof m == "number" && Number.isFinite(m))) {
334
+ a = !0;
335
+ break;
336
+ }
337
+ }
338
+ a ? r.push(i) : c && o.push(i);
339
+ });
340
+ const s = r[0] || o[0] || "";
341
+ return { numericProps: r, categoricalProps: o, defaultProp: s };
342
+ }
343
+ async function pt(e, t = null) {
344
+ return await dt(e);
345
+ }
346
+ async function yt(e, t, n = null) {
347
+ return await mt(e, t);
348
+ }
349
+ function gt(e = [], t = "") {
350
+ if (!e.length) return null;
351
+ const { numericProps: n, categoricalProps: r, defaultProp: o } = Xe(e), s = e.map((a) => a.id || a.holeId).filter(Boolean), i = qe({
352
+ holeIds: s,
353
+ focusedHoleId: t,
354
+ plotCount: 4,
355
+ defaultProp: o,
356
+ categoricalProps: r,
357
+ numericDefaultChartType: "line"
358
+ });
359
+ return {
360
+ holes: e,
361
+ numericProps: n,
362
+ categoricalProps: r,
363
+ defaultProp: o,
364
+ traceConfigs: i
365
+ };
366
+ }
367
+ async function bn(e, t = "", n = null) {
368
+ const { holes: r } = await ft(e, n), o = gt(r, t);
369
+ if (!o) throw new Error("No valid assay intervals found.");
370
+ return o;
371
+ }
372
+ function Cn(e, t = null) {
373
+ return new Promise((n, r) => {
374
+ ee.parse(e, {
375
+ header: !0,
376
+ dynamicTyping: !0,
377
+ skipEmptyLines: !0,
378
+ complete: (o) => {
379
+ const s = o.data.map((i) => bt(i, t)).filter((i) => i[x] && Number.isFinite(i[V]) && Number.isFinite(i[B]) && Number.isFinite(i[j]));
380
+ n(s);
381
+ },
382
+ error: (o) => r(P("parseSurveyCSV", o))
383
+ });
384
+ });
385
+ }
386
+ function bt(e, t = null) {
387
+ const n = ce(e, null, t), r = n[x], o = n[Z] || n.project || n.project_code, s = ne(n[q]), i = ne(n[X]), a = ne(n[V]), c = ne(n[B]), l = ne(n[j]), u = ne(n.maxdepth);
388
+ return {
389
+ raw: n,
390
+ [x]: r,
391
+ [Z]: o,
392
+ [q]: s,
393
+ [X]: i,
394
+ [V]: a,
395
+ [B]: c,
396
+ [j]: l,
397
+ maxdepth: u,
398
+ // Legacy field names for backwards compatibility
399
+ project_code: o,
400
+ latitude: s,
401
+ longitude: i,
402
+ surveydepth: a
403
+ };
404
+ }
405
+ const ne = (e) => {
406
+ const t = Number(e);
407
+ return Number.isFinite(t) ? t : void 0;
408
+ };
409
+ function _n(e, t) {
410
+ var l, u, m, f;
411
+ const n = /* @__PURE__ */ new Map();
412
+ e.forEach((d) => {
413
+ const p = (d[x] || d.holeId || d.id || "").toString().trim();
414
+ if (!p) return;
415
+ const y = p.toLowerCase();
416
+ n.has(y) || n.set(y, d);
417
+ });
418
+ const r = ((l = e[0]) == null ? void 0 : l.lat) ?? ((u = e[0]) == null ? void 0 : u[q]) ?? 0, o = ((m = e[0]) == null ? void 0 : m.lng) ?? ((f = e[0]) == null ? void 0 : f[X]) ?? 0, s = 111132, i = 111320 * Math.cos(r * Math.PI / 180), a = /* @__PURE__ */ new Map();
419
+ t.forEach((d) => {
420
+ const p = (d[x] || "").toString().trim();
421
+ if (!p) return;
422
+ const y = p.toLowerCase();
423
+ a.has(y) || a.set(y, []), a.get(y).push(d);
424
+ });
425
+ const c = [];
426
+ return a.forEach((d, p) => {
427
+ const y = n.get(p);
428
+ if (!y) return;
429
+ const h = d.filter((b) => Number.isFinite(b[V] ?? b.surveydepth)).sort((b, _) => (b[V] ?? b.surveydepth) - (_[V] ?? _.surveydepth));
430
+ if (!h.length) return;
431
+ const A = y.lat ?? y[q], O = y.lng ?? y[X], F = 111132, D = 111320 * Math.cos(A * Math.PI / 180), R = (O - o) * i, w = (A - r) * s, I = [];
432
+ let N = 0, z = 0, C = 0;
433
+ for (let b = 0; b < h.length; b += 1) {
434
+ const _ = h[b], M = h[b - 1], L = _[V] ?? _.surveydepth, v = _[j] ?? _.azimuth, T = _[B] ?? _.dip;
435
+ if (!M) {
436
+ I.push({
437
+ x: R + N,
438
+ y: w + z,
439
+ z: 0,
440
+ md: L,
441
+ azimuth: v,
442
+ dip: T
443
+ });
444
+ continue;
445
+ }
446
+ const S = M[V] ?? M.surveydepth, Y = M[j] ?? M.azimuth, ue = M[B] ?? M.dip, de = L - S;
447
+ if (de <= 0) continue;
448
+ const ie = Fe(ue), se = Fe(T), ge = Ee(Y), be = Ee(v), Ce = Math.acos(
449
+ Math.sin(ie) * Math.sin(se) * Math.cos(ge - be) + Math.cos(ie) * Math.cos(se)
450
+ ), _e = Ce > 1e-6 ? 2 / Ce * Math.tan(Ce / 2) : 1, et = 0.5 * de * (Math.sin(ie) * Math.cos(ge) + Math.sin(se) * Math.cos(be)) * _e, tt = 0.5 * de * (Math.sin(ie) * Math.sin(ge) + Math.sin(se) * Math.sin(be)) * _e, nt = 0.5 * de * (Math.cos(ie) + Math.cos(se)) * _e;
451
+ N += et, z += tt, C += nt, I.push({
452
+ x: R + N,
453
+ y: w + z,
454
+ z: -C,
455
+ // render with z up; depth down
456
+ md: L,
457
+ azimuth: v,
458
+ dip: T
459
+ });
460
+ }
461
+ const E = I.map((b) => ({
462
+ ...b,
463
+ lat: A + b.y / F,
464
+ lng: O + b.x / D
465
+ }));
466
+ c.push({
467
+ id: y[x] || y.holeId || p,
468
+ project: y[Z] || y.project_id || y.project || "",
469
+ points: E,
470
+ collar: y
471
+ });
472
+ }), c;
473
+ }
474
+ const Ee = (e) => e * Math.PI / 180, Fe = (e) => {
475
+ const t = Number(e), n = 90 + (Number.isFinite(t) ? t : 0), r = Math.min(180, Math.max(0, n));
476
+ return Ee(r);
477
+ };
478
+ function G(e, t = void 0) {
479
+ const n = Number(e);
480
+ return Number.isFinite(n) ? n : t;
481
+ }
482
+ function Se(e) {
483
+ return e == null ? "" : `${e}`.trim();
484
+ }
485
+ function pe(e = [], t = null) {
486
+ const n = t || "hole_id", o = [n, "hole_id", "holeId", "id"].find((s) => e.some((i) => Se(i == null ? void 0 : i[s])));
487
+ if (!o)
488
+ throw P("canonicalizeHoleIdRows", new Error(`hole id column '${n}' not found`));
489
+ return {
490
+ aliasCol: o,
491
+ rows: e.map((s) => ({
492
+ ...s,
493
+ hole_id: Se(s == null ? void 0 : s[o])
494
+ }))
495
+ };
496
+ }
497
+ function ke(e) {
498
+ return Number(e) * Math.PI / 180;
499
+ }
500
+ function xe(e, t) {
501
+ const n = ke(e), r = ke(t), o = Math.cos(r) * Math.sin(n), s = Math.cos(r) * Math.cos(n), i = Math.sin(r) * -1;
502
+ return { ca: o, cb: s, cc: i };
503
+ }
504
+ function Ct(e, t, n, r, o, s = "minimum_curvature") {
505
+ const i = xe(t, n), a = xe(r, o);
506
+ if (s === "tangential")
507
+ return {
508
+ dx: e * i.ca,
509
+ dy: e * i.cb,
510
+ dz: e * i.cc,
511
+ azimuth: t,
512
+ dip: n
513
+ };
514
+ if (s === "balanced_tangential") {
515
+ const m = 0.5 * (t + r), f = 0.5 * (n + o), d = xe(m, f);
516
+ return {
517
+ dx: e * d.ca,
518
+ dy: e * d.cb,
519
+ dz: e * d.cc,
520
+ azimuth: m,
521
+ dip: f
522
+ };
523
+ }
524
+ const c = i.ca * a.ca + i.cb * a.cb + i.cc * a.cc, l = Math.acos(Math.max(-1, Math.min(1, c))), u = l > 1e-6 ? 2 * Math.tan(l / 2) / l : 1;
525
+ return {
526
+ dx: 0.5 * e * (i.ca + a.ca) * u,
527
+ dy: 0.5 * e * (i.cb + a.cb) * u,
528
+ dz: 0.5 * e * (i.cc + a.cc) * u,
529
+ azimuth: r,
530
+ dip: o
531
+ };
532
+ }
533
+ function ve(e = [], t = [], n = {}) {
534
+ const {
535
+ step: r = 1,
536
+ holeIdCol: o = null,
537
+ method: s = "minimum_curvature"
538
+ } = n, i = Number.isFinite(Number(r)) && Number(r) > 0 ? Number(r) : 1, a = pe(e, o), c = pe(t, o || a.aliasCol);
539
+ if (!a.rows.length || !c.rows.length) return [];
540
+ const l = /* @__PURE__ */ new Map();
541
+ a.rows.forEach((f) => {
542
+ !f.hole_id || l.has(f.hole_id) || l.set(f.hole_id, f);
543
+ });
544
+ const u = /* @__PURE__ */ new Map();
545
+ c.rows.forEach((f) => {
546
+ f.hole_id && (u.has(f.hole_id) || u.set(f.hole_id, []), u.get(f.hole_id).push(f));
547
+ });
548
+ const m = [];
549
+ return u.forEach((f, d) => {
550
+ const p = l.get(d);
551
+ if (!p) return;
552
+ const y = [...f].map((I) => ({
553
+ ...I,
554
+ from: G(I.from),
555
+ azimuth: G(I.azimuth),
556
+ dip: G(I.dip)
557
+ })).filter((I) => Number.isFinite(I.from) && Number.isFinite(I.azimuth) && Number.isFinite(I.dip)).sort((I, N) => I.from - N.from);
558
+ if (!y.length) return;
559
+ let h = G(p.x, 0), A = G(p.y, 0), O = G(p.z, 0), F = y[0].from;
560
+ const D = y[0].azimuth, R = y[0].dip, w = {
561
+ hole_id: d,
562
+ md: F,
563
+ x: h,
564
+ y: A,
565
+ z: O,
566
+ azimuth: D,
567
+ dip: R
568
+ };
569
+ a.aliasCol !== "hole_id" && p[a.aliasCol] !== void 0 && (w[a.aliasCol] = p[a.aliasCol]), m.push(w);
570
+ for (let I = 0; I < y.length - 1; I += 1) {
571
+ const N = y[I], z = y[I + 1], C = N.from, b = z.from - C;
572
+ if (b <= 0) continue;
573
+ const _ = Math.max(1, Math.ceil(b / i)), M = b / _;
574
+ for (let L = 0; L < _; L += 1) {
575
+ F += M;
576
+ const v = (F - C) / b, T = N.azimuth + v * (z.azimuth - N.azimuth), S = N.dip + v * (z.dip - N.dip), Y = Ct(M, N.azimuth, N.dip, z.azimuth, z.dip, s);
577
+ h += Y.dx, A += Y.dy, O += Y.dz;
578
+ const ue = {
579
+ hole_id: d,
580
+ md: F,
581
+ x: h,
582
+ y: A,
583
+ z: O,
584
+ azimuth: s === "minimum_curvature" ? T : Y.azimuth,
585
+ dip: s === "minimum_curvature" ? S : Y.dip
586
+ };
587
+ a.aliasCol !== "hole_id" && p[a.aliasCol] !== void 0 && (ue[a.aliasCol] = p[a.aliasCol]), m.push(ue);
588
+ }
589
+ }
590
+ }), m;
591
+ }
592
+ function _t(e, t, n = {}) {
593
+ return ve(e, t, { ...n, method: "minimum_curvature" });
594
+ }
595
+ function zn(e, t, n = {}) {
596
+ return ve(e, t, { ...n, method: "tangential" });
597
+ }
598
+ function xn(e, t, n = {}) {
599
+ return ve(e, t, { ...n, method: "balanced_tangential" });
600
+ }
601
+ function Nn(e, t, n = {}) {
602
+ return _t(e, t, n);
603
+ }
604
+ function zt(e, t) {
605
+ if (!e.length || !Number.isFinite(t)) return null;
606
+ let n = null, r = 1 / 0;
607
+ for (let o = 0; o < e.length; o += 1) {
608
+ const s = e[o], i = G(s.md);
609
+ if (!Number.isFinite(i)) continue;
610
+ const a = Math.abs(i - t);
611
+ a < r && (r = a, n = s);
612
+ }
613
+ return n;
614
+ }
615
+ function Mn(e = [], t = [], n = {}) {
616
+ const r = n.holeIdCol || "hole_id", o = pe(e, r), s = pe(t, r);
617
+ if (!o.rows.length || !s.rows.length) return [...o.rows];
618
+ const i = /* @__PURE__ */ new Map();
619
+ return s.rows.forEach((a) => {
620
+ a.hole_id && (i.has(a.hole_id) || i.set(a.hole_id, []), i.get(a.hole_id).push(a));
621
+ }), i.forEach((a, c) => {
622
+ i.set(c, [...a].sort((l, u) => G(l.md, 0) - G(u.md, 0)));
623
+ }), o.rows.map((a) => {
624
+ const c = G(a.from), l = G(a.to), u = Number.isFinite(c) && Number.isFinite(l) ? 0.5 * (c + l) : void 0;
625
+ if (!a.hole_id || !Number.isFinite(u)) return { ...a };
626
+ const m = zt(i.get(a.hole_id) || [], u);
627
+ if (!m) return { ...a };
628
+ const f = { ...a };
629
+ return ["md", "x", "y", "z", "azimuth", "dip"].forEach((d) => {
630
+ m[d] !== void 0 && (Object.prototype.hasOwnProperty.call(f, d) ? f[`${d}_trace`] = m[d] : f[d] = m[d]);
631
+ }), f;
632
+ });
633
+ }
634
+ function An(e, t = null) {
635
+ return new Promise((n, r) => {
636
+ ee.parse(e, {
637
+ header: !0,
638
+ dynamicTyping: !0,
639
+ skipEmptyLines: !0,
640
+ complete: (o) => {
641
+ const s = /* @__PURE__ */ new Map();
642
+ o.data.forEach((a, c) => {
643
+ const l = ce(a, null, t), u = l[x], m = u !== void 0 ? `${u}`.trim() : "", f = l[K] ?? l.x, d = l[J] ?? l.y, p = l[oe] ?? l.z, y = l.order ?? c;
644
+ !m || f === null || f === void 0 || d === null || d === void 0 || p === null || p === void 0 || (s.has(m) || s.set(m, []), s.get(m).push({
645
+ ...l,
646
+ holeId: m,
647
+ order: y,
648
+ x: Number(f) ?? 0,
649
+ y: Number(d) ?? 0,
650
+ z: Number(p) ?? 0
651
+ }));
652
+ });
653
+ const i = Array.from(s.entries()).map(([a, c]) => ({
654
+ id: a,
655
+ points: c.sort((l, u) => l.order - u.order).map((l) => ({
656
+ ...l,
657
+ x: Number(l.x) || 0,
658
+ y: Number(l.y) || 0,
659
+ z: Number(l.z) || 0
660
+ }))
661
+ }));
662
+ n({ holes: i });
663
+ },
664
+ error: (o) => r(P("parseDrillholesCSV", o))
665
+ });
666
+ });
667
+ }
668
+ function le(e) {
669
+ return e ? Array.isArray(e) ? [...e] : [] : [];
670
+ }
671
+ function U(e) {
672
+ const t = Number(e);
673
+ return Number.isFinite(t) ? t : void 0;
674
+ }
675
+ function We(e = [], t = []) {
676
+ const n = [...e];
677
+ return n.sort((r, o) => {
678
+ for (let s = 0; s < t.length; s += 1) {
679
+ const i = t[s], a = r == null ? void 0 : r[i], c = o == null ? void 0 : o[i];
680
+ if (a !== c)
681
+ return a == null ? 1 : c == null ? -1 : typeof a == "number" && typeof c == "number" ? a - c : `${a}`.localeCompare(`${c}`);
682
+ }
683
+ return 0;
684
+ }), n;
685
+ }
686
+ function xt(e, t = {}) {
687
+ return new Promise((n, r) => {
688
+ ee.parse(e, {
689
+ header: !0,
690
+ dynamicTyping: !0,
691
+ skipEmptyLines: !0,
692
+ ...t,
693
+ complete: (o) => n(Array.isArray(o == null ? void 0 : o.data) ? o.data : []),
694
+ error: (o) => r(P("loadTable(csv)", o))
695
+ });
696
+ });
697
+ }
698
+ function Nt(e = [], t = null, n = null) {
699
+ return e.map((r) => ce(r, t, n));
700
+ }
701
+ async function De(e, t = {}) {
702
+ const {
703
+ kind: n = "csv",
704
+ columnMap: r = null,
705
+ sourceColumnMap: o = null,
706
+ papaParseConfig: s = {}
707
+ } = t;
708
+ let i;
709
+ if (Array.isArray(e))
710
+ i = le(e);
711
+ else if (n === "csv")
712
+ i = await xt(e, s);
713
+ else throw n === "parquet" || n === "sql" ? P("loadTable", new Error(`Unsupported kind in JS runtime: ${n}`)) : P("loadTable", new Error(`Unsupported kind: ${n}`));
714
+ return Nt(i, r, o);
715
+ }
716
+ async function In(e, t = {}) {
717
+ const {
718
+ crs: n = null,
719
+ sourceColumnMap: r = null,
720
+ keepAll: o = !0,
721
+ ...s
722
+ } = t, i = await De(e, { ...s, sourceColumnMap: r });
723
+ if (!i.some((f) => x in f))
724
+ throw P("loadCollars", new Error(`Collar table missing column: ${x}`));
725
+ const c = i.some((f) => K in f && J in f), l = i.some((f) => q in f && X in f);
726
+ if (!c && !l)
727
+ throw P("loadCollars", new Error("Collar table missing coordinate columns (need easting/northing or latitude/longitude)"));
728
+ const u = i.map((f) => {
729
+ const d = { ...f };
730
+ if (x in d) {
731
+ const p = d[x];
732
+ d[x] = p == null ? "" : `${p}`.trim();
733
+ }
734
+ return q in d && (d[q] = U(d[q])), X in d && (d[X] = U(d[X])), oe in d && (d[oe] = U(d[oe])), K in d && (d[K] = U(d[K])), J in d && (d[J] = U(d[J])), !("datasource_hole_id" in d) && x in d && (d.datasource_hole_id = d[x]), d;
735
+ });
736
+ if (!u.every((f) => !(!f[x] || l && (!Number.isFinite(f[q]) || !Number.isFinite(f[X])) || c && !l && (!Number.isFinite(f[K]) || !Number.isFinite(f[J])))))
737
+ throw P("loadCollars", new Error("Collar table has missing required values"));
738
+ return u;
739
+ }
740
+ async function En(e, t = {}) {
741
+ const {
742
+ sourceColumnMap: n = null,
743
+ keepAll: r = !0,
744
+ ...o
745
+ } = t, s = await De(e, { ...o, sourceColumnMap: n }), i = [x, V, j, B];
746
+ for (const l of i)
747
+ if (!s.some((m) => l in m))
748
+ throw P("loadSurveys", new Error(`Survey table missing column: ${l}`));
749
+ const a = s.map((l) => {
750
+ const u = { ...l };
751
+ if (x in u) {
752
+ const m = u[x];
753
+ u[x] = m == null ? "" : `${m}`.trim();
754
+ }
755
+ return V in u && (u[V] = U(u[V])), H in u && (u[H] = U(u[H])), j in u && (u[j] = U(u[j])), B in u && (u[B] = U(u[B])), u;
756
+ });
757
+ if (!a.every((l) => !(!l[x] || !Number.isFinite(l[V]) || !Number.isFinite(l[j]) || !Number.isFinite(l[B]))))
758
+ throw P("loadSurveys", new Error("Survey table has missing required values"));
759
+ return We(a, [x, V]);
760
+ }
761
+ async function vn(e, t = {}) {
762
+ const {
763
+ sourceColumnMap: n = null,
764
+ keepAll: r = !0,
765
+ ...o
766
+ } = t, s = await De(e, { ...o, sourceColumnMap: n }), i = [x, $, H];
767
+ for (const l of i)
768
+ if (!s.some((m) => l in m))
769
+ throw P("loadAssays", new Error(`Assay table missing column: ${l}`));
770
+ const a = s.map((l) => {
771
+ const u = { ...l };
772
+ if (x in u) {
773
+ const m = u[x];
774
+ u[x] = m == null ? "" : `${m}`.trim();
775
+ }
776
+ return $ in u && (u[$] = U(u[$])), H in u && (u[H] = U(u[H])), $ in u && H in u && Number.isFinite(u[$]) && Number.isFinite(u[H]) && (u[we] = 0.5 * (u[$] + u[H])), u;
777
+ });
778
+ if (!a.every((l) => !(!l[x] || !Number.isFinite(l[$]) || !Number.isFinite(l[H]))))
779
+ throw P("loadAssays", new Error("Assay table has missing required values"));
780
+ return We(a, [x, $, H]);
781
+ }
782
+ function Dn(e = [], t = [], n = {}) {
783
+ const r = Array.isArray(n.onCols) && n.onCols.length ? n.onCols : [x];
784
+ if (!t.length) return [...e];
785
+ const o = (i) => r.map((a) => `${(i == null ? void 0 : i[a]) ?? ""}`).join("|"), s = /* @__PURE__ */ new Map();
786
+ return t.forEach((i) => {
787
+ s.set(o(i), i);
788
+ }), e.map((i) => {
789
+ const a = s.get(o(i));
790
+ if (!a) return { ...i };
791
+ const c = { ...i };
792
+ return Object.entries(a).forEach(([l, u]) => {
793
+ r.includes(l) || (Object.prototype.hasOwnProperty.call(c, l) ? c[`${l}_trace`] = u : c[l] = u);
794
+ }), c;
795
+ });
796
+ }
797
+ function Ln(e = [], t = null) {
798
+ return t == null ? [...e] : e.length ? e.some((r) => Z in r) ? e.filter((r) => (r == null ? void 0 : r[Z]) === t) : [...e] : [];
799
+ }
800
+ function Tn(e = [], t = []) {
801
+ return e.map((n) => {
802
+ const r = { ...n };
803
+ return t.forEach((o) => {
804
+ if (!(o in r)) return;
805
+ const s = U(r[o]);
806
+ r[o] = s;
807
+ }), r;
808
+ });
809
+ }
810
+ function Pn({
811
+ collars: e = [],
812
+ surveys: t = [],
813
+ assays: n = [],
814
+ structures: r = [],
815
+ metadata: o = {}
816
+ } = {}) {
817
+ return {
818
+ collars: le(e),
819
+ surveys: le(t),
820
+ assays: le(n),
821
+ structures: le(r),
822
+ metadata: o || {}
823
+ };
824
+ }
825
+ function On(e) {
826
+ return new Promise((t, n) => {
827
+ ee.parse(e, {
828
+ header: !0,
829
+ dynamicTyping: !0,
830
+ complete: (r) => {
831
+ const o = r.data.filter(
832
+ (a) => a.center_x !== null && a.center_y !== null && a.center_z !== null
833
+ ), s = ["center_x", "center_y", "center_z", "size_x", "size_y", "size_z"], i = Object.keys(o[0] || {}).filter(
834
+ (a) => !s.includes(a)
835
+ );
836
+ t({ data: o, properties: i });
837
+ },
838
+ error: (r) => {
839
+ n(P("parseBlockModelCSV", r));
840
+ }
841
+ });
842
+ });
843
+ }
844
+ function Fn(e, t) {
845
+ const n = e.map((s) => s[t]).filter((s) => s != null);
846
+ if (n.every((s) => typeof s == "number")) {
847
+ const s = Math.min(...n), i = Math.max(...n);
848
+ return { type: "numeric", min: s, max: i, values: n };
849
+ }
850
+ return { type: "categorical", categories: [...new Set(n)], values: n };
851
+ }
852
+ function Mt(e, t, n) {
853
+ if (!t) return new n.Color("#888888");
854
+ if (t.type === "numeric") {
855
+ const s = t.max - t.min, a = (1 - (s === 0 ? 0.5 : (e - t.min) / s)) * 240;
856
+ return new n.Color().setHSL(a / 360, 0.8, 0.5);
857
+ }
858
+ const o = t.categories.indexOf(e) / Math.max(t.categories.length, 1) * 360;
859
+ return new n.Color().setHSL(o / 360, 0.7, 0.5);
860
+ }
861
+ const He = "#8b1e3f", At = "#a8324f", It = "#6b7280";
862
+ function Ve(e, t) {
863
+ var r;
864
+ if (!e || !t) return !1;
865
+ const n = e.points || [];
866
+ for (let o = 0; o < n.length; o += 1) {
867
+ const s = (r = n[o]) == null ? void 0 : r[t];
868
+ if (s != null && (typeof s == "number" && Number.isFinite(s) || typeof s == "string" && s.trim() !== ""))
869
+ return !0;
870
+ }
871
+ return !1;
872
+ }
873
+ function Et(e, t, n) {
874
+ if (!e || !t) return [];
875
+ const r = (e == null ? void 0 : e.points) || [], o = [], s = /* @__PURE__ */ new Set();
876
+ return r.forEach((i) => {
877
+ const a = Number(
878
+ i.from ?? i.samp_from ?? i.sample_from ?? i.fromdepth ?? i.from_depth ?? i.depth_from
879
+ ), c = Number(
880
+ i.to ?? i.samp_to ?? i.sample_to ?? i.todepth ?? i.to_depth ?? i.depth_to
881
+ ), l = i == null ? void 0 : i[t];
882
+ if (!Number.isFinite(a) || !Number.isFinite(c) || c <= a || l == null || l === "") return;
883
+ const u = `${t}:${a}-${c}`;
884
+ if (s.has(u)) return;
885
+ s.add(u);
886
+ const m = (a + c) / 2, f = n ? l : Number(l);
887
+ !n && !Number.isFinite(f) || o.push({
888
+ z: m,
889
+ val: f,
890
+ from: a,
891
+ to: c,
892
+ errorPlus: c - m,
893
+ errorMinus: m - a
894
+ });
895
+ }), o.sort((i, a) => a.z - i.z);
896
+ }
897
+ function vt(e, t) {
898
+ if (!e.length) return { data: [], layout: {} };
899
+ const n = [...e].sort((c, l) => l.z - c.z), r = [];
900
+ for (let c = 0; c < n.length; c += 1) {
901
+ const l = n[c], u = n[c + 1], m = l.z, f = u ? u.z : l.z - 20;
902
+ f !== m && r.push({ y0: m, y1: f, category: l.val || "unknown" });
903
+ }
904
+ const o = ["#8b1e3f", "#a8324f", "#b84c68", "#d16587", "#e07ba0", "#f091b6", "#f7a7c8", "#fbcfe8"], s = r.map((c, l) => ({
905
+ type: "rect",
906
+ xref: "x",
907
+ yref: "y",
908
+ x0: 0,
909
+ x1: 1,
910
+ y0: c.y0,
911
+ y1: c.y1,
912
+ fillcolor: o[l % o.length],
913
+ line: { width: 0 }
914
+ }));
915
+ return { data: [{
916
+ x: r.map(() => 0.5),
917
+ y: r.map((c) => (c.y0 + c.y1) / 2),
918
+ mode: "text",
919
+ text: r.map((c) => c.category),
920
+ textposition: "middle center",
921
+ showlegend: !1,
922
+ hoverinfo: "text",
923
+ customdata: r.map((c) => [c.y0, c.y1]),
924
+ hovertemplate: "Category: %{text}<br>from: %{customdata[0]} to %{customdata[1]}<extra></extra>"
925
+ }], layout: {
926
+ height: 260,
927
+ margin: { l: 50, r: 10, t: 10, b: 30 },
928
+ xaxis: { range: [0, 1], visible: !1, fixedrange: !0 },
929
+ yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
930
+ shapes: s,
931
+ showlegend: !1,
932
+ title: t || void 0
933
+ } };
934
+ }
935
+ function Dt(e, t, n) {
936
+ if (!e.length) return { data: [], layout: {} };
937
+ const r = n === "bar", o = n === "markers", s = n === "line", i = {
938
+ x: e.map((u) => u.val),
939
+ y: e.map((u) => u.z),
940
+ hovertemplate: `${t}: %{x}<br>from: %{customdata[0]} to %{customdata[1]}<extra></extra>`,
941
+ customdata: e.map((u) => [u.from, u.to])
942
+ }, a = {
943
+ type: "data",
944
+ symmetric: !1,
945
+ array: e.map((u) => u.errorPlus),
946
+ arrayminus: e.map((u) => u.errorMinus),
947
+ thickness: 1.5,
948
+ width: 2,
949
+ color: It
950
+ };
951
+ return { data: [r ? {
952
+ ...i,
953
+ type: "bar",
954
+ orientation: "h",
955
+ marker: { color: He },
956
+ error_y: a
957
+ } : {
958
+ ...i,
959
+ type: "scatter",
960
+ mode: o ? "markers" : s ? "lines" : "lines+markers",
961
+ line: { color: He, width: 2 },
962
+ marker: { size: 7, color: At },
963
+ error_y: s ? void 0 : a
964
+ }], layout: {
965
+ height: 260,
966
+ margin: { l: 50, r: 10, t: 10, b: 30 },
967
+ xaxis: { title: t, zeroline: !1 },
968
+ yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
969
+ barmode: "overlay",
970
+ showlegend: !1
971
+ } };
972
+ }
973
+ function Lt({ points: e, isCategorical: t, property: n, chartType: r }) {
974
+ return !e || !e.length || !n ? { data: [], layout: {} } : t || r === "categorical" ? vt(e, n) : Dt(e, n, r);
975
+ }
976
+ const Le = "markers+line", Tt = [{ value: "categorical", label: "Categorical bands" }], Pt = [
977
+ { value: "bar", label: "Bars" },
978
+ { value: "markers", label: "Markers" },
979
+ { value: Le, label: "Markers + Line" },
980
+ { value: "line", label: "Line only" }
981
+ ];
982
+ function Ot(e, t) {
983
+ var n;
984
+ return e.some((r) => r.value === t) ? t : ((n = e[0]) == null ? void 0 : n.value) || Le;
985
+ }
986
+ function Sn({ config: e, graph: t, holeOptions: n = [], propertyOptions: r = [], onConfigChange: o }) {
987
+ const s = rt(null), i = t == null ? void 0 : t.hole, a = (t == null ? void 0 : t.points) || [], c = (e == null ? void 0 : e.property) || "", l = (e == null ? void 0 : e.chartType) || Le, u = (e == null ? void 0 : e.holeId) || "", m = (t == null ? void 0 : t.isCategorical) || !1, f = m ? Tt : Pt, d = Ot(f, l), [p, y] = W("");
988
+ return re(() => {
989
+ if (!i || !c || a.length === 0) return;
990
+ const h = s.current;
991
+ if (!h) return;
992
+ const { data: A, layout: O } = Lt({ points: a, isCategorical: m, property: c, chartType: d });
993
+ if (!A || A.length === 0) return;
994
+ const F = {
995
+ displayModeBar: !0,
996
+ responsive: !0,
997
+ useResizeHandler: !0,
998
+ modeBarButtonsToRemove: ["select2d", "lasso2d", "zoom2d", "zoomIn2d", "zoomOut2d", "autoScale2d"]
999
+ };
1000
+ try {
1001
+ y(""), me.react(h, A, O, F), requestAnimationFrame(() => {
1002
+ h && h.parentElement && me.Plots.resize(h);
1003
+ });
1004
+ } catch (D) {
1005
+ console.error("Plot render error", D), y((D == null ? void 0 : D.message) || "Plot render error");
1006
+ }
1007
+ return () => {
1008
+ if (h)
1009
+ try {
1010
+ me.purge(h);
1011
+ } catch (D) {
1012
+ console.warn("Plot purge error", D);
1013
+ }
1014
+ };
1015
+ }, [i, c, d, m, a]), re(() => {
1016
+ const h = s.current;
1017
+ if (!h || typeof ResizeObserver > "u") return;
1018
+ const A = new ResizeObserver(() => {
1019
+ try {
1020
+ h && h.data && me.Plots.resize(h);
1021
+ } catch (O) {
1022
+ console.warn("Plot resize error", O);
1023
+ }
1024
+ });
1025
+ return A.observe(h), () => A.disconnect();
1026
+ }, []), !i || !c ? /* @__PURE__ */ k("div", { className: "plot-card empty", children: /* @__PURE__ */ k("div", { className: "placeholder", children: e != null && e.holeId ? t != null && t.loading ? `Loading ${e.holeId}...` : "Select a property" : "Loading demo data..." }) }) : a.length === 0 ? /* @__PURE__ */ k("div", { className: "plot-card empty", children: /* @__PURE__ */ ae("div", { className: "placeholder", children: [
1027
+ "No numeric data for ",
1028
+ c
1029
+ ] }) }) : p ? /* @__PURE__ */ k("div", { className: "plot-card empty", children: /* @__PURE__ */ ae("div", { className: "placeholder", children: [
1030
+ "Plot error: ",
1031
+ p
1032
+ ] }) }) : /* @__PURE__ */ ae("div", { className: "plot-card", children: [
1033
+ /* @__PURE__ */ k("div", { className: "plot-title", children: /* @__PURE__ */ k(
1034
+ "select",
1035
+ {
1036
+ className: "plot-select",
1037
+ value: u,
1038
+ onChange: (h) => o && o({ holeId: h.target.value }),
1039
+ children: n.map((h) => {
1040
+ const A = typeof h == "string" ? h : h.holeId, O = typeof h == "string" ? h : h.label || h.holeId;
1041
+ return /* @__PURE__ */ k("option", { value: A, children: O }, A);
1042
+ })
1043
+ }
1044
+ ) }),
1045
+ /* @__PURE__ */ ae("div", { className: "plot-controls column", children: [
1046
+ r.length > 0 && /* @__PURE__ */ k(
1047
+ "select",
1048
+ {
1049
+ className: "plot-select",
1050
+ value: c,
1051
+ onChange: (h) => o && o({ property: h.target.value }),
1052
+ children: r.map((h) => /* @__PURE__ */ k("option", { value: h, children: h }, h))
1053
+ }
1054
+ ),
1055
+ /* @__PURE__ */ k(
1056
+ "select",
1057
+ {
1058
+ className: "plot-select",
1059
+ value: d,
1060
+ onChange: (h) => o && o({ chartType: h.target.value }),
1061
+ children: f.map((h) => /* @__PURE__ */ k("option", { value: h.value, children: h.label }, h.value))
1062
+ }
1063
+ )
1064
+ ] }),
1065
+ /* @__PURE__ */ k("div", { className: "plotly-chart", ref: s })
1066
+ ] });
1067
+ }
1068
+ function kn({
1069
+ initialFocusedHoleId: e = "",
1070
+ sourceFile: t = null,
1071
+ plotCount: n = 4
1072
+ } = {}) {
1073
+ const [r, o] = W([]), [s, i] = W([]), [a, c] = W([]), [l, u] = W([]), [m, f] = W(""), [d, p] = W([]), [y, h] = W(""), [A, O] = W(e || ""), [F, D] = W([]);
1074
+ re(() => {
1075
+ !t || s.length > 0 || pt(t).then((z) => {
1076
+ if (!z) return;
1077
+ const C = Array.from(new Map(z.map((E) => [E.holeId, E])).values());
1078
+ i(C), p(qe({
1079
+ holeIds: C.map((E) => E.holeId),
1080
+ focusedHoleId: A,
1081
+ plotCount: n,
1082
+ defaultProp: "",
1083
+ categoricalProps: l,
1084
+ numericDefaultChartType: "markers+line"
1085
+ }));
1086
+ }).catch((z) => {
1087
+ console.info("Assay metadata load skipped:", z.message);
1088
+ });
1089
+ }, [t, s.length, A, n, l]), re(() => {
1090
+ h((z) => z && z.startsWith("Loading assays for hole") ? z : "");
1091
+ }, [d]), re(() => {
1092
+ if (!s.length) {
1093
+ p([]);
1094
+ return;
1095
+ }
1096
+ const z = Ge(s.map((C) => C.holeId), A);
1097
+ p((C) => Array.from({ length: n }).map((b, _) => {
1098
+ var S;
1099
+ const M = C[_] || {}, L = s.some((Y) => Y.holeId === M.holeId) ? M.holeId : z[_] || ((S = s[_]) == null ? void 0 : S.holeId) || "", v = M.property || m, T = he({
1100
+ property: v,
1101
+ chartType: M.chartType,
1102
+ categoricalProps: l,
1103
+ numericDefaultChartType: "markers+line"
1104
+ });
1105
+ return { holeId: L, property: v, chartType: T };
1106
+ }));
1107
+ }, [s, A, m, l, n]), re(() => {
1108
+ if (!t) return;
1109
+ d.map((C) => C.holeId).filter(Boolean).forEach((C) => {
1110
+ const E = r.some((_) => (_.id || _.holeId) === C), b = F.includes(C);
1111
+ E || b || (D((_) => [..._, C]), yt(t, C).then((_) => {
1112
+ D((M) => M.filter((L) => L !== C)), _ && o((M) => {
1113
+ const L = [...M.filter((T) => (T.id || T.holeId) !== C), _], v = Xe(L);
1114
+ return c(v.numericProps), u(v.categoricalProps), !m && v.defaultProp && (f(v.defaultProp), p((T) => T.map((S) => ({
1115
+ ...S,
1116
+ property: S.property || v.defaultProp,
1117
+ chartType: he({
1118
+ property: S.property || v.defaultProp,
1119
+ chartType: S.chartType,
1120
+ categoricalProps: v.categoricalProps,
1121
+ numericDefaultChartType: "markers+line"
1122
+ })
1123
+ })))), L;
1124
+ });
1125
+ }).catch((_) => {
1126
+ console.error(_), D((M) => M.filter((L) => L !== C)), h(_.message || `Error loading hole ${C}`);
1127
+ }));
1128
+ });
1129
+ }, [d, t, r, F, m]);
1130
+ const R = ze(() => [...a, ...l], [a, l]), w = ze(
1131
+ () => s.map((z) => ({ holeId: z.holeId, label: z.holeId })).sort((z, C) => z.label.localeCompare(C.label)),
1132
+ [s]
1133
+ ), I = ze(() => Array.from({ length: n }).map((z, C) => {
1134
+ const E = d[C] || {}, b = r.find((S) => (S.id || S.holeId) === E.holeId) || null;
1135
+ let _ = E.property || m;
1136
+ if (b && (!_ || !Ve(b, _))) {
1137
+ const S = [...a, ...l].find((Y) => Ve(b, Y));
1138
+ S && (_ = S);
1139
+ }
1140
+ const M = E.chartType || (_ && l.includes(_) ? "categorical" : "markers+line"), L = E.holeId || (b == null ? void 0 : b.id) || (b == null ? void 0 : b.holeId) || "", v = l.includes(_), T = Et(b, _, v);
1141
+ return {
1142
+ config: { holeId: L, property: _, chartType: M },
1143
+ hole: b,
1144
+ loading: F.includes(E.holeId),
1145
+ isCategorical: v,
1146
+ points: T,
1147
+ label: L
1148
+ };
1149
+ }), [d, r, m, l, F, n, a]), N = (z, C) => {
1150
+ p((E) => {
1151
+ const b = [...E], M = { ...b[z] || {}, ...C };
1152
+ return C.property && (M.chartType = he({
1153
+ property: C.property,
1154
+ chartType: M.chartType,
1155
+ categoricalProps: l,
1156
+ numericDefaultChartType: "markers+line"
1157
+ })), b[z] = M, b;
1158
+ });
1159
+ };
1160
+ return {
1161
+ error: y,
1162
+ focusedHoleId: A,
1163
+ setFocusedHoleId: O,
1164
+ setError: h,
1165
+ holeCount: s.length,
1166
+ numericProps: a,
1167
+ categoricalProps: l,
1168
+ propertyOptions: R,
1169
+ labeledHoleOptions: w,
1170
+ traceGraphs: I,
1171
+ handleConfigChange: N
1172
+ };
1173
+ }
1174
+ const Ft = [
1175
+ "#313695",
1176
+ "#4575b4",
1177
+ "#74add1",
1178
+ "#abd9e9",
1179
+ "#e0f3f8",
1180
+ "#fee090",
1181
+ "#fdae61",
1182
+ "#f46d43",
1183
+ "#d73027",
1184
+ "#a50026"
1185
+ ];
1186
+ function St(e = [], t = Ft) {
1187
+ const n = e.filter((l) => Number.isFinite(l));
1188
+ if (!n.length)
1189
+ return {
1190
+ min: null,
1191
+ max: null,
1192
+ step: null,
1193
+ bins: [],
1194
+ colors: t
1195
+ };
1196
+ const r = n.slice().sort((l, u) => l - u), o = r[0], s = r[r.length - 1], i = t.length;
1197
+ if (s === o) {
1198
+ const l = t.map((u, m) => ({
1199
+ index: m,
1200
+ min: o,
1201
+ max: s,
1202
+ label: `${o}`
1203
+ }));
1204
+ return {
1205
+ min: o,
1206
+ max: s,
1207
+ step: 0,
1208
+ bins: l,
1209
+ colors: t
1210
+ };
1211
+ }
1212
+ const a = t.map((l, u) => {
1213
+ const m = u / i, f = (u + 1) / i, d = Math.floor(m * r.length), p = Math.min(r.length - 1, Math.floor(f * r.length)), y = r[d], h = u === i - 1 ? s : r[p];
1214
+ return {
1215
+ index: u,
1216
+ min: y,
1217
+ max: h,
1218
+ label: kt(y, h)
1219
+ };
1220
+ }), c = (s - o) / i;
1221
+ return {
1222
+ min: o,
1223
+ max: s,
1224
+ step: c,
1225
+ bins: a,
1226
+ colors: t
1227
+ };
1228
+ }
1229
+ function kt(e, t) {
1230
+ 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";
1231
+ return `${n(e)} – ${n(t)}`;
1232
+ }
1233
+ function Ze(e, t) {
1234
+ if (!Number.isFinite(e) || !t || !Array.isArray(t.bins) || !t.bins.length)
1235
+ return -1;
1236
+ if (t.max === t.min)
1237
+ return e === t.min ? 0 : -1;
1238
+ for (let n = 0; n < t.bins.length; n += 1) {
1239
+ const r = t.bins[n];
1240
+ if (e >= r.min && (e <= r.max || n === t.bins.length - 1))
1241
+ return n;
1242
+ }
1243
+ return -1;
1244
+ }
1245
+ function Ht(e, t, n = "#8b1e3f") {
1246
+ const r = Ze(e, t);
1247
+ return r < 0 ? n : t.colors[r] || n;
1248
+ }
1249
+ function Ke(e) {
1250
+ return Array.isArray(e) ? e : [];
1251
+ }
1252
+ function Ne(e) {
1253
+ const t = Number(e);
1254
+ return Number.isFinite(t) ? t : void 0;
1255
+ }
1256
+ function Je(e = {}) {
1257
+ return {
1258
+ ...e,
1259
+ x: Ne(e.x),
1260
+ y: Ne(e.y),
1261
+ z: Ne(e.z)
1262
+ };
1263
+ }
1264
+ function Vt(e = [], t = [0, 0], n = 0) {
1265
+ const [r, o] = t, s = Number(n) * Math.PI / 180, i = Math.cos(s), a = Math.sin(s);
1266
+ return Ke(e).map(Je).map((c) => {
1267
+ if (!Number.isFinite(c.x) || !Number.isFinite(c.y)) return { ...c };
1268
+ const l = c.x - r, u = c.y - o;
1269
+ return {
1270
+ ...c,
1271
+ along: l * a + u * i,
1272
+ across: l * i - u * a
1273
+ };
1274
+ });
1275
+ }
1276
+ function Rt(e = [], t = [0, 0], n = 0, r = 50) {
1277
+ const o = Vt(e, t, n), s = 0.5 * Number(r || 0);
1278
+ return !Number.isFinite(s) || s <= 0 ? o : o.filter((i) => Number.isFinite(i.across) && Math.abs(i.across) <= s);
1279
+ }
1280
+ function Hn(e = [], t = null, n = null) {
1281
+ let r = Ke(e).map(Je);
1282
+ if (Array.isArray(t) && t.length === 2) {
1283
+ const [o, s] = t;
1284
+ r = r.filter((i) => Number.isFinite(i.z) && i.z <= Number(o) && i.z >= Number(s));
1285
+ }
1286
+ return n && (r = r.map((o) => ({
1287
+ ...o,
1288
+ color_value: o == null ? void 0 : o[n]
1289
+ }))), r;
1290
+ }
1291
+ function Vn(e = [], t = [0, 0], n = 0, r = 50, o = null) {
1292
+ let s = Rt(e, t, n, r);
1293
+ return o && (s = s.map((i) => ({
1294
+ ...i,
1295
+ color_value: i == null ? void 0 : i[o]
1296
+ }))), s;
1297
+ }
1298
+ function Te(e) {
1299
+ return Array.isArray(e) ? e : [];
1300
+ }
1301
+ function Pe(e = {}) {
1302
+ return e.hole_id ?? e.holeId ?? e.id;
1303
+ }
1304
+ function te(e, t = void 0) {
1305
+ const n = Number(e);
1306
+ return Number.isFinite(n) ? n : t;
1307
+ }
1308
+ function Rn(e = [], t = null) {
1309
+ const n = /* @__PURE__ */ new Map();
1310
+ Te(e).forEach((o) => {
1311
+ const s = Pe(o);
1312
+ if (s == null || `${s}`.trim() === "") return;
1313
+ const i = `${s}`;
1314
+ n.has(i) || n.set(i, []), n.get(i).push(o);
1315
+ });
1316
+ const r = [];
1317
+ return n.forEach((o, s) => {
1318
+ const i = [...o].sort((c, l) => te(c.md, 0) - te(l.md, 0)), a = {
1319
+ hole_id: s,
1320
+ x: i.map((c) => te(c.x, 0)),
1321
+ y: i.map((c) => te(c.y, 0)),
1322
+ z: i.map((c) => te(c.z, 0)),
1323
+ color: null
1324
+ };
1325
+ t && (a.color = i.map((c) => c == null ? void 0 : c[t])), r.push(a);
1326
+ }), r;
1327
+ }
1328
+ function wn(e = [], t = 1, n = null) {
1329
+ return Te(e).map((r) => ({
1330
+ hole_id: Pe(r),
1331
+ from: r == null ? void 0 : r.from,
1332
+ to: r == null ? void 0 : r.to,
1333
+ radius: t,
1334
+ color: n ? r == null ? void 0 : r[n] : null,
1335
+ value: n ? r == null ? void 0 : r[n] : null
1336
+ }));
1337
+ }
1338
+ function $n(e = [], t = null) {
1339
+ return t ? Te(e).filter((n) => Object.prototype.hasOwnProperty.call(n || {}, t)).map((n) => ({
1340
+ hole_id: Pe(n),
1341
+ label: n == null ? void 0 : n[t],
1342
+ depth: 0.5 * (te(n == null ? void 0 : n.from, 0) + te(n == null ? void 0 : n.to, 0))
1343
+ })) : [];
1344
+ }
1345
+ function Oe(e) {
1346
+ var n, r, o, s, i, a, c, l, u;
1347
+ if (!e) return "";
1348
+ const t = (m) => Number.isFinite(m) ? m.toFixed(3) : "nan";
1349
+ return [
1350
+ t((n = e.camera) == null ? void 0 : n.x),
1351
+ t((r = e.camera) == null ? void 0 : r.y),
1352
+ t((o = e.camera) == null ? void 0 : o.z),
1353
+ t((s = e.target) == null ? void 0 : s.x),
1354
+ t((i = e.target) == null ? void 0 : i.y),
1355
+ t((a = e.target) == null ? void 0 : a.z),
1356
+ t((c = e.up) == null ? void 0 : c.x),
1357
+ t((l = e.up) == null ? void 0 : l.y),
1358
+ t((u = e.up) == null ? void 0 : u.z)
1359
+ ].join("|");
1360
+ }
1361
+ function Qe(e) {
1362
+ return !e.camera || !e.controls ? null : {
1363
+ camera: {
1364
+ x: e.camera.position.x,
1365
+ y: e.camera.position.y,
1366
+ z: e.camera.position.z
1367
+ },
1368
+ target: {
1369
+ x: e.controls.target.x,
1370
+ y: e.controls.target.y,
1371
+ z: e.controls.target.z
1372
+ },
1373
+ up: {
1374
+ x: e.camera.up.x,
1375
+ y: e.camera.up.y,
1376
+ z: e.camera.up.z
1377
+ }
1378
+ };
1379
+ }
1380
+ function wt(e, t) {
1381
+ if (!e.camera || !e.controls || !t) return !1;
1382
+ const n = t.camera || {}, r = t.target || {}, o = t.up || {};
1383
+ 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 = Oe(t), !0) : !1;
1384
+ }
1385
+ function $t(e) {
1386
+ if (!e.viewChangeHandler) return;
1387
+ const t = Date.now();
1388
+ if (t - e._lastViewEmitMs < 250) return;
1389
+ const n = Qe(e);
1390
+ if (!n) return;
1391
+ const r = Oe(n);
1392
+ r !== e._lastViewSignature && (e._lastViewSignature = r, e._lastViewEmitMs = t, e.viewChangeHandler(n));
1393
+ }
1394
+ function Me(e, { minX: t, maxX: n, minY: r, maxY: o, minZ: s, maxZ: i }) {
1395
+ const a = (t + n) / 2, c = (r + o) / 2, l = (s + i) / 2, u = n - t, m = o - r, f = i - s, p = Math.max(u, m, f, 1) * 2;
1396
+ e.controls.target.set(a, c, l), e.camera.position.set(a + p, c + p, l + p), e.camera.lookAt(a, c, l), e.controls.update();
1397
+ }
1398
+ function jt(e, t = 1e3) {
1399
+ !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());
1400
+ }
1401
+ function Bt(e, t = 2e3) {
1402
+ !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());
1403
+ }
1404
+ function Ut(e, t = 0, n = 0) {
1405
+ e.controls && typeof e.controls.pan == "function" && (e.controls.pan(t, n), e.controls.update());
1406
+ }
1407
+ function Yt(e, t = 1.1) {
1408
+ !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());
1409
+ }
1410
+ function Gt(e, t = 1.2) {
1411
+ if (!e.lastBounds) return;
1412
+ const {
1413
+ minX: n,
1414
+ maxX: r,
1415
+ minY: o,
1416
+ maxY: s,
1417
+ minZ: i,
1418
+ maxZ: a
1419
+ } = e.lastBounds, c = (r - n) * t, l = (s - o) * t, u = (a - i) * t, m = (n + r) / 2, f = (o + s) / 2, d = (i + a) / 2, y = Math.max(c, l, u, 1) * 2;
1420
+ e.controls.target.set(m, f, d), e.camera.position.set(m + y, f + y, d + y), e.camera.lookAt(m, f, d), e.controls.update();
1421
+ }
1422
+ function qt(e, t = "orbit") {
1423
+ if (e.controlMode = t === "fly" ? "fly" : "orbit", e.controlMode === "fly")
1424
+ e.controls && (e.controls.enabled = !1), e.flyControls && (e.flyControls.enabled = !0);
1425
+ else if (e.flyControls && (e.flyControls.enabled = !1), e.controls) {
1426
+ e.controls.enabled = !0, e.camera.getWorldDirection(e._tmpDir);
1427
+ const n = e.camera.position.clone().addScaledVector(e._tmpDir, 10);
1428
+ e.controls.target.copy(n), e.controls.update();
1429
+ }
1430
+ }
1431
+ const Q = "#9ca3af";
1432
+ function Re(e, t) {
1433
+ const n = Number(e == null ? void 0 : e.md), r = Number(t == null ? void 0 : t.md);
1434
+ if (!Number.isFinite(n) || !Number.isFinite(r)) return null;
1435
+ const o = Math.min(n, r), s = Math.max(n, r);
1436
+ return s <= o ? null : { segStart: o, segEnd: s };
1437
+ }
1438
+ function Xt(e, t, n) {
1439
+ let r = 0, o = 0;
1440
+ for (let i = 0; i < e.length; i += 1) {
1441
+ const a = e[i], c = Number(a == null ? void 0 : a.from), l = Number(a == null ? void 0 : a.to), u = Number(a == null ? void 0 : a.value);
1442
+ if (!Number.isFinite(c) || !Number.isFinite(l) || !Number.isFinite(u) || l <= c) continue;
1443
+ const m = Math.max(t, c), d = Math.min(n, l) - m;
1444
+ d <= 0 || (r += u * d, o += d);
1445
+ }
1446
+ if (o <= 0) return null;
1447
+ const s = r / o;
1448
+ return Number.isFinite(s) ? s : null;
1449
+ }
1450
+ function Wt(e, t) {
1451
+ if (!Number.isFinite(e)) return new g.Color(Q);
1452
+ if (Ze(e, t) < 0) return new g.Color(Q);
1453
+ const r = Ht(e, t, Q);
1454
+ return new g.Color(r);
1455
+ }
1456
+ function Zt(e = {}) {
1457
+ return {
1458
+ preserveView: !!e.preserveView,
1459
+ assayIntervalsByHole: e.assayIntervalsByHole || null,
1460
+ selectedAssayVariable: e.selectedAssayVariable || ""
1461
+ };
1462
+ }
1463
+ function Kt(e, t) {
1464
+ if (!e || !t) return [];
1465
+ const n = [];
1466
+ return Object.values(e).forEach((r) => {
1467
+ (r || []).forEach((o) => {
1468
+ const s = Number(o == null ? void 0 : o.value);
1469
+ Number.isFinite(s) && n.push(s);
1470
+ });
1471
+ }), n;
1472
+ }
1473
+ function Ae(e) {
1474
+ return {
1475
+ holeId: e.id,
1476
+ project: e.project
1477
+ };
1478
+ }
1479
+ class jn {
1480
+ constructor() {
1481
+ 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.frameId = null, this.clock = new g.Clock(), this.handleCanvasClick = null, this.raycaster = new g.Raycaster(), this.pointer = new g.Vector2(), this.drillholeClickHandler = null, this.controlMode = "orbit", this._tmpDir = new g.Vector3(), this.viewChangeHandler = null, this._lastViewSignature = "", this._lastViewEmitMs = 0;
1482
+ }
1483
+ init(t) {
1484
+ if (!t) return;
1485
+ this.container = t;
1486
+ const n = t.clientWidth, r = t.clientHeight;
1487
+ this.scene = new g.Scene(), this.scene.background = new g.Color(16777215), this.camera = new g.PerspectiveCamera(28, n / r, 1e-3, 1e5), this.camera.up.set(0, 0, 1), this.camera.position.set(50, 50, 50), this.camera.lookAt(0, 0, 0), this.renderer = new g.WebGLRenderer({ antialias: !0 }), this.renderer.setSize(n, r), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.autoClear = !1, t.appendChild(this.renderer.domElement);
1488
+ const o = new g.AmbientLight(16777215, 0.5);
1489
+ this.scene.add(o);
1490
+ const s = new g.DirectionalLight(16777215, 0.6);
1491
+ s.position.set(10, 10, 5), this.scene.add(s);
1492
+ const i = new g.AxesHelper(20);
1493
+ this.scene.add(i), this.controls = new ot(this.camera, this.renderer.domElement), this.controls.enableDamping = !1, this.controls.screenSpacePanning = !0, this.controls.enableZoom = !0, this.controls.zoomSpeed = 1.2, this.controls.minDistance = 3e-3, this.controls.maxDistance = 4e4, this.controls.mouseButtons = {
1494
+ LEFT: g.MOUSE.PAN,
1495
+ MIDDLE: g.MOUSE.DOLLY,
1496
+ RIGHT: g.MOUSE.ROTATE
1497
+ }, this.controls.touches = {
1498
+ ONE: g.TOUCH.ROTATE,
1499
+ TWO: g.TOUCH.PAN
1500
+ }, this.controls.maxPolarAngle = Math.PI, this.flyControls = new it(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 st(this.camera, this.renderer, {
1501
+ container: this.container,
1502
+ placement: "top-right",
1503
+ size: 110,
1504
+ offset: { top: 12, right: 12 },
1505
+ animated: !0,
1506
+ speed: 1.5
1507
+ }), this.gizmo.attachControls(this.controls), this._attachCanvasClickHandler();
1508
+ const a = () => {
1509
+ var l;
1510
+ this.frameId = requestAnimationFrame(a);
1511
+ const c = this.clock.getDelta();
1512
+ this.renderer.clear(), this.controlMode === "fly" && ((l = this.flyControls) != null && l.enabled) ? this.flyControls.update(c) : this.controls && this.controls.update(), this._emitViewChangeIfNeeded(), this.renderer.render(this.scene, this.camera), this.gizmo && this.gizmo.render();
1513
+ };
1514
+ a();
1515
+ }
1516
+ setViewChangeHandler(t) {
1517
+ this.viewChangeHandler = typeof t == "function" ? t : null;
1518
+ }
1519
+ getViewState() {
1520
+ return Qe(this);
1521
+ }
1522
+ setViewState(t) {
1523
+ return wt(this, t);
1524
+ }
1525
+ _buildViewSignature(t) {
1526
+ return Oe(t);
1527
+ }
1528
+ _emitViewChangeIfNeeded() {
1529
+ $t(this);
1530
+ }
1531
+ _attachCanvasClickHandler() {
1532
+ const t = this.renderer;
1533
+ t && (this.handleCanvasClick = (n) => {
1534
+ var u, m, f, d;
1535
+ if (n.button !== 0) return;
1536
+ if ((u = this.gizmo) != null && u.domElement) {
1537
+ const p = this.gizmo.domElement.getBoundingClientRect();
1538
+ if (n.clientX >= p.left && n.clientX <= p.right && n.clientY >= p.top && n.clientY <= p.bottom)
1539
+ return;
1540
+ }
1541
+ const r = t.domElement.getBoundingClientRect(), o = n.clientX - r.left, s = n.clientY - r.top;
1542
+ this.pointer.x = o / r.width * 2 - 1, this.pointer.y = -(s / r.height * 2) + 1, this.raycaster.setFromCamera(this.pointer, this.camera);
1543
+ const i = this.raycaster.intersectObjects(this.drillMeshes, !0);
1544
+ if (i.length === 0) return;
1545
+ let a = i[0].object;
1546
+ for (; a && a.parent && !((m = a.userData) != null && m.holeId); )
1547
+ a = a.parent;
1548
+ const c = (f = a == null ? void 0 : a.userData) == null ? void 0 : f.holeId, l = (d = a == null ? void 0 : a.userData) == null ? void 0 : d.project;
1549
+ c && this.drillholeClickHandler && this.drillholeClickHandler({ holeId: c, project: l });
1550
+ }, t.domElement.addEventListener("click", this.handleCanvasClick));
1551
+ }
1552
+ resize() {
1553
+ if (!this.container || !this.camera || !this.renderer) return;
1554
+ const t = this.container.clientWidth, n = this.container.clientHeight;
1555
+ this.camera.aspect = t / n, this.camera.updateProjectionMatrix(), this.renderer.setSize(t, n), this.gizmo && this.gizmo.update();
1556
+ }
1557
+ setBlocks(t, n, r) {
1558
+ if (!this.scene || (this._clearBlocks(), !t || !n || !r)) return;
1559
+ let o = 1 / 0, s = -1 / 0, i = 1 / 0, a = -1 / 0, c = 1 / 0, l = -1 / 0;
1560
+ t.forEach((u) => {
1561
+ const {
1562
+ center_x: m = 0,
1563
+ center_y: f = 0,
1564
+ center_z: d = 0,
1565
+ size_x: p = 1,
1566
+ size_y: y = 1,
1567
+ size_z: h = 1
1568
+ } = u;
1569
+ o = Math.min(o, m - p / 2), s = Math.max(s, m + p / 2), i = Math.min(i, f - y / 2), a = Math.max(a, f + y / 2), c = Math.min(c, d - h / 2), l = Math.max(l, d + h / 2);
1570
+ const A = new g.BoxGeometry(p, y, h), O = Mt(u[n], r, g), F = new g.MeshStandardMaterial({
1571
+ color: O,
1572
+ transparent: !0,
1573
+ opacity: 0.7,
1574
+ side: g.DoubleSide
1575
+ }), D = new g.Mesh(A, F);
1576
+ D.position.set(m, f, d), this.scene.add(D), this.blocks.push(D);
1577
+ }), this.camera && this.controls && (this.lastBounds = { minX: o, maxX: s, minY: i, maxY: a, minZ: c, maxZ: l }, Me(this, { minX: o, maxX: s, minY: i, maxY: a, minZ: c, maxZ: l }));
1578
+ }
1579
+ setDrillholes(t, n = {}) {
1580
+ if (!this.scene || (this._clearDrillholes(), !t || t.length === 0)) return;
1581
+ const { preserveView: r, assayIntervalsByHole: o, selectedAssayVariable: s } = Zt(n), i = Kt(o, s), a = St(i);
1582
+ let c = 1 / 0, l = -1 / 0, u = 1 / 0, m = -1 / 0, f = 1 / 0, d = -1 / 0;
1583
+ const p = new g.Vector3(), y = new g.Vector3(0, 1, 0);
1584
+ t.forEach((h, A) => {
1585
+ const F = A * 137.5 % 360 / 360, D = new g.Color().setHSL(F, 0.75, 0.55), R = (h.points || []).map((N) => {
1586
+ c = Math.min(c, N.x), l = Math.max(l, N.x), u = Math.min(u, N.y), m = Math.max(m, N.y), f = Math.min(f, N.z), d = Math.max(d, N.z);
1587
+ const z = new g.Vector3(N.x, N.y, N.z);
1588
+ return z.md = N.md, z;
1589
+ });
1590
+ if (R.length < 2) {
1591
+ if (R.length === 1) {
1592
+ const N = new g.SphereGeometry(5, 12, 12), z = new g.MeshLambertMaterial({
1593
+ color: D,
1594
+ emissive: D,
1595
+ emissiveIntensity: 0.2
1596
+ }), C = new g.Mesh(N, z);
1597
+ C.position.copy(R[0]), C.userData = Ae(h), this.scene.add(C), this.drillLines.push(C), this.drillMeshes.push(C);
1598
+ }
1599
+ return;
1600
+ }
1601
+ const w = new g.Group();
1602
+ w.userData = Ae(h);
1603
+ const I = s ? this._resolveAssayIntervalsForHole(h, o) : [];
1604
+ for (let N = 0; N < R.length - 1; N += 1) {
1605
+ const z = R[N], C = R[N + 1], E = p.subVectors(C, z), b = E.length();
1606
+ if (b <= 1e-3) continue;
1607
+ const _ = 2.2, M = new g.CylinderGeometry(_, _, b, 6, 1, !1), L = this._getSegmentColor({
1608
+ selectedAssayVariable: s,
1609
+ assayIntervals: I,
1610
+ assayScale: a,
1611
+ holeId: h.id,
1612
+ segmentIndex: N,
1613
+ p1: z,
1614
+ p2: C
1615
+ }), v = new g.MeshLambertMaterial({
1616
+ color: L,
1617
+ flatShading: !0,
1618
+ emissive: L,
1619
+ emissiveIntensity: 0.15
1620
+ }), T = new g.Mesh(M, v);
1621
+ T.position.copy(z.clone().addScaledVector(E, 0.5)), T.quaternion.setFromUnitVectors(y, E.clone().normalize()), T.userData = Ae(h), w.add(T), this.drillMeshes.push(T);
1622
+ }
1623
+ this.scene.add(w), this.drillLines.push(w);
1624
+ }), this.camera && this.controls && (this.lastBounds = { minX: c, maxX: l, minY: u, maxY: m, minZ: f, maxZ: d }, r || Me(this, { minX: c, maxX: l, minY: u, maxY: m, minZ: f, maxZ: d }));
1625
+ }
1626
+ _getSegmentColor({ selectedAssayVariable: t, assayIntervals: n, assayScale: r, holeId: o, segmentIndex: s, p1: i, p2: a }) {
1627
+ if (!t)
1628
+ return Qt(o, s);
1629
+ if (t === "__HAS_ASSAY__") {
1630
+ if (!(n != null && n.length)) return new g.Color(Q);
1631
+ const u = Re(i, a);
1632
+ return u ? n.some((f) => {
1633
+ const d = Number(f == null ? void 0 : f.from), p = Number(f == null ? void 0 : f.to);
1634
+ if (!Number.isFinite(d) || !Number.isFinite(p)) return !1;
1635
+ const y = Math.max(u.segStart, d);
1636
+ return Math.min(u.segEnd, p) > y;
1637
+ }) ? new g.Color("#ff8c42") : new g.Color(Q) : new g.Color(Q);
1638
+ }
1639
+ if (!(n != null && n.length)) return new g.Color(Q);
1640
+ const c = Re(i, a);
1641
+ if (!c) return new g.Color(Q);
1642
+ const l = Xt(n, c.segStart, c.segEnd);
1643
+ return Wt(l, r);
1644
+ }
1645
+ _resolveAssayIntervalsForHole(t, n) {
1646
+ if (!n || !t) return [];
1647
+ const r = t.id || t.holeId;
1648
+ if (!r) return [];
1649
+ const o = n[r];
1650
+ if (Array.isArray(o) && o.length) return o;
1651
+ const s = Jt(r);
1652
+ if (s) {
1653
+ const i = n[s];
1654
+ if (Array.isArray(i) && i.length) return i;
1655
+ }
1656
+ return [];
1657
+ }
1658
+ _fitCameraToBounds({ minX: t, maxX: n, minY: r, maxY: o, minZ: s, maxZ: i }) {
1659
+ Me(this, { minX: t, maxX: n, minY: r, maxY: o, minZ: s, maxZ: i });
1660
+ }
1661
+ recenterCameraToOrigin(t = 1e3) {
1662
+ jt(this, t);
1663
+ }
1664
+ lookDown(t = 2e3) {
1665
+ Bt(this, t);
1666
+ }
1667
+ pan(t = 0, n = 0) {
1668
+ Ut(this, t, n);
1669
+ }
1670
+ dolly(t = 1.1) {
1671
+ Yt(this, t);
1672
+ }
1673
+ focusOnLastBounds(t = 1.2) {
1674
+ Gt(this, t);
1675
+ }
1676
+ _clearBlocks() {
1677
+ this.blocks.forEach((t) => {
1678
+ this.scene.remove(t), t.geometry.dispose(), t.material.dispose();
1679
+ }), this.blocks = [];
1680
+ }
1681
+ _clearDrillholes() {
1682
+ this.drillLines.forEach((t) => {
1683
+ this.scene.remove(t), t.isGroup ? t.traverse((n) => {
1684
+ n.isMesh && (n.geometry.dispose(), n.material.dispose());
1685
+ }) : t.isMesh && (t.geometry.dispose(), t.material.dispose());
1686
+ }), this.drillLines = [], this.drillMeshes = [];
1687
+ }
1688
+ dispose() {
1689
+ 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, this._clearBlocks(), this._clearDrillholes(), 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));
1690
+ }
1691
+ setDrillholeClickHandler(t) {
1692
+ this.drillholeClickHandler = t;
1693
+ }
1694
+ setControlMode(t = "orbit") {
1695
+ qt(this, t);
1696
+ }
1697
+ }
1698
+ function Jt(e) {
1699
+ return `${e ?? ""}`.trim().toLowerCase();
1700
+ }
1701
+ function Qt(e, t) {
1702
+ const n = `${e ?? ""}:${t ?? 0}`, r = en(n), o = (t ?? 0) % 14 / 14, s = (r * 0.15 + o * 0.85) % 1, i = new g.Color();
1703
+ return i.setHSL(s, 1, 0.5), i;
1704
+ }
1705
+ function en(e) {
1706
+ const t = `${e ?? ""}`;
1707
+ let n = 2166136261;
1708
+ for (let r = 0; r < t.length; r += 1)
1709
+ n ^= t.charCodeAt(r), n = Math.imul(n, 16777619);
1710
+ return (n >>> 0) / 4294967295;
1711
+ }
1712
+ function Bn({
1713
+ controlMode: e = "orbit",
1714
+ onToggleFly: t = () => {
1715
+ },
1716
+ onRecenter: n = () => {
1717
+ },
1718
+ onLookDown: r = () => {
1719
+ },
1720
+ onFit: o = () => {
1721
+ }
1722
+ }) {
1723
+ return /* @__PURE__ */ ae("div", { className: "baselode-3d-controls", children: [
1724
+ /* @__PURE__ */ k("button", { type: "button", className: "ghost-button", onClick: n, children: "Recenter to (0,0,0)" }),
1725
+ /* @__PURE__ */ k("button", { type: "button", className: "ghost-button", onClick: r, children: "Look down" }),
1726
+ /* @__PURE__ */ k("button", { type: "button", className: "ghost-button", onClick: o, children: "Fit to scene" }),
1727
+ /* @__PURE__ */ k("button", { type: "button", className: "ghost-button", onClick: t, children: e === "orbit" ? "Enable fly controls" : "Disable fly controls" })
1728
+ ] });
1729
+ }
1730
+ export {
1731
+ Ft as ASSAY_COLOR_PALETTE_10,
1732
+ Be as ASSAY_NON_VALUE_FIELDS,
1733
+ j as AZIMUTH,
1734
+ dn as BASELODE_DATA_MODEL_DRILL_ASSAY,
1735
+ cn as BASELODE_DATA_MODEL_DRILL_COLLAR,
1736
+ un as BASELODE_DATA_MODEL_DRILL_SURVEY,
1737
+ Bn as Baselode3DControls,
1738
+ jn as Baselode3DScene,
1739
+ $e as CRS,
1740
+ at as DEFAULT_COLUMN_MAP,
1741
+ V as DEPTH,
1742
+ B as DIP,
1743
+ K as EASTING,
1744
+ oe as ELEVATION,
1745
+ It as ERROR_COLOR,
1746
+ $ as FROM,
1747
+ x as HOLE_ID,
1748
+ q as LATITUDE,
1749
+ X as LONGITUDE,
1750
+ we as MID,
1751
+ J as NORTHING,
1752
+ He as NUMERIC_LINE_COLOR,
1753
+ At as NUMERIC_MARKER_COLOR,
1754
+ Z as PROJECT_ID,
1755
+ H as TO,
1756
+ Sn as TracePlot,
1757
+ $n as annotationsFromIntervals,
1758
+ Pn as assembleDataset,
1759
+ Mn as attachAssayPositions,
1760
+ xn as balancedTangentialDesurvey,
1761
+ gt as buildAssayState,
1762
+ St as buildEqualRangeColorScale,
1763
+ Et as buildIntervalPoints,
1764
+ Lt as buildPlotConfig,
1765
+ Nn as buildTraces,
1766
+ Oe as buildViewSignature,
1767
+ Fn as calculatePropertyStats,
1768
+ Tn as coerceNumeric,
1769
+ Xe as deriveAssayProps,
1770
+ _n as desurveyTraces,
1771
+ Yt as dolly,
1772
+ $t as emitViewChangeIfNeeded,
1773
+ Ln as filterByProject,
1774
+ Me as fitCameraToBounds,
1775
+ Gt as focusOnLastBounds,
1776
+ Mt as getColorForValue,
1777
+ Ze as getEqualRangeBinIndex,
1778
+ Ht as getEqualRangeColor,
1779
+ Qe as getViewState,
1780
+ Ve as holeHasData,
1781
+ wn as intervalsAsTubes,
1782
+ Dn as joinAssaysToTraces,
1783
+ bn as loadAssayFile,
1784
+ yt as loadAssayHole,
1785
+ pt as loadAssayMetadata,
1786
+ vn as loadAssays,
1787
+ In as loadCollars,
1788
+ En as loadSurveys,
1789
+ De as loadTable,
1790
+ hn as logDataInfo,
1791
+ fn as logDataWarning,
1792
+ Bt as lookDown,
1793
+ _t as minimumCurvatureDesurvey,
1794
+ yn as normalizeCsvRow,
1795
+ fe as normalizeFieldName,
1796
+ Ut as pan,
1797
+ mt as parseAssayHole,
1798
+ pn as parseAssayHoleIds,
1799
+ dt as parseAssayHoleIdsWithAssays,
1800
+ ft as parseAssaysCSV,
1801
+ On as parseBlockModelCSV,
1802
+ An as parseDrillholesCSV,
1803
+ Cn as parseSurveyCSV,
1804
+ gn as pickFirstPresent,
1805
+ Hn as planView,
1806
+ Vt as projectTraceToSection,
1807
+ jt as recenterCameraToOrigin,
1808
+ Ge as reorderHoleIds,
1809
+ Vn as sectionView,
1810
+ Rt as sectionWindow,
1811
+ qt as setControlMode,
1812
+ wt as setViewState,
1813
+ ce as standardizeColumns,
1814
+ mn as standardizeRowArray,
1815
+ zn as tangentialDesurvey,
1816
+ lt as toError,
1817
+ Rn as tracesAsSegments,
1818
+ kn as useDrillholeTraceGrid,
1819
+ P as withDataErrorContext
1820
+ };
1821
+ //# sourceMappingURL=baselode.js.map