baselode 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/baselode.js CHANGED
@@ -1,97 +1,107 @@
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 = {
1
+ import Z from "papaparse";
2
+ import { jsx as q, jsxs as Ne } from "react/jsx-runtime";
3
+ import { useRef as ot, useState as K, useEffect as oe, useMemo as ve } from "react";
4
+ import xe from "plotly.js-dist-min";
5
+ import * as x from "three";
6
+ import { OrbitControls as It } from "three/examples/jsm/controls/OrbitControls";
7
+ import { FlyControls as At } from "three/examples/jsm/controls/FlyControls";
8
+ import { ViewportGizmo as St } from "three-viewport-gizmo";
9
+ const z = "hole_id", ee = "latitude", te = "longitude", he = "elevation", O = "azimuth", k = "dip", B = "from", R = "to", Ve = "mid", re = "project_id", ie = "easting", se = "northing", it = "crs", H = "depth", st = "alpha", at = "beta", Et = "strike", Qn = {
10
10
  // A unique hole identifier across the entire dataset and all future data sets
11
- [x]: "string",
11
+ [z]: "string",
12
12
  // The hole ID from the original collar source
13
13
  datasource_hole_id: "string",
14
14
  // The project ID or project code from the original collar source, if available
15
- [Z]: "string",
15
+ [re]: "string",
16
16
  // The latitude of the collar, in decimal degrees (WGS84)
17
- [q]: "number",
17
+ [ee]: "number",
18
18
  // The longitude of the collar, in decimal degrees (WGS84)
19
- [X]: "number",
19
+ [te]: "number",
20
20
  // The elevation of the collar, in meters above sea level (WGS84)
21
- [oe]: "number",
21
+ [he]: "number",
22
22
  // The easting coordinate of the collar, in meters (projected CRS)
23
- [K]: "number",
23
+ [ie]: "number",
24
24
  // The northing coordinate of the collar, in meters (projected CRS)
25
- [J]: "number",
25
+ [se]: "number",
26
26
  // The coordinate reference system of the collar coordinates for easting/northing, as an EPSG code or proj string
27
- [$e]: "string"
28
- }, un = {
27
+ [it]: "string"
28
+ }, er = {
29
29
  // The unique hole id that maps to the collar and any other data tables
30
- [x]: "string",
30
+ [z]: "string",
31
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
32
  [H]: "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
+ [R]: "number",
35
35
  // The azimuth of the hole at the survey depth, in degrees from north
36
- [j]: "number",
36
+ [O]: "number",
37
37
  // The dip of the hole at the survey depth, in degrees from horizontal (negative values indicate downward inclination)
38
- [B]: "number"
39
- }, dn = {
38
+ [k]: "number"
39
+ }, tr = {
40
40
  // The unique hole id that maps to the collar and any other data tables
41
- [x]: "string",
41
+ [z]: "string",
42
42
  // The depth along the hole where the assay interval starts
43
- [$]: "number",
43
+ [B]: "number",
44
44
  // The depth along the hole where the assay interval ends
45
- [H]: "number",
45
+ [R]: "number",
46
46
  // The midpoint depth of the assay interval
47
- [we]: "number"
47
+ [Ve]: "number"
48
48
  // assay value columns are variable and not standardized here.
49
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"],
50
+ }, nr = {
51
+ [z]: "string",
52
+ [H]: "number",
53
+ [k]: "number",
54
+ [O]: "number",
55
+ [st]: "number",
56
+ [at]: "number",
57
+ comments: "string"
58
+ }, vt = {
59
+ [z]: ["hole_id", "holeid", "hole id", "hole-id"],
52
60
  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))
61
+ [re]: ["project_id", "projectid", "project id", "project-id", "project_code", "projectcode", "project code", "project-code", "companyId", "company_id", "companyid", "company id", "company-id", "dataset", "project"],
62
+ [ee]: ["latitude", "lat"],
63
+ [te]: ["longitude", "lon"],
64
+ [he]: ["elevation", "rl", "elev", "z"],
65
+ [ie]: ["easting", "x"],
66
+ [se]: ["northing", "y"],
67
+ [it]: ["crs", "epsg", "projection"],
68
+ [B]: ["from", "depth_from", "from_depth", "samp_from", "sample_from", "sampfrom", "fromdepth"],
69
+ [R]: ["to", "depth_to", "to_depth", "samp_to", "sample_to", "sampto", "todepth"],
70
+ [O]: ["azimuth", "az", "dip_direction", "dipdir", "dip direction", "dipdrn", "dipdirection", "dip_dir", "computed_plane_azimuth", "calc_dipdir", "calc_dipdir_deg", "dipdrn", "dipdir_calc", "dipdirect_calc"],
71
+ [k]: ["dip", "computed_plane_dip", "calc_dip", "calc_dip_deg", "dip_calc"],
72
+ [st]: ["alpha", "alpha_angle", "alpha_angle_deg", "alpha_2"],
73
+ [at]: ["beta", "beta_angle", "beta_angle_deg", "beta_2"],
74
+ [H]: ["depth", "survey_depth", "surveydepth"],
75
+ [Et]: ["strike", "str"]
76
+ }, lt = {};
77
+ for (const [e, t] of Object.entries(vt))
68
78
  for (const n of t) {
69
79
  const r = n.toLowerCase().trim();
70
- je[r] = e;
80
+ lt[r] = e;
71
81
  }
72
- function fe(e) {
82
+ function ze(e) {
73
83
  return (e || "").toString().trim().toLowerCase().replace(/\s+/g, "_");
74
84
  }
75
- function ce(e, t = null, n = null) {
76
- const r = { ...je };
85
+ function ue(e, t = null, n = null) {
86
+ const r = { ...lt };
77
87
  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;
88
+ for (const [i, s] of Object.entries(n))
89
+ if (i != null && s != null) {
90
+ const l = ze(i), u = ze(s);
91
+ r[l] = u;
82
92
  }
83
93
  }
84
94
  const o = {};
85
- for (const [s, i] of Object.entries(e)) {
86
- const a = fe(s), c = r[a] || a;
87
- o[c] = i;
95
+ for (const [i, s] of Object.entries(e)) {
96
+ const l = ze(i), u = r[l] || l;
97
+ o[u] = s;
88
98
  }
89
99
  return o;
90
100
  }
91
- function mn(e, t = null, n = null) {
92
- return e.map((r) => ce(r, t, n));
101
+ function rr(e, t = null, n = null) {
102
+ return e.map((r) => ue(r, t, n));
93
103
  }
94
- const Be = /* @__PURE__ */ new Set([
104
+ const Pt = /* @__PURE__ */ new Set([
95
105
  "hole_id",
96
106
  "holeid",
97
107
  "id",
@@ -123,153 +133,153 @@ const Be = /* @__PURE__ */ new Set([
123
133
  "todepth",
124
134
  "comment",
125
135
  "z"
126
- ]), Ie = "[baselode:data]";
127
- function lt(e, t = "Unknown error") {
136
+ ]), Fe = "[baselode:data]";
137
+ function Dt(e, t = "Unknown error") {
128
138
  if (e instanceof Error) return e;
129
139
  const n = typeof e == "string" && e.trim() ? e : t;
130
140
  return new Error(n);
131
141
  }
132
- function P(e, t, n = "Operation failed") {
133
- const r = lt(t, n), o = new Error(`${e}: ${r.message}`);
142
+ function $(e, t, n = "Operation failed") {
143
+ const r = Dt(t, n), o = new Error(`${e}: ${r.message}`);
134
144
  return o.cause = r, o;
135
145
  }
136
- function fn(e, t) {
146
+ function or(e, t) {
137
147
  if (t !== void 0) {
138
- console.warn(`${Ie} ${e}`, t);
148
+ console.warn(`${Fe} ${e}`, t);
139
149
  return;
140
150
  }
141
- console.warn(`${Ie} ${e}`);
151
+ console.warn(`${Fe} ${e}`);
142
152
  }
143
- function hn(e) {
144
- console.info(`${Ie} ${e}`);
153
+ function ir(e) {
154
+ console.info(`${Fe} ${e}`);
145
155
  }
146
- const ye = (e, t = null) => ce(e, null, t);
147
- function ct(e) {
148
- return { holeId: e[x] };
156
+ const Se = (e, t = null) => ue(e, null, t);
157
+ function Lt(e) {
158
+ return { holeId: e[z] };
149
159
  }
150
- function Ue(e, t = null) {
151
- const n = e[x], r = n !== void 0 ? `${n}`.trim() : "";
160
+ function ct(e, t = null) {
161
+ const n = e[z], r = n !== void 0 ? `${n}`.trim() : "";
152
162
  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 : {
163
+ const o = e[re] || e.project || e.project_code, i = Number(e[B]), s = Number(e[R]);
164
+ return !Number.isFinite(i) || !Number.isFinite(s) || s <= i ? null : {
155
165
  holeId: r,
156
166
  project: o,
157
- from: s,
158
- to: i,
167
+ from: i,
168
+ to: s,
159
169
  ...e
160
170
  };
161
171
  }
162
- function Ye(e, t) {
172
+ function ut(e, t) {
163
173
  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
174
+ const n = t.sort((i, s) => i.from - s.from), r = [];
175
+ return n.forEach((i) => {
176
+ const { from: s, to: l, project: u, ...a } = i, c = {
177
+ z: s,
178
+ from: s,
179
+ to: l,
180
+ [z]: e,
181
+ [re]: u,
182
+ ...a
173
183
  };
174
- r.push(u), r.push({ ...u, z: a });
184
+ r.push(c), r.push({ ...c, z: l });
175
185
  }), { id: e, project: (o = n[0]) == null ? void 0 : o.project, points: r };
176
186
  }
177
- function pn(e, t = null) {
187
+ function sr(e, t = null) {
178
188
  return new Promise((n, r) => {
179
189
  const o = /* @__PURE__ */ new Set();
180
- ee.parse(e, {
190
+ Z.parse(e, {
181
191
  header: !0,
182
192
  dynamicTyping: !0,
183
193
  skipEmptyLines: !0,
184
- step: (s) => {
185
- const a = ye(s.data, t)[x];
186
- a !== void 0 && `${a}`.trim() !== "" && o.add(`${a}`.trim());
194
+ step: (i) => {
195
+ const l = Se(i.data, t)[z];
196
+ l !== void 0 && `${l}`.trim() !== "" && o.add(`${l}`.trim());
187
197
  },
188
198
  complete: () => n(Array.from(o)),
189
- error: (s) => r(P("parseAssayHoleIds", s))
199
+ error: (i) => r($("parseAssayHoleIds", i))
190
200
  });
191
201
  });
192
202
  }
193
- function ut(e) {
194
- return Object.entries(e || {}).some(([t, n]) => !(Be.has(t) || n == null || typeof n == "string" && n.trim() === ""));
203
+ function Tt(e) {
204
+ return Object.entries(e || {}).some(([t, n]) => !(Pt.has(t) || n == null || typeof n == "string" && n.trim() === ""));
195
205
  }
196
- function dt(e, t = null) {
206
+ function Ft(e, t = null) {
197
207
  return new Promise((n, r) => {
198
208
  const o = /* @__PURE__ */ new Map();
199
- ee.parse(e, {
209
+ Z.parse(e, {
200
210
  header: !0,
201
211
  dynamicTyping: !0,
202
212
  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
213
+ step: (i) => {
214
+ const s = Se(i.data, t);
215
+ if (!Tt(s)) return;
216
+ const u = Lt(s).holeId;
217
+ if (u !== void 0 && `${u}`.trim() !== "") {
218
+ const a = `${u}`.trim();
219
+ o.has(a) || o.set(a, {
220
+ holeId: a
211
221
  });
212
222
  }
213
223
  },
214
224
  complete: () => n(Array.from(o.values())),
215
- error: (s) => r(P("parseAssayHoleIdsWithAssays", s))
225
+ error: (i) => r($("parseAssayHoleIdsWithAssays", i))
216
226
  });
217
227
  });
218
228
  }
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")));
229
+ function Ot(e, t, n = null, r = null) {
230
+ return new Promise((o, i) => {
231
+ const s = `${t}`.trim();
232
+ if (!s) {
233
+ i($("parseAssayHole", new Error("Missing hole id")));
224
234
  return;
225
235
  }
226
- const a = [];
227
- ee.parse(e, {
236
+ const l = [];
237
+ Z.parse(e, {
228
238
  header: !0,
229
239
  dynamicTyping: !0,
230
240
  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);
241
+ step: (u) => {
242
+ const a = Se(u.data, r), c = ct(a, r);
243
+ c && `${c.holeId}`.trim() === s && l.push(c);
234
244
  },
235
245
  complete: () => {
236
- if (!a.length) {
246
+ if (!l.length) {
237
247
  o(null);
238
248
  return;
239
249
  }
240
- const c = Ye(i, a);
241
- o(c);
250
+ const u = ut(s, l);
251
+ o(u);
242
252
  },
243
- error: (c) => s(P("parseAssayHole", c))
253
+ error: (u) => i($("parseAssayHole", u))
244
254
  });
245
255
  });
246
256
  }
247
- function ft(e, t = null, n = null) {
257
+ function kt(e, t = null, n = null) {
248
258
  return new Promise((r, o) => {
249
- ee.parse(e, {
259
+ Z.parse(e, {
250
260
  header: !0,
251
261
  dynamicTyping: !0,
252
262
  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));
263
+ complete: (i) => {
264
+ const s = /* @__PURE__ */ new Map();
265
+ i.data.forEach((u) => {
266
+ const a = Se(u, n), c = ct(a, n);
267
+ c && (s.has(c.holeId) || s.set(c.holeId, []), s.get(c.holeId).push(c));
258
268
  });
259
- const a = Array.from(i.entries()).map(([c, l]) => Ye(c, l));
260
- r({ holes: a });
269
+ const l = Array.from(s.entries()).map(([u, a]) => ut(u, a));
270
+ r({ holes: l });
261
271
  },
262
- error: (s) => o(P("parseAssaysCSV", s))
272
+ error: (i) => o($("parseAssaysCSV", i))
263
273
  });
264
274
  });
265
275
  }
266
- function yn(e = {}) {
276
+ function ar(e = {}) {
267
277
  const t = {};
268
278
  return Object.entries(e || {}).forEach(([n, r]) => {
269
- n && (t[fe(n)] = r);
279
+ n && (t[ze(n)] = r);
270
280
  }), t;
271
281
  }
272
- function gn(e = {}, t = [], n) {
282
+ function lr(e = {}, t = [], n) {
273
283
  for (const r of t) {
274
284
  const o = e[r];
275
285
  if (o != null && `${o}`.trim() !== "")
@@ -277,537 +287,656 @@ function gn(e = {}, t = [], n) {
277
287
  }
278
288
  return n;
279
289
  }
280
- const ht = 4;
281
- function Ge(e = [], t = "") {
290
+ const Vt = 4;
291
+ function mt(e = [], t = "") {
282
292
  if (!e.length) return [];
283
293
  if (!t) return e;
284
- const n = e.findIndex((s) => s === t);
294
+ const n = e.findIndex((i) => i === t);
285
295
  if (n === -1) return e;
286
- const r = e[n], o = e.filter((s, i) => i !== n);
296
+ const r = e[n], o = e.filter((i, s) => s !== n);
287
297
  return [r, ...o];
288
298
  }
289
- function he({
299
+ function Me({
290
300
  property: e = "",
291
301
  chartType: t = "",
292
302
  categoricalProps: n = [],
293
- numericDefaultChartType: r = "markers+line"
303
+ commentProps: r = [],
304
+ numericDefaultChartType: o = "markers+line"
294
305
  } = {}) {
295
- return e ? n.includes(e) ? "categorical" : !t || t === "categorical" ? r : t : t || r;
306
+ return e ? r.includes(e) ? "comment" : n.includes(e) ? "categorical" : e === "dip" ? "tadpole" : !t || t === "categorical" || t === "comment" || t === "tadpole" ? o : t : t || o;
296
307
  }
297
- function qe({
308
+ function dt({
298
309
  holeIds: e = [],
299
310
  focusedHoleId: t = "",
300
- plotCount: n = ht,
311
+ plotCount: n = Vt,
301
312
  defaultProp: r = "",
302
313
  categoricalProps: o = [],
314
+ commentProps: i = [],
303
315
  numericDefaultChartType: s = "markers+line"
304
316
  } = {}) {
305
- const i = Ge(e, t);
306
- return Array.from({ length: n }).map((a, c) => {
307
- const l = i[c] || e[c] || "", u = he({
317
+ const l = mt(e, t);
318
+ return Array.from({ length: n }).map((u, a) => {
319
+ const c = l[a] || e[a] || "", m = Me({
308
320
  property: r,
309
321
  chartType: "",
310
322
  categoricalProps: o,
323
+ commentProps: i,
311
324
  numericDefaultChartType: s
312
325
  });
313
326
  return {
314
- holeId: l,
327
+ holeId: c,
315
328
  property: r,
316
- chartType: u
329
+ chartType: m
317
330
  };
318
331
  });
319
332
  }
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;
333
+ const ye = "numeric", _e = "categorical", pe = "comment", Ce = "hidden", Oe = "tadpole", Ue = {
334
+ [ye]: [
335
+ { value: "bar", label: "Bars" },
336
+ { value: "markers", label: "Markers" },
337
+ { value: "markers+line", label: "Markers + Line" },
338
+ { value: "line", label: "Line only" }
339
+ ],
340
+ [_e]: [
341
+ { value: "categorical", label: "Categorical bands" }
342
+ ],
343
+ [pe]: [
344
+ { value: "comment", label: "Comments" }
345
+ ],
346
+ [Oe]: [
347
+ { value: "tadpole", label: "Tadpole" }
348
+ ],
349
+ [Ce]: []
350
+ }, Ye = /* @__PURE__ */ new Set([
351
+ // Hole identifiers
352
+ "hole_id",
353
+ "holeid",
354
+ "id",
355
+ "holetype",
356
+ "datasource_hole_id",
357
+ "anumber",
358
+ "collarid",
359
+ "companyholeid",
360
+ "company_hole_id",
361
+ "company_id",
362
+ // Project codes
363
+ "project_id",
364
+ "project_code",
365
+ "project",
366
+ "projectcode",
367
+ "projectid",
368
+ // Geographic coordinates
369
+ "latitude",
370
+ "longitude",
371
+ "lat",
372
+ "lon",
373
+ "lng",
374
+ "easting",
375
+ "northing",
376
+ "x",
377
+ "y",
378
+ "z",
379
+ "elevation",
380
+ "elev",
381
+ "rl",
382
+ // Depth / interval columns
383
+ "from",
384
+ "to",
385
+ "mid",
386
+ "depth",
387
+ "md",
388
+ "samp_from",
389
+ "samp_to",
390
+ "sample_from",
391
+ "sample_to",
392
+ "depth_from",
393
+ "depth_to",
394
+ "fromdepth",
395
+ "todepth",
396
+ // Geometry / CRS
397
+ "shape",
398
+ "geometry",
399
+ "crs",
400
+ "epsg",
401
+ // Internal / synthetic columns
402
+ "data_source",
403
+ "_hole_key",
404
+ "_hole_id_key"
405
+ ]), wt = /* @__PURE__ */ new Set([
406
+ "comments",
407
+ "comment",
408
+ "notes",
409
+ "note",
410
+ "description",
411
+ "remarks",
412
+ "remark",
413
+ "log_description",
414
+ "struct_comment",
415
+ "structcomment"
416
+ ]);
417
+ function Rt(e) {
418
+ if (!(e != null && e.length))
419
+ return { byType: {}, numericCols: [], categoricalCols: [], commentCols: [] };
420
+ const t = new Set(e.flatMap((r) => Object.keys(r || {}))), n = {};
421
+ for (const r of t) {
422
+ const o = r.toLowerCase().trim();
423
+ if (Ye.has(o) || Ye.has(r)) {
424
+ n[r] = Ce;
425
+ continue;
426
+ }
427
+ if (wt.has(o)) {
428
+ const l = e.some((u) => {
429
+ const a = u[r];
430
+ return a != null && String(a).trim() !== "" && String(a) !== "null";
431
+ });
432
+ n[r] = l ? pe : Ce;
433
+ continue;
434
+ }
435
+ let i = !1, s = !1;
436
+ for (const l of e) {
437
+ const u = l[r];
438
+ if (!(u == null || typeof u == "string" && u.trim() === "") && (s = !0, typeof u == "number" && Number.isFinite(u))) {
439
+ i = !0;
335
440
  break;
336
441
  }
337
442
  }
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 };
443
+ s ? i ? n[r] = ye : n[r] = _e : n[r] = Ce;
444
+ }
445
+ return {
446
+ byType: n,
447
+ numericCols: Object.entries(n).filter(([, r]) => r === ye).map(([r]) => r),
448
+ categoricalCols: Object.entries(n).filter(([, r]) => r === _e).map(([r]) => r),
449
+ commentCols: Object.entries(n).filter(([, r]) => r === pe).map(([r]) => r)
450
+ };
451
+ }
452
+ function we(e) {
453
+ return Ue[e] ?? Ue[ye];
454
+ }
455
+ function cr(e) {
456
+ const t = we(e);
457
+ return t.length ? e === ye ? "line" : t[0].value : "markers+line";
458
+ }
459
+ function Ie(e = []) {
460
+ const t = e.flatMap((l) => l.points || []), { numericCols: n, categoricalCols: r, commentCols: o, byType: i } = Rt(t), s = n[0] || r[0] || "";
461
+ return {
462
+ numericProps: n,
463
+ categoricalProps: r,
464
+ commentProps: o,
465
+ columnMeta: i,
466
+ defaultProp: s
467
+ };
342
468
  }
343
- async function pt(e, t = null) {
344
- return await dt(e);
469
+ async function $t(e, t = null) {
470
+ return await Ft(e);
345
471
  }
346
- async function yt(e, t, n = null) {
347
- return await mt(e, t);
472
+ async function Ht(e, t, n = null) {
473
+ return await Ot(e, t);
348
474
  }
349
- function gt(e = [], t = "") {
475
+ function jt(e = [], t = "") {
350
476
  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,
477
+ const { numericProps: n, categoricalProps: r, commentProps: o, columnMeta: i, defaultProp: s } = Ie(e), l = e.map((a) => a.id || a.holeId).filter(Boolean), u = dt({
478
+ holeIds: l,
353
479
  focusedHoleId: t,
354
480
  plotCount: 4,
355
- defaultProp: o,
481
+ defaultProp: s,
356
482
  categoricalProps: r,
483
+ commentProps: o,
357
484
  numericDefaultChartType: "line"
358
485
  });
359
486
  return {
360
487
  holes: e,
361
488
  numericProps: n,
362
489
  categoricalProps: r,
363
- defaultProp: o,
364
- traceConfigs: i
490
+ commentProps: o,
491
+ columnMeta: i,
492
+ defaultProp: s,
493
+ traceConfigs: u
365
494
  };
366
495
  }
367
- async function bn(e, t = "", n = null) {
368
- const { holes: r } = await ft(e, n), o = gt(r, t);
496
+ async function ur(e, t = "", n = null) {
497
+ const { holes: r } = await kt(e, n), o = jt(r, t);
369
498
  if (!o) throw new Error("No valid assay intervals found.");
370
499
  return o;
371
500
  }
372
- function Cn(e, t = null) {
501
+ function mr(e, t = null) {
373
502
  return new Promise((n, r) => {
374
- ee.parse(e, {
503
+ Z.parse(e, {
375
504
  header: !0,
376
505
  dynamicTyping: !0,
377
506
  skipEmptyLines: !0,
378
507
  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);
508
+ const i = o.data.map((s) => Gt(s, t)).filter((s) => s[z] && Number.isFinite(s[H]) && Number.isFinite(s[k]) && Number.isFinite(s[O]));
509
+ n(i);
381
510
  },
382
- error: (o) => r(P("parseSurveyCSV", o))
511
+ error: (o) => r($("parseSurveyCSV", o))
383
512
  });
384
513
  });
385
514
  }
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);
515
+ function Gt(e, t = null) {
516
+ const n = ue(e, null, t), r = n[z], o = n[re] || n.project || n.project_code, i = fe(n[ee]), s = fe(n[te]), l = fe(n[H]), u = fe(n[k]), a = fe(n[O]), c = fe(n.maxdepth);
388
517
  return {
389
518
  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,
519
+ [z]: r,
520
+ [re]: o,
521
+ [ee]: i,
522
+ [te]: s,
523
+ [H]: l,
524
+ [k]: u,
525
+ [O]: a,
526
+ maxdepth: c,
398
527
  // Legacy field names for backwards compatibility
399
528
  project_code: o,
400
- latitude: s,
401
- longitude: i,
402
- surveydepth: a
529
+ latitude: i,
530
+ longitude: s,
531
+ surveydepth: l
403
532
  };
404
533
  }
405
- const ne = (e) => {
534
+ const fe = (e) => {
406
535
  const t = Number(e);
407
536
  return Number.isFinite(t) ? t : void 0;
408
537
  };
409
- function _n(e, t) {
410
- var l, u, m, f;
538
+ function dr(e, t) {
539
+ var a, c, m, d;
411
540
  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);
541
+ e.forEach((f) => {
542
+ const y = (f[z] || f.holeId || f.id || "").toString().trim();
543
+ if (!y) return;
544
+ const p = y.toLowerCase();
545
+ n.has(p) || n.set(p, f);
424
546
  });
425
- const c = [];
426
- return a.forEach((d, p) => {
427
- const y = n.get(p);
547
+ const r = ((a = e[0]) == null ? void 0 : a.lat) ?? ((c = e[0]) == null ? void 0 : c[ee]) ?? 0, o = ((m = e[0]) == null ? void 0 : m.lng) ?? ((d = e[0]) == null ? void 0 : d[te]) ?? 0, i = 111132, s = 111320 * Math.cos(r * Math.PI / 180), l = /* @__PURE__ */ new Map();
548
+ t.forEach((f) => {
549
+ const y = (f[z] || "").toString().trim();
428
550
  if (!y) return;
429
- const h = d.filter((b) => Number.isFinite(b[V] ?? b.surveydepth)).sort((b, _) => (b[V] ?? b.surveydepth) - (_[V] ?? _.surveydepth));
551
+ const p = y.toLowerCase();
552
+ l.has(p) || l.set(p, []), l.get(p).push(f);
553
+ });
554
+ const u = [];
555
+ return l.forEach((f, y) => {
556
+ const p = n.get(y);
557
+ if (!p) return;
558
+ const h = f.filter((D) => Number.isFinite(D[H] ?? D.surveydepth)).sort((D, G) => (D[H] ?? D.surveydepth) - (G[H] ?? G.surveydepth));
430
559
  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,
560
+ const g = p.lat ?? p[ee], b = p.lng ?? p[te], _ = 111132, I = 111320 * Math.cos(g * Math.PI / 180), N = (b - o) * s, P = (g - r) * i, E = [];
561
+ let M = 0, F = 0, j = 0;
562
+ for (let D = 0; D < h.length; D += 1) {
563
+ const G = h[D], U = h[D - 1], S = G[H] ?? G.surveydepth, C = G[O] ?? G.azimuth, v = G[k] ?? G.dip;
564
+ if (!U) {
565
+ E.push({
566
+ x: N + M,
567
+ y: P + F,
439
568
  z: 0,
440
- md: L,
441
- azimuth: v,
442
- dip: T
569
+ md: S,
570
+ azimuth: C,
571
+ dip: v
443
572
  });
444
573
  continue;
445
574
  }
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,
575
+ const L = U[H] ?? U.surveydepth, A = U[O] ?? U.azimuth, V = U[k] ?? U.dip, w = S - L;
576
+ if (w <= 0) continue;
577
+ const T = qe(V), Y = qe(v), X = ke(A), le = ke(C), be = Math.acos(
578
+ Math.sin(T) * Math.sin(Y) * Math.cos(X - le) + Math.cos(T) * Math.cos(Y)
579
+ ), me = be > 1e-6 ? 2 / be * Math.tan(be / 2) : 1, Ee = 0.5 * w * (Math.sin(T) * Math.cos(X) + Math.sin(Y) * Math.cos(le)) * me, de = 0.5 * w * (Math.sin(T) * Math.sin(X) + Math.sin(Y) * Math.sin(le)) * me, Ct = 0.5 * w * (Math.cos(T) + Math.cos(Y)) * me;
580
+ M += Ee, F += de, j += Ct, E.push({
581
+ x: N + M,
582
+ y: P + F,
583
+ z: -j,
455
584
  // render with z up; depth down
456
- md: L,
457
- azimuth: v,
458
- dip: T
585
+ md: S,
586
+ azimuth: C,
587
+ dip: v
459
588
  });
460
589
  }
461
- const E = I.map((b) => ({
462
- ...b,
463
- lat: A + b.y / F,
464
- lng: O + b.x / D
590
+ const W = E.map((D) => ({
591
+ ...D,
592
+ lat: g + D.y / _,
593
+ lng: b + D.x / I
465
594
  }));
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
595
+ u.push({
596
+ id: p[z] || p.holeId || y,
597
+ project: p[re] || p.project_id || p.project || "",
598
+ points: W,
599
+ collar: p
471
600
  });
472
- }), c;
601
+ }), u;
473
602
  }
474
- const Ee = (e) => e * Math.PI / 180, Fe = (e) => {
603
+ const ke = (e) => e * Math.PI / 180, qe = (e) => {
475
604
  const t = Number(e), n = 90 + (Number.isFinite(t) ? t : 0), r = Math.min(180, Math.max(0, n));
476
- return Ee(r);
605
+ return ke(r);
477
606
  };
478
- function G(e, t = void 0) {
607
+ function Q(e, t = void 0) {
479
608
  const n = Number(e);
480
609
  return Number.isFinite(n) ? n : t;
481
610
  }
482
- function Se(e) {
611
+ function Xe(e) {
483
612
  return e == null ? "" : `${e}`.trim();
484
613
  }
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])));
614
+ function Ae(e = [], t = null) {
615
+ const n = t || "hole_id", o = [n, "hole_id", "holeId", "id"].find((i) => e.some((s) => Xe(s == null ? void 0 : s[i])));
487
616
  if (!o)
488
- throw P("canonicalizeHoleIdRows", new Error(`hole id column '${n}' not found`));
617
+ throw $("canonicalizeHoleIdRows", new Error(`hole id column '${n}' not found`));
489
618
  return {
490
619
  aliasCol: o,
491
- rows: e.map((s) => ({
492
- ...s,
493
- hole_id: Se(s == null ? void 0 : s[o])
620
+ rows: e.map((i) => ({
621
+ ...i,
622
+ hole_id: Xe(i == null ? void 0 : i[o])
494
623
  }))
495
624
  };
496
625
  }
497
- function ke(e) {
626
+ function Ze(e) {
498
627
  return Number(e) * Math.PI / 180;
499
628
  }
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 };
629
+ function Pe(e, t) {
630
+ const n = Ze(e), r = Ze(t), o = Math.cos(r) * Math.sin(n), i = Math.cos(r) * Math.cos(n), s = Math.sin(r) * -1;
631
+ return { ca: o, cb: i, cc: s };
503
632
  }
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")
633
+ function Bt(e, t, n, r, o, i = "minimum_curvature") {
634
+ const s = Pe(t, n), l = Pe(r, o);
635
+ if (i === "tangential")
507
636
  return {
508
- dx: e * i.ca,
509
- dy: e * i.cb,
510
- dz: e * i.cc,
637
+ dx: e * s.ca,
638
+ dy: e * s.cb,
639
+ dz: e * s.cc,
511
640
  azimuth: t,
512
641
  dip: n
513
642
  };
514
- if (s === "balanced_tangential") {
515
- const m = 0.5 * (t + r), f = 0.5 * (n + o), d = xe(m, f);
643
+ if (i === "balanced_tangential") {
644
+ const m = 0.5 * (t + r), d = 0.5 * (n + o), f = Pe(m, d);
516
645
  return {
517
- dx: e * d.ca,
518
- dy: e * d.cb,
519
- dz: e * d.cc,
646
+ dx: e * f.ca,
647
+ dy: e * f.cb,
648
+ dz: e * f.cc,
520
649
  azimuth: m,
521
- dip: f
650
+ dip: d
522
651
  };
523
652
  }
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;
653
+ const u = s.ca * l.ca + s.cb * l.cb + s.cc * l.cc, a = Math.acos(Math.max(-1, Math.min(1, u))), c = a > 1e-6 ? 2 * Math.tan(a / 2) / a : 1;
525
654
  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,
655
+ dx: 0.5 * e * (s.ca + l.ca) * c,
656
+ dy: 0.5 * e * (s.cb + l.cb) * c,
657
+ dz: 0.5 * e * (s.cc + l.cc) * c,
529
658
  azimuth: r,
530
659
  dip: o
531
660
  };
532
661
  }
533
- function ve(e = [], t = [], n = {}) {
662
+ function Re(e = [], t = [], n = {}) {
534
663
  const {
535
664
  step: r = 1,
536
665
  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);
666
+ method: i = "minimum_curvature"
667
+ } = n, s = Number.isFinite(Number(r)) && Number(r) > 0 ? Number(r) : 1, l = Ae(e, o), u = Ae(t, o || l.aliasCol);
668
+ if (!l.rows.length || !u.rows.length) return [];
669
+ const a = /* @__PURE__ */ new Map();
670
+ l.rows.forEach((d) => {
671
+ !d.hole_id || a.has(d.hole_id) || a.set(d.hole_id, d);
543
672
  });
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));
673
+ const c = /* @__PURE__ */ new Map();
674
+ u.rows.forEach((d) => {
675
+ d.hole_id && (c.has(d.hole_id) || c.set(d.hole_id, []), c.get(d.hole_id).push(d));
547
676
  });
548
677
  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,
678
+ return c.forEach((d, f) => {
679
+ const y = a.get(f);
680
+ if (!y) return;
681
+ const p = [...d].map((E) => ({
682
+ ...E,
683
+ from: Q(E.from),
684
+ azimuth: Q(E.azimuth),
685
+ dip: Q(E.dip)
686
+ })).filter((E) => Number.isFinite(E.from) && Number.isFinite(E.azimuth) && Number.isFinite(E.dip)).sort((E, M) => E.from - M.from);
687
+ if (!p.length) return;
688
+ let h = Q(y.x, 0), g = Q(y.y, 0), b = Q(y.z, 0), _ = p[0].from;
689
+ const I = p[0].azimuth, N = p[0].dip, P = {
690
+ hole_id: f,
691
+ md: _,
563
692
  x: h,
564
- y: A,
565
- z: O,
566
- azimuth: D,
567
- dip: R
693
+ y: g,
694
+ z: b,
695
+ azimuth: I,
696
+ dip: N
568
697
  };
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,
698
+ l.aliasCol !== "hole_id" && y[l.aliasCol] !== void 0 && (P[l.aliasCol] = y[l.aliasCol]), m.push(P);
699
+ for (let E = 0; E < p.length - 1; E += 1) {
700
+ const M = p[E], F = p[E + 1], j = M.from, D = F.from - j;
701
+ if (D <= 0) continue;
702
+ const G = Math.max(1, Math.ceil(D / s)), U = D / G;
703
+ for (let S = 0; S < G; S += 1) {
704
+ _ += U;
705
+ const C = (_ - j) / D, v = M.azimuth + C * (F.azimuth - M.azimuth), L = M.dip + C * (F.dip - M.dip), A = Bt(U, M.azimuth, M.dip, F.azimuth, F.dip, i);
706
+ h += A.dx, g += A.dy, b += A.dz;
707
+ const V = {
708
+ hole_id: f,
709
+ md: _,
581
710
  x: h,
582
- y: A,
583
- z: O,
584
- azimuth: s === "minimum_curvature" ? T : Y.azimuth,
585
- dip: s === "minimum_curvature" ? S : Y.dip
711
+ y: g,
712
+ z: b,
713
+ azimuth: i === "minimum_curvature" ? v : A.azimuth,
714
+ dip: i === "minimum_curvature" ? L : A.dip
586
715
  };
587
- a.aliasCol !== "hole_id" && p[a.aliasCol] !== void 0 && (ue[a.aliasCol] = p[a.aliasCol]), m.push(ue);
716
+ l.aliasCol !== "hole_id" && y[l.aliasCol] !== void 0 && (V[l.aliasCol] = y[l.aliasCol]), m.push(V);
588
717
  }
589
718
  }
590
719
  }), m;
591
720
  }
592
- function _t(e, t, n = {}) {
593
- return ve(e, t, { ...n, method: "minimum_curvature" });
721
+ function Ut(e, t, n = {}) {
722
+ return Re(e, t, { ...n, method: "minimum_curvature" });
594
723
  }
595
- function zn(e, t, n = {}) {
596
- return ve(e, t, { ...n, method: "tangential" });
724
+ function fr(e, t, n = {}) {
725
+ return Re(e, t, { ...n, method: "tangential" });
597
726
  }
598
- function xn(e, t, n = {}) {
599
- return ve(e, t, { ...n, method: "balanced_tangential" });
727
+ function hr(e, t, n = {}) {
728
+ return Re(e, t, { ...n, method: "balanced_tangential" });
600
729
  }
601
- function Nn(e, t, n = {}) {
602
- return _t(e, t, n);
730
+ function pr(e, t, n = {}) {
731
+ return Ut(e, t, n);
603
732
  }
604
- function zt(e, t) {
733
+ function Yt(e, t) {
605
734
  if (!e.length || !Number.isFinite(t)) return null;
606
735
  let n = null, r = 1 / 0;
607
736
  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);
737
+ const i = e[o], s = Q(i.md);
738
+ if (!Number.isFinite(s)) continue;
739
+ const l = Math.abs(s - t);
740
+ l < r && (r = l, n = i);
612
741
  }
613
742
  return n;
614
743
  }
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;
744
+ function yr(e = [], t = [], n = {}) {
745
+ const r = n.holeIdCol || "hole_id", o = Ae(e, r), i = Ae(t, r);
746
+ if (!o.rows.length || !i.rows.length) return [...o.rows];
747
+ const s = /* @__PURE__ */ new Map();
748
+ return i.rows.forEach((l) => {
749
+ l.hole_id && (s.has(l.hole_id) || s.set(l.hole_id, []), s.get(l.hole_id).push(l));
750
+ }), s.forEach((l, u) => {
751
+ s.set(u, [...l].sort((a, c) => Q(a.md, 0) - Q(c.md, 0)));
752
+ }), o.rows.map((l) => {
753
+ const u = Q(l.from), a = Q(l.to), c = Number.isFinite(u) && Number.isFinite(a) ? 0.5 * (u + a) : void 0;
754
+ if (!l.hole_id || !Number.isFinite(c)) return { ...l };
755
+ const m = Yt(s.get(l.hole_id) || [], c);
756
+ if (!m) return { ...l };
757
+ const d = { ...l };
758
+ return ["md", "x", "y", "z", "azimuth", "dip"].forEach((f) => {
759
+ m[f] !== void 0 && (Object.prototype.hasOwnProperty.call(d, f) ? d[`${f}_trace`] = m[f] : d[f] = m[f]);
760
+ }), d;
632
761
  });
633
762
  }
634
- function An(e, t = null) {
763
+ function br(e, t = null) {
635
764
  return new Promise((n, r) => {
636
- ee.parse(e, {
765
+ Z.parse(e, {
637
766
  header: !0,
638
767
  dynamicTyping: !0,
639
768
  skipEmptyLines: !0,
640
769
  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,
770
+ const i = /* @__PURE__ */ new Map();
771
+ o.data.forEach((l, u) => {
772
+ const a = ue(l, null, t), c = a[z], m = c !== void 0 ? `${c}`.trim() : "", d = a[ie] ?? a.x, f = a[se] ?? a.y, y = a[he] ?? a.z, p = a.order ?? u;
773
+ !m || d === null || d === void 0 || f === null || f === void 0 || y === null || y === void 0 || (i.has(m) || i.set(m, []), i.get(m).push({
774
+ ...a,
646
775
  holeId: m,
647
- order: y,
648
- x: Number(f) ?? 0,
649
- y: Number(d) ?? 0,
650
- z: Number(p) ?? 0
776
+ order: p,
777
+ x: Number(d) ?? 0,
778
+ y: Number(f) ?? 0,
779
+ z: Number(y) ?? 0
651
780
  }));
652
781
  });
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
782
+ const s = Array.from(i.entries()).map(([l, u]) => ({
783
+ id: l,
784
+ points: u.sort((a, c) => a.order - c.order).map((a) => ({
785
+ ...a,
786
+ x: Number(a.x) || 0,
787
+ y: Number(a.y) || 0,
788
+ z: Number(a.z) || 0
660
789
  }))
661
790
  }));
662
- n({ holes: i });
791
+ n({ holes: s });
663
792
  },
664
- error: (o) => r(P("parseDrillholesCSV", o))
793
+ error: (o) => r($("parseDrillholesCSV", o))
665
794
  });
666
795
  });
667
796
  }
668
- function le(e) {
797
+ function ge(e) {
669
798
  return e ? Array.isArray(e) ? [...e] : [] : [];
670
799
  }
671
- function U(e) {
800
+ function J(e) {
672
801
  const t = Number(e);
673
802
  return Number.isFinite(t) ? t : void 0;
674
803
  }
675
- function We(e = [], t = []) {
804
+ function ft(e = [], t = []) {
676
805
  const n = [...e];
677
806
  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}`);
807
+ for (let i = 0; i < t.length; i += 1) {
808
+ const s = t[i], l = r == null ? void 0 : r[s], u = o == null ? void 0 : o[s];
809
+ if (l !== u)
810
+ return l == null ? 1 : u == null ? -1 : typeof l == "number" && typeof u == "number" ? l - u : `${l}`.localeCompare(`${u}`);
682
811
  }
683
812
  return 0;
684
813
  }), n;
685
814
  }
686
- function xt(e, t = {}) {
815
+ function qt(e, t = {}) {
687
816
  return new Promise((n, r) => {
688
- ee.parse(e, {
817
+ Z.parse(e, {
689
818
  header: !0,
690
819
  dynamicTyping: !0,
691
820
  skipEmptyLines: !0,
692
821
  ...t,
693
822
  complete: (o) => n(Array.isArray(o == null ? void 0 : o.data) ? o.data : []),
694
- error: (o) => r(P("loadTable(csv)", o))
823
+ error: (o) => r($("loadTable(csv)", o))
695
824
  });
696
825
  });
697
826
  }
698
- function Nt(e = [], t = null, n = null) {
699
- return e.map((r) => ce(r, t, n));
827
+ function Xt(e = [], t = null, n = null) {
828
+ return e.map((r) => ue(r, t, n));
700
829
  }
701
- async function De(e, t = {}) {
830
+ async function $e(e, t = {}) {
702
831
  const {
703
832
  kind: n = "csv",
704
833
  columnMap: r = null,
705
834
  sourceColumnMap: o = null,
706
- papaParseConfig: s = {}
835
+ papaParseConfig: i = {}
707
836
  } = t;
708
- let i;
837
+ let s;
709
838
  if (Array.isArray(e))
710
- i = le(e);
839
+ s = ge(e);
711
840
  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);
841
+ s = await qt(e, i);
842
+ else throw n === "parquet" || n === "sql" ? $("loadTable", new Error(`Unsupported kind in JS runtime: ${n}`)) : $("loadTable", new Error(`Unsupported kind: ${n}`));
843
+ return Xt(s, r, o);
715
844
  }
716
- async function In(e, t = {}) {
845
+ async function gr(e, t = {}) {
717
846
  const {
718
847
  crs: n = null,
719
848
  sourceColumnMap: r = null,
720
849
  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();
850
+ ...i
851
+ } = t, s = await $e(e, { ...i, sourceColumnMap: r });
852
+ if (!s.some((d) => z in d))
853
+ throw $("loadCollars", new Error(`Collar table missing column: ${z}`));
854
+ const u = s.some((d) => ie in d && se in d), a = s.some((d) => ee in d && te in d);
855
+ if (!u && !a)
856
+ throw $("loadCollars", new Error("Collar table missing coordinate columns (need easting/northing or latitude/longitude)"));
857
+ const c = s.map((d) => {
858
+ const f = { ...d };
859
+ if (z in f) {
860
+ const y = f[z];
861
+ f[z] = y == null ? "" : `${y}`.trim();
733
862
  }
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;
863
+ return ee in f && (f[ee] = J(f[ee])), te in f && (f[te] = J(f[te])), he in f && (f[he] = J(f[he])), ie in f && (f[ie] = J(f[ie])), se in f && (f[se] = J(f[se])), !("datasource_hole_id" in f) && z in f && (f.datasource_hole_id = f[z]), f;
735
864
  });
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;
865
+ if (!c.every((d) => !(!d[z] || a && (!Number.isFinite(d[ee]) || !Number.isFinite(d[te])) || u && !a && (!Number.isFinite(d[ie]) || !Number.isFinite(d[se])))))
866
+ throw $("loadCollars", new Error("Collar table has missing required values"));
867
+ return c;
739
868
  }
740
- async function En(e, t = {}) {
869
+ async function _r(e, t = {}) {
741
870
  const {
742
871
  sourceColumnMap: n = null,
743
872
  keepAll: r = !0,
744
873
  ...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();
874
+ } = t, i = await $e(e, { ...o, sourceColumnMap: n }), s = [z, H, O, k];
875
+ for (const a of s)
876
+ if (!i.some((m) => a in m))
877
+ throw $("loadSurveys", new Error(`Survey table missing column: ${a}`));
878
+ const l = i.map((a) => {
879
+ const c = { ...a };
880
+ if (z in c) {
881
+ const m = c[z];
882
+ c[z] = m == null ? "" : `${m}`.trim();
754
883
  }
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;
884
+ return H in c && (c[H] = J(c[H])), R in c && (c[R] = J(c[R])), O in c && (c[O] = J(c[O])), k in c && (c[k] = J(c[k])), c;
756
885
  });
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]);
886
+ if (!l.every((a) => !(!a[z] || !Number.isFinite(a[H]) || !Number.isFinite(a[O]) || !Number.isFinite(a[k]))))
887
+ throw $("loadSurveys", new Error("Survey table has missing required values"));
888
+ return ft(l, [z, H]);
760
889
  }
761
- async function vn(e, t = {}) {
890
+ async function xr(e, t = {}) {
762
891
  const {
763
892
  sourceColumnMap: n = null,
764
893
  keepAll: r = !0,
765
894
  ...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();
895
+ } = t, i = await $e(e, { ...o, sourceColumnMap: n }), s = [z, B, R];
896
+ for (const a of s)
897
+ if (!i.some((m) => a in m))
898
+ throw $("loadAssays", new Error(`Assay table missing column: ${a}`));
899
+ const l = i.map((a) => {
900
+ const c = { ...a };
901
+ if (z in c) {
902
+ const m = c[z];
903
+ c[z] = m == null ? "" : `${m}`.trim();
775
904
  }
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;
905
+ return B in c && (c[B] = J(c[B])), R in c && (c[R] = J(c[R])), B in c && R in c && Number.isFinite(c[B]) && Number.isFinite(c[R]) && (c[Ve] = 0.5 * (c[B] + c[R])), c;
777
906
  });
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]);
907
+ if (!l.every((a) => !(!a[z] || !Number.isFinite(a[B]) || !Number.isFinite(a[R]))))
908
+ throw $("loadAssays", new Error("Assay table has missing required values"));
909
+ return ft(l, [z, B, R]);
781
910
  }
782
- function Dn(e = [], t = [], n = {}) {
783
- const r = Array.isArray(n.onCols) && n.onCols.length ? n.onCols : [x];
911
+ function Nr(e = [], t = [], n = {}) {
912
+ const r = Array.isArray(n.onCols) && n.onCols.length ? n.onCols : [z];
784
913
  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;
914
+ const o = (s) => r.map((l) => `${(s == null ? void 0 : s[l]) ?? ""}`).join("|"), i = /* @__PURE__ */ new Map();
915
+ return t.forEach((s) => {
916
+ i.set(o(s), s);
917
+ }), e.map((s) => {
918
+ const l = i.get(o(s));
919
+ if (!l) return { ...s };
920
+ const u = { ...s };
921
+ return Object.entries(l).forEach(([a, c]) => {
922
+ r.includes(a) || (Object.prototype.hasOwnProperty.call(u, a) ? u[`${a}_trace`] = c : u[a] = c);
923
+ }), u;
795
924
  });
796
925
  }
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] : [];
926
+ function zr(e = [], t = null) {
927
+ return t == null ? [...e] : e.length ? e.some((r) => re in r) ? e.filter((r) => (r == null ? void 0 : r[re]) === t) : [...e] : [];
799
928
  }
800
- function Tn(e = [], t = []) {
929
+ function Mr(e = [], t = []) {
801
930
  return e.map((n) => {
802
931
  const r = { ...n };
803
932
  return t.forEach((o) => {
804
933
  if (!(o in r)) return;
805
- const s = U(r[o]);
806
- r[o] = s;
934
+ const i = J(r[o]);
935
+ r[o] = i;
807
936
  }), r;
808
937
  });
809
938
  }
810
- function Pn({
939
+ function Cr({
811
940
  collars: e = [],
812
941
  surveys: t = [],
813
942
  assays: n = [],
@@ -815,93 +944,407 @@ function Pn({
815
944
  metadata: o = {}
816
945
  } = {}) {
817
946
  return {
818
- collars: le(e),
819
- surveys: le(t),
820
- assays: le(n),
821
- structures: le(r),
947
+ collars: ge(e),
948
+ surveys: ge(t),
949
+ assays: ge(n),
950
+ structures: ge(r),
822
951
  metadata: o || {}
823
952
  };
824
953
  }
825
- function On(e) {
954
+ function Ir(e) {
826
955
  return new Promise((t, n) => {
827
- ee.parse(e, {
956
+ Z.parse(e, {
828
957
  header: !0,
829
958
  dynamicTyping: !0,
830
959
  complete: (r) => {
831
960
  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)
961
+ (l) => l.center_x !== null && l.center_y !== null && l.center_z !== null
962
+ ), i = ["center_x", "center_y", "center_z", "size_x", "size_y", "size_z"], s = Object.keys(o[0] || {}).filter(
963
+ (l) => !i.includes(l)
835
964
  );
836
- t({ data: o, properties: i });
965
+ t({ data: o, properties: s });
837
966
  },
838
967
  error: (r) => {
839
- n(P("parseBlockModelCSV", r));
968
+ n($("parseBlockModelCSV", r));
840
969
  }
841
970
  });
842
971
  });
843
972
  }
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 };
973
+ function Ar(e, t) {
974
+ const n = e.map((i) => i[t]).filter((i) => i != null);
975
+ if (n.every((i) => typeof i == "number")) {
976
+ const i = Math.min(...n), s = Math.max(...n);
977
+ return { type: "numeric", min: i, max: s, values: n };
849
978
  }
850
979
  return { type: "categorical", categories: [...new Set(n)], values: n };
851
980
  }
852
- function Mt(e, t, n) {
981
+ function Zt(e, t, n) {
853
982
  if (!t) return new n.Color("#888888");
854
983
  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);
984
+ const i = t.max - t.min, l = (1 - (i === 0 ? 0.5 : (e - t.min) / i)) * 240;
985
+ return new n.Color().setHSL(l / 360, 0.8, 0.5);
857
986
  }
858
987
  const o = t.categories.indexOf(e) / Math.max(t.categories.length, 1) * 360;
859
988
  return new n.Color().setHSL(o / 360, 0.7, 0.5);
860
989
  }
861
- const He = "#8b1e3f", At = "#a8324f", It = "#6b7280";
862
- function Ve(e, t) {
990
+ const He = (e, t = null) => ue(e, null, t);
991
+ function Wt(e) {
992
+ if (!e.length) return null;
993
+ const t = e[0], n = B in t && R in t, r = H in t && !n;
994
+ return n ? "interval" : r ? "point" : null;
995
+ }
996
+ function ne(e) {
997
+ const t = Number(e);
998
+ return Number.isFinite(t) ? t : null;
999
+ }
1000
+ function ht(e) {
1001
+ const t = e[z] !== void 0 ? `${e[z]}`.trim() : "";
1002
+ if (!t) return null;
1003
+ const n = ne(e[H]);
1004
+ return n === null ? null : {
1005
+ [z]: t,
1006
+ [H]: n,
1007
+ [k]: ne(e[k]),
1008
+ [O]: ne(e[O]),
1009
+ comments: e.comments != null ? `${e.comments}` : null,
1010
+ ...e
1011
+ };
1012
+ }
1013
+ function pt(e) {
1014
+ const t = e[z] !== void 0 ? `${e[z]}`.trim() : "";
1015
+ if (!t) return null;
1016
+ const n = ne(e[B]), r = ne(e[R]);
1017
+ if (n === null || r === null || r <= n) return null;
1018
+ const o = 0.5 * (n + r);
1019
+ return {
1020
+ [z]: t,
1021
+ [B]: n,
1022
+ [R]: r,
1023
+ mid: o,
1024
+ [k]: ne(e[k]),
1025
+ [O]: ne(e[O]),
1026
+ classification: e.classification != null ? `${e.classification}` : null,
1027
+ comments: e.comments != null ? `${e.comments}` : null,
1028
+ ...e
1029
+ };
1030
+ }
1031
+ function Sr(e) {
1032
+ const t = [], n = [];
1033
+ for (const r of e) {
1034
+ const o = [], i = ne(r[k]), s = ne(r[O]);
1035
+ i !== null && (i < 0 || i > 90) && o.push(`dip ${i} out of range [0, 90]`), s !== null && (s < 0 || s >= 360) && o.push(`azimuth ${s} out of range [0, 360)`), o.length ? n.push({ row: r, message: o.join("; ") }) : t.push(r);
1036
+ }
1037
+ return { valid: t, errors: n };
1038
+ }
1039
+ function Er(e, t = null) {
1040
+ return new Promise((n, r) => {
1041
+ const o = {
1042
+ header: !0,
1043
+ dynamicTyping: !0,
1044
+ skipEmptyLines: !0,
1045
+ complete: (i) => {
1046
+ const s = [];
1047
+ for (const l of i.data) {
1048
+ const u = He(l, t), a = ht(u);
1049
+ a && s.push(a);
1050
+ }
1051
+ n(s);
1052
+ },
1053
+ error: (i) => r($("parseStructuralPointsCSV", i))
1054
+ };
1055
+ typeof e == "string" && !e.startsWith("data:") && e.includes(`
1056
+ `) ? Z.parse(e, o) : Z.parse(e, o);
1057
+ });
1058
+ }
1059
+ function vr(e, t = null) {
1060
+ return new Promise((n, r) => {
1061
+ Z.parse(e, {
1062
+ header: !0,
1063
+ dynamicTyping: !0,
1064
+ skipEmptyLines: !0,
1065
+ complete: (o) => {
1066
+ const i = [];
1067
+ for (const s of o.data) {
1068
+ const l = He(s, t), u = pt(l);
1069
+ u && i.push(u);
1070
+ }
1071
+ n(i);
1072
+ },
1073
+ error: (o) => r($("parseStructuralIntervalsCSV", o))
1074
+ });
1075
+ });
1076
+ }
1077
+ function Kt(e, t = z) {
1078
+ const n = /* @__PURE__ */ new Map();
1079
+ for (const r of e) {
1080
+ const o = r[t] != null ? String(r[t]).trim() : "";
1081
+ o && (n.has(o) || n.set(o, { holeId: o, points: [] }), n.get(o).points.push(r));
1082
+ }
1083
+ return Array.from(n.values());
1084
+ }
1085
+ function Jt(e, t = null) {
1086
+ return new Promise((n, r) => {
1087
+ Z.parse(e, {
1088
+ header: !0,
1089
+ dynamicTyping: !0,
1090
+ skipEmptyLines: !0,
1091
+ complete: (o) => {
1092
+ const i = o.data.map((u) => He(u, t)), s = Wt(i);
1093
+ if (!s) {
1094
+ r($(
1095
+ "parseStructuralCSV",
1096
+ new Error("Structural CSV requires either 'depth' (point) or 'from'/'to' (interval) columns")
1097
+ ));
1098
+ return;
1099
+ }
1100
+ const l = [];
1101
+ for (const u of i) {
1102
+ const a = s === "interval" ? pt(u) : ht(u);
1103
+ a && l.push(a);
1104
+ }
1105
+ n({ schema: s, rows: l });
1106
+ },
1107
+ error: (o) => r($("parseStructuralCSV", o))
1108
+ });
1109
+ });
1110
+ }
1111
+ function Qt(e) {
1112
+ return new Promise((t) => {
1113
+ Z.parse(e, {
1114
+ header: !0,
1115
+ dynamicTyping: !0,
1116
+ skipEmptyLines: !0,
1117
+ complete: (n) => {
1118
+ const r = /* @__PURE__ */ new Map();
1119
+ for (const i of n.data) {
1120
+ const s = ue(i), l = s[z] != null ? `${s[z]}`.trim() : "";
1121
+ if (!l) continue;
1122
+ const u = Number(s[B]), a = Number(s[R]);
1123
+ if (!Number.isFinite(u) || !Number.isFinite(a) || a <= u) continue;
1124
+ const c = (u + a) / 2, { [k]: m, [O]: d, ...f } = s, y = {
1125
+ ...f,
1126
+ [z]: l,
1127
+ [B]: u,
1128
+ [R]: a,
1129
+ [Ve]: c,
1130
+ [H]: c,
1131
+ // unified depth field for y-axis rendering
1132
+ _source: "assay"
1133
+ };
1134
+ r.has(l) || r.set(l, []), r.get(l).push(y);
1135
+ }
1136
+ const o = Array.from(r.entries()).map(([i, s]) => ({
1137
+ holeId: i,
1138
+ points: s.sort((l, u) => l[B] - u[B])
1139
+ }));
1140
+ t(o);
1141
+ }
1142
+ });
1143
+ });
1144
+ }
1145
+ async function Pr({ assayCsv: e, structuralCsv: t } = {}) {
1146
+ const [n, r] = await Promise.all([
1147
+ e ? Qt(e) : Promise.resolve([]),
1148
+ t ? Jt(t).then(
1149
+ ({ rows: i }) => Kt(i.map((s) => ({ ...s, _source: "structural" })))
1150
+ ) : Promise.resolve([])
1151
+ ]), o = new Map(n.map((i) => [i.holeId, { ...i, points: [...i.points] }]));
1152
+ for (const i of r) {
1153
+ const s = i.holeId;
1154
+ if (s)
1155
+ if (o.has(s)) {
1156
+ const l = o.get(s);
1157
+ o.set(s, { ...l, points: [...l.points, ...i.points || []] });
1158
+ } else
1159
+ o.set(s, i);
1160
+ }
1161
+ return { holes: Array.from(o.values()) };
1162
+ }
1163
+ function en(e, t) {
1164
+ if (!e || e.length === 0 || !Number.isFinite(t)) return null;
1165
+ const n = e.length;
1166
+ if (n === 1) {
1167
+ const b = e[0];
1168
+ return { x: Number(b.x), y: Number(b.y), z: Number(b.z), dx: 0, dy: 0, dz: -1 };
1169
+ }
1170
+ let r = -1;
1171
+ for (let b = 0; b < n - 1; b++) {
1172
+ const _ = Number(e[b].md), I = Number(e[b + 1].md);
1173
+ if (t >= _ && t <= I) {
1174
+ r = b;
1175
+ break;
1176
+ }
1177
+ }
1178
+ let o, i, s;
1179
+ if (r === -1) {
1180
+ t < Number(e[0].md) ? (o = e[0], i = e[1]) : (o = e[n - 2], i = e[n - 1]);
1181
+ const b = Number(o.md), I = Number(i.md) - b;
1182
+ s = I > 0 ? (t - b) / I : t < b ? 0 : 1;
1183
+ } else {
1184
+ o = e[r], i = e[r + 1];
1185
+ const b = Number(o.md), I = Number(i.md) - b;
1186
+ s = I > 0 ? (t - b) / I : 0;
1187
+ }
1188
+ const l = Number(o.x) + s * (Number(i.x) - Number(o.x)), u = Number(o.y) + s * (Number(i.y) - Number(o.y)), a = Number(o.z) + s * (Number(i.z) - Number(o.z));
1189
+ let c, m, d;
1190
+ const f = Number(o.azimuth), y = Number(o.dip), p = Number(i.azimuth), h = Number(i.dip);
1191
+ if (Number.isFinite(f) && Number.isFinite(y)) {
1192
+ const b = Number.isFinite(p) && Number.isFinite(h) ? f + s * (p - f) : f, _ = Number.isFinite(p) && Number.isFinite(h) ? y + s * (h - y) : y, I = b * Math.PI / 180, N = _ * Math.PI / 180;
1193
+ c = Math.cos(N) * Math.sin(I), m = Math.cos(N) * Math.cos(I), d = -Math.sin(N);
1194
+ } else {
1195
+ const b = Number(i.x) - Number(o.x), _ = Number(i.y) - Number(o.y), I = Number(i.z) - Number(o.z), N = Math.sqrt(b * b + _ * _ + I * I);
1196
+ if (N < 1e-10) return { x: l, y: u, z: a, dx: 0, dy: 0, dz: -1 };
1197
+ c = b / N, m = _ / N, d = I / N;
1198
+ }
1199
+ const g = Math.sqrt(c * c + m * m + d * d);
1200
+ return g < 1e-10 ? { x: l, y: u, z: a, dx: 0, dy: 0, dz: -1 } : { x: l, y: u, z: a, dx: c / g, dy: m / g, dz: d / g };
1201
+ }
1202
+ function tn(e, t, n, r = {}) {
1203
+ const { betaZeroAxis: o = "B", betaHandedness: i = 1 } = r, { dx: s, dy: l, dz: u } = n, a = [s, l, u];
1204
+ let c = [0, 0, 1];
1205
+ const m = a[0] * c[0] + a[1] * c[1] + a[2] * c[2];
1206
+ Math.abs(m) > 0.99 && (c = [0, 1, 0]);
1207
+ const d = [
1208
+ c[1] * a[2] - c[2] * a[1],
1209
+ c[2] * a[0] - c[0] * a[2],
1210
+ c[0] * a[1] - c[1] * a[0]
1211
+ ], f = Math.sqrt(d[0] ** 2 + d[1] ** 2 + d[2] ** 2), y = f > 1e-10 ? [d[0] / f, d[1] / f, d[2] / f] : [1, 0, 0], p = [
1212
+ a[1] * y[2] - a[2] * y[1],
1213
+ a[2] * y[0] - a[0] * y[2],
1214
+ a[0] * y[1] - a[1] * y[0]
1215
+ ], h = Math.sqrt(p[0] ** 2 + p[1] ** 2 + p[2] ** 2), g = h > 1e-10 ? [p[0] / h, p[1] / h, p[2] / h] : [0, 1, 0], b = o === "R" ? y : g, _ = t * Math.PI / 180 * i, I = Math.cos(_), N = Math.sin(_), P = b[0] * a[0] + b[1] * a[1] + b[2] * a[2], E = [
1216
+ a[1] * b[2] - a[2] * b[1],
1217
+ a[2] * b[0] - a[0] * b[2],
1218
+ a[0] * b[1] - a[1] * b[0]
1219
+ ], M = [
1220
+ b[0] * I + E[0] * N + a[0] * P * (1 - I),
1221
+ b[1] * I + E[1] * N + a[1] * P * (1 - I),
1222
+ b[2] * I + E[2] * N + a[2] * P * (1 - I)
1223
+ ], F = (90 - e) * Math.PI / 180, j = Math.cos(F), W = Math.sin(F), D = j * M[0] + W * a[0], G = j * M[1] + W * a[1], U = j * M[2] + W * a[2], S = Math.sqrt(D * D + G * G + U * U);
1224
+ return S < 1e-10 ? { nx: 0, ny: 0, nz: 1 } : { nx: D / S, ny: G / S, nz: U / S };
1225
+ }
1226
+ function nn(e, t, n = {}) {
1227
+ if (!(e != null && e.length) || !(t != null && t.length)) return [];
1228
+ const r = /* @__PURE__ */ new Map();
1229
+ for (const i of t) {
1230
+ const s = i.hole_id != null ? `${i.hole_id}`.trim().toLowerCase() : "";
1231
+ s && (r.has(s) || r.set(s, []), r.get(s).push(i));
1232
+ }
1233
+ for (const [, i] of r)
1234
+ i.sort((s, l) => Number(s.md) - Number(l.md));
1235
+ const o = [];
1236
+ for (const i of e) {
1237
+ const s = i.hole_id != null ? `${i.hole_id}`.trim().toLowerCase() : "";
1238
+ if (!s) continue;
1239
+ const l = r.get(s);
1240
+ if (!l || l.length === 0) continue;
1241
+ const u = i.depth != null ? Number(i.depth) : i.mid != null ? Number(i.mid) : null;
1242
+ if (!Number.isFinite(u)) continue;
1243
+ const a = en(l, u);
1244
+ if (!a) continue;
1245
+ const { x: c, y: m, z: d, dx: f, dy: y, dz: p } = a;
1246
+ let h, g, b;
1247
+ const _ = i.alpha != null ? Number(i.alpha) : null, I = i.beta != null ? Number(i.beta) : null;
1248
+ if (Number.isFinite(_)) {
1249
+ const N = Number.isFinite(I) ? I : 0, P = tn(_, N, { dx: f, dy: y, dz: p }, n);
1250
+ h = P.nx, g = P.ny, b = P.nz;
1251
+ } else {
1252
+ const N = i.dip != null ? Number(i.dip) : null, P = i.azimuth != null ? Number(i.azimuth) : null;
1253
+ if (!Number.isFinite(N) || !Number.isFinite(P)) continue;
1254
+ const E = N * Math.PI / 180, M = P * Math.PI / 180;
1255
+ h = Math.sin(M) * Math.sin(E), g = Math.cos(M) * Math.sin(E), b = Math.cos(E);
1256
+ }
1257
+ o.push({ ...i, x: c, y: m, z: d, nx: h, ny: g, nz: b });
1258
+ }
1259
+ return o;
1260
+ }
1261
+ const We = "#8b1e3f", rn = "#a8324f", on = "#6b7280", sn = { l: 4, r: 4, t: 4, b: 4 }, Ke = 10, Je = 12;
1262
+ function Qe(e) {
1263
+ return e ? typeof e == "string" ? { text: e } : e : {};
1264
+ }
1265
+ function yt(e = {}) {
1266
+ const t = Qe(e.xaxis && e.xaxis.title), n = Qe(e.yaxis && e.yaxis.title);
1267
+ return {
1268
+ ...e,
1269
+ margin: sn,
1270
+ autosize: !0,
1271
+ width: void 0,
1272
+ xaxis: {
1273
+ ...e.xaxis || {},
1274
+ tickfont: {
1275
+ ...e.xaxis && e.xaxis.tickfont || {},
1276
+ size: Ke
1277
+ },
1278
+ title: {
1279
+ ...t,
1280
+ font: { ...t.font || {}, size: Je }
1281
+ }
1282
+ },
1283
+ yaxis: {
1284
+ ...e.yaxis || {},
1285
+ tickfont: {
1286
+ ...e.yaxis && e.yaxis.tickfont || {},
1287
+ size: Ke
1288
+ },
1289
+ title: {
1290
+ ...n,
1291
+ font: { ...n.font || {}, size: Je }
1292
+ }
1293
+ }
1294
+ };
1295
+ }
1296
+ function an(e, t) {
863
1297
  var r;
864
1298
  if (!e || !t) return !1;
865
1299
  const n = e.points || [];
866
1300
  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() !== ""))
1301
+ const i = (r = n[o]) == null ? void 0 : r[t];
1302
+ if (i != null && (typeof i == "number" && Number.isFinite(i) || typeof i == "string" && i.trim() !== ""))
869
1303
  return !0;
870
1304
  }
871
1305
  return !1;
872
1306
  }
873
- function Et(e, t, n) {
1307
+ function ln(e, t, n) {
874
1308
  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({
1309
+ const r = (e == null ? void 0 : e.points) || [], o = [], i = /* @__PURE__ */ new Set();
1310
+ return r.forEach((s) => {
1311
+ let l = Number(
1312
+ s.from ?? s.samp_from ?? s.sample_from ?? s.fromdepth ?? s.from_depth ?? s.depth_from
1313
+ ), u = Number(
1314
+ s.to ?? s.samp_to ?? s.sample_to ?? s.todepth ?? s.to_depth ?? s.depth_to
1315
+ );
1316
+ if (!Number.isFinite(l) || !Number.isFinite(u)) {
1317
+ const f = Number(s.depth ?? s.md);
1318
+ Number.isFinite(f) && (l = f, u = f);
1319
+ }
1320
+ const a = s == null ? void 0 : s[t];
1321
+ if (!Number.isFinite(l) || !Number.isFinite(u) || u < l || a == null || a === "" || n && typeof a == "string" && /^(nan|null|none)$/i.test(a.trim())) return;
1322
+ const c = `${t}:${l}-${u}`;
1323
+ if (i.has(c)) return;
1324
+ i.add(c);
1325
+ const m = (l + u) / 2, d = n ? a : Number(a);
1326
+ !n && !Number.isFinite(d) || o.push({
888
1327
  z: m,
889
- val: f,
890
- from: a,
891
- to: c,
892
- errorPlus: c - m,
893
- errorMinus: m - a
1328
+ val: d,
1329
+ from: l,
1330
+ to: u,
1331
+ errorPlus: u - m,
1332
+ errorMinus: m - l
894
1333
  });
895
- }), o.sort((i, a) => a.z - i.z);
1334
+ }), o.sort((s, l) => l.z - s.z);
896
1335
  }
897
- function vt(e, t) {
1336
+ function cn(e, t) {
898
1337
  if (!e.length) return { data: [], layout: {} };
899
- const n = [...e].sort((c, l) => l.z - c.z), r = [];
1338
+ const n = [...e].sort((c, m) => m.z - c.z), r = [];
900
1339
  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" });
1340
+ const m = n[c], d = n[c + 1], f = m.z, y = d ? d.z : m.z - 20;
1341
+ if (y === f) continue;
1342
+ const p = m.val == null ? "" : String(m.val).trim();
1343
+ !p || /^(nan|null|none)$/i.test(p) || r.push({ y0: f, y1: y, category: p, fromVal: m.from, toVal: m.to });
903
1344
  }
904
- const o = ["#8b1e3f", "#a8324f", "#b84c68", "#d16587", "#e07ba0", "#f091b6", "#f7a7c8", "#fbcfe8"], s = r.map((c, l) => ({
1345
+ const o = ["#4e79a7", "#f28e2b", "#e15759", "#76b7b2", "#59a14f", "#edc948", "#b07aa1", "#ff9da7", "#9c755f", "#bab0ac", "#d4a6c8", "#86bcb6"], i = [...new Set(r.map((c) => c.category))], s = Object.fromEntries(
1346
+ i.map((c, m) => [c, o[m % o.length]])
1347
+ ), l = r.map((c) => ({
905
1348
  type: "rect",
906
1349
  xref: "x",
907
1350
  yref: "y",
@@ -909,7 +1352,7 @@ function vt(e, t) {
909
1352
  x1: 1,
910
1353
  y0: c.y0,
911
1354
  y1: c.y1,
912
- fillcolor: o[l % o.length],
1355
+ fillcolor: s[c.category],
913
1356
  line: { width: 0 }
914
1357
  }));
915
1358
  return { data: [{
@@ -920,258 +1363,549 @@ function vt(e, t) {
920
1363
  textposition: "middle center",
921
1364
  showlegend: !1,
922
1365
  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 },
1366
+ customdata: r.map((c) => [Math.min(c.fromVal, c.toVal), Math.max(c.fromVal, c.toVal)]),
1367
+ hovertemplate: "Category: %{text}<br>from: %{customdata[0]} to: %{customdata[1]}<extra></extra>"
1368
+ }], layout: yt({
928
1369
  xaxis: { range: [0, 1], visible: !1, fixedrange: !0 },
929
1370
  yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
930
- shapes: s,
1371
+ shapes: l,
931
1372
  showlegend: !1,
932
1373
  title: t || void 0
933
- } };
1374
+ }) };
934
1375
  }
935
- function Dt(e, t, n) {
1376
+ function un(e, t, n) {
936
1377
  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 = {
1378
+ const r = n === "bar", o = n === "markers", i = n === "line", s = {
1379
+ x: e.map((c) => c.val),
1380
+ y: e.map((c) => c.z),
1381
+ hovertemplate: `${t}: %{x}<br>from: %{customdata[0]} to: %{customdata[1]}<extra></extra>`,
1382
+ customdata: e.map((c) => [Math.min(c.from, c.to), Math.max(c.from, c.to)])
1383
+ }, l = {
943
1384
  type: "data",
944
1385
  symmetric: !1,
945
- array: e.map((u) => u.errorPlus),
946
- arrayminus: e.map((u) => u.errorMinus),
1386
+ array: e.map((c) => c.errorPlus),
1387
+ arrayminus: e.map((c) => c.errorMinus),
947
1388
  thickness: 1.5,
948
1389
  width: 2,
949
- color: It
1390
+ color: on
950
1391
  };
951
1392
  return { data: [r ? {
952
- ...i,
1393
+ ...s,
953
1394
  type: "bar",
954
1395
  orientation: "h",
955
- marker: { color: He },
956
- error_y: a
1396
+ marker: { color: We },
1397
+ error_y: l
957
1398
  } : {
958
- ...i,
1399
+ ...s,
959
1400
  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 },
1401
+ mode: o ? "markers" : i ? "lines" : "lines+markers",
1402
+ line: { color: We, width: 2 },
1403
+ marker: { size: 7, color: rn },
1404
+ error_y: i ? void 0 : l
1405
+ }], layout: yt({
967
1406
  xaxis: { title: t, zeroline: !1 },
968
1407
  yaxis: { title: "Depth (m)", autorange: "reversed", zeroline: !1 },
969
1408
  barmode: "overlay",
970
1409
  showlegend: !1
1410
+ }) };
1411
+ }
1412
+ function mn({ points: e, isCategorical: t, property: n, chartType: r }) {
1413
+ return !e || !e.length || !n ? { data: [], layout: {} } : t || r === "categorical" ? cn(e, n) : un(e, n, r);
1414
+ }
1415
+ const bt = [
1416
+ "#0f172a",
1417
+ "#1e3a5f",
1418
+ "#7c3aed",
1419
+ "#dc2626",
1420
+ "#16a34a",
1421
+ "#d97706",
1422
+ "#0ea5e9",
1423
+ "#db2777",
1424
+ "#65a30d",
1425
+ "#9333ea"
1426
+ ], dn = { l: 4, r: 4, t: 4, b: 4 }, et = 10, tt = 12;
1427
+ function gt(e = {}) {
1428
+ return {
1429
+ ...e,
1430
+ margin: dn,
1431
+ autosize: !0,
1432
+ width: void 0,
1433
+ xaxis: {
1434
+ ...e.xaxis || {},
1435
+ tickfont: {
1436
+ ...e.xaxis && e.xaxis.tickfont || {},
1437
+ size: et
1438
+ },
1439
+ title: {
1440
+ ...e.xaxis && e.xaxis.title || {},
1441
+ font: {
1442
+ ...e.xaxis && e.xaxis.title && e.xaxis.title.font || {},
1443
+ size: tt
1444
+ }
1445
+ }
1446
+ },
1447
+ yaxis: {
1448
+ ...e.yaxis || {},
1449
+ tickfont: {
1450
+ ...e.yaxis && e.yaxis.tickfont || {},
1451
+ size: et
1452
+ },
1453
+ title: {
1454
+ ...e.yaxis && e.yaxis.title || {},
1455
+ font: {
1456
+ ...e.yaxis && e.yaxis.title && e.yaxis.title.font || {},
1457
+ size: tt
1458
+ }
1459
+ }
1460
+ }
1461
+ };
1462
+ }
1463
+ function fn(e, {
1464
+ tailScale: t = 5,
1465
+ colorBy: n = null,
1466
+ palette: r = bt,
1467
+ depthCol: o = H,
1468
+ dipCol: i = k,
1469
+ azCol: s = O
1470
+ } = {}) {
1471
+ const l = e.filter(
1472
+ (y) => y[o] != null && y[i] != null && y[s] != null
1473
+ );
1474
+ if (!l.length)
1475
+ return { data: [], layout: {} };
1476
+ const u = {};
1477
+ n && [...new Set(l.map((p) => p[n]).filter((p) => p != null))].sort().forEach((p, h) => {
1478
+ u[p] = r[h % r.length];
1479
+ });
1480
+ const a = /* @__PURE__ */ new Map(), c = [];
1481
+ for (const y of l) {
1482
+ const p = Number(y[o]), h = Number(y[i]), g = Number(y[s]), b = n ? y[n] ?? "_default" : "_default", _ = n ? u[b] ?? "#0f172a" : "#0f172a";
1483
+ a.has(b) || a.set(b, { xs: [], ys: [], dips: [], azs: [], color: _ });
1484
+ const I = a.get(b);
1485
+ I.xs.push(h), I.ys.push(p), I.dips.push(h), I.azs.push(g);
1486
+ const N = g * Math.PI / 180, P = t * (Math.abs(h) / 90), E = Math.sin(N) * P, M = Math.cos(N) * P;
1487
+ c.push({
1488
+ type: "line",
1489
+ x0: h,
1490
+ y0: p,
1491
+ x1: h + E,
1492
+ y1: p + M,
1493
+ line: { color: _, width: 2 }
1494
+ });
1495
+ }
1496
+ const m = [], d = n && a.size > 1;
1497
+ for (const [y, p] of a.entries())
1498
+ m.push({
1499
+ type: "scatter",
1500
+ x: p.xs,
1501
+ y: p.ys,
1502
+ mode: "markers",
1503
+ name: y !== "_default" ? String(y) : void 0,
1504
+ marker: { size: 8, color: p.color },
1505
+ showlegend: d && y !== "_default",
1506
+ customdata: p.dips.map((h, g) => [h, p.azs[g]]),
1507
+ hovertemplate: "Depth: %{y}<br>Dip: %{customdata[0]}<br>Az: %{customdata[1]}<extra></extra>"
1508
+ });
1509
+ return { data: m, layout: {
1510
+ shapes: c,
1511
+ height: 400,
1512
+ margin: { l: 40, r: 10, t: 10, b: 40 },
1513
+ xaxis: {
1514
+ title: "Dip (°)",
1515
+ autorange: !0,
1516
+ fixedrange: !0,
1517
+ zeroline: !0,
1518
+ tickvals: [-90, -60, -30, 0, 30, 60, 90]
1519
+ },
1520
+ yaxis: { title: "Depth (m)", autorange: "reversed" },
1521
+ showlegend: !!d
971
1522
  } };
972
1523
  }
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);
1524
+ function Dr(e, {
1525
+ labelCol: t = "structure_type",
1526
+ palette: n = bt,
1527
+ fromCol: r = B,
1528
+ toCol: o = R
1529
+ } = {}) {
1530
+ const i = e.filter((m) => m[r] != null && m[o] != null && Number(m[o]) > Number(m[r])).filter((m) => {
1531
+ const d = m[t];
1532
+ if (d == null) return !1;
1533
+ const f = String(d).trim();
1534
+ return f !== "" && !/^(nan|null|none)$/i.test(f);
1535
+ }).map((m) => ({ from: Number(m[r]), to: Number(m[o]), label: String(m[t]).trim() })).sort((m, d) => m.from - d.from);
1536
+ if (!i.length)
1537
+ return { data: [], layout: {} };
1538
+ const s = [], l = [], u = [];
1539
+ return i.forEach((m, d) => {
1540
+ s.push({
1541
+ type: "rect",
1542
+ xref: "x",
1543
+ yref: "y",
1544
+ x0: 0,
1545
+ x1: 1,
1546
+ y0: m.from,
1547
+ y1: m.to,
1548
+ fillcolor: n[d % n.length],
1549
+ line: { width: 0 }
1550
+ }), l.push(0.5 * (m.from + m.to)), u.push(m.label);
1551
+ }), { data: [{
1552
+ type: "scatter",
1553
+ x: Array(u.length).fill(0.5),
1554
+ y: l,
1555
+ mode: "text",
1556
+ text: u,
1557
+ textposition: "middle center",
1558
+ showlegend: !1,
1559
+ hoverinfo: "text"
1560
+ }], layout: gt({
1561
+ shapes: s,
1562
+ height: 400,
1563
+ xaxis: { range: [0, 1], visible: !1, fixedrange: !0 },
1564
+ yaxis: { title: "Depth (m)", autorange: "reversed" },
1565
+ showlegend: !1
1566
+ }) };
975
1567
  }
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 = {
1568
+ function hn(e, t) {
1569
+ if (!e) return "";
1570
+ const n = String(e).trim().split(/\s+/), r = [];
1571
+ let o = "";
1572
+ for (const i of n)
1573
+ o && o.length + 1 + i.length > t ? (r.push(o), o = i) : o = o ? `${o} ${i}` : i;
1574
+ return o && r.push(o), r.join("<br>");
1575
+ }
1576
+ function pn(e, {
1577
+ commentCol: t = "comments",
1578
+ fromCol: n = B,
1579
+ toCol: r = R,
1580
+ bgColor: o = "#f1f5f9",
1581
+ borderColor: i = "#cbd5e1",
1582
+ textColor: s = "#1e293b",
1583
+ charsPerLine: l = 18
1584
+ } = {}) {
1585
+ const u = e.filter((h) => h[n] != null && h[r] != null && Number(h[r]) > Number(h[n])).map((h) => {
1586
+ const g = h[t], b = g != null && String(g).trim() !== "" && String(g) !== "null" ? String(g).trim() : "";
1587
+ return { from: Number(h[n]), to: Number(h[r]), comment: b };
1588
+ }).sort((h, g) => h.from - g.from);
1589
+ if (!u.length)
1590
+ return { data: [], layout: {} };
1591
+ const a = [], c = [], m = [], d = [], f = [];
1592
+ for (const h of u) {
1593
+ const g = 0.5 * (h.from + h.to), b = !!h.comment;
1594
+ a.push({
1595
+ type: "rect",
1596
+ xref: "x",
1597
+ yref: "y",
1598
+ x0: 0,
1599
+ x1: 1,
1600
+ y0: h.from,
1601
+ y1: h.to,
1602
+ fillcolor: b ? o : "rgba(0,0,0,0)",
1603
+ line: { color: i, width: 1 }
1604
+ }), b && (c.push(0.5), m.push(g), d.push(hn(h.comment, l)), f.push(`${h.from}–${h.to} m: ${h.comment}`));
1605
+ }
1606
+ return { data: c.length ? [{
1607
+ type: "scatter",
1608
+ x: c,
1609
+ y: m,
1610
+ mode: "text",
1611
+ text: d,
1612
+ textposition: "middle center",
1613
+ textfont: { color: s, size: 10 },
1614
+ hovertext: f,
1615
+ hoverinfo: "text",
1616
+ showlegend: !1
1617
+ }] : [], layout: gt({
1618
+ shapes: a,
1619
+ height: 400,
1620
+ xaxis: { range: [0, 1], visible: !1, fixedrange: !0 },
1621
+ yaxis: { title: "Depth (m)", autorange: "reversed" },
1622
+ showlegend: !1
1623
+ }) };
1624
+ }
1625
+ function Lr(e, {
1626
+ symbolSize: t = 10,
1627
+ xCol: n = "easting",
1628
+ yCol: r = "northing"
1629
+ } = {}) {
1630
+ const o = e[n] != null ? Number(e[n]) : null, i = e[r] != null ? Number(e[r]) : null, s = e[k] != null ? Number(e[k]) : null, l = e[O] != null ? Number(e[O]) : null;
1631
+ if (o === null || i === null || s === null || l === null) return null;
1632
+ const u = (l - 90 + 360) % 360, a = u * Math.PI / 180, c = l * Math.PI / 180, m = t * Math.sin(a), d = t * Math.cos(a), f = t * 0.4 * (s / 90), y = f * Math.sin(c), p = f * Math.cos(c);
1633
+ return {
1634
+ strike: u,
1635
+ dipValue: s,
1636
+ x: o,
1637
+ y: i,
1638
+ strikeX0: o - m,
1639
+ strikeY0: i - d,
1640
+ strikeX1: o + m,
1641
+ strikeY1: i + d,
1642
+ tickX1: o + y,
1643
+ tickY1: i + p
1644
+ };
1645
+ }
1646
+ const _t = "markers+line";
1647
+ function yn(e, t) {
1648
+ var r;
1649
+ const n = we(e);
1650
+ return n.some((o) => o.value === t) ? t : ((r = n[0]) == null ? void 0 : r.value) || _t;
1651
+ }
1652
+ function Tr({ config: e, graph: t, holeOptions: n = [], propertyOptions: r = [], onConfigChange: o }) {
1653
+ const i = ot(null), s = t == null ? void 0 : t.hole, l = (t == null ? void 0 : t.points) || [], u = (e == null ? void 0 : e.property) || "", a = (e == null ? void 0 : e.chartType) || _t, c = (e == null ? void 0 : e.holeId) || "", m = (t == null ? void 0 : t.displayType) || (t != null && t.isComment ? pe : t != null && t.isCategorical ? _e : ye), d = we(m), f = yn(m, a), [y, p] = K("");
1654
+ return oe(() => {
1655
+ const h = m === pe, g = m === Oe;
1656
+ if (!s || !u || !h && !g && l.length === 0) return;
1657
+ const b = i.current;
1658
+ if (!b) return;
1659
+ let _;
1660
+ try {
1661
+ h ? _ = pn(l, { commentCol: u, fromCol: "from", toCol: "to" }) : g ? _ = fn(l) : _ = mn({
1662
+ points: l,
1663
+ isCategorical: m === _e,
1664
+ property: u,
1665
+ chartType: f
1666
+ });
1667
+ } catch (N) {
1668
+ console.error("Plot build error", N), p((N == null ? void 0 : N.message) || "Plot build error");
1669
+ return;
1670
+ }
1671
+ if ((!(_ != null && _.data) || _.data.length === 0) && !h)
1672
+ return;
1673
+ const I = {
995
1674
  displayModeBar: !0,
996
1675
  responsive: !0,
997
1676
  useResizeHandler: !0,
998
1677
  modeBarButtonsToRemove: ["select2d", "lasso2d", "zoom2d", "zoomIn2d", "zoomOut2d", "autoScale2d"]
999
1678
  };
1000
1679
  try {
1001
- y(""), me.react(h, A, O, F), requestAnimationFrame(() => {
1002
- h && h.parentElement && me.Plots.resize(h);
1680
+ p(""), xe.react(b, _.data, _.layout, I), requestAnimationFrame(() => {
1681
+ b && b.parentElement && xe.Plots.resize(b);
1003
1682
  });
1004
- } catch (D) {
1005
- console.error("Plot render error", D), y((D == null ? void 0 : D.message) || "Plot render error");
1683
+ } catch (N) {
1684
+ console.error("Plot render error", N), p((N == null ? void 0 : N.message) || "Plot render error");
1006
1685
  }
1007
1686
  return () => {
1008
- if (h)
1687
+ if (b)
1009
1688
  try {
1010
- me.purge(h);
1011
- } catch (D) {
1012
- console.warn("Plot purge error", D);
1689
+ xe.purge(b);
1690
+ } catch (N) {
1691
+ console.warn("Plot purge error", N);
1013
1692
  }
1014
1693
  };
1015
- }, [i, c, d, m, a]), re(() => {
1016
- const h = s.current;
1694
+ }, [s, u, f, m, l]), oe(() => {
1695
+ const h = i.current;
1017
1696
  if (!h || typeof ResizeObserver > "u") return;
1018
- const A = new ResizeObserver(() => {
1697
+ const g = new ResizeObserver(() => {
1019
1698
  try {
1020
- h && h.data && me.Plots.resize(h);
1021
- } catch (O) {
1022
- console.warn("Plot resize error", O);
1699
+ h && h.data && xe.Plots.resize(h);
1700
+ } catch (b) {
1701
+ console.warn("Plot resize error", b);
1023
1702
  }
1024
1703
  });
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: [
1704
+ return g.observe(h), () => g.disconnect();
1705
+ }, []), !s || !u ? /* @__PURE__ */ q("div", { className: "plot-card empty", children: /* @__PURE__ */ q("div", { className: "placeholder", children: e != null && e.holeId ? t != null && t.loading ? `Loading ${e.holeId}...` : "Select a property" : "Loading demo data..." }) }) : m !== pe && m !== Oe && l.length === 0 ? /* @__PURE__ */ q("div", { className: "plot-card empty", children: /* @__PURE__ */ q("div", { className: "placeholder", children: "No data" }) }) : y ? /* @__PURE__ */ q("div", { className: "plot-card empty", children: /* @__PURE__ */ Ne("div", { className: "placeholder", children: [
1030
1706
  "Plot error: ",
1031
- p
1032
- ] }) }) : /* @__PURE__ */ ae("div", { className: "plot-card", children: [
1033
- /* @__PURE__ */ k("div", { className: "plot-title", children: /* @__PURE__ */ k(
1707
+ y
1708
+ ] }) }) : /* @__PURE__ */ Ne("div", { className: "plot-card", children: [
1709
+ /* @__PURE__ */ q("div", { className: "plot-title", children: /* @__PURE__ */ q(
1034
1710
  "select",
1035
1711
  {
1036
1712
  className: "plot-select",
1037
- value: u,
1713
+ value: c,
1038
1714
  onChange: (h) => o && o({ holeId: h.target.value }),
1039
1715
  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);
1716
+ const g = typeof h == "string" ? h : h.holeId, b = typeof h == "string" ? h : h.label || h.holeId;
1717
+ return /* @__PURE__ */ q("option", { value: g, children: b }, g);
1042
1718
  })
1043
1719
  }
1044
1720
  ) }),
1045
- /* @__PURE__ */ ae("div", { className: "plot-controls column", children: [
1046
- r.length > 0 && /* @__PURE__ */ k(
1721
+ /* @__PURE__ */ Ne("div", { className: "plot-controls column", children: [
1722
+ r.length > 0 && /* @__PURE__ */ q(
1047
1723
  "select",
1048
1724
  {
1049
1725
  className: "plot-select",
1050
- value: c,
1726
+ value: u,
1051
1727
  onChange: (h) => o && o({ property: h.target.value }),
1052
- children: r.map((h) => /* @__PURE__ */ k("option", { value: h, children: h }, h))
1728
+ children: r.map((h) => /* @__PURE__ */ q("option", { value: h, children: h }, h))
1053
1729
  }
1054
1730
  ),
1055
- /* @__PURE__ */ k(
1731
+ d.length > 1 && /* @__PURE__ */ q(
1056
1732
  "select",
1057
1733
  {
1058
1734
  className: "plot-select",
1059
- value: d,
1735
+ value: f,
1060
1736
  onChange: (h) => o && o({ chartType: h.target.value }),
1061
- children: f.map((h) => /* @__PURE__ */ k("option", { value: h.value, children: h.label }, h.value))
1737
+ children: d.map((h) => /* @__PURE__ */ q("option", { value: h.value, children: h.label }, h.value))
1062
1738
  }
1063
1739
  )
1064
1740
  ] }),
1065
- /* @__PURE__ */ k("div", { className: "plotly-chart", ref: s })
1741
+ /* @__PURE__ */ q("div", { className: "plotly-chart", ref: i })
1066
1742
  ] });
1067
1743
  }
1068
- function kn({
1744
+ function nt(e, t) {
1745
+ if (!(t != null && t.length)) return e;
1746
+ const n = new Map(e.map((r) => [r.id || r.holeId, { ...r }]));
1747
+ for (const r of t) {
1748
+ const o = r.id || r.holeId;
1749
+ if (o)
1750
+ if (n.has(o)) {
1751
+ const i = n.get(o);
1752
+ n.set(o, { ...i, points: [...i.points || [], ...r.points || []] });
1753
+ } else
1754
+ n.set(o, r);
1755
+ }
1756
+ return Array.from(n.values());
1757
+ }
1758
+ function bn(e, t) {
1759
+ if (!e || !t) return [];
1760
+ const n = /* @__PURE__ */ new Set(), r = [];
1761
+ for (const o of e.points || []) {
1762
+ const i = Number(o.from ?? o.samp_from ?? o.depth_from ?? o.from_depth), s = Number(o.to ?? o.samp_to ?? o.depth_to ?? o.to_depth);
1763
+ if (!Number.isFinite(i) || !Number.isFinite(s) || s <= i) continue;
1764
+ const l = `${i}-${s}`;
1765
+ n.has(l) || (n.add(l), r.push({ from: i, to: s, [t]: o[t] ?? "" }));
1766
+ }
1767
+ return r;
1768
+ }
1769
+ function Fr({
1069
1770
  initialFocusedHoleId: e = "",
1070
1771
  sourceFile: t = null,
1071
- plotCount: n = 4
1772
+ extraHoles: n = [],
1773
+ plotCount: r = 4
1072
1774
  } = {}) {
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,
1775
+ const [o, i] = K([]), [s, l] = K([]), [u, a] = K([]), [c, m] = K([]), [d, f] = K([]), [y, p] = K({}), [h, g] = K(""), [b, _] = K([]), [I, N] = K(""), [P, E] = K(e || ""), [M, F] = K([]), j = ot(null);
1776
+ oe(() => {
1777
+ !t || j.current === t || (j.current = t, $t(t).then((S) => {
1778
+ if (!S) return;
1779
+ const C = Array.from(new Map(S.map((v) => [v.holeId, v])).values());
1780
+ l(C), _(dt({
1781
+ holeIds: C.map((v) => v.holeId),
1782
+ focusedHoleId: P,
1783
+ plotCount: r,
1082
1784
  defaultProp: "",
1083
- categoricalProps: l,
1785
+ categoricalProps: c,
1786
+ commentProps: d,
1084
1787
  numericDefaultChartType: "markers+line"
1085
1788
  }));
1086
- }).catch((z) => {
1087
- console.info("Assay metadata load skipped:", z.message);
1789
+ }).catch((S) => {
1790
+ console.info("Assay metadata load skipped:", S.message);
1791
+ }));
1792
+ }, [t, P, r, c, d]), oe(() => {
1793
+ if (!(n != null && n.length)) return;
1794
+ const S = n.map((C) => ({ holeId: C.id || C.holeId })).filter((C) => C.holeId);
1795
+ l((C) => {
1796
+ const v = new Set(C.map((A) => A.holeId)), L = S.filter((A) => !v.has(A.holeId));
1797
+ return L.length ? [...C, ...L] : C;
1088
1798
  });
1089
- }, [t, s.length, A, n, l]), re(() => {
1090
- h((z) => z && z.startsWith("Loading assays for hole") ? z : "");
1091
- }, [d]), re(() => {
1799
+ }, [n]), oe(() => {
1800
+ N((S) => S && S.startsWith("Loading data for hole") ? S : "");
1801
+ }, [b]), oe(() => {
1092
1802
  if (!s.length) {
1093
- p([]);
1803
+ _([]);
1094
1804
  return;
1095
1805
  }
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,
1806
+ const S = mt(s.map((C) => C.holeId), P);
1807
+ _((C) => Array.from({ length: r }).map((L, A) => {
1808
+ var X;
1809
+ const V = C[A] || {}, w = s.some((le) => le.holeId === V.holeId) ? V.holeId : S[A] || ((X = s[A]) == null ? void 0 : X.holeId) || "", T = V.property || h, Y = Me({
1810
+ property: T,
1811
+ chartType: V.chartType,
1812
+ categoricalProps: c,
1813
+ commentProps: d,
1103
1814
  numericDefaultChartType: "markers+line"
1104
1815
  });
1105
- return { holeId: L, property: v, chartType: T };
1816
+ return { holeId: w, property: T, chartType: Y };
1106
1817
  }));
1107
- }, [s, A, m, l, n]), re(() => {
1818
+ }, [s, P, h, c, d, r]), oe(() => {
1108
1819
  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,
1820
+ b.map((C) => C.holeId).filter(Boolean).forEach((C) => {
1821
+ const v = o.some((A) => (A.id || A.holeId) === C), L = M.includes(C);
1822
+ v || L || (F((A) => [...A, C]), Ht(t, C).then((A) => {
1823
+ F((V) => V.filter((w) => w !== C)), A && i((V) => {
1824
+ const w = nt(
1825
+ [...V.filter((Y) => (Y.id || Y.holeId) !== C), A],
1826
+ n
1827
+ ), T = Ie(w);
1828
+ return a(T.numericProps), m(T.categoricalProps), f(T.commentProps), p(T.columnMeta), !h && T.defaultProp && (g(T.defaultProp), _((Y) => Y.map((X) => ({
1829
+ ...X,
1830
+ property: X.property || T.defaultProp,
1831
+ chartType: Me({
1832
+ property: X.property || T.defaultProp,
1833
+ chartType: X.chartType,
1834
+ categoricalProps: T.categoricalProps,
1835
+ commentProps: T.commentProps,
1121
1836
  numericDefaultChartType: "markers+line"
1122
1837
  })
1123
- })))), L;
1838
+ })))), w;
1124
1839
  });
1125
- }).catch((_) => {
1126
- console.error(_), D((M) => M.filter((L) => L !== C)), h(_.message || `Error loading hole ${C}`);
1840
+ }).catch((A) => {
1841
+ console.error(A), F((V) => V.filter((w) => w !== C)), N(A.message || `Error loading hole ${C}`);
1127
1842
  }));
1128
1843
  });
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)),
1844
+ }, [b, t, o, M, h, n]), oe(() => {
1845
+ n != null && n.length && i((S) => {
1846
+ if (!S.length) {
1847
+ const L = Ie(n);
1848
+ return a(L.numericProps), m(L.categoricalProps), f(L.commentProps), p(L.columnMeta), !h && L.defaultProp && g(L.defaultProp), n;
1849
+ }
1850
+ const C = nt(S, n), v = Ie(C);
1851
+ return a(v.numericProps), m(v.categoricalProps), f(v.commentProps), p(v.columnMeta), !h && v.defaultProp && g(v.defaultProp), C;
1852
+ });
1853
+ }, [n]);
1854
+ const W = ve(
1855
+ () => [...u, ...c, ...d],
1856
+ [u, c, d]
1857
+ ), D = ve(
1858
+ () => s.map((S) => ({ holeId: S.holeId, label: S.holeId })).sort((S, C) => S.label.localeCompare(C.label)),
1132
1859
  [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({
1860
+ ), G = ve(() => {
1861
+ const S = [...u, ...c, ...d];
1862
+ return Array.from({ length: r }).map((C, v) => {
1863
+ const L = b[v] || {}, A = o.find((de) => (de.id || de.holeId) === L.holeId) || null, V = A ? S.filter((de) => an(A, de)) : S;
1864
+ let w = L.property || h;
1865
+ A && !V.includes(w) && (w = V[0] || w);
1866
+ const T = d.includes(w), Y = !T && c.includes(w), X = !T && !Y && w === "dip", le = T ? "comment" : X ? "tadpole" : Y ? "categorical" : "numeric", be = X ? "tadpole" : L.chartType || (T ? "comment" : Y ? "categorical" : "markers+line"), me = L.holeId || (A == null ? void 0 : A.id) || (A == null ? void 0 : A.holeId) || "", Ee = X ? (A == null ? void 0 : A.points) || [] : T ? bn(A, w) : ln(A, w, Y);
1867
+ return {
1868
+ config: { holeId: me, property: w, chartType: be },
1869
+ hole: A,
1870
+ loading: M.includes(L.holeId),
1871
+ isCategorical: Y,
1872
+ isComment: T,
1873
+ isTadpole: X,
1874
+ displayType: le,
1875
+ points: Ee,
1876
+ propertyOptions: V,
1877
+ label: me
1878
+ };
1879
+ });
1880
+ }, [b, o, h, c, d, M, r, u]), U = (S, C) => {
1881
+ _((v) => {
1882
+ const L = [...v], V = { ...L[S] || {}, ...C };
1883
+ return C.property && (V.chartType = Me({
1153
1884
  property: C.property,
1154
- chartType: M.chartType,
1155
- categoricalProps: l,
1885
+ chartType: V.chartType,
1886
+ categoricalProps: c,
1887
+ commentProps: d,
1156
1888
  numericDefaultChartType: "markers+line"
1157
- })), b[z] = M, b;
1889
+ })), L[S] = V, L;
1158
1890
  });
1159
1891
  };
1160
1892
  return {
1161
- error: y,
1162
- focusedHoleId: A,
1163
- setFocusedHoleId: O,
1164
- setError: h,
1893
+ error: I,
1894
+ focusedHoleId: P,
1895
+ setFocusedHoleId: E,
1896
+ setError: N,
1165
1897
  holeCount: s.length,
1166
- numericProps: a,
1167
- categoricalProps: l,
1168
- propertyOptions: R,
1169
- labeledHoleOptions: w,
1170
- traceGraphs: I,
1171
- handleConfigChange: N
1898
+ numericProps: u,
1899
+ categoricalProps: c,
1900
+ commentProps: d,
1901
+ columnMeta: y,
1902
+ propertyOptions: W,
1903
+ labeledHoleOptions: D,
1904
+ traceGraphs: G,
1905
+ handleConfigChange: U
1172
1906
  };
1173
1907
  }
1174
- const Ft = [
1908
+ const gn = [
1175
1909
  "#313695",
1176
1910
  "#4575b4",
1177
1911
  "#74add1",
@@ -1183,8 +1917,8 @@ const Ft = [
1183
1917
  "#d73027",
1184
1918
  "#a50026"
1185
1919
  ];
1186
- function St(e = [], t = Ft) {
1187
- const n = e.filter((l) => Number.isFinite(l));
1920
+ function _n(e = [], t = gn) {
1921
+ const n = e.filter((a) => Number.isFinite(a));
1188
1922
  if (!n.length)
1189
1923
  return {
1190
1924
  min: null,
@@ -1193,44 +1927,44 @@ function St(e = [], t = Ft) {
1193
1927
  bins: [],
1194
1928
  colors: t
1195
1929
  };
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) => ({
1930
+ const r = n.slice().sort((a, c) => a - c), o = r[0], i = r[r.length - 1], s = t.length;
1931
+ if (i === o) {
1932
+ const a = t.map((c, m) => ({
1199
1933
  index: m,
1200
1934
  min: o,
1201
- max: s,
1935
+ max: i,
1202
1936
  label: `${o}`
1203
1937
  }));
1204
1938
  return {
1205
1939
  min: o,
1206
- max: s,
1940
+ max: i,
1207
1941
  step: 0,
1208
- bins: l,
1942
+ bins: a,
1209
1943
  colors: t
1210
1944
  };
1211
1945
  }
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];
1946
+ const l = t.map((a, c) => {
1947
+ const m = c / s, d = (c + 1) / s, f = Math.floor(m * r.length), y = Math.min(r.length - 1, Math.floor(d * r.length)), p = r[f], h = c === s - 1 ? i : r[y];
1214
1948
  return {
1215
- index: u,
1216
- min: y,
1949
+ index: c,
1950
+ min: p,
1217
1951
  max: h,
1218
- label: kt(y, h)
1952
+ label: xn(p, h)
1219
1953
  };
1220
- }), c = (s - o) / i;
1954
+ }), u = (i - o) / s;
1221
1955
  return {
1222
1956
  min: o,
1223
- max: s,
1224
- step: c,
1225
- bins: a,
1957
+ max: i,
1958
+ step: u,
1959
+ bins: l,
1226
1960
  colors: t
1227
1961
  };
1228
1962
  }
1229
- function kt(e, t) {
1963
+ function xn(e, t) {
1230
1964
  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
1965
  return `${n(e)} – ${n(t)}`;
1232
1966
  }
1233
- function Ze(e, t) {
1967
+ function xt(e, t) {
1234
1968
  if (!Number.isFinite(e) || !t || !Array.isArray(t.bins) || !t.bins.length)
1235
1969
  return -1;
1236
1970
  if (t.max === t.min)
@@ -1242,92 +1976,92 @@ function Ze(e, t) {
1242
1976
  }
1243
1977
  return -1;
1244
1978
  }
1245
- function Ht(e, t, n = "#8b1e3f") {
1246
- const r = Ze(e, t);
1979
+ function Nn(e, t, n = "#8b1e3f") {
1980
+ const r = xt(e, t);
1247
1981
  return r < 0 ? n : t.colors[r] || n;
1248
1982
  }
1249
- function Ke(e) {
1983
+ function Nt(e) {
1250
1984
  return Array.isArray(e) ? e : [];
1251
1985
  }
1252
- function Ne(e) {
1986
+ function De(e) {
1253
1987
  const t = Number(e);
1254
1988
  return Number.isFinite(t) ? t : void 0;
1255
1989
  }
1256
- function Je(e = {}) {
1990
+ function zt(e = {}) {
1257
1991
  return {
1258
1992
  ...e,
1259
- x: Ne(e.x),
1260
- y: Ne(e.y),
1261
- z: Ne(e.z)
1993
+ x: De(e.x),
1994
+ y: De(e.y),
1995
+ z: De(e.z)
1262
1996
  };
1263
1997
  }
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;
1998
+ function zn(e = [], t = [0, 0], n = 0) {
1999
+ const [r, o] = t, i = Number(n) * Math.PI / 180, s = Math.cos(i), l = Math.sin(i);
2000
+ return Nt(e).map(zt).map((u) => {
2001
+ if (!Number.isFinite(u.x) || !Number.isFinite(u.y)) return { ...u };
2002
+ const a = u.x - r, c = u.y - o;
1269
2003
  return {
1270
- ...c,
1271
- along: l * a + u * i,
1272
- across: l * i - u * a
2004
+ ...u,
2005
+ along: a * l + c * s,
2006
+ across: a * s - c * l
1273
2007
  };
1274
2008
  });
1275
2009
  }
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);
2010
+ function Mn(e = [], t = [0, 0], n = 0, r = 50) {
2011
+ const o = zn(e, t, n), i = 0.5 * Number(r || 0);
2012
+ return !Number.isFinite(i) || i <= 0 ? o : o.filter((s) => Number.isFinite(s.across) && Math.abs(s.across) <= i);
1279
2013
  }
1280
- function Hn(e = [], t = null, n = null) {
1281
- let r = Ke(e).map(Je);
2014
+ function Or(e = [], t = null, n = null) {
2015
+ let r = Nt(e).map(zt);
1282
2016
  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));
2017
+ const [o, i] = t;
2018
+ r = r.filter((s) => Number.isFinite(s.z) && s.z <= Number(o) && s.z >= Number(i));
1285
2019
  }
1286
2020
  return n && (r = r.map((o) => ({
1287
2021
  ...o,
1288
2022
  color_value: o == null ? void 0 : o[n]
1289
2023
  }))), r;
1290
2024
  }
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;
2025
+ function kr(e = [], t = [0, 0], n = 0, r = 50, o = null) {
2026
+ let i = Mn(e, t, n, r);
2027
+ return o && (i = i.map((s) => ({
2028
+ ...s,
2029
+ color_value: s == null ? void 0 : s[o]
2030
+ }))), i;
1297
2031
  }
1298
- function Te(e) {
2032
+ function je(e) {
1299
2033
  return Array.isArray(e) ? e : [];
1300
2034
  }
1301
- function Pe(e = {}) {
2035
+ function Ge(e = {}) {
1302
2036
  return e.hole_id ?? e.holeId ?? e.id;
1303
2037
  }
1304
- function te(e, t = void 0) {
2038
+ function ce(e, t = void 0) {
1305
2039
  const n = Number(e);
1306
2040
  return Number.isFinite(n) ? n : t;
1307
2041
  }
1308
- function Rn(e = [], t = null) {
2042
+ function Vr(e = [], t = null) {
1309
2043
  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);
2044
+ je(e).forEach((o) => {
2045
+ const i = Ge(o);
2046
+ if (i == null || `${i}`.trim() === "") return;
2047
+ const s = `${i}`;
2048
+ n.has(s) || n.set(s, []), n.get(s).push(o);
1315
2049
  });
1316
2050
  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)),
2051
+ return n.forEach((o, i) => {
2052
+ const s = [...o].sort((u, a) => ce(u.md, 0) - ce(a.md, 0)), l = {
2053
+ hole_id: i,
2054
+ x: s.map((u) => ce(u.x, 0)),
2055
+ y: s.map((u) => ce(u.y, 0)),
2056
+ z: s.map((u) => ce(u.z, 0)),
1323
2057
  color: null
1324
2058
  };
1325
- t && (a.color = i.map((c) => c == null ? void 0 : c[t])), r.push(a);
2059
+ t && (l.color = s.map((u) => u == null ? void 0 : u[t])), r.push(l);
1326
2060
  }), r;
1327
2061
  }
1328
- function wn(e = [], t = 1, n = null) {
1329
- return Te(e).map((r) => ({
1330
- hole_id: Pe(r),
2062
+ function wr(e = [], t = 1, n = null) {
2063
+ return je(e).map((r) => ({
2064
+ hole_id: Ge(r),
1331
2065
  from: r == null ? void 0 : r.from,
1332
2066
  to: r == null ? void 0 : r.to,
1333
2067
  radius: t,
@@ -1335,30 +2069,91 @@ function wn(e = [], t = 1, n = null) {
1335
2069
  value: n ? r == null ? void 0 : r[n] : null
1336
2070
  }));
1337
2071
  }
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),
2072
+ function Rr(e = [], t = null) {
2073
+ return t ? je(e).filter((n) => Object.prototype.hasOwnProperty.call(n || {}, t)).map((n) => ({
2074
+ hole_id: Ge(n),
1341
2075
  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))
2076
+ depth: 0.5 * (ce(n == null ? void 0 : n.from, 0) + ce(n == null ? void 0 : n.to, 0))
1343
2077
  })) : [];
1344
2078
  }
1345
- function Oe(e) {
1346
- var n, r, o, s, i, a, c, l, u;
2079
+ const Cn = {
2080
+ bedding: "#2563eb",
2081
+ foliation: "#16a34a",
2082
+ joint: "#9333ea",
2083
+ fault: "#dc2626",
2084
+ vein: "#f59e0b",
2085
+ "shear zone": "#0ea5e9",
2086
+ "fault zone": "#ef4444"
2087
+ };
2088
+ function In(e, t) {
2089
+ const n = t || Cn, r = (e || "").toLowerCase().trim(), o = n[r] || "#888888";
2090
+ return new x.Color(o).getHex();
2091
+ }
2092
+ function An(e, t) {
2093
+ const n = e * Math.PI / 180, r = t * Math.PI / 180;
2094
+ return new x.Vector3(
2095
+ Math.sin(r) * Math.sin(n),
2096
+ // East component
2097
+ Math.cos(r) * Math.sin(n),
2098
+ // North component
2099
+ Math.cos(n)
2100
+ // Up component
2101
+ ).normalize();
2102
+ }
2103
+ function Sn(e, t = {}) {
2104
+ const {
2105
+ radius: n = 5,
2106
+ discThickness: r = 0.2,
2107
+ opacity: o = 0.7,
2108
+ segments: i = 32,
2109
+ colorMap: s = null
2110
+ } = t, l = new x.Group(), u = new x.Vector3(0, 1, 0);
2111
+ for (const a of e) {
2112
+ const c = a.x != null ? a.x : a.easting != null ? a.easting : null, m = a.y != null ? a.y : a.northing != null ? a.northing : null, d = a.z != null ? a.z : a.elevation != null ? a.elevation : null;
2113
+ if (c == null || m == null || d == null || !Number.isFinite(c) || !Number.isFinite(m) || !Number.isFinite(d)) continue;
2114
+ const f = a[k] != null ? Number(a[k]) : null, y = a[O] != null ? Number(a[O]) : null;
2115
+ let p;
2116
+ if (a.nx != null && Number.isFinite(a.nx) && a.ny != null && Number.isFinite(a.ny) && a.nz != null && Number.isFinite(a.nz))
2117
+ p = new x.Vector3(a.nx, a.ny, a.nz).normalize();
2118
+ else {
2119
+ if (f == null || y == null || !Number.isFinite(f) || !Number.isFinite(y)) continue;
2120
+ p = An(f, y);
2121
+ }
2122
+ const h = new x.CylinderGeometry(n, n, r, i, 1, !1), g = new x.MeshStandardMaterial({
2123
+ color: In(a.structure_type, s),
2124
+ transparent: !0,
2125
+ opacity: o,
2126
+ side: x.DoubleSide
2127
+ }), b = new x.Mesh(h, g);
2128
+ b.position.set(c, m, d), b.quaternion.setFromUnitVectors(u, p), b.userData = {
2129
+ type: "structure",
2130
+ hole_id: a.hole_id,
2131
+ depth: a.depth ?? a.mid,
2132
+ structure_type: a.structure_type,
2133
+ dip: f,
2134
+ azimuth: y,
2135
+ comments: a.comments
2136
+ }, l.add(b);
2137
+ }
2138
+ return l;
2139
+ }
2140
+ function Be(e) {
2141
+ var n, r, o, i, s, l, u, a, c;
1347
2142
  if (!e) return "";
1348
2143
  const t = (m) => Number.isFinite(m) ? m.toFixed(3) : "nan";
1349
2144
  return [
1350
2145
  t((n = e.camera) == null ? void 0 : n.x),
1351
2146
  t((r = e.camera) == null ? void 0 : r.y),
1352
2147
  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)
2148
+ t((i = e.target) == null ? void 0 : i.x),
2149
+ t((s = e.target) == null ? void 0 : s.y),
2150
+ t((l = e.target) == null ? void 0 : l.z),
2151
+ t((u = e.up) == null ? void 0 : u.x),
2152
+ t((a = e.up) == null ? void 0 : a.y),
2153
+ t((c = e.up) == null ? void 0 : c.z)
1359
2154
  ].join("|");
1360
2155
  }
1361
- function Qe(e) {
2156
+ function Mt(e) {
1362
2157
  return !e.camera || !e.controls ? null : {
1363
2158
  camera: {
1364
2159
  x: e.camera.position.x,
@@ -1377,49 +2172,55 @@ function Qe(e) {
1377
2172
  }
1378
2173
  };
1379
2174
  }
1380
- function wt(e, t) {
2175
+ function En(e, t) {
1381
2176
  if (!e.camera || !e.controls || !t) return !1;
1382
2177
  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;
2178
+ 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 = Be(t), !0) : !1;
1384
2179
  }
1385
- function $t(e) {
2180
+ function vn(e) {
1386
2181
  if (!e.viewChangeHandler) return;
1387
2182
  const t = Date.now();
1388
2183
  if (t - e._lastViewEmitMs < 250) return;
1389
- const n = Qe(e);
2184
+ const n = Mt(e);
1390
2185
  if (!n) return;
1391
- const r = Oe(n);
2186
+ const r = Be(n);
1392
2187
  r !== e._lastViewSignature && (e._lastViewSignature = r, e._lastViewEmitMs = t, e.viewChangeHandler(n));
1393
2188
  }
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();
2189
+ function Le(e, { minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: s }) {
2190
+ const l = (t + n) / 2, u = (r + o) / 2, a = (i + s) / 2, c = n - t, m = o - r, d = s - i, y = Math.max(c, m, d, 1) * 2;
2191
+ e.controls.target.set(l, u, a), e.camera.position.set(l + y, u + y, a + y), e.camera.lookAt(l, u, a), e.controls.update();
1397
2192
  }
1398
- function jt(e, t = 1e3) {
2193
+ function Pn(e, t = 1e3) {
1399
2194
  !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
2195
  }
1401
- function Bt(e, t = 2e3) {
2196
+ function Dn(e, t = 2e3) {
1402
2197
  !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
2198
  }
1404
- function Ut(e, t = 0, n = 0) {
2199
+ function Ln(e, t = 0, n = 0) {
1405
2200
  e.controls && typeof e.controls.pan == "function" && (e.controls.pan(t, n), e.controls.update());
1406
2201
  }
1407
- function Yt(e, t = 1.1) {
2202
+ function Tn(e, t = 1.1) {
1408
2203
  !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
2204
  }
1410
- function Gt(e, t = 1.2) {
2205
+ function Fn(e, t = 1.2) {
1411
2206
  if (!e.lastBounds) return;
1412
2207
  const {
1413
2208
  minX: n,
1414
2209
  maxX: r,
1415
2210
  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") {
2211
+ maxY: i,
2212
+ minZ: s,
2213
+ maxZ: l
2214
+ } = e.lastBounds, u = (r - n) * t, a = (i - o) * t, c = (l - s) * t, m = (n + r) / 2, d = (o + i) / 2, f = (s + l) / 2, p = Math.max(u, a, c, 1) * 2;
2215
+ e.controls.target.set(m, d, f), e.camera.position.set(m + p, d + p, f + p), e.camera.lookAt(m, d, f), e.controls.update();
2216
+ }
2217
+ const On = 1, kn = 120;
2218
+ function Vn(e, t) {
2219
+ if (!e.camera || !e.controls || !Number.isFinite(t)) return !1;
2220
+ const n = Math.min(kn, Math.max(On, t)), r = e.controls.target, o = e.camera.position.distanceTo(r), i = e.camera.fov * Math.PI / 180, s = 2 * o * Math.tan(i / 2), l = n * Math.PI / 180, u = s / (2 * Math.tan(l / 2)), a = e.camera.position.clone().sub(r).normalize();
2221
+ return e.camera.position.copy(r).addScaledVector(a, u), e.camera.fov = n, e.camera.updateProjectionMatrix(), e.controls.update(), !0;
2222
+ }
2223
+ function wn(e, t = "orbit") {
1423
2224
  if (e.controlMode = t === "fly" ? "fly" : "orbit", e.controlMode === "fly")
1424
2225
  e.controls && (e.controls.enabled = !1), e.flyControls && (e.flyControls.enabled = !0);
1425
2226
  else if (e.flyControls && (e.flyControls.enabled = !1), e.controls) {
@@ -1428,76 +2229,76 @@ function qt(e, t = "orbit") {
1428
2229
  e.controls.target.copy(n), e.controls.update();
1429
2230
  }
1430
2231
  }
1431
- const Q = "#9ca3af";
1432
- function Re(e, t) {
2232
+ const ae = "#9ca3af";
2233
+ function rt(e, t) {
1433
2234
  const n = Number(e == null ? void 0 : e.md), r = Number(t == null ? void 0 : t.md);
1434
2235
  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 };
2236
+ const o = Math.min(n, r), i = Math.max(n, r);
2237
+ return i <= o ? null : { segStart: o, segEnd: i };
1437
2238
  }
1438
- function Xt(e, t, n) {
2239
+ function Rn(e, t, n) {
1439
2240
  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);
2241
+ for (let s = 0; s < e.length; s += 1) {
2242
+ const l = e[s], u = Number(l == null ? void 0 : l.from), a = Number(l == null ? void 0 : l.to), c = Number(l == null ? void 0 : l.value);
2243
+ if (!Number.isFinite(u) || !Number.isFinite(a) || !Number.isFinite(c) || a <= u) continue;
2244
+ const m = Math.max(t, u), f = Math.min(n, a) - m;
2245
+ f <= 0 || (r += c * f, o += f);
1445
2246
  }
1446
2247
  if (o <= 0) return null;
1447
- const s = r / o;
1448
- return Number.isFinite(s) ? s : null;
2248
+ const i = r / o;
2249
+ return Number.isFinite(i) ? i : null;
1449
2250
  }
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);
2251
+ function $n(e, t) {
2252
+ if (!Number.isFinite(e)) return new x.Color(ae);
2253
+ if (xt(e, t) < 0) return new x.Color(ae);
2254
+ const r = Nn(e, t, ae);
2255
+ return new x.Color(r);
1455
2256
  }
1456
- function Zt(e = {}) {
2257
+ function Hn(e = {}) {
1457
2258
  return {
1458
2259
  preserveView: !!e.preserveView,
1459
2260
  assayIntervalsByHole: e.assayIntervalsByHole || null,
1460
2261
  selectedAssayVariable: e.selectedAssayVariable || ""
1461
2262
  };
1462
2263
  }
1463
- function Kt(e, t) {
2264
+ function jn(e, t) {
1464
2265
  if (!e || !t) return [];
1465
2266
  const n = [];
1466
2267
  return Object.values(e).forEach((r) => {
1467
2268
  (r || []).forEach((o) => {
1468
- const s = Number(o == null ? void 0 : o.value);
1469
- Number.isFinite(s) && n.push(s);
2269
+ const i = Number(o == null ? void 0 : o.value);
2270
+ Number.isFinite(i) && n.push(i);
1470
2271
  });
1471
2272
  }), n;
1472
2273
  }
1473
- function Ae(e) {
2274
+ function Te(e) {
1474
2275
  return {
1475
2276
  holeId: e.id,
1476
2277
  project: e.project
1477
2278
  };
1478
2279
  }
1479
- class jn {
2280
+ class $r {
1480
2281
  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;
2282
+ 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.frameId = null, this.clock = new x.Clock(), this.handleCanvasClick = null, this.raycaster = new x.Raycaster(), this.pointer = new x.Vector2(), this.drillholeClickHandler = null, this.controlMode = "orbit", this._tmpDir = new x.Vector3(), this.viewChangeHandler = null, this._lastViewSignature = "", this._lastViewEmitMs = 0;
1482
2283
  }
1483
2284
  init(t) {
1484
2285
  if (!t) return;
1485
2286
  this.container = t;
1486
2287
  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);
2288
+ this.scene = new x.Scene(), this.scene.background = new x.Color(16777215), this.camera = new x.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 x.WebGLRenderer({ antialias: !0 }), this.renderer.setSize(n, r), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.autoClear = !1, t.appendChild(this.renderer.domElement);
2289
+ const o = new x.AmbientLight(16777215, 0.5);
1489
2290
  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
2291
+ const i = new x.DirectionalLight(16777215, 0.6);
2292
+ i.position.set(10, 10, 5), this.scene.add(i);
2293
+ const s = new x.AxesHelper(20);
2294
+ this.scene.add(s), this.controls = new It(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 = {
2295
+ LEFT: x.MOUSE.PAN,
2296
+ MIDDLE: x.MOUSE.DOLLY,
2297
+ RIGHT: x.MOUSE.ROTATE
1497
2298
  }, 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, {
2299
+ ONE: x.TOUCH.ROTATE,
2300
+ TWO: x.TOUCH.PAN
2301
+ }, this.controls.maxPolarAngle = Math.PI, this.flyControls = new At(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
2302
  container: this.container,
1502
2303
  placement: "top-right",
1503
2304
  size: 110,
@@ -1505,48 +2306,53 @@ class jn {
1505
2306
  animated: !0,
1506
2307
  speed: 1.5
1507
2308
  }), 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();
2309
+ const l = () => {
2310
+ var a;
2311
+ this.frameId = requestAnimationFrame(l);
2312
+ const u = this.clock.getDelta();
2313
+ this.renderer.clear(), this.controlMode === "fly" && ((a = this.flyControls) != null && a.enabled) ? this.flyControls.update(u) : this.controls && this.controls.update(), this._emitViewChangeIfNeeded(), this.renderer.render(this.scene, this.camera), this.gizmo && this.gizmo.render();
1513
2314
  };
1514
- a();
2315
+ l();
1515
2316
  }
1516
2317
  setViewChangeHandler(t) {
1517
2318
  this.viewChangeHandler = typeof t == "function" ? t : null;
1518
2319
  }
1519
2320
  getViewState() {
1520
- return Qe(this);
2321
+ return Mt(this);
1521
2322
  }
1522
2323
  setViewState(t) {
1523
- return wt(this, t);
2324
+ return En(this, t);
1524
2325
  }
1525
2326
  _buildViewSignature(t) {
1526
- return Oe(t);
2327
+ return Be(t);
1527
2328
  }
1528
2329
  _emitViewChangeIfNeeded() {
1529
- $t(this);
2330
+ vn(this);
1530
2331
  }
1531
2332
  _attachCanvasClickHandler() {
1532
2333
  const t = this.renderer;
1533
2334
  t && (this.handleCanvasClick = (n) => {
1534
- var u, m, f, d;
2335
+ var f, y, p, h, g, b;
1535
2336
  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)
2337
+ if ((f = this.gizmo) != null && f.domElement) {
2338
+ const _ = this.gizmo.domElement.getBoundingClientRect();
2339
+ if (n.clientX >= _.left && n.clientX <= _.right && n.clientY >= _.top && n.clientY <= _.bottom)
1539
2340
  return;
1540
2341
  }
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 });
2342
+ const r = t.domElement.getBoundingClientRect(), o = n.clientX - r.left, i = n.clientY - r.top;
2343
+ this.pointer.x = o / r.width * 2 - 1, this.pointer.y = -(i / r.height * 2) + 1, this.raycaster.setFromCamera(this.pointer, this.camera);
2344
+ const s = this.raycaster.intersectObjects(this.drillMeshes, !0), l = this.raycaster.intersectObjects(this.structuralMeshes, !0), u = ((y = s[0]) == null ? void 0 : y.distance) ?? 1 / 0;
2345
+ if ((((p = l[0]) == null ? void 0 : p.distance) ?? 1 / 0) < u && l.length > 0) {
2346
+ const _ = l[0].object;
2347
+ this.drillholeClickHandler && this.drillholeClickHandler({ type: "structure", ..._.userData });
2348
+ return;
2349
+ }
2350
+ if (s.length === 0) return;
2351
+ let c = s[0].object;
2352
+ for (; c && c.parent && !((h = c.userData) != null && h.holeId); )
2353
+ c = c.parent;
2354
+ const m = (g = c == null ? void 0 : c.userData) == null ? void 0 : g.holeId, d = (b = c == null ? void 0 : c.userData) == null ? void 0 : b.project;
2355
+ m && this.drillholeClickHandler && this.drillholeClickHandler({ holeId: m, project: d });
1550
2356
  }, t.domElement.addEventListener("click", this.handleCanvasClick));
1551
2357
  }
1552
2358
  resize() {
@@ -1556,91 +2362,91 @@ class jn {
1556
2362
  }
1557
2363
  setBlocks(t, n, r) {
1558
2364
  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) => {
2365
+ let o = 1 / 0, i = -1 / 0, s = 1 / 0, l = -1 / 0, u = 1 / 0, a = -1 / 0;
2366
+ t.forEach((c) => {
1561
2367
  const {
1562
2368
  center_x: m = 0,
1563
- center_y: f = 0,
1564
- center_z: d = 0,
1565
- size_x: p = 1,
1566
- size_y: y = 1,
2369
+ center_y: d = 0,
2370
+ center_z: f = 0,
2371
+ size_x: y = 1,
2372
+ size_y: p = 1,
1567
2373
  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,
2374
+ } = c;
2375
+ o = Math.min(o, m - y / 2), i = Math.max(i, m + y / 2), s = Math.min(s, d - p / 2), l = Math.max(l, d + p / 2), u = Math.min(u, f - h / 2), a = Math.max(a, f + h / 2);
2376
+ const g = new x.BoxGeometry(y, p, h), b = Zt(c[n], r, x), _ = new x.MeshStandardMaterial({
2377
+ color: b,
1572
2378
  transparent: !0,
1573
2379
  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 }));
2380
+ side: x.DoubleSide
2381
+ }), I = new x.Mesh(g, _);
2382
+ I.position.set(m, d, f), this.scene.add(I), this.blocks.push(I);
2383
+ }), this.camera && this.controls && (this.lastBounds = { minX: o, maxX: i, minY: s, maxY: l, minZ: u, maxZ: a }, Le(this, { minX: o, maxX: i, minY: s, maxY: l, minZ: u, maxZ: a }));
1578
2384
  }
1579
2385
  setDrillholes(t, n = {}) {
1580
2386
  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;
2387
+ const { preserveView: r, assayIntervalsByHole: o, selectedAssayVariable: i } = Hn(n), s = jn(o, i), l = _n(s);
2388
+ let u = 1 / 0, a = -1 / 0, c = 1 / 0, m = -1 / 0, d = 1 / 0, f = -1 / 0;
2389
+ const y = new x.Vector3(), p = new x.Vector3(0, 1, 0);
2390
+ t.forEach((h, g) => {
2391
+ const _ = g * 137.5 % 360 / 360, I = new x.Color().setHSL(_, 0.75, 0.55), N = (h.points || []).map((M) => {
2392
+ u = Math.min(u, M.x), a = Math.max(a, M.x), c = Math.min(c, M.y), m = Math.max(m, M.y), d = Math.min(d, M.z), f = Math.max(f, M.z);
2393
+ const F = new x.Vector3(M.x, M.y, M.z);
2394
+ return F.md = M.md, F;
1589
2395
  });
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,
2396
+ if (N.length < 2) {
2397
+ if (N.length === 1) {
2398
+ const M = new x.SphereGeometry(5, 12, 12), F = new x.MeshLambertMaterial({
2399
+ color: I,
2400
+ emissive: I,
1595
2401
  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);
2402
+ }), j = new x.Mesh(M, F);
2403
+ j.position.copy(N[0]), j.userData = Te(h), this.scene.add(j), this.drillLines.push(j), this.drillMeshes.push(j);
1598
2404
  }
1599
2405
  return;
1600
2406
  }
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,
2407
+ const P = new x.Group();
2408
+ P.userData = Te(h);
2409
+ const E = i ? this._resolveAssayIntervalsForHole(h, o) : [];
2410
+ for (let M = 0; M < N.length - 1; M += 1) {
2411
+ const F = N[M], j = N[M + 1], W = y.subVectors(j, F), D = W.length();
2412
+ if (D <= 1e-3) continue;
2413
+ const G = 2.2, U = new x.CylinderGeometry(G, G, D, 6, 1, !0), S = this._getSegmentColor({
2414
+ selectedAssayVariable: i,
2415
+ assayIntervals: E,
2416
+ assayScale: l,
1611
2417
  holeId: h.id,
1612
- segmentIndex: N,
1613
- p1: z,
1614
- p2: C
1615
- }), v = new g.MeshLambertMaterial({
1616
- color: L,
2418
+ segmentIndex: M,
2419
+ p1: F,
2420
+ p2: j
2421
+ }), C = new x.MeshLambertMaterial({
2422
+ color: S,
1617
2423
  flatShading: !0,
1618
- emissive: L,
2424
+ emissive: S,
1619
2425
  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);
2426
+ }), v = new x.Mesh(U, C);
2427
+ v.position.copy(F.clone().addScaledVector(W, 0.5)), v.quaternion.setFromUnitVectors(p, W.clone().normalize()), v.userData = Te(h), P.add(v), this.drillMeshes.push(v);
1622
2428
  }
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 }));
2429
+ this.scene.add(P), this.drillLines.push(P);
2430
+ }), this.camera && this.controls && (this.lastBounds = { minX: u, maxX: a, minY: c, maxY: m, minZ: d, maxZ: f }, r || Le(this, { minX: u, maxX: a, minY: c, maxY: m, minZ: d, maxZ: f }));
1625
2431
  }
1626
- _getSegmentColor({ selectedAssayVariable: t, assayIntervals: n, assayScale: r, holeId: o, segmentIndex: s, p1: i, p2: a }) {
2432
+ _getSegmentColor({ selectedAssayVariable: t, assayIntervals: n, assayScale: r, holeId: o, segmentIndex: i, p1: s, p2: l }) {
1627
2433
  if (!t)
1628
- return Qt(o, s);
2434
+ return Bn(o, i);
1629
2435
  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);
2436
+ if (!(n != null && n.length)) return new x.Color(ae);
2437
+ const c = rt(s, l);
2438
+ return c ? n.some((d) => {
2439
+ const f = Number(d == null ? void 0 : d.from), y = Number(d == null ? void 0 : d.to);
2440
+ if (!Number.isFinite(f) || !Number.isFinite(y)) return !1;
2441
+ const p = Math.max(c.segStart, f);
2442
+ return Math.min(c.segEnd, y) > p;
2443
+ }) ? new x.Color("#ff8c42") : new x.Color(ae) : new x.Color(ae);
1638
2444
  }
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);
2445
+ if (!(n != null && n.length)) return new x.Color(ae);
2446
+ const u = rt(s, l);
2447
+ if (!u) return new x.Color(ae);
2448
+ const a = Rn(n, u.segStart, u.segEnd);
2449
+ return $n(a, r);
1644
2450
  }
1645
2451
  _resolveAssayIntervalsForHole(t, n) {
1646
2452
  if (!n || !t) return [];
@@ -1648,36 +2454,67 @@ class jn {
1648
2454
  if (!r) return [];
1649
2455
  const o = n[r];
1650
2456
  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;
2457
+ const i = Gn(r);
2458
+ if (i) {
2459
+ const s = n[i];
2460
+ if (Array.isArray(s) && s.length) return s;
1655
2461
  }
1656
2462
  return [];
1657
2463
  }
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 });
2464
+ _fitCameraToBounds({ minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: s }) {
2465
+ Le(this, { minX: t, maxX: n, minY: r, maxY: o, minZ: i, maxZ: s });
1660
2466
  }
1661
2467
  recenterCameraToOrigin(t = 1e3) {
1662
- jt(this, t);
2468
+ Pn(this, t);
1663
2469
  }
1664
2470
  lookDown(t = 2e3) {
1665
- Bt(this, t);
2471
+ Dn(this, t);
1666
2472
  }
1667
2473
  pan(t = 0, n = 0) {
1668
- Ut(this, t, n);
2474
+ Ln(this, t, n);
1669
2475
  }
1670
2476
  dolly(t = 1.1) {
1671
- Yt(this, t);
2477
+ Tn(this, t);
1672
2478
  }
1673
2479
  focusOnLastBounds(t = 1.2) {
1674
- Gt(this, t);
2480
+ Fn(this, t);
1675
2481
  }
1676
2482
  _clearBlocks() {
1677
2483
  this.blocks.forEach((t) => {
1678
2484
  this.scene.remove(t), t.geometry.dispose(), t.material.dispose();
1679
2485
  }), this.blocks = [];
1680
2486
  }
2487
+ setStructuralDiscs(t, n, r = {}) {
2488
+ if (!this.scene || (this._clearStructuralDiscs(), !(t != null && t.length) || !(n != null && n.length))) return;
2489
+ const { maxDiscs: o = 3e3 } = r;
2490
+ let i = t;
2491
+ if (i.length > o) {
2492
+ const u = i.length / o, a = [];
2493
+ for (let c = 0; c < o; c++)
2494
+ a.push(i[Math.floor(c * u)]);
2495
+ i = a;
2496
+ }
2497
+ const s = n.flatMap((u) => (u.points || []).map((a) => ({ ...a, hole_id: u.id }))), l = nn(i, s, r);
2498
+ l.length && (this.structuralGroup = Sn(l, r), this.scene.add(this.structuralGroup), this.structuralGroup.traverse((u) => {
2499
+ u.isMesh && this.structuralMeshes.push(u);
2500
+ }));
2501
+ }
2502
+ /**
2503
+ * Change the camera field-of-view while keeping the visible scene the same apparent size.
2504
+ * FOV is clamped to [FOV_MIN_DEG, FOV_MAX_DEG]. Delegates to setFov in baselode3dCameraControls.
2505
+ * @param {number} fovDeg - Desired FOV in degrees
2506
+ */
2507
+ setCameraFov(t) {
2508
+ Vn(this, t);
2509
+ }
2510
+ setStructuralDiscsVisible(t) {
2511
+ this.structuralGroup && (this.structuralGroup.visible = !!t);
2512
+ }
2513
+ _clearStructuralDiscs() {
2514
+ this.structuralGroup && (this.scene.remove(this.structuralGroup), this.structuralGroup.traverse((t) => {
2515
+ t.isMesh && (t.geometry.dispose(), t.material.dispose());
2516
+ }), this.structuralGroup = null), this.structuralMeshes = [];
2517
+ }
1681
2518
  _clearDrillholes() {
1682
2519
  this.drillLines.forEach((t) => {
1683
2520
  this.scene.remove(t), t.isGroup ? t.traverse((n) => {
@@ -1686,30 +2523,30 @@ class jn {
1686
2523
  }), this.drillLines = [], this.drillMeshes = [];
1687
2524
  }
1688
2525
  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));
2526
+ 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._clearStructuralDiscs(), 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
2527
  }
1691
2528
  setDrillholeClickHandler(t) {
1692
2529
  this.drillholeClickHandler = t;
1693
2530
  }
1694
2531
  setControlMode(t = "orbit") {
1695
- qt(this, t);
2532
+ wn(this, t);
1696
2533
  }
1697
2534
  }
1698
- function Jt(e) {
2535
+ function Gn(e) {
1699
2536
  return `${e ?? ""}`.trim().toLowerCase();
1700
2537
  }
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;
2538
+ function Bn(e, t) {
2539
+ const n = `${e ?? ""}:${t ?? 0}`, r = Un(n), o = (t ?? 0) % 14 / 14, i = (r * 0.15 + o * 0.85) % 1, s = new x.Color();
2540
+ return s.setHSL(i, 1, 0.5), s;
1704
2541
  }
1705
- function en(e) {
2542
+ function Un(e) {
1706
2543
  const t = `${e ?? ""}`;
1707
2544
  let n = 2166136261;
1708
2545
  for (let r = 0; r < t.length; r += 1)
1709
2546
  n ^= t.charCodeAt(r), n = Math.imul(n, 16777619);
1710
2547
  return (n >>> 0) / 4294967295;
1711
2548
  }
1712
- function Bn({
2549
+ function Hr({
1713
2550
  controlMode: e = "orbit",
1714
2551
  onToggleFly: t = () => {
1715
2552
  },
@@ -1720,102 +2557,134 @@ function Bn({
1720
2557
  onFit: o = () => {
1721
2558
  }
1722
2559
  }) {
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" })
2560
+ return /* @__PURE__ */ Ne("div", { className: "baselode-3d-controls", children: [
2561
+ /* @__PURE__ */ q("button", { type: "button", className: "ghost-button", onClick: n, children: "Recenter to (0,0,0)" }),
2562
+ /* @__PURE__ */ q("button", { type: "button", className: "ghost-button", onClick: r, children: "Look down" }),
2563
+ /* @__PURE__ */ q("button", { type: "button", className: "ghost-button", onClick: o, children: "Fit to scene" }),
2564
+ /* @__PURE__ */ q("button", { type: "button", className: "ghost-button", onClick: t, children: e === "orbit" ? "Enable fly controls" : "Disable fly controls" })
1728
2565
  ] });
1729
2566
  }
1730
2567
  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
2568
+ gn as ASSAY_COLOR_PALETTE_10,
2569
+ Pt as ASSAY_NON_VALUE_FIELDS,
2570
+ O as AZIMUTH,
2571
+ tr as BASELODE_DATA_MODEL_DRILL_ASSAY,
2572
+ Qn as BASELODE_DATA_MODEL_DRILL_COLLAR,
2573
+ er as BASELODE_DATA_MODEL_DRILL_SURVEY,
2574
+ nr as BASELODE_DATA_MODEL_STRUCTURAL_POINT,
2575
+ Hr as Baselode3DControls,
2576
+ $r as Baselode3DScene,
2577
+ Ue as CHART_OPTIONS,
2578
+ wt as COMMENT_COLUMN_NAMES,
2579
+ it as CRS,
2580
+ vt as DEFAULT_COLUMN_MAP,
2581
+ H as DEPTH,
2582
+ k as DIP,
2583
+ _e as DISPLAY_CATEGORICAL,
2584
+ pe as DISPLAY_COMMENT,
2585
+ Ce as DISPLAY_HIDDEN,
2586
+ ye as DISPLAY_NUMERIC,
2587
+ Oe as DISPLAY_TADPOLE,
2588
+ ie as EASTING,
2589
+ he as ELEVATION,
2590
+ on as ERROR_COLOR,
2591
+ kn as FOV_MAX_DEG,
2592
+ On as FOV_MIN_DEG,
2593
+ B as FROM,
2594
+ Ye as HIDDEN_COLUMNS,
2595
+ z as HOLE_ID,
2596
+ ee as LATITUDE,
2597
+ te as LONGITUDE,
2598
+ Ve as MID,
2599
+ se as NORTHING,
2600
+ We as NUMERIC_LINE_COLOR,
2601
+ rn as NUMERIC_MARKER_COLOR,
2602
+ re as PROJECT_ID,
2603
+ Et as STRIKE,
2604
+ R as TO,
2605
+ Tr as TracePlot,
2606
+ tn as alphaBetaToNormal,
2607
+ Rr as annotationsFromIntervals,
2608
+ Cr as assembleDataset,
2609
+ yr as attachAssayPositions,
2610
+ hr as balancedTangentialDesurvey,
2611
+ jt as buildAssayState,
2612
+ pn as buildCommentsConfig,
2613
+ _n as buildEqualRangeColorScale,
2614
+ ln as buildIntervalPoints,
2615
+ mn as buildPlotConfig,
2616
+ Lr as buildStrikeDipSymbol,
2617
+ Sn as buildStructuralDiscs,
2618
+ Dr as buildStructuralStripConfig,
2619
+ fn as buildTadpoleConfig,
2620
+ pr as buildTraces,
2621
+ Be as buildViewSignature,
2622
+ Ar as calculatePropertyStats,
2623
+ Rt as classifyColumns,
2624
+ Mr as coerceNumeric,
2625
+ nn as computeStructuralPositions,
2626
+ cr as defaultChartType,
2627
+ Ie as deriveAssayProps,
2628
+ dr as desurveyTraces,
2629
+ An as dipAzimuthToNormal,
2630
+ Tn as dolly,
2631
+ vn as emitViewChangeIfNeeded,
2632
+ zr as filterByProject,
2633
+ Le as fitCameraToBounds,
2634
+ Fn as focusOnLastBounds,
2635
+ we as getChartOptions,
2636
+ Zt as getColorForValue,
2637
+ xt as getEqualRangeBinIndex,
2638
+ Nn as getEqualRangeColor,
2639
+ Mt as getViewState,
2640
+ Kt as groupRowsByHole,
2641
+ an as holeHasData,
2642
+ en as interpolateTrace,
2643
+ wr as intervalsAsTubes,
2644
+ Nr as joinAssaysToTraces,
2645
+ ur as loadAssayFile,
2646
+ Ht as loadAssayHole,
2647
+ $t as loadAssayMetadata,
2648
+ xr as loadAssays,
2649
+ gr as loadCollars,
2650
+ _r as loadSurveys,
2651
+ $e as loadTable,
2652
+ ir as logDataInfo,
2653
+ or as logDataWarning,
2654
+ Dn as lookDown,
2655
+ Ut as minimumCurvatureDesurvey,
2656
+ ar as normalizeCsvRow,
2657
+ ze as normalizeFieldName,
2658
+ Ln as pan,
2659
+ Qt as parseAssayCsvTextToHoles,
2660
+ Ot as parseAssayHole,
2661
+ sr as parseAssayHoleIds,
2662
+ Ft as parseAssayHoleIdsWithAssays,
2663
+ kt as parseAssaysCSV,
2664
+ Ir as parseBlockModelCSV,
2665
+ br as parseDrillholesCSV,
2666
+ Jt as parseStructuralCSV,
2667
+ vr as parseStructuralIntervalsCSV,
2668
+ Er as parseStructuralPointsCSV,
2669
+ mr as parseSurveyCSV,
2670
+ Pr as parseUnifiedDataset,
2671
+ lr as pickFirstPresent,
2672
+ Or as planView,
2673
+ zn as projectTraceToSection,
2674
+ Pn as recenterCameraToOrigin,
2675
+ mt as reorderHoleIds,
2676
+ kr as sectionView,
2677
+ Mn as sectionWindow,
2678
+ wn as setControlMode,
2679
+ Vn as setFov,
2680
+ En as setViewState,
2681
+ ue as standardizeColumns,
2682
+ rr as standardizeRowArray,
2683
+ fr as tangentialDesurvey,
2684
+ Dt as toError,
2685
+ Vr as tracesAsSegments,
2686
+ Fr as useDrillholeTraceGrid,
2687
+ Sr as validateStructuralPoints,
2688
+ $ as withDataErrorContext
1820
2689
  };
1821
2690
  //# sourceMappingURL=baselode.js.map