@welldot/render 0.2.3 → 0.3.0-next.20261015.d7c7365
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/README.md +71 -14
- package/dist/chunk-ODRL222Y.js +10 -0
- package/dist/chunk-ODRL222Y.js.map +1 -0
- package/dist/index.cjs +1493 -325
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +332 -33
- package/dist/index.d.ts +332 -33
- package/dist/index.js +1501 -331
- package/dist/index.js.map +1 -1
- package/dist/textures.cjs +339 -0
- package/dist/textures.cjs.map +1 -0
- package/dist/textures.d.cts +9 -0
- package/dist/textures.d.ts +9 -0
- package/dist/textures.js +7 -0
- package/dist/textures.js.map +1 -0
- package/package.json +11 -4
package/dist/index.cjs
CHANGED
|
@@ -330,10 +330,13 @@ __export(index_exports, {
|
|
|
330
330
|
WellRenderer: () => WellRenderer,
|
|
331
331
|
applyRenderLocale: () => applyRenderLocale,
|
|
332
332
|
drawWellLegend: () => drawWellLegend,
|
|
333
|
+
drawWellLegendSymbol: () => drawWellLegendSymbol,
|
|
333
334
|
formatDiameter: () => formatDiameter,
|
|
334
335
|
formatLength: () => formatLength,
|
|
335
336
|
getDiameterUnit: () => getDiameterUnit,
|
|
336
337
|
getLengthUnit: () => getLengthUnit,
|
|
338
|
+
getProfileTopDepth: () => getProfileTopDepth,
|
|
339
|
+
getWellLegendItems: () => getWellLegendItems,
|
|
337
340
|
importFgdcTextures: () => importFgdcTextures,
|
|
338
341
|
resolveRenderLabel: () => resolveRenderLabel
|
|
339
342
|
});
|
|
@@ -343,6 +346,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
343
346
|
var import_d3 = require("d3");
|
|
344
347
|
|
|
345
348
|
// src/utils/format.utils.ts
|
|
349
|
+
var import_core = require("@welldot/core");
|
|
346
350
|
var import_utils = require("@welldot/utils");
|
|
347
351
|
var MM_TO_INCHES = 0.0393701;
|
|
348
352
|
var M_TO_FT = 3.28084;
|
|
@@ -360,8 +364,7 @@ function getDiameterUnit(units, locale) {
|
|
|
360
364
|
return locale === "en" ? "in." : '"';
|
|
361
365
|
}
|
|
362
366
|
function resolveRenderLabel(value, locale) {
|
|
363
|
-
|
|
364
|
-
return locale === "en" && value.en ? value.en : value.pt;
|
|
367
|
+
return (0, import_core.resolveLanguageText)(value, locale, "pt");
|
|
365
368
|
}
|
|
366
369
|
|
|
367
370
|
// src/configs/render.configs.ts
|
|
@@ -386,6 +389,8 @@ var RENDER_LABELS = {
|
|
|
386
389
|
wellCase: { pt: "Revestimento", en: "Casing" },
|
|
387
390
|
wellScreen: { pt: "Filtro", en: "Screen" },
|
|
388
391
|
reduction: { pt: "Redu\xE7\xE3o", en: "Reduction" },
|
|
392
|
+
centralizer: { pt: "Centralizador", en: "Centralizer" },
|
|
393
|
+
pump: { pt: "Bomba e edutor", en: "Pump and riser" },
|
|
389
394
|
cementPad: { pt: "Laje de cimento", en: "Cement pad" },
|
|
390
395
|
conflict: { pt: "Conflito", en: "Conflict" }
|
|
391
396
|
}
|
|
@@ -409,9 +414,38 @@ var RENDER_LABELS = {
|
|
|
409
414
|
wellCase: { title: { pt: "REVESTIMENTO", en: "CASING" } },
|
|
410
415
|
wellScreen: {
|
|
411
416
|
title: { pt: "FILTROS", en: "SCREENS" },
|
|
412
|
-
slot: { pt: "Ranhura:", en: "Slot:" }
|
|
417
|
+
slot: { pt: "Ranhura:", en: "Slot:" },
|
|
418
|
+
material: { pt: "Material:", en: "Material:" },
|
|
419
|
+
slotType: { pt: "Tipo:", en: "Type:" }
|
|
413
420
|
},
|
|
414
421
|
reduction: { title: { pt: "REDU\xC7\xC3O", en: "REDUCTION" } },
|
|
422
|
+
centralizer: {
|
|
423
|
+
title: { pt: "CENTRALIZADOR", en: "CENTRALIZER" },
|
|
424
|
+
depth: { pt: "Profundidade:", en: "Depth:" },
|
|
425
|
+
spacing: { pt: "Espa\xE7amento:", en: "Spacing:" }
|
|
426
|
+
},
|
|
427
|
+
pump: {
|
|
428
|
+
title: { pt: "BOMBA", en: "PUMP" },
|
|
429
|
+
intakeDepth: { pt: "Profundidade do crivo:", en: "Intake depth:" },
|
|
430
|
+
model: { pt: "Modelo:", en: "Model:" },
|
|
431
|
+
power: { pt: "Pot\xEAncia:", en: "Power:" },
|
|
432
|
+
riser: { pt: "Edutor:", en: "Riser:" },
|
|
433
|
+
type_submersible: { pt: "Bomba submersa", en: "Submersible pump" },
|
|
434
|
+
type_vertical_turbine: {
|
|
435
|
+
pt: "Bomba de eixo vertical",
|
|
436
|
+
en: "Vertical turbine pump"
|
|
437
|
+
},
|
|
438
|
+
type_jet: { pt: "Bomba injetora", en: "Jet pump" },
|
|
439
|
+
type_progressive_cavity: {
|
|
440
|
+
pt: "Bomba helicoidal",
|
|
441
|
+
en: "Progressive cavity pump"
|
|
442
|
+
},
|
|
443
|
+
type_hand_pump: { pt: "Bomba manual", en: "Hand pump" },
|
|
444
|
+
type_compressor_airlift: {
|
|
445
|
+
pt: "Compressor (air-lift)",
|
|
446
|
+
en: "Compressor (air-lift)"
|
|
447
|
+
}
|
|
448
|
+
},
|
|
415
449
|
conflict: { title: { pt: "CONFLITO", en: "CONFLICT" } },
|
|
416
450
|
fracture: {
|
|
417
451
|
title: { pt: "FRATURA", en: "FRACTURE" },
|
|
@@ -437,6 +471,19 @@ var RENDER_LABELS = {
|
|
|
437
471
|
fractureWater: { pt: "fratura aberta", en: "open fracture" },
|
|
438
472
|
cave: { pt: "caverna", en: "cave" },
|
|
439
473
|
caveWater: { pt: "caverna \xFAmida", en: "wet cave" }
|
|
474
|
+
},
|
|
475
|
+
columnHeaders: {
|
|
476
|
+
depth: { pt: "PROF.", en: "DEPTH" },
|
|
477
|
+
lithology: { pt: "LIT.", en: "LITH." },
|
|
478
|
+
construction: { pt: "CONSTRU\xC7\xC3O", en: "CONSTRUCTION" },
|
|
479
|
+
description: { pt: "DESCRI\xC7\xC3O GEOL\xD3GICA", en: "GEOLOGICAL DESCRIPTION" }
|
|
480
|
+
},
|
|
481
|
+
continuation: { prefix: { pt: "continua\xE7\xE3o", en: "continued" } },
|
|
482
|
+
overlap: {
|
|
483
|
+
label: {
|
|
484
|
+
pt: "{range} repetido da p\xE1g. anterior",
|
|
485
|
+
en: "{range} repeated from previous page"
|
|
486
|
+
}
|
|
440
487
|
}
|
|
441
488
|
};
|
|
442
489
|
function resolveGroup(group, locale) {
|
|
@@ -457,6 +504,8 @@ function resolveTooltipLabels(locale) {
|
|
|
457
504
|
wellCase: resolveGroup(t.wellCase, locale),
|
|
458
505
|
wellScreen: resolveGroup(t.wellScreen, locale),
|
|
459
506
|
reduction: resolveGroup(t.reduction, locale),
|
|
507
|
+
centralizer: resolveGroup(t.centralizer, locale),
|
|
508
|
+
pump: resolveGroup(t.pump, locale),
|
|
460
509
|
conflict: resolveGroup(t.conflict, locale),
|
|
461
510
|
fracture: resolveGroup(t.fracture, locale),
|
|
462
511
|
cementPad: resolveGroup(t.cementPad, locale),
|
|
@@ -478,7 +527,19 @@ function applyRenderLocale(config, locale) {
|
|
|
478
527
|
tooltipLabels: resolveTooltipLabels(locale),
|
|
479
528
|
labels: {
|
|
480
529
|
...config.labels,
|
|
481
|
-
typeLabels: resolveGroup(RENDER_LABELS.typeLabels, locale)
|
|
530
|
+
typeLabels: resolveGroup(RENDER_LABELS.typeLabels, locale),
|
|
531
|
+
continuation: {
|
|
532
|
+
...config.labels.continuation,
|
|
533
|
+
prefix: resolveRenderLabel(RENDER_LABELS.continuation.prefix, locale)
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
columnHeaders: {
|
|
537
|
+
...config.columnHeaders,
|
|
538
|
+
labels: resolveGroup(RENDER_LABELS.columnHeaders, locale)
|
|
539
|
+
},
|
|
540
|
+
overlap: {
|
|
541
|
+
...config.overlap,
|
|
542
|
+
label: resolveRenderLabel(RENDER_LABELS.overlap.label, locale)
|
|
482
543
|
}
|
|
483
544
|
};
|
|
484
545
|
}
|
|
@@ -504,7 +565,7 @@ var DEFAULT_WELL_THEME = {
|
|
|
504
565
|
crackStrokeWidth: 0.7
|
|
505
566
|
}
|
|
506
567
|
},
|
|
507
|
-
cementPad: { stroke: "#303030", strokeWidth:
|
|
568
|
+
cementPad: { stroke: "#303030", strokeWidth: 1 },
|
|
508
569
|
boreHole: {
|
|
509
570
|
fill: "#ffffff",
|
|
510
571
|
stroke: "#191919",
|
|
@@ -513,10 +574,24 @@ var DEFAULT_WELL_THEME = {
|
|
|
513
574
|
strokeWidth: 1.2
|
|
514
575
|
},
|
|
515
576
|
surfaceCase: { stroke: "#000000", strokeWidth: 4 },
|
|
516
|
-
holeFill: { stroke: "#303030", strokeWidth: 2 },
|
|
577
|
+
holeFill: { stroke: "#303030", strokeWidth: 1.2 },
|
|
517
578
|
wellCase: { fill: "#ffffff", stroke: "#303030", strokeWidth: 2 },
|
|
518
|
-
wellScreen: {
|
|
579
|
+
wellScreen: {
|
|
580
|
+
stroke: "#303030",
|
|
581
|
+
strokeWidth: 2,
|
|
582
|
+
endStrokeWidth: 0.75,
|
|
583
|
+
endDasharray: "3, 2"
|
|
584
|
+
},
|
|
519
585
|
reduction: { fill: "#ffffff", stroke: "#303030", strokeWidth: 2 },
|
|
586
|
+
centralizer: { fill: "none", stroke: "#303030", strokeWidth: 1.4 },
|
|
587
|
+
pump: {
|
|
588
|
+
fill: "#5b6b7a",
|
|
589
|
+
stroke: "#202020",
|
|
590
|
+
strokeWidth: 1.2,
|
|
591
|
+
riserFill: "#a3adb7",
|
|
592
|
+
riserStroke: "#2f3a44",
|
|
593
|
+
riserStrokeWidth: 1
|
|
594
|
+
},
|
|
520
595
|
conflict: { stroke: "#e52117", strokeWidth: 4 },
|
|
521
596
|
unitLabels: {
|
|
522
597
|
geologicFill: "#f0f0f0",
|
|
@@ -552,6 +627,39 @@ var DEFAULT_WELL_THEME = {
|
|
|
552
627
|
headerFontWeight: 600,
|
|
553
628
|
bodyFontWeight: 400
|
|
554
629
|
},
|
|
630
|
+
overview: {
|
|
631
|
+
stroke: "#303030",
|
|
632
|
+
strokeWidth: 0.5,
|
|
633
|
+
emptyFill: "#d9d9d9",
|
|
634
|
+
windowStroke: "#c0392b",
|
|
635
|
+
windowStrokeWidth: 1.2
|
|
636
|
+
},
|
|
637
|
+
columnHeaders: {
|
|
638
|
+
fontSize: 6.5,
|
|
639
|
+
color: "#303030",
|
|
640
|
+
fontFamily: "sans-serif",
|
|
641
|
+
fontWeight: 600,
|
|
642
|
+
ruleStroke: "#101010",
|
|
643
|
+
ruleStrokeWidth: 1
|
|
644
|
+
},
|
|
645
|
+
markers: {
|
|
646
|
+
fill: "#ffffff",
|
|
647
|
+
stroke: "#101010",
|
|
648
|
+
strokeWidth: 0.6,
|
|
649
|
+
color: "#101010",
|
|
650
|
+
fontSize: 6,
|
|
651
|
+
fontFamily: "sans-serif",
|
|
652
|
+
fontWeight: 600
|
|
653
|
+
},
|
|
654
|
+
overlap: {
|
|
655
|
+
stroke: "#9a9a9a",
|
|
656
|
+
strokeWidth: 0.6,
|
|
657
|
+
size: 6,
|
|
658
|
+
ruleStroke: "#9a9a9a",
|
|
659
|
+
labelColor: "#555555",
|
|
660
|
+
fontSize: 6.5,
|
|
661
|
+
fontFamily: "monospace"
|
|
662
|
+
},
|
|
555
663
|
legend: {
|
|
556
664
|
borderStrokeWidth: 0.8,
|
|
557
665
|
fractureStrokeWidth: 1.5,
|
|
@@ -609,8 +717,17 @@ var STATIC_RENDER_CONFIG = {
|
|
|
609
717
|
}
|
|
610
718
|
},
|
|
611
719
|
construction: {
|
|
612
|
-
cementPad: {
|
|
613
|
-
|
|
720
|
+
cementPad: { widthRatio: 1.4, height: 6 },
|
|
721
|
+
casingShoe: { active: true, size: 4 },
|
|
722
|
+
screenEnds: { active: true },
|
|
723
|
+
surfaceCase: { diameterPaddingRatio: 0.1 },
|
|
724
|
+
centralizer: { markerHalfHeight: 4 },
|
|
725
|
+
pump: {
|
|
726
|
+
active: true,
|
|
727
|
+
bodyHeight: 22,
|
|
728
|
+
bodyWidthRatio: 0.6,
|
|
729
|
+
riserWidthRatio: 0.3
|
|
730
|
+
}
|
|
614
731
|
},
|
|
615
732
|
tooltipLabels: resolveTooltipLabels("pt"),
|
|
616
733
|
labels: {
|
|
@@ -623,7 +740,11 @@ var STATIC_RENDER_CONFIG = {
|
|
|
623
740
|
stackingLineHeight: 10,
|
|
624
741
|
stackingGap: 0,
|
|
625
742
|
fractureLabelLeaderGap: 5,
|
|
626
|
-
lithology: true
|
|
743
|
+
lithology: true,
|
|
744
|
+
continuation: {
|
|
745
|
+
active: false,
|
|
746
|
+
prefix: resolveRenderLabel(RENDER_LABELS.continuation.prefix, "pt")
|
|
747
|
+
}
|
|
627
748
|
},
|
|
628
749
|
unitLabels: {
|
|
629
750
|
active: true,
|
|
@@ -681,10 +802,22 @@ var STATIC_RENDER_CONFIG = {
|
|
|
681
802
|
wellCase: "Revestimento",
|
|
682
803
|
wellScreen: "Filtro",
|
|
683
804
|
reduction: "Redu\xE7\xE3o",
|
|
805
|
+
centralizer: "Centralizador",
|
|
806
|
+
pump: "Bomba e edutor",
|
|
684
807
|
cementPad: "Laje de cimento",
|
|
685
808
|
conflict: "Conflito"
|
|
686
809
|
}
|
|
687
810
|
},
|
|
811
|
+
overview: { active: false, x: 4, width: 8, height: 200 },
|
|
812
|
+
columnHeaders: {
|
|
813
|
+
active: false,
|
|
814
|
+
height: 14,
|
|
815
|
+
labels: resolveGroup(RENDER_LABELS.columnHeaders, "pt")
|
|
816
|
+
},
|
|
817
|
+
markers: { lithology: false, fractures: false, radius: 4.5 },
|
|
818
|
+
overlap: {
|
|
819
|
+
label: resolveRenderLabel(RENDER_LABELS.overlap.label, "pt")
|
|
820
|
+
},
|
|
688
821
|
highlights: DEFAULT_HIGHLIGHT_CONFIG
|
|
689
822
|
};
|
|
690
823
|
var INTERACTIVE_RENDER_CONFIG = {
|
|
@@ -720,8 +853,17 @@ var INTERACTIVE_RENDER_CONFIG = {
|
|
|
720
853
|
}
|
|
721
854
|
},
|
|
722
855
|
construction: {
|
|
723
|
-
cementPad: {
|
|
724
|
-
|
|
856
|
+
cementPad: { widthRatio: 1.4, height: 6 },
|
|
857
|
+
casingShoe: { active: true, size: 4 },
|
|
858
|
+
screenEnds: { active: true },
|
|
859
|
+
surfaceCase: { diameterPaddingRatio: 0.1 },
|
|
860
|
+
centralizer: { markerHalfHeight: 4 },
|
|
861
|
+
pump: {
|
|
862
|
+
active: true,
|
|
863
|
+
bodyHeight: 22,
|
|
864
|
+
bodyWidthRatio: 0.6,
|
|
865
|
+
riserWidthRatio: 0.3
|
|
866
|
+
}
|
|
725
867
|
},
|
|
726
868
|
tooltipLabels: resolveTooltipLabels("pt"),
|
|
727
869
|
labels: {
|
|
@@ -732,7 +874,11 @@ var INTERACTIVE_RENDER_CONFIG = {
|
|
|
732
874
|
descriptionXOffset: 78,
|
|
733
875
|
descriptionMaxWidth: 226,
|
|
734
876
|
stackingLineHeight: 11,
|
|
735
|
-
stackingGap: 0
|
|
877
|
+
stackingGap: 0,
|
|
878
|
+
continuation: {
|
|
879
|
+
active: false,
|
|
880
|
+
prefix: resolveRenderLabel(RENDER_LABELS.continuation.prefix, "pt")
|
|
881
|
+
}
|
|
736
882
|
},
|
|
737
883
|
unitLabels: {
|
|
738
884
|
active: false,
|
|
@@ -789,10 +935,22 @@ var INTERACTIVE_RENDER_CONFIG = {
|
|
|
789
935
|
wellCase: "Revestimento",
|
|
790
936
|
wellScreen: "Filtro",
|
|
791
937
|
reduction: "Redu\xE7\xE3o",
|
|
938
|
+
centralizer: "Centralizador",
|
|
939
|
+
pump: "Bomba e edutor",
|
|
792
940
|
cementPad: "Laje de cimento",
|
|
793
941
|
conflict: "Conflito"
|
|
794
942
|
}
|
|
795
943
|
},
|
|
944
|
+
overview: { active: false, x: 4, width: 8, height: 200 },
|
|
945
|
+
columnHeaders: {
|
|
946
|
+
active: false,
|
|
947
|
+
height: 14,
|
|
948
|
+
labels: resolveGroup(RENDER_LABELS.columnHeaders, "pt")
|
|
949
|
+
},
|
|
950
|
+
markers: { lithology: false, fractures: false, radius: 4.5 },
|
|
951
|
+
overlap: {
|
|
952
|
+
label: resolveRenderLabel(RENDER_LABELS.overlap.label, "pt")
|
|
953
|
+
},
|
|
796
954
|
highlights: DEFAULT_HIGHLIGHT_CONFIG
|
|
797
955
|
};
|
|
798
956
|
|
|
@@ -809,6 +967,8 @@ var import_defu2 = require("defu");
|
|
|
809
967
|
|
|
810
968
|
// src/configs/render.textures.ts
|
|
811
969
|
var import_textures = __toESM(require("textures"), 1);
|
|
970
|
+
var dot = (x, y, r) => `M${x - r},${y}a${r},${r} 0 1,0 ${2 * r},0a${r},${r} 0 1,0 ${-2 * r},0Z`;
|
|
971
|
+
var concreteAggregate = (s) => `M${s * 0.08},${s * 0.42}l${s * 0.3},0l${-s * 0.12},${-s * 0.26}ZM${s * 0.55},${s * 0.92}l${s * 0.26},${-s * 0.06}l${-s * 0.16},${-s * 0.2}Z${dot(s * 0.72, s * 0.24, s * 0.06)}${dot(s * 0.22, s * 0.78, s * 0.05)}`;
|
|
812
972
|
function createWellTextures(cfg) {
|
|
813
973
|
const pad = {
|
|
814
974
|
background: "#ffffff",
|
|
@@ -856,7 +1016,9 @@ function createWellTextures(cfg) {
|
|
|
856
1016
|
...cfg?.surface_case
|
|
857
1017
|
};
|
|
858
1018
|
return {
|
|
859
|
-
|
|
1019
|
+
// Concrete: aggregate (small triangles and dots) on a light ground, so it
|
|
1020
|
+
// reads apart from the seal's diagonals and the gravel pack's circles.
|
|
1021
|
+
pad: import_textures.default.paths().d(concreteAggregate).size(6).strokeWidth(0.4).stroke(pad.stroke).fill(pad.stroke).background(pad.background),
|
|
860
1022
|
conflict: import_textures.default.lines().heavier().stroke(conflict.stroke),
|
|
861
1023
|
cave_dry: import_textures.default.lines().size(cave_dry.size).orientation("6/8").heavier(0.3).thinner(0.8).background(cave_dry.background).stroke(cave_dry.stroke),
|
|
862
1024
|
cave_wet: import_textures.default.lines().size(cave_wet.size).orientation("6/8").heavier(0.3).thinner(0.8).background(cave_wet.background).stroke(cave_wet.stroke),
|
|
@@ -868,8 +1030,8 @@ function createWellTextures(cfg) {
|
|
|
868
1030
|
}
|
|
869
1031
|
|
|
870
1032
|
// src/Renderer.ts
|
|
871
|
-
var
|
|
872
|
-
var
|
|
1033
|
+
var import_core4 = require("@welldot/core");
|
|
1034
|
+
var import_utils10 = require("@welldot/utils");
|
|
873
1035
|
|
|
874
1036
|
// src/configs/render.classnames.ts
|
|
875
1037
|
var DEFAULT_COMPONENTS_CLASS_NAMES = {
|
|
@@ -927,6 +1089,14 @@ var DEFAULT_COMPONENTS_CLASS_NAMES = {
|
|
|
927
1089
|
group: "well-screen",
|
|
928
1090
|
rect: "well-screen-rect"
|
|
929
1091
|
},
|
|
1092
|
+
centralizer: {
|
|
1093
|
+
group: "centralizer",
|
|
1094
|
+
item: "centralizer-marker"
|
|
1095
|
+
},
|
|
1096
|
+
pump: {
|
|
1097
|
+
group: "pump",
|
|
1098
|
+
item: "pump-item"
|
|
1099
|
+
},
|
|
930
1100
|
reduction: {
|
|
931
1101
|
group: "reduction",
|
|
932
1102
|
item: "reduction-poly"
|
|
@@ -958,6 +1128,26 @@ var DEFAULT_COMPONENTS_CLASS_NAMES = {
|
|
|
958
1128
|
caveFill: "cave-fill",
|
|
959
1129
|
constructionRect: "construction-rect"
|
|
960
1130
|
},
|
|
1131
|
+
overview: {
|
|
1132
|
+
group: "wp-overview",
|
|
1133
|
+
item: "wp-overview-item",
|
|
1134
|
+
window: "wp-overview-window"
|
|
1135
|
+
},
|
|
1136
|
+
columnHeaders: {
|
|
1137
|
+
group: "wp-column-headers",
|
|
1138
|
+
text: "wp-column-header",
|
|
1139
|
+
rule: "wp-column-headers-rule"
|
|
1140
|
+
},
|
|
1141
|
+
markers: {
|
|
1142
|
+
group: "wp-markers",
|
|
1143
|
+
lithology: "wp-marker-lithology",
|
|
1144
|
+
fracture: "wp-marker-fracture"
|
|
1145
|
+
},
|
|
1146
|
+
overlap: {
|
|
1147
|
+
group: "wp-overlap",
|
|
1148
|
+
band: "wp-overlap-band",
|
|
1149
|
+
label: "wp-overlap-label"
|
|
1150
|
+
},
|
|
961
1151
|
highlights: {
|
|
962
1152
|
geologicGroup: "wp-highlights-geologic",
|
|
963
1153
|
constructionGroup: "wp-highlights-construction",
|
|
@@ -972,6 +1162,156 @@ var DEFAULT_COMPONENTS_CLASS_NAMES = {
|
|
|
972
1162
|
// src/utils/render.utils.ts
|
|
973
1163
|
var import_textures2 = __toESM(require("textures"), 1);
|
|
974
1164
|
|
|
1165
|
+
// src/utils/construction.geometry.ts
|
|
1166
|
+
var JOINT_EPS = 1e-3;
|
|
1167
|
+
function diameterAt(items, depth) {
|
|
1168
|
+
return items.find((i) => depth >= i.from && depth <= i.to)?.diameter;
|
|
1169
|
+
}
|
|
1170
|
+
function getIntervalEnds(item, string, depthFrom, depthTo) {
|
|
1171
|
+
return {
|
|
1172
|
+
cutTop: item.from < depthFrom - JOINT_EPS,
|
|
1173
|
+
cutBottom: item.to > depthTo + JOINT_EPS,
|
|
1174
|
+
joinedTop: string.some(
|
|
1175
|
+
(o) => o !== item && Math.abs(o.to - item.from) < JOINT_EPS
|
|
1176
|
+
),
|
|
1177
|
+
joinedBottom: string.some(
|
|
1178
|
+
(o) => o !== item && Math.abs(o.from - item.to) < JOINT_EPS
|
|
1179
|
+
)
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
function pipeWallsPath(xLeft, xRight, yTop, yBottom) {
|
|
1183
|
+
return `M${xLeft},${yTop}V${yBottom}M${xRight},${yTop}V${yBottom}`;
|
|
1184
|
+
}
|
|
1185
|
+
function shoePath(xLeft, xRight, y, size) {
|
|
1186
|
+
return `M${xLeft},${y - size}L${xLeft},${y}L${xLeft - size},${y}ZM${xRight},${y - size}L${xRight},${y}L${xRight + size},${y}Z`;
|
|
1187
|
+
}
|
|
1188
|
+
function screenEndPath(xLeft, xRight, y) {
|
|
1189
|
+
return `M${xLeft},${y}H${xRight}`;
|
|
1190
|
+
}
|
|
1191
|
+
var clampDepth = (s, depth) => Math.min(Math.max(depth, s.depthFrom), s.depthTo);
|
|
1192
|
+
var inPanel = (s, depth) => depth >= s.depthFrom - JOINT_EPS && depth <= s.depthTo + JOINT_EPS;
|
|
1193
|
+
var shoulders = (s, a, b, y) => `M${s.left(a)},${y}H${s.left(b)}M${s.right(a)},${y}H${s.right(b)}`;
|
|
1194
|
+
function boreHoleOutlinePath(item, holes, s) {
|
|
1195
|
+
const yTop = s.y(clampDepth(s, item.from));
|
|
1196
|
+
const yBottom = s.y(clampDepth(s, item.to));
|
|
1197
|
+
let d = pipeWallsPath(
|
|
1198
|
+
s.left(item.diameter),
|
|
1199
|
+
s.right(item.diameter),
|
|
1200
|
+
yTop,
|
|
1201
|
+
yBottom
|
|
1202
|
+
);
|
|
1203
|
+
if (item.from > JOINT_EPS && inPanel(s, item.from)) {
|
|
1204
|
+
const above = holes.find(
|
|
1205
|
+
(o) => o !== item && o.from < item.from && o.to >= item.from - JOINT_EPS
|
|
1206
|
+
);
|
|
1207
|
+
if (above && above.diameter < item.diameter)
|
|
1208
|
+
d += shoulders(s, above.diameter, item.diameter, yTop);
|
|
1209
|
+
}
|
|
1210
|
+
if (inPanel(s, item.to)) {
|
|
1211
|
+
const below = holes.find(
|
|
1212
|
+
(o) => o !== item && o.from <= item.to + JOINT_EPS && o.to > item.to
|
|
1213
|
+
);
|
|
1214
|
+
if (!below) {
|
|
1215
|
+
d += `M${s.left(item.diameter)},${yBottom}H${s.right(item.diameter)}`;
|
|
1216
|
+
} else if (below.diameter < item.diameter) {
|
|
1217
|
+
d += shoulders(s, item.diameter, below.diameter, yBottom);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return d;
|
|
1221
|
+
}
|
|
1222
|
+
function holeFillOutlinePath(item, pipes, s) {
|
|
1223
|
+
const yTop = s.y(clampDepth(s, item.from));
|
|
1224
|
+
const yBottom = s.y(clampDepth(s, item.to));
|
|
1225
|
+
const xL = s.left(item.diameter);
|
|
1226
|
+
const xR = s.right(item.diameter);
|
|
1227
|
+
let d = pipeWallsPath(xL, xR, yTop, yBottom);
|
|
1228
|
+
const interfaces = [item.from, item.to].filter(
|
|
1229
|
+
(depth) => depth > JOINT_EPS && inPanel(s, depth)
|
|
1230
|
+
);
|
|
1231
|
+
for (const depth of interfaces) {
|
|
1232
|
+
const y = s.y(depth);
|
|
1233
|
+
const pipe = diameterAt(pipes, depth);
|
|
1234
|
+
if (pipe !== void 0 && pipe < item.diameter) {
|
|
1235
|
+
d += `M${xL},${y}H${s.left(pipe)}M${s.right(pipe)},${y}H${xR}`;
|
|
1236
|
+
} else {
|
|
1237
|
+
d += `M${xL},${y}H${xR}`;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
return d;
|
|
1241
|
+
}
|
|
1242
|
+
function pipeSlices(pipes, from, to) {
|
|
1243
|
+
const cuts = [.../* @__PURE__ */ new Set([from, to, ...pipes.flatMap((p) => [p.from, p.to])])].filter((d) => d >= from && d <= to).sort((a, b) => a - b);
|
|
1244
|
+
const slices = [];
|
|
1245
|
+
for (let i = 1; i < cuts.length; i++) {
|
|
1246
|
+
const a = cuts[i - 1];
|
|
1247
|
+
const b = cuts[i];
|
|
1248
|
+
const mid = (a + b) / 2;
|
|
1249
|
+
const widest = Math.max(
|
|
1250
|
+
0,
|
|
1251
|
+
...pipes.filter((p) => p.from <= mid && p.to >= mid).map((p) => p.diameter)
|
|
1252
|
+
);
|
|
1253
|
+
if (widest === 0) continue;
|
|
1254
|
+
const last = slices[slices.length - 1];
|
|
1255
|
+
if (last && last.to === a && last.diameter === widest) last.to = b;
|
|
1256
|
+
else slices.push({ from: a, to: b, diameter: widest });
|
|
1257
|
+
}
|
|
1258
|
+
return slices;
|
|
1259
|
+
}
|
|
1260
|
+
function annulusFillPath(item, pipes, s) {
|
|
1261
|
+
const from = clampDepth(s, item.from);
|
|
1262
|
+
const to = clampDepth(s, item.to);
|
|
1263
|
+
const box = (dia, a, b) => `M${s.left(dia)},${s.y(a)}H${s.right(dia)}V${s.y(b)}H${s.left(dia)}Z`;
|
|
1264
|
+
const inner = pipes.filter((p) => p.diameter < item.diameter);
|
|
1265
|
+
return box(item.diameter, from, to) + pipeSlices(inner, from, to).map((p) => box(p.diameter, p.from, p.to)).join("");
|
|
1266
|
+
}
|
|
1267
|
+
function getPadDiameters(data, surfaceCasePaddingRatio) {
|
|
1268
|
+
const surfaceCase = diameterAt(data.surface_case, 0);
|
|
1269
|
+
const paddedSurfaceCase = surfaceCase === void 0 ? void 0 : surfaceCase * (1 + surfaceCasePaddingRatio);
|
|
1270
|
+
const casing = diameterAt([...data.well_case, ...data.well_screen], 0);
|
|
1271
|
+
const hole = diameterAt(data.bore_hole, 0);
|
|
1272
|
+
const opening = casing ?? paddedSurfaceCase ?? hole ?? 0;
|
|
1273
|
+
const outer = Math.max(
|
|
1274
|
+
opening,
|
|
1275
|
+
paddedSurfaceCase ?? 0,
|
|
1276
|
+
hole ?? 0,
|
|
1277
|
+
diameterAt(data.hole_fill, 0) ?? 0
|
|
1278
|
+
);
|
|
1279
|
+
return { opening, outer };
|
|
1280
|
+
}
|
|
1281
|
+
function getCementPadGeometry(pocoWidth, pocoCenter, surfaceY, config, openingWidth = 0, outerWidth = openingWidth) {
|
|
1282
|
+
const h = config.height;
|
|
1283
|
+
const opening = Math.max(0, openingWidth);
|
|
1284
|
+
const width = Math.max(
|
|
1285
|
+
pocoWidth * config.widthRatio,
|
|
1286
|
+
opening + 3 * h,
|
|
1287
|
+
outerWidth + 2 * h
|
|
1288
|
+
);
|
|
1289
|
+
const xLeft = (pocoCenter - width) / 2;
|
|
1290
|
+
const xRight = xLeft + width;
|
|
1291
|
+
const oLeft = (pocoCenter - opening) / 2;
|
|
1292
|
+
const oRight = oLeft + opening;
|
|
1293
|
+
const yTop = surfaceY - h;
|
|
1294
|
+
const a = h * 0.3;
|
|
1295
|
+
const breakLine = (x, y0, y1, dir) => `L${x + dir * a},${y0 + (y1 - y0) * 0.4}L${x - dir * a},${y0 + (y1 - y0) * 0.6}L${x},${y1}`;
|
|
1296
|
+
const bbox = { x: xLeft, y: yTop, width, height: h };
|
|
1297
|
+
if (opening === 0) {
|
|
1298
|
+
return {
|
|
1299
|
+
bbox,
|
|
1300
|
+
slabs: [
|
|
1301
|
+
`M${xLeft},${yTop}H${xRight}${breakLine(xRight, yTop, surfaceY, 1)}H${xLeft}${breakLine(xLeft, surfaceY, yTop, -1)}Z`,
|
|
1302
|
+
""
|
|
1303
|
+
]
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
return {
|
|
1307
|
+
bbox,
|
|
1308
|
+
slabs: [
|
|
1309
|
+
`M${oLeft},${yTop}H${xLeft}${breakLine(xLeft, yTop, surfaceY, -1)}H${oLeft}Z`,
|
|
1310
|
+
`M${oRight},${yTop}H${xRight}${breakLine(xRight, yTop, surfaceY, 1)}H${oRight}Z`
|
|
1311
|
+
]
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
975
1315
|
// src/utils/d3.utils.ts
|
|
976
1316
|
function mergeEnter(enter, update) {
|
|
977
1317
|
return enter.merge(update);
|
|
@@ -1042,6 +1382,7 @@ var makeSeededPrng = (seed, scramble = 6271) => {
|
|
|
1042
1382
|
// src/utils/tooltips.utils.ts
|
|
1043
1383
|
var import_d3_tip = __toESM(require("d3-tip"), 1);
|
|
1044
1384
|
var import_sanitize_html = __toESM(require("sanitize-html"), 1);
|
|
1385
|
+
var import_core2 = require("@welldot/core");
|
|
1045
1386
|
var import_utils2 = require("@welldot/utils");
|
|
1046
1387
|
var esc = (v) => (0, import_sanitize_html.default)(String(v ?? ""), { allowedTags: [], allowedAttributes: {} });
|
|
1047
1388
|
var _tooltipCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1052,6 +1393,7 @@ var populateTooltips = (svg, customClasses, units, tooltipConfig, labels, locale
|
|
|
1052
1393
|
if (cached && cached.signature === signature) {
|
|
1053
1394
|
return cached.tooltips;
|
|
1054
1395
|
}
|
|
1396
|
+
const material = (value) => (0, import_core2.getVocabLabel)(import_core2.CONSTRUCTION_MATERIALS, value, locale);
|
|
1055
1397
|
const tipsText = {
|
|
1056
1398
|
geology: (_, d) => `
|
|
1057
1399
|
<span class="${customClasses.tooltip.title}">${labels.geology.title}</span>
|
|
@@ -1084,14 +1426,15 @@ var populateTooltips = (svg, customClasses, units, tooltipConfig, labels, locale
|
|
|
1084
1426
|
<span class="${customClasses.tooltip.secondaryInfo}">
|
|
1085
1427
|
<strong>${labels.common.diameter}</strong> ${esc(formatDiameter(d.diameter, units.diameter, locale))} ${esc(getDiameterUnit(units.diameter, locale))}
|
|
1086
1428
|
</span>
|
|
1087
|
-
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.type}</strong> ${esc(d.type)}</span>
|
|
1429
|
+
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.type}</strong> ${esc(material(d.type))}</span>
|
|
1088
1430
|
`,
|
|
1089
1431
|
wellScreen: (_, d) => `
|
|
1090
1432
|
<span class="${customClasses.tooltip.title}">${labels.wellScreen.title}</span>
|
|
1091
1433
|
<span class="${customClasses.tooltip.primaryInfo}">${labels.common.from} ${esc(formatLength(d.from, units.length, locale))} ${esc(getLengthUnit(units.length))} ${labels.common.to} ${esc(formatLength(d.to, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>
|
|
1092
1434
|
<span class="${customClasses.tooltip.secondaryInfo}">
|
|
1093
1435
|
<strong>${labels.common.diameter}</strong> ${esc(formatDiameter(d.diameter, units.diameter, locale))} ${esc(getDiameterUnit(units.diameter, locale))}</span>
|
|
1094
|
-
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.
|
|
1436
|
+
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.wellScreen.material}</strong> ${esc(material(d.type))}</span>
|
|
1437
|
+
${d.slot_type ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.wellScreen.slotType}</strong> ${esc((0, import_core2.getVocabLabel)(import_core2.SCREEN_SLOT_TYPES, d.slot_type, locale))}</span>` : ""}
|
|
1095
1438
|
<span class="${customClasses.tooltip.secondaryInfo}">
|
|
1096
1439
|
<strong>${labels.wellScreen.slot}</strong> ${esc((0, import_utils2.formatNumber)(d.screen_slot, { maximumFractionDigits: 2, locale }))} mm
|
|
1097
1440
|
</span>
|
|
@@ -1102,8 +1445,29 @@ var populateTooltips = (svg, customClasses, units, tooltipConfig, labels, locale
|
|
|
1102
1445
|
<span class="${customClasses.tooltip.secondaryInfo}">
|
|
1103
1446
|
<strong>${labels.common.diameter}</strong> ${esc(formatDiameter(d.diam_from, units.diameter, locale))} \u2192 ${esc(formatDiameter(d.diam_to, units.diameter, locale))} ${esc(getDiameterUnit(units.diameter, locale))}
|
|
1104
1447
|
</span>
|
|
1105
|
-
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.type}</strong> ${esc(d.type)}</span>
|
|
1448
|
+
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.type}</strong> ${esc(material(d.type))}</span>
|
|
1106
1449
|
`,
|
|
1450
|
+
centralizer: (_, d) => `
|
|
1451
|
+
<span class="${customClasses.tooltip.title}">${labels.centralizer.title}</span>
|
|
1452
|
+
<span class="${customClasses.tooltip.primaryInfo}"><strong>${labels.centralizer.depth}</strong> ${esc(formatLength(d.depth, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>
|
|
1453
|
+
${d.from !== d.to ? `<span class="${customClasses.tooltip.secondaryInfo}">${labels.common.from} ${esc(formatLength(d.from, units.length, locale))} ${esc(getLengthUnit(units.length))} ${labels.common.to} ${esc(formatLength(d.to, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>` : ""}
|
|
1454
|
+
${d.spacing ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.centralizer.spacing}</strong> ${esc(formatLength(d.spacing, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>` : ""}
|
|
1455
|
+
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.type}</strong> ${esc((0, import_core2.getVocabLabel)(import_core2.CENTRALIZER_TYPES, d.type, locale))}</span>
|
|
1456
|
+
${d.diameter ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.diameter}</strong> ${esc(formatDiameter(d.diameter, units.diameter, locale))} ${esc(getDiameterUnit(units.diameter, locale))}</span>` : ""}
|
|
1457
|
+
${d.description ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.description}</strong> ${esc(d.description)}</span>` : ""}
|
|
1458
|
+
`,
|
|
1459
|
+
pump: (_, d) => {
|
|
1460
|
+
const typeLabel = labels.pump[`type_${d.type}`] ?? d.type;
|
|
1461
|
+
const model = [d.manufacturer, d.model].filter(Boolean).join(" ");
|
|
1462
|
+
return `
|
|
1463
|
+
<span class="${customClasses.tooltip.title}">${labels.pump.title}</span>
|
|
1464
|
+
<span class="${customClasses.tooltip.primaryInfo}">${esc(typeLabel)}</span>
|
|
1465
|
+
${d.intake_depth !== void 0 ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.pump.intakeDepth}</strong> ${esc(formatLength(d.intake_depth, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>` : ""}
|
|
1466
|
+
${model ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.pump.model}</strong> ${esc(model)}</span>` : ""}
|
|
1467
|
+
${d.rated_power !== void 0 ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.pump.power}</strong> ${esc((0, import_utils2.formatNumber)((0, import_core2.powerFromCanonical)(d.rated_power, units.power ?? "kW"), { maximumFractionDigits: 2, locale }))} ${esc(units.power ?? "kW")}</span>` : ""}
|
|
1468
|
+
${d.riser_diameter !== void 0 ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.pump.riser}</strong> ${esc(formatDiameter(d.riser_diameter, units.diameter, locale))} ${esc(getDiameterUnit(units.diameter, locale))}${d.riser_material ? ` \xB7 ${esc(material(d.riser_material))}` : ""}</span>` : ""}
|
|
1469
|
+
`;
|
|
1470
|
+
},
|
|
1107
1471
|
conflict: (_, d) => `
|
|
1108
1472
|
<span class="${customClasses.tooltip.title}">${labels.conflict.title}</span>
|
|
1109
1473
|
<span class="${customClasses.tooltip.primaryInfo}">${labels.common.from} ${esc(formatLength(d.from, units.length, locale))} ${esc(getLengthUnit(units.length))} ${labels.common.to} ${esc(formatLength(d.to, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>
|
|
@@ -1114,14 +1478,14 @@ var populateTooltips = (svg, customClasses, units, tooltipConfig, labels, locale
|
|
|
1114
1478
|
<span class="${customClasses.tooltip.title}">${title}</span>
|
|
1115
1479
|
<span class="${customClasses.tooltip.primaryInfo}"><strong>${labels.fracture.depth}</strong> ${esc(formatLength(d.depth, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>
|
|
1116
1480
|
${d.water_intake ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.fracture.waterIntake}</strong> ${esc(formatLength(d.depth, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>` : ""}
|
|
1117
|
-
|
|
1118
|
-
|
|
1481
|
+
${typeof d.dip === "number" ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.fracture.dip}</strong> ${esc(d.dip)}\xB0</span>` : ""}
|
|
1482
|
+
${typeof d.azimuth === "number" ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.fracture.azimuth}</strong> ${esc(d.azimuth)}\xB0</span>` : ""}
|
|
1119
1483
|
${d.description ? `<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.common.description}</strong> ${esc(d.description)}</span>` : ""}
|
|
1120
1484
|
`;
|
|
1121
1485
|
},
|
|
1122
1486
|
cementPad: (_, d) => `
|
|
1123
1487
|
<span class="${customClasses.tooltip.title}">${labels.cementPad.title}</span>
|
|
1124
|
-
<span class="${customClasses.tooltip.primaryInfo}">${esc(d.type)}</span>
|
|
1488
|
+
<span class="${customClasses.tooltip.primaryInfo}">${esc((0, import_core2.getVocabLabel)(import_core2.CEMENT_PAD_TYPES, d.type, locale))}</span>
|
|
1125
1489
|
<span class="${customClasses.tooltip.secondaryInfo}"><strong>${labels.cementPad.thickness}</strong>
|
|
1126
1490
|
${esc(formatLength(d.thickness, units.length, locale))} ${esc(getLengthUnit(units.length))}</span>
|
|
1127
1491
|
<span class="${customClasses.tooltip.secondaryInfo}">
|
|
@@ -1159,6 +1523,17 @@ var populateTooltips = (svg, customClasses, units, tooltipConfig, labels, locale
|
|
|
1159
1523
|
};
|
|
1160
1524
|
|
|
1161
1525
|
// src/utils/render.utils.ts
|
|
1526
|
+
var fractureDip = (dip) => typeof dip === "number" && Number.isFinite(dip) ? dip : 0;
|
|
1527
|
+
function getCementPadRect(pocoWidth, pocoCenter, surfaceY, config, openingWidth = 0, outerWidth = openingWidth) {
|
|
1528
|
+
return getCementPadGeometry(
|
|
1529
|
+
pocoWidth,
|
|
1530
|
+
pocoCenter,
|
|
1531
|
+
surfaceY,
|
|
1532
|
+
config,
|
|
1533
|
+
openingWidth,
|
|
1534
|
+
outerWidth
|
|
1535
|
+
).bbox;
|
|
1536
|
+
}
|
|
1162
1537
|
var _fgdcTextures = {};
|
|
1163
1538
|
var _fgdcTexturesPromise = null;
|
|
1164
1539
|
var preloadFgdcTextures = () => {
|
|
@@ -1267,14 +1642,23 @@ function drawAnnotationLabels(ctx, data) {
|
|
|
1267
1642
|
}
|
|
1268
1643
|
const items = [];
|
|
1269
1644
|
if (active.has("lithology")) {
|
|
1645
|
+
const continuation = s.continuation;
|
|
1270
1646
|
data.lithology.filter((d) => d.from < ctx.depthTo).forEach((d) => {
|
|
1647
|
+
const range = `${formatLength(d.from, ctx.units.length, ctx.locale)}\u2013${formatLength(d.to, ctx.units.length, ctx.locale)}${getLengthUnit(ctx.units.length)}`;
|
|
1648
|
+
const continues = continuation?.active && d.from < ctx.depthFrom;
|
|
1271
1649
|
items.push({
|
|
1272
1650
|
sortDepth: d.from,
|
|
1273
1651
|
baseY: ctx.yScale(Math.max(d.from, ctx.depthFrom)),
|
|
1274
1652
|
originX: ctx.geoXRight,
|
|
1275
1653
|
originY: ctx.yScale(Math.max(d.from, ctx.depthFrom)),
|
|
1276
|
-
header:
|
|
1277
|
-
description: d.description || ""
|
|
1654
|
+
header: continues ? `\u2191 ${continuation.prefix} \xB7 ${range}` : range,
|
|
1655
|
+
description: continues ? "" : d.description || "",
|
|
1656
|
+
...show.has("units") ? {
|
|
1657
|
+
unit: d.geologic_unit || void 0,
|
|
1658
|
+
aquifer: continues ? void 0 : d.aquifer_unit || void 0
|
|
1659
|
+
} : {},
|
|
1660
|
+
...show.has("swatch") && !continues ? { swatch: d } : {},
|
|
1661
|
+
...show.has("rules") ? { rule: continues ? "dashed" : "solid" } : {}
|
|
1278
1662
|
});
|
|
1279
1663
|
});
|
|
1280
1664
|
}
|
|
@@ -1287,7 +1671,8 @@ function drawAnnotationLabels(ctx, data) {
|
|
|
1287
1671
|
originX: ctx.pocoCenterX,
|
|
1288
1672
|
originY: ctx.yScale(d.depth),
|
|
1289
1673
|
header: `${formatLength(d.depth, ctx.units.length, ctx.locale)}${getLengthUnit(ctx.units.length)} \xB7 ${typeLabel}`,
|
|
1290
|
-
description: d.description || ""
|
|
1674
|
+
description: d.description || "",
|
|
1675
|
+
...show.has("rules") ? { rule: "dashed" } : {}
|
|
1291
1676
|
});
|
|
1292
1677
|
});
|
|
1293
1678
|
}
|
|
@@ -1307,14 +1692,15 @@ function drawAnnotationLabels(ctx, data) {
|
|
|
1307
1692
|
}
|
|
1308
1693
|
items.sort((a, b) => a.sortDepth - b.sortDepth);
|
|
1309
1694
|
const labelPositions = [];
|
|
1310
|
-
let currY = 0;
|
|
1695
|
+
let currY = ctx.repeatedTo != null ? s.stackingLineHeight + 2 : 0;
|
|
1311
1696
|
const charsPerLine = Math.max(
|
|
1312
1697
|
1,
|
|
1313
1698
|
Math.floor(s.descriptionMaxWidth / (st.fontSize * 0.6))
|
|
1314
1699
|
);
|
|
1315
1700
|
items.forEach((item) => {
|
|
1316
|
-
const descLines = Math.ceil((item.description.length || 1) / charsPerLine);
|
|
1317
|
-
const
|
|
1701
|
+
const descLines = show.has("units") ? item.description ? wrapText(item.description, charsPerLine).length : 0 : Math.ceil((item.description.length || 1) / charsPerLine);
|
|
1702
|
+
const extraLines = (item.unit ? 1 : 0) + (item.aquifer ? 1 : 0);
|
|
1703
|
+
const estH = (1 + descLines + extraLines) * s.stackingLineHeight + 4;
|
|
1318
1704
|
const yLabel = Math.max(item.baseY, currY + s.stackingGap);
|
|
1319
1705
|
currY = yLabel + estH;
|
|
1320
1706
|
labelPositions.push({ item, yLabel, estH });
|
|
@@ -1331,16 +1717,41 @@ function drawAnnotationLabels(ctx, data) {
|
|
|
1331
1717
|
if (show.has("description")) {
|
|
1332
1718
|
const lineH = s.stackingLineHeight;
|
|
1333
1719
|
const bgFill = st.annotationBg ?? "white";
|
|
1720
|
+
const swatchFill = labelPositions.some((p) => p.item.swatch) ? getLithologyFill(data.lithology, ctx.svg, ctx.theme.lithologyTexture) : null;
|
|
1334
1721
|
labelPositions.forEach(({ item, yLabel, estH }) => {
|
|
1335
1722
|
const labelG = ctx.groups.lithologyLabelsGroup.append("g").attr("class", ctx.classes.labels.lithology.label).attr("transform", `translate(${labelX},${yLabel})`);
|
|
1336
1723
|
labelG.append("rect").attr("x", 0).attr("y", 0).attr("width", s.descriptionMaxWidth).attr("height", estH).attr("rx", st.annotationRadius ?? 2).attr("fill", bgFill).attr("fill-opacity", st.annotationBgOpacity ?? 0.85).attr("stroke", st.annotationBorderColor ?? "none");
|
|
1337
|
-
|
|
1724
|
+
if (item.rule) {
|
|
1725
|
+
labelG.append("line").attr("x1", 0).attr("x2", s.descriptionMaxWidth).attr("y1", 0).attr("y2", 0).attr("stroke", ctx.theme.labels.color).attr(
|
|
1726
|
+
"stroke-width",
|
|
1727
|
+
item.rule === "solid" ? 0.8 : ctx.theme.labels.dividerStrokeWidth
|
|
1728
|
+
).attr(
|
|
1729
|
+
"stroke-dasharray",
|
|
1730
|
+
item.rule === "solid" ? null : ctx.theme.labels.dividerStrokeDasharray
|
|
1731
|
+
);
|
|
1732
|
+
}
|
|
1733
|
+
let headerX = 0;
|
|
1734
|
+
if (item.swatch && swatchFill) {
|
|
1735
|
+
const size = lineH * 0.75;
|
|
1736
|
+
labelG.append("rect").attr("x", 0).attr("y", lineH * 0.85 - size + 1).attr("width", size).attr("height", size).attr("fill", swatchFill(item.swatch)).attr("stroke", ctx.theme.lithology.stroke).attr("stroke-width", 0.5);
|
|
1737
|
+
headerX = size + 3;
|
|
1738
|
+
}
|
|
1739
|
+
labelG.append("text").attr("class", "wp-annotation-header").attr("fill", ctx.theme.labels.color).attr("font-weight", st.headerFontWeight ?? 600).attr("font-family", ctx.theme.labels.headerFont).attr("x", headerX).attr("y", lineH * 0.85).attr("font-size", st.fontSize).text(item.header);
|
|
1740
|
+
let lineY = lineH * 0.85 + lineH;
|
|
1741
|
+
if (item.unit) {
|
|
1742
|
+
labelG.append("text").attr("class", "wp-annotation-unit").attr("fill", ctx.theme.labels.color).attr("font-weight", st.headerFontWeight ?? 600).attr("font-family", ctx.theme.labels.bodyFont ?? "sans-serif").attr("x", 0).attr("y", lineY).attr("font-size", st.fontSize).text(item.unit);
|
|
1743
|
+
lineY += lineH;
|
|
1744
|
+
}
|
|
1338
1745
|
if (item.description) {
|
|
1339
1746
|
const lines = wrapText(item.description, charsPerLine);
|
|
1340
|
-
const bodyEl = labelG.append("text").attr("class", "wp-annotation-body").attr("fill", ctx.theme.labels.bodyColor).attr("font-weight", st.bodyFontWeight ?? 400).attr("font-family", ctx.theme.labels.bodyFont ?? "sans-serif").attr("x", 0).attr("y",
|
|
1747
|
+
const bodyEl = labelG.append("text").attr("class", "wp-annotation-body").attr("fill", ctx.theme.labels.bodyColor).attr("font-weight", st.bodyFontWeight ?? 400).attr("font-family", ctx.theme.labels.bodyFont ?? "sans-serif").attr("x", 0).attr("y", lineY).attr("font-size", st.fontSize);
|
|
1341
1748
|
lines.forEach((line, i) => {
|
|
1342
1749
|
bodyEl.append("tspan").attr("x", 0).attr("dy", i === 0 ? 0 : lineH).text(line);
|
|
1343
1750
|
});
|
|
1751
|
+
lineY += lines.length * lineH;
|
|
1752
|
+
}
|
|
1753
|
+
if (item.aquifer) {
|
|
1754
|
+
labelG.append("text").attr("class", "wp-annotation-aquifer").attr("fill", ctx.theme.labels.bodyColor).attr("font-style", "italic").attr("font-family", ctx.theme.labels.bodyFont ?? "sans-serif").attr("x", 0).attr("y", lineY).attr("font-size", st.fontSize).text(item.aquifer);
|
|
1344
1755
|
}
|
|
1345
1756
|
});
|
|
1346
1757
|
}
|
|
@@ -1361,7 +1772,6 @@ var makePointKey = (type) => (d, i) => {
|
|
|
1361
1772
|
|
|
1362
1773
|
// src/renderers/caves.renderer.ts
|
|
1363
1774
|
function drawCaves(ctx, data) {
|
|
1364
|
-
if (!data.length) return;
|
|
1365
1775
|
const {
|
|
1366
1776
|
groups: { cavesGroup },
|
|
1367
1777
|
geoXLeft,
|
|
@@ -1371,7 +1781,7 @@ function drawCaves(ctx, data) {
|
|
|
1371
1781
|
yScale,
|
|
1372
1782
|
renderConfig,
|
|
1373
1783
|
theme,
|
|
1374
|
-
textures:
|
|
1784
|
+
textures: textures4,
|
|
1375
1785
|
classes,
|
|
1376
1786
|
tooltips
|
|
1377
1787
|
} = ctx;
|
|
@@ -1408,7 +1818,7 @@ function drawCaves(ctx, data) {
|
|
|
1408
1818
|
const botPath = botCut ? `M ${geoXLeft.toFixed(1)},${yBot.toFixed(1)} L ${geoXRight.toFixed(1)},${yBot.toFixed(1)}` : ptsToSmoothPath(botPts);
|
|
1409
1819
|
const botReversed = botCut ? `L ${geoXLeft.toFixed(1)},${yBot.toFixed(1)}` : ptsToSmoothPath([...botPts].reverse(), { omitMoveTo: true });
|
|
1410
1820
|
const closedPath = `${topPath} L ${geoXRight.toFixed(1)},${yBot.toFixed(1)}${botReversed} L ${geoXLeft.toFixed(1)},${yTop.toFixed(1)} Z`;
|
|
1411
|
-
const caveTexture = cave.water_intake ?
|
|
1821
|
+
const caveTexture = cave.water_intake ? textures4.cave_wet : textures4.cave_dry;
|
|
1412
1822
|
const caveStroke = cave.water_intake ? theme.cave.wetStroke : theme.cave.dryStroke;
|
|
1413
1823
|
g.append("path").attr("class", classes.caves.fill).attr("d", closedPath).attr("fill", caveTexture.url()).attr("fill-opacity", theme.cave.fillOpacity).attr("stroke", "none");
|
|
1414
1824
|
g.append("path").attr("class", classes.caves.contact).attr("d", topPath).attr("fill", "none").attr("stroke", caveStroke).attr("stroke-width", theme.cave.contactStrokeWidth).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
@@ -1417,9 +1827,148 @@ function drawCaves(ctx, data) {
|
|
|
1417
1827
|
merged.transition(ctx.transition).style("opacity", 1);
|
|
1418
1828
|
}
|
|
1419
1829
|
|
|
1420
|
-
// src/renderers/
|
|
1830
|
+
// src/renderers/centralizers.renderer.ts
|
|
1421
1831
|
var d32 = __toESM(require("d3"), 1);
|
|
1422
1832
|
var import_utils3 = require("@welldot/utils");
|
|
1833
|
+
function drawCentralizers(ctx, data) {
|
|
1834
|
+
const group = ctx.groups.centralizerGroup;
|
|
1835
|
+
const cls = ctx.classes.centralizer;
|
|
1836
|
+
const maxXValue = d32.max((0, import_utils3.getProfileDiamValues)(ctx.constructionData)) || 0;
|
|
1837
|
+
const xScale = d32.scaleLinear().domain([0, maxXValue]).range([0, ctx.POCO_WIDTH]);
|
|
1838
|
+
const pipes = [
|
|
1839
|
+
...ctx.constructionData.well_case,
|
|
1840
|
+
...ctx.constructionData.well_screen
|
|
1841
|
+
];
|
|
1842
|
+
const holes = ctx.constructionData.bore_hole;
|
|
1843
|
+
const markers = (data.centralizers ?? []).flatMap(
|
|
1844
|
+
(c) => (0, import_utils3.getCentralizerDepths)(c).filter((depth) => depth >= ctx.depthFrom && depth < ctx.depthTo).map((depth) => ({ ...c, depth }))
|
|
1845
|
+
);
|
|
1846
|
+
const halfH = ctx.renderConfig.construction.centralizer.markerHalfHeight;
|
|
1847
|
+
const bowPoints = (m, side) => {
|
|
1848
|
+
const outerD = m.diameter ?? diameterAt(holes, m.depth) ?? maxXValue;
|
|
1849
|
+
const pipeD = diameterAt(pipes, m.depth) ?? outerD * 0.75;
|
|
1850
|
+
const pipeX = (ctx.POCO_CENTER + side * xScale(pipeD)) / 2;
|
|
1851
|
+
const outerX = (ctx.POCO_CENTER + side * xScale(outerD)) / 2;
|
|
1852
|
+
const y = ctx.yScale(m.depth);
|
|
1853
|
+
return `${pipeX},${y - halfH} ${outerX},${y} ${pipeX},${y + halfH}`;
|
|
1854
|
+
};
|
|
1855
|
+
const selection = group.selectAll(`g.${cls.item}`).data(markers, (d) => `${d.from}:${d.to}:${d.depth}`);
|
|
1856
|
+
selection.exit().remove();
|
|
1857
|
+
const entered = selection.enter().append("g").attr("class", cls.item).on("mouseover", ctx.tooltips.centralizer.show).on("mouseout", ctx.tooltips.centralizer.hide);
|
|
1858
|
+
entered.append("polyline").attr("class", `${cls.item}-left`);
|
|
1859
|
+
entered.append("polyline").attr("class", `${cls.item}-right`);
|
|
1860
|
+
const merged = entered.merge(selection);
|
|
1861
|
+
merged.selectAll("polyline").attr("fill", ctx.theme.centralizer.fill).attr("stroke", ctx.theme.centralizer.stroke).attr("stroke-width", ctx.theme.centralizer.strokeWidth).attr("stroke-linejoin", "round");
|
|
1862
|
+
merged.each((d, i, nodes) => {
|
|
1863
|
+
const g = d32.select(nodes[i]);
|
|
1864
|
+
g.select(`.${cls.item}-left`).attr("points", bowPoints(d, -1));
|
|
1865
|
+
g.select(`.${cls.item}-right`).attr("points", bowPoints(d, 1));
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
// src/utils/layout.utils.ts
|
|
1870
|
+
function getProfileTopDepth(profile) {
|
|
1871
|
+
return Math.min(
|
|
1872
|
+
0,
|
|
1873
|
+
...[
|
|
1874
|
+
...profile.surface_case ?? [],
|
|
1875
|
+
...profile.well_case ?? [],
|
|
1876
|
+
...profile.well_screen ?? []
|
|
1877
|
+
].map((i) => i.from).filter(Number.isFinite)
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1880
|
+
function resolvePanelWindows(panels, totalDepth, topDepth = 0) {
|
|
1881
|
+
if (panels.length > 0 && panels.every((p) => p.depthRange)) {
|
|
1882
|
+
return panels.map((p) => [p.depthRange[0], p.depthRange[1]]);
|
|
1883
|
+
}
|
|
1884
|
+
if (panels.length === 1) return [[topDepth, totalDepth]];
|
|
1885
|
+
const totalHeight = panels.reduce((s, p) => s + p.height, 0) || 1;
|
|
1886
|
+
const metersPerPx = (totalDepth - topDepth) / totalHeight;
|
|
1887
|
+
let current = topDepth;
|
|
1888
|
+
return panels.map((p) => {
|
|
1889
|
+
const from = current;
|
|
1890
|
+
current = from + p.height * metersPerPx;
|
|
1891
|
+
return [from, current];
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1894
|
+
function getColumnHeaderPositions(geometry) {
|
|
1895
|
+
const { marginLeft, geoXLeft, geoXRight, pocoCenterX, descriptionX } = geometry;
|
|
1896
|
+
return {
|
|
1897
|
+
depth: marginLeft - 2,
|
|
1898
|
+
lithology: marginLeft + (geoXLeft + geoXRight) / 2,
|
|
1899
|
+
construction: marginLeft + pocoCenterX,
|
|
1900
|
+
...descriptionX != null ? { description: marginLeft + descriptionX } : {}
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
function getLithologyMarkers(lithology, depthFrom, depthTo) {
|
|
1904
|
+
const markers = [];
|
|
1905
|
+
lithology.forEach((layer, i) => {
|
|
1906
|
+
const from = Math.max(layer.from, depthFrom);
|
|
1907
|
+
const to = Math.min(layer.to, depthTo);
|
|
1908
|
+
if (to > from) markers.push({ index: i + 1, from, to });
|
|
1909
|
+
});
|
|
1910
|
+
return markers;
|
|
1911
|
+
}
|
|
1912
|
+
function getFractureMarkers(fractures, depthFrom, depthTo) {
|
|
1913
|
+
const markers = [];
|
|
1914
|
+
fractures.forEach((f, i) => {
|
|
1915
|
+
if (f.depth >= depthFrom && f.depth < depthTo) {
|
|
1916
|
+
markers.push({ label: `F${i + 1}`, depth: f.depth });
|
|
1917
|
+
}
|
|
1918
|
+
});
|
|
1919
|
+
return markers;
|
|
1920
|
+
}
|
|
1921
|
+
function getOverviewGeometry(totalDepth, height, depthFrom, depthTo) {
|
|
1922
|
+
const ratio = totalDepth > 0 ? height / totalDepth : 0;
|
|
1923
|
+
const y = (depth) => Math.min(height, Math.max(0, depth * ratio));
|
|
1924
|
+
return {
|
|
1925
|
+
y,
|
|
1926
|
+
window: { y: y(depthFrom), height: Math.max(1, y(depthTo) - y(depthFrom)) }
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
function formatOverlapLabel(template, range) {
|
|
1930
|
+
return template.replace("{range}", range);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
// src/renderers/column-headers.renderer.ts
|
|
1934
|
+
function hasDescriptionColumn(ctx) {
|
|
1935
|
+
const { active, lithology } = ctx.renderConfig.labels;
|
|
1936
|
+
if (active === false) return false;
|
|
1937
|
+
if (Array.isArray(active) && !active.includes("lithology")) return false;
|
|
1938
|
+
if (lithology === false) return false;
|
|
1939
|
+
return !Array.isArray(lithology) || lithology.includes("description");
|
|
1940
|
+
}
|
|
1941
|
+
function drawColumnHeaders(ctx) {
|
|
1942
|
+
const group = ctx.groups.columnHeadersGroup;
|
|
1943
|
+
group.selectAll("*").remove();
|
|
1944
|
+
const cfg = ctx.renderConfig.columnHeaders;
|
|
1945
|
+
if (!cfg.active) return;
|
|
1946
|
+
const theme = ctx.theme.columnHeaders;
|
|
1947
|
+
const { margins } = ctx.state;
|
|
1948
|
+
const positions = getColumnHeaderPositions({
|
|
1949
|
+
marginLeft: margins.left,
|
|
1950
|
+
geoXLeft: ctx.geoXLeft,
|
|
1951
|
+
geoXRight: ctx.geoXRight,
|
|
1952
|
+
pocoCenterX: ctx.pocoCenterX,
|
|
1953
|
+
descriptionX: hasDescriptionColumn(ctx) ? ctx.geoXRight + ctx.renderConfig.labels.descriptionXOffset : void 0
|
|
1954
|
+
});
|
|
1955
|
+
const ruleY = margins.top - 2 - ctx.renderConfig.construction.cementPad.height;
|
|
1956
|
+
const textY = ruleY - 4;
|
|
1957
|
+
const addText = (x, text, anchor) => group.append("text").attr("class", ctx.classes.columnHeaders.text).attr("x", x).attr("y", textY).attr("text-anchor", anchor).attr("font-size", theme.fontSize).attr("font-family", theme.fontFamily ?? "sans-serif").attr("font-weight", theme.fontWeight ?? 600).attr("fill", theme.color).text(text);
|
|
1958
|
+
addText(positions.depth, cfg.labels.depth, "end");
|
|
1959
|
+
addText(positions.lithology, cfg.labels.lithology, "middle");
|
|
1960
|
+
addText(positions.construction, cfg.labels.construction, "middle");
|
|
1961
|
+
if (positions.description != null) {
|
|
1962
|
+
addText(positions.description, cfg.labels.description, "start");
|
|
1963
|
+
}
|
|
1964
|
+
const overview = ctx.renderConfig.overview;
|
|
1965
|
+
group.append("line").attr("class", ctx.classes.columnHeaders.rule).attr("x1", overview.active ? overview.x : 0).attr("x2", ctx.svgWidth).attr("y1", ruleY).attr("y2", ruleY).attr("stroke", theme.ruleStroke).attr("stroke-width", theme.ruleStrokeWidth);
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
// src/renderers/construction-labels.renderer.ts
|
|
1969
|
+
var d33 = __toESM(require("d3"), 1);
|
|
1970
|
+
var import_core3 = require("@welldot/core");
|
|
1971
|
+
var import_utils4 = require("@welldot/utils");
|
|
1423
1972
|
function drawConstructionLabels(ctx, data) {
|
|
1424
1973
|
if (!ctx.renderConfig.constructionLabels.active) return;
|
|
1425
1974
|
ctx.groups.constructionLabelsGroup.selectAll("*").remove();
|
|
@@ -1427,16 +1976,18 @@ function drawConstructionLabels(ctx, data) {
|
|
|
1427
1976
|
const clct = ctx.theme.constructionLabels;
|
|
1428
1977
|
const fmtD = (mm) => formatDiameter(mm, ctx.units.diameter, ctx.locale);
|
|
1429
1978
|
const dUnit = getDiameterUnit(ctx.units.diameter, ctx.locale);
|
|
1430
|
-
const
|
|
1431
|
-
const
|
|
1979
|
+
const material = (value) => (0, import_core3.getVocabLabel)(import_core3.CONSTRUCTION_MATERIALS, value, ctx.locale);
|
|
1980
|
+
const maxXValues = (0, import_utils4.getProfileDiamValues)(ctx.constructionData);
|
|
1981
|
+
const xScale = d33.scaleLinear().domain([0, d33.max(maxXValues) || 0]).range([0, ctx.POCO_WIDTH]);
|
|
1432
1982
|
const occupied = [];
|
|
1433
|
-
const
|
|
1983
|
+
const onRight = clc.side === "right";
|
|
1984
|
+
const continuation = ctx.renderConfig.labels.continuation;
|
|
1985
|
+
const placeLabel = (d, label) => {
|
|
1434
1986
|
const clampedFrom = Math.max(d.from, ctx.depthFrom);
|
|
1435
1987
|
const clampedTo = Math.min(d.to, ctx.depthTo);
|
|
1436
1988
|
if (clampedFrom >= clampedTo) return;
|
|
1989
|
+
const text = continuation?.active && d.from < ctx.depthFrom ? `\u2191 ${label}` : label;
|
|
1437
1990
|
const midY = ctx.yScale((clampedFrom + clampedTo) / 2);
|
|
1438
|
-
const leftEdgeX = (ctx.POCO_CENTER - xScale(d.diameter)) / 2;
|
|
1439
|
-
const labelRightX = leftEdgeX - clc.xOffset;
|
|
1440
1991
|
const charW = clct.fontSize * 0.52;
|
|
1441
1992
|
const lineH = clct.fontSize * 1.35;
|
|
1442
1993
|
const vertPad = 6;
|
|
@@ -1453,16 +2004,17 @@ function drawConstructionLabels(ctx, data) {
|
|
|
1453
2004
|
lines = [text];
|
|
1454
2005
|
boxW = text.length * charW + 8;
|
|
1455
2006
|
}
|
|
2007
|
+
const labelRightX = onRight ? (ctx.POCO_CENTER + ctx.POCO_WIDTH) / 2 + clc.xOffset + boxW : (ctx.POCO_CENTER - xScale(d.diameter)) / 2 - clc.xOffset;
|
|
1456
2008
|
const labelH = lines.length * lineH + vertPad;
|
|
1457
|
-
let labelY = midY - labelH / 2;
|
|
2009
|
+
let labelY = onRight ? ctx.yScale(clampedFrom) + 1 : midY - labelH / 2;
|
|
1458
2010
|
for (const pos of occupied) {
|
|
1459
2011
|
if (labelY < pos.bot && labelY + labelH > pos.top) labelY = pos.bot + 2;
|
|
1460
2012
|
}
|
|
1461
2013
|
occupied.push({ top: labelY, bot: labelY + labelH });
|
|
1462
2014
|
ctx.groups.constructionLabelsGroup.append("rect").attr("x", labelRightX - boxW).attr("y", labelY).attr("width", boxW).attr("height", labelH).attr("rx", clc.labelRadius).attr("fill", clct.labelFill ?? "white").attr("stroke", clct.labelColor ?? "#303030").attr("stroke-width", 0.5);
|
|
1463
|
-
const textEl = ctx.groups.constructionLabelsGroup.append("text").attr("x", labelRightX - 4).attr("y", labelY + lineH * 0.85).attr("font-size", clct.fontSize).attr("font-family", clct.fontFamily ?? "sans-serif").attr("font-weight", clct.fontWeight ?? 400).attr("text-anchor", "end").attr("fill", clct.labelColor ?? "#303030");
|
|
2015
|
+
const textEl = ctx.groups.constructionLabelsGroup.append("text").attr("x", onRight ? labelRightX - boxW + 4 : labelRightX - 4).attr("y", labelY + lineH * 0.85).attr("font-size", clct.fontSize).attr("font-family", clct.fontFamily ?? "sans-serif").attr("font-weight", clct.fontWeight ?? 400).attr("text-anchor", onRight ? "start" : "end").attr("fill", clct.labelColor ?? "#303030");
|
|
1464
2016
|
lines.forEach((line, i) => {
|
|
1465
|
-
textEl.append("tspan").attr("x", labelRightX - 4).attr("dy", i === 0 ? 0 : lineH).text(line);
|
|
2017
|
+
textEl.append("tspan").attr("x", onRight ? labelRightX - boxW + 4 : labelRightX - 4).attr("dy", i === 0 ? 0 : lineH).text(line);
|
|
1466
2018
|
});
|
|
1467
2019
|
};
|
|
1468
2020
|
let lastDiam = 0;
|
|
@@ -1475,7 +2027,7 @@ function drawConstructionLabels(ctx, data) {
|
|
|
1475
2027
|
}).forEach(
|
|
1476
2028
|
(d) => placeLabel(
|
|
1477
2029
|
d,
|
|
1478
|
-
`${clc.labels.wellCasePrefix} ${fmtD(d.diameter)}${dUnit} ${d.type}`
|
|
2030
|
+
`${clc.labels.wellCasePrefix} ${fmtD(d.diameter)}${dUnit} ${material(d.type)}`
|
|
1479
2031
|
)
|
|
1480
2032
|
);
|
|
1481
2033
|
lastDiam = 0;
|
|
@@ -1488,122 +2040,319 @@ function drawConstructionLabels(ctx, data) {
|
|
|
1488
2040
|
}).forEach(
|
|
1489
2041
|
(d) => placeLabel(
|
|
1490
2042
|
d,
|
|
1491
|
-
`${clc.labels.wellScreenPrefix} ${fmtD(d.diameter)}${dUnit} ${d.type} ${clc.labels.wellScreenSlotPrefix} ${fmtD(d.screen_slot)}${dUnit}`
|
|
2043
|
+
`${clc.labels.wellScreenPrefix} ${fmtD(d.diameter)}${dUnit} ${material(d.type)} ${clc.labels.wellScreenSlotPrefix} ${fmtD(d.screen_slot)}${dUnit}`
|
|
1492
2044
|
)
|
|
1493
2045
|
);
|
|
1494
2046
|
}
|
|
1495
2047
|
|
|
1496
2048
|
// src/renderers/construction.renderer.ts
|
|
1497
|
-
var
|
|
1498
|
-
var
|
|
2049
|
+
var d34 = __toESM(require("d3"), 1);
|
|
2050
|
+
var import_utils5 = require("@welldot/utils");
|
|
2051
|
+
var entering = /* @__PURE__ */ new WeakSet();
|
|
2052
|
+
function constructionXScale(ctx) {
|
|
2053
|
+
const max6 = d34.max((0, import_utils5.getProfileDiamValues)(ctx.constructionData)) || 0;
|
|
2054
|
+
return d34.scaleLinear().domain([0, max6]).range([0, ctx.POCO_WIDTH]);
|
|
2055
|
+
}
|
|
2056
|
+
function outlineScales(ctx) {
|
|
2057
|
+
const x = constructionXScale(ctx);
|
|
2058
|
+
return {
|
|
2059
|
+
y: ctx.yScale,
|
|
2060
|
+
left: (d) => (ctx.POCO_CENTER - x(d)) / 2,
|
|
2061
|
+
right: (d) => (ctx.POCO_CENTER + x(d)) / 2,
|
|
2062
|
+
depthFrom: ctx.depthFrom,
|
|
2063
|
+
depthTo: ctx.depthTo
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
var surfaceCaseDiameter = (ctx, diameter) => diameter * (1 + ctx.renderConfig.construction.surfaceCase.diameterPaddingRatio);
|
|
2067
|
+
function joinIntervalLayer(ctx, group, cls, data, key, tooltip, { shoe = false, pathFill = false, ends = false } = {}) {
|
|
2068
|
+
const sel = group.selectAll(`g.${cls}`).data(data, makeIntervalKey(key));
|
|
2069
|
+
sel.exit().transition(ctx.transition).style("opacity", 0).remove();
|
|
2070
|
+
const top = (d) => ctx.yScale(Math.max(d.from, ctx.depthFrom));
|
|
2071
|
+
const entered = sel.enter().append("g").attr("class", cls).each((_d, i, nodes) => entering.add(nodes[i])).on("mouseover", tooltip.show).on("mouseout", tooltip.hide);
|
|
2072
|
+
if (pathFill)
|
|
2073
|
+
entered.append("path").attr("class", `${cls}-fill`).attr("stroke", "none").attr("fill-rule", "evenodd").attr("d", "");
|
|
2074
|
+
else
|
|
2075
|
+
entered.append("rect").attr("class", `${cls}-fill`).attr("stroke", "none").attr("y", top).attr("height", 0);
|
|
2076
|
+
entered.append("path").attr("class", `${cls}-outline`).attr("fill", "none").attr("d", "");
|
|
2077
|
+
if (shoe)
|
|
2078
|
+
entered.append("path").attr("class", `${cls}-shoe`).attr("stroke-linejoin", "round").attr("d", "");
|
|
2079
|
+
if (ends)
|
|
2080
|
+
entered.append("path").attr("class", `${cls}-ends`).attr("fill", "none").attr("d", "");
|
|
2081
|
+
return entered.merge(sel);
|
|
2082
|
+
}
|
|
2083
|
+
function drawCementPad(ctx, pad) {
|
|
2084
|
+
const cls = ctx.classes.cementPad.item;
|
|
2085
|
+
const visible = !!pad?.thickness && ctx.depthFrom <= 0 && ctx.depthTo > 0;
|
|
2086
|
+
const sel = ctx.groups.cementPadGroup.selectAll(`g.${cls}`).data(visible ? [pad] : [], () => "cement_pad");
|
|
2087
|
+
sel.exit().remove();
|
|
2088
|
+
if (!visible) return;
|
|
2089
|
+
const entered = sel.enter().append("g").attr("class", cls).on("mouseover", ctx.tooltips.cementPad.show).on("mouseout", ctx.tooltips.cementPad.hide);
|
|
2090
|
+
entered.append("path").attr("class", `${cls}-slab`);
|
|
2091
|
+
entered.append("path").attr("class", `${cls}-slab`);
|
|
2092
|
+
const x = constructionXScale(ctx);
|
|
2093
|
+
const { opening, outer } = getPadDiameters(
|
|
2094
|
+
ctx.constructionData,
|
|
2095
|
+
ctx.renderConfig.construction.surfaceCase.diameterPaddingRatio
|
|
2096
|
+
);
|
|
2097
|
+
const { slabs } = getCementPadGeometry(
|
|
2098
|
+
ctx.POCO_WIDTH,
|
|
2099
|
+
ctx.POCO_CENTER,
|
|
2100
|
+
ctx.yScale(0),
|
|
2101
|
+
ctx.renderConfig.construction.cementPad,
|
|
2102
|
+
x(opening),
|
|
2103
|
+
x(outer)
|
|
2104
|
+
);
|
|
2105
|
+
entered.merge(sel).selectAll("path").attr("d", (_d, i) => slabs[i] ?? "").attr("fill", ctx.textures.pad.url()).attr("stroke", ctx.theme.cementPad.stroke).attr("stroke-width", ctx.theme.cementPad.strokeWidth).attr("stroke-linejoin", "round");
|
|
2106
|
+
}
|
|
2107
|
+
function layoutConstruction(ctx, animate = false) {
|
|
2108
|
+
const c = ctx.classes;
|
|
2109
|
+
const scales = outlineScales(ctx);
|
|
2110
|
+
const data = ctx.constructionData;
|
|
2111
|
+
const motion = (sel) => animate ? withTransition(sel, ctx.transition) : sel;
|
|
2112
|
+
const yTop = (d) => ctx.yScale(Math.max(d.from, ctx.depthFrom));
|
|
2113
|
+
const yBottom = (d) => ctx.yScale(Math.min(d.to, ctx.depthTo));
|
|
2114
|
+
const collapsed = (d) => ({
|
|
2115
|
+
...scales,
|
|
2116
|
+
y: () => yTop(d)
|
|
2117
|
+
});
|
|
2118
|
+
const shapeParts = (items, part, attr, shape) => {
|
|
2119
|
+
const parts = items.select(part);
|
|
2120
|
+
if (animate)
|
|
2121
|
+
parts.filter(function() {
|
|
2122
|
+
return entering.has(this.parentNode);
|
|
2123
|
+
}).attr(attr, (d) => shape(d, collapsed(d)));
|
|
2124
|
+
motion(parts).attr(attr, (d) => shape(d, scales));
|
|
2125
|
+
};
|
|
2126
|
+
const layoutLayer = (group, cls, diameter, outline, {
|
|
2127
|
+
shoe: shoe2,
|
|
2128
|
+
ends,
|
|
2129
|
+
fill
|
|
2130
|
+
} = {}) => {
|
|
2131
|
+
const items = group.selectAll(`g.${cls}`);
|
|
2132
|
+
shapeParts(items, `.${cls}-outline`, "d", outline);
|
|
2133
|
+
if (shoe2) shapeParts(items, `.${cls}-shoe`, "d", shoe2);
|
|
2134
|
+
if (ends) shapeParts(items, `.${cls}-ends`, "d", ends);
|
|
2135
|
+
if (fill) {
|
|
2136
|
+
shapeParts(items, `.${cls}-fill`, "d", fill);
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
motion(
|
|
2140
|
+
items.select(`.${cls}-fill`).attr("x", (d) => scales.left(diameter(d))).attr(
|
|
2141
|
+
"width",
|
|
2142
|
+
(d) => scales.right(diameter(d)) - scales.left(diameter(d))
|
|
2143
|
+
)
|
|
2144
|
+
).attr("y", yTop).attr("height", (d) => Math.max(0, yBottom(d) - yTop(d)));
|
|
2145
|
+
};
|
|
2146
|
+
const walls = (d, s, dia = d.diameter) => pipeWallsPath(
|
|
2147
|
+
s.left(dia),
|
|
2148
|
+
s.right(dia),
|
|
2149
|
+
s.y(Math.max(d.from, s.depthFrom)),
|
|
2150
|
+
s.y(Math.min(d.to, s.depthTo))
|
|
2151
|
+
);
|
|
2152
|
+
layoutLayer(
|
|
2153
|
+
ctx.groups.holeGroup,
|
|
2154
|
+
c.boreHole.rect,
|
|
2155
|
+
(d) => d.diameter,
|
|
2156
|
+
(d, s) => boreHoleOutlinePath(d, data.bore_hole, s)
|
|
2157
|
+
);
|
|
2158
|
+
const pipes = [...data.well_case, ...data.well_screen];
|
|
2159
|
+
const insideSurface = [...data.bore_hole, ...data.hole_fill, ...pipes];
|
|
2160
|
+
const scDiameter = (d) => surfaceCaseDiameter(ctx, d.diameter);
|
|
2161
|
+
layoutLayer(
|
|
2162
|
+
ctx.groups.surfaceCaseGroup,
|
|
2163
|
+
c.surfaceCase.rect,
|
|
2164
|
+
scDiameter,
|
|
2165
|
+
(d, s) => walls(d, s, scDiameter(d)),
|
|
2166
|
+
// Only the ring outside the hole: the texture never shows under the casing.
|
|
2167
|
+
{
|
|
2168
|
+
fill: (d, s) => annulusFillPath({ ...d, diameter: scDiameter(d) }, insideSurface, s)
|
|
2169
|
+
}
|
|
2170
|
+
);
|
|
2171
|
+
layoutLayer(
|
|
2172
|
+
ctx.groups.holeFillGroup,
|
|
2173
|
+
c.holeFill.rect,
|
|
2174
|
+
(d) => d.diameter,
|
|
2175
|
+
(d, s) => holeFillOutlinePath(d, pipes, s),
|
|
2176
|
+
{ fill: (d, s) => annulusFillPath(d, pipes, s) }
|
|
2177
|
+
);
|
|
2178
|
+
const string = [...pipes, ...data.reduction ?? []];
|
|
2179
|
+
const shoeCfg = ctx.renderConfig.construction.casingShoe;
|
|
2180
|
+
const endsCfg = ctx.renderConfig.construction.screenEnds;
|
|
2181
|
+
const room = (d, depth, size) => {
|
|
2182
|
+
const hole = diameterAt(data.bore_hole, depth);
|
|
2183
|
+
const annulus = hole !== void 0 && hole > d.diameter ? scales.left(d.diameter) - scales.left(hole) - 1 : size;
|
|
2184
|
+
return Math.max(2, Math.min(size, annulus));
|
|
2185
|
+
};
|
|
2186
|
+
const shoe = (d, s) => {
|
|
2187
|
+
const ends = getIntervalEnds(d, string, ctx.depthFrom, ctx.depthTo);
|
|
2188
|
+
if (!shoeCfg.active || ends.cutBottom || ends.joinedBottom) return "";
|
|
2189
|
+
return shoePath(
|
|
2190
|
+
s.left(d.diameter),
|
|
2191
|
+
s.right(d.diameter),
|
|
2192
|
+
s.y(Math.min(d.to, s.depthTo)),
|
|
2193
|
+
room(d, d.to, shoeCfg.size)
|
|
2194
|
+
);
|
|
2195
|
+
};
|
|
2196
|
+
const screenEnds = (d, s) => {
|
|
2197
|
+
if (!endsCfg.active) return "";
|
|
2198
|
+
const ends = getIntervalEnds(d, string, ctx.depthFrom, ctx.depthTo);
|
|
2199
|
+
const mark = (depth) => screenEndPath(s.left(d.diameter), s.right(d.diameter), s.y(depth));
|
|
2200
|
+
return (ends.cutTop ? "" : mark(d.from)) + (ends.cutBottom ? "" : mark(d.to));
|
|
2201
|
+
};
|
|
2202
|
+
layoutLayer(
|
|
2203
|
+
ctx.groups.wellCaseGroup,
|
|
2204
|
+
c.wellCase.rect,
|
|
2205
|
+
(d) => d.diameter,
|
|
2206
|
+
walls,
|
|
2207
|
+
{ shoe }
|
|
2208
|
+
);
|
|
2209
|
+
layoutLayer(
|
|
2210
|
+
ctx.groups.wellScreenGroup,
|
|
2211
|
+
c.wellScreen.rect,
|
|
2212
|
+
(d) => d.diameter,
|
|
2213
|
+
walls,
|
|
2214
|
+
{ shoe, ends: screenEnds }
|
|
2215
|
+
);
|
|
2216
|
+
const reductions = ctx.groups.reductionGroup.selectAll(`g.${c.reduction.item}`);
|
|
2217
|
+
const corners = (d, s) => {
|
|
2218
|
+
const t = s.y(Math.max(d.from, s.depthFrom));
|
|
2219
|
+
const b = s.y(Math.min(d.to, s.depthTo));
|
|
2220
|
+
return {
|
|
2221
|
+
tl: `${s.left(d.diam_from)},${t}`,
|
|
2222
|
+
tr: `${s.right(d.diam_from)},${t}`,
|
|
2223
|
+
bl: `${s.left(d.diam_to)},${b}`,
|
|
2224
|
+
br: `${s.right(d.diam_to)},${b}`
|
|
2225
|
+
};
|
|
2226
|
+
};
|
|
2227
|
+
shapeParts(reductions, `.${c.reduction.item}-fill`, "points", (d, s) => {
|
|
2228
|
+
const p = corners(d, s);
|
|
2229
|
+
return `${p.tl} ${p.tr} ${p.br} ${p.bl}`;
|
|
2230
|
+
});
|
|
2231
|
+
shapeParts(reductions, `.${c.reduction.item}-outline`, "d", (d, s) => {
|
|
2232
|
+
const p = corners(d, s);
|
|
2233
|
+
return `M${p.tl}L${p.bl}M${p.tr}L${p.br}`;
|
|
2234
|
+
});
|
|
2235
|
+
if (animate) {
|
|
2236
|
+
for (const group of [
|
|
2237
|
+
ctx.groups.holeGroup,
|
|
2238
|
+
ctx.groups.surfaceCaseGroup,
|
|
2239
|
+
ctx.groups.holeFillGroup,
|
|
2240
|
+
ctx.groups.wellCaseGroup,
|
|
2241
|
+
ctx.groups.wellScreenGroup,
|
|
2242
|
+
ctx.groups.reductionGroup
|
|
2243
|
+
])
|
|
2244
|
+
group.selectAll("g").each(function() {
|
|
2245
|
+
entering.delete(this);
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
1499
2249
|
function drawConstructive(ctx, data) {
|
|
1500
2250
|
const { getHeight, getYPos } = getYAxisFunctions(ctx.yScale, {
|
|
1501
2251
|
from: ctx.depthFrom,
|
|
1502
2252
|
to: ctx.depthTo
|
|
1503
2253
|
});
|
|
1504
|
-
const
|
|
1505
|
-
const
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
).attr("
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
withTransition(mergedHole, ctx.transition).attr("y", getYPos).attr("height", getHeight);
|
|
1531
|
-
const surfaceCaseGs = ctx.groups.surfaceCaseGroup.selectAll(`g.${ctx.classes.surfaceCase.rect}`).data(data.surface_case, makeIntervalKey("surface_case"));
|
|
1532
|
-
surfaceCaseGs.exit().transition(ctx.transition).style("opacity", 0).remove();
|
|
1533
|
-
const newSC = surfaceCaseGs.enter().append("g").attr("class", ctx.classes.surfaceCase.rect).on("mouseover", ctx.tooltips.surfaceCase.show).on("mouseout", ctx.tooltips.surfaceCase.hide);
|
|
1534
|
-
newSC.append("rect").attr("class", "surface-case-fill").attr("stroke", "none").attr("y", yPos).attr("height", 0);
|
|
1535
|
-
newSC.append("line").attr("class", "surface-case-side").attr("stroke", ctx.theme.surfaceCase.stroke).attr("stroke-width", ctx.theme.surfaceCase.strokeWidth);
|
|
1536
|
-
newSC.append("line").attr("class", "surface-case-side").attr("stroke", ctx.theme.surfaceCase.stroke).attr("stroke-width", ctx.theme.surfaceCase.strokeWidth);
|
|
1537
|
-
const mergedSC = mergeEnter(newSC, surfaceCaseGs);
|
|
1538
|
-
mergedSC.each((d, i, nodes) => {
|
|
1539
|
-
const x = (ctx.POCO_CENTER - xScale(
|
|
1540
|
-
d.diameter + d.diameter * rcc.surfaceCase.diameterPaddingRatio
|
|
1541
|
-
)) / 2;
|
|
1542
|
-
const w = xScale(
|
|
1543
|
-
d.diameter + d.diameter * rcc.surfaceCase.diameterPaddingRatio
|
|
2254
|
+
const c = ctx.classes;
|
|
2255
|
+
const theme = ctx.theme;
|
|
2256
|
+
drawCementPad(ctx, data.cement_pad);
|
|
2257
|
+
joinIntervalLayer(
|
|
2258
|
+
ctx,
|
|
2259
|
+
ctx.groups.holeGroup,
|
|
2260
|
+
c.boreHole.rect,
|
|
2261
|
+
data.bore_hole,
|
|
2262
|
+
"bore_hole",
|
|
2263
|
+
ctx.tooltips.hole
|
|
2264
|
+
).attr("opacity", theme.boreHole.opacity).call((g) => {
|
|
2265
|
+
g.select(`.${c.boreHole.rect}-fill`).attr("fill", theme.boreHole.fill);
|
|
2266
|
+
g.select(`.${c.boreHole.rect}-outline`).attr("stroke", theme.boreHole.stroke).attr("stroke-width", theme.boreHole.strokeWidth).attr("stroke-dasharray", theme.boreHole.strokeDasharray);
|
|
2267
|
+
});
|
|
2268
|
+
joinIntervalLayer(
|
|
2269
|
+
ctx,
|
|
2270
|
+
ctx.groups.surfaceCaseGroup,
|
|
2271
|
+
c.surfaceCase.rect,
|
|
2272
|
+
data.surface_case,
|
|
2273
|
+
"surface_case",
|
|
2274
|
+
ctx.tooltips.surfaceCase,
|
|
2275
|
+
{ pathFill: true }
|
|
2276
|
+
).call((g) => {
|
|
2277
|
+
g.select(`.${c.surfaceCase.rect}-fill`).attr(
|
|
2278
|
+
"fill",
|
|
2279
|
+
ctx.textures.surface_case.url()
|
|
1544
2280
|
);
|
|
1545
|
-
|
|
1546
|
-
g.select(".surface-case-fill").attr("x", x).attr("width", w).attr("fill", ctx.textures.surface_case.url());
|
|
1547
|
-
const sideNodes = g.selectAll(".surface-case-side").nodes();
|
|
1548
|
-
d33.select(sideNodes[0]).attr("x1", x).attr("x2", x);
|
|
1549
|
-
d33.select(sideNodes[1]).attr("x1", x + w).attr("x2", x + w);
|
|
2281
|
+
g.select(`.${c.surfaceCase.rect}-outline`).attr("stroke", theme.surfaceCase.stroke).attr("stroke-width", theme.surfaceCase.strokeWidth);
|
|
1550
2282
|
});
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
ctx.
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
"
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
2283
|
+
joinIntervalLayer(
|
|
2284
|
+
ctx,
|
|
2285
|
+
ctx.groups.holeFillGroup,
|
|
2286
|
+
c.holeFill.rect,
|
|
2287
|
+
data.hole_fill,
|
|
2288
|
+
"hole_fill",
|
|
2289
|
+
ctx.tooltips.holeFill,
|
|
2290
|
+
{ pathFill: true }
|
|
2291
|
+
).call((g) => {
|
|
2292
|
+
g.select(`.${c.holeFill.rect}-fill`).attr(
|
|
2293
|
+
"fill",
|
|
2294
|
+
(d) => ctx.textures[d.type].url()
|
|
2295
|
+
);
|
|
2296
|
+
g.select(`.${c.holeFill.rect}-outline`).attr("stroke", theme.holeFill.stroke).attr("stroke-width", theme.holeFill.strokeWidth);
|
|
2297
|
+
});
|
|
2298
|
+
for (const [group, cls, items, key, tooltip, fill, stroke] of [
|
|
2299
|
+
[
|
|
2300
|
+
ctx.groups.wellCaseGroup,
|
|
2301
|
+
c.wellCase.rect,
|
|
2302
|
+
data.well_case,
|
|
2303
|
+
"well_case",
|
|
2304
|
+
ctx.tooltips.wellCase,
|
|
2305
|
+
theme.wellCase.fill,
|
|
2306
|
+
theme.wellCase
|
|
2307
|
+
],
|
|
2308
|
+
[
|
|
2309
|
+
ctx.groups.wellScreenGroup,
|
|
2310
|
+
c.wellScreen.rect,
|
|
2311
|
+
data.well_screen,
|
|
2312
|
+
"well_screen",
|
|
2313
|
+
ctx.tooltips.wellScreen,
|
|
2314
|
+
ctx.textures.well_screen.url(),
|
|
2315
|
+
theme.wellScreen
|
|
2316
|
+
]
|
|
2317
|
+
]) {
|
|
2318
|
+
joinIntervalLayer(ctx, group, cls, items, key, tooltip, {
|
|
2319
|
+
shoe: true,
|
|
2320
|
+
ends: cls === c.wellScreen.rect
|
|
2321
|
+
}).call((g) => {
|
|
2322
|
+
g.select(`.${cls}-fill`).attr("fill", fill);
|
|
2323
|
+
g.select(`.${cls}-outline`).attr("stroke", stroke.stroke).attr("stroke-width", stroke.strokeWidth);
|
|
2324
|
+
g.select(`.${cls}-shoe`).attr("fill", stroke.stroke).attr("stroke", stroke.stroke).attr("stroke-width", 0.5);
|
|
2325
|
+
g.select(`.${cls}-ends`).attr("stroke", stroke.stroke).attr("stroke-width", theme.wellScreen.endStrokeWidth).attr("stroke-dasharray", theme.wellScreen.endDasharray);
|
|
2326
|
+
});
|
|
2327
|
+
}
|
|
2328
|
+
const reduction = ctx.groups.reductionGroup.selectAll(`g.${c.reduction.item}`).data(data.reduction ?? [], makeIntervalKey("reduction"));
|
|
1582
2329
|
reduction.exit().transition(ctx.transition).style("opacity", 0).remove();
|
|
1583
|
-
const
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
2330
|
+
const newReduction = reduction.enter().append("g").attr("class", c.reduction.item).each((_d, i, nodes) => entering.add(nodes[i])).on("mouseover", ctx.tooltips.reduction.show).on("mouseout", ctx.tooltips.reduction.hide);
|
|
2331
|
+
newReduction.append("polygon").attr("class", `${c.reduction.item}-fill`).attr("stroke", "none");
|
|
2332
|
+
newReduction.append("path").attr("class", `${c.reduction.item}-outline`).attr("fill", "none");
|
|
2333
|
+
newReduction.merge(reduction).call((g) => {
|
|
2334
|
+
g.select(`.${c.reduction.item}-fill`).attr("fill", theme.reduction.fill);
|
|
2335
|
+
g.select(`.${c.reduction.item}-outline`).attr("stroke", theme.reduction.stroke).attr("stroke-width", theme.reduction.strokeWidth);
|
|
2336
|
+
});
|
|
2337
|
+
const mergedConflicts = mergeConflicts(
|
|
2338
|
+
[
|
|
2339
|
+
...getConflictAreas(data.well_case, data.well_screen),
|
|
2340
|
+
...getConflictAreas(data.well_screen, data.well_case)
|
|
2341
|
+
],
|
|
2342
|
+
1
|
|
1593
2343
|
);
|
|
1594
|
-
const
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
const mergedConflicts = mergeConflicts(conflictAreas, 1);
|
|
1598
|
-
const conflict = ctx.groups.conflictGroup.selectAll(`.${ctx.classes.conflict.rect}`).data(mergedConflicts, makeIntervalKey("conflict"));
|
|
2344
|
+
const xScale = constructionXScale(ctx);
|
|
2345
|
+
const yPos = getYPos;
|
|
2346
|
+
const conflict = ctx.groups.conflictGroup.selectAll(`.${c.conflict.rect}`).data(mergedConflicts, makeIntervalKey("conflict"));
|
|
1599
2347
|
conflict.exit().transition(ctx.transition).attr("height", 0).remove();
|
|
1600
|
-
const newConflict = conflict.enter().append("rect").attr("class",
|
|
2348
|
+
const newConflict = conflict.enter().append("rect").attr("class", c.conflict.rect).attr("fill", ctx.textures.conflict.url()).attr("stroke", theme.conflict.stroke).attr("stroke-width", theme.conflict.strokeWidth).on("mouseover", ctx.tooltips.conflict.show).on("mouseout", ctx.tooltips.conflict.hide).attr("y", yPos).attr("height", 0);
|
|
1601
2349
|
const mergedConflict = mergeEnter(newConflict, conflict).attr("x", (d) => (ctx.POCO_CENTER - xScale(d.diameter)) / 2).attr("width", (d) => xScale(d.diameter));
|
|
1602
|
-
withTransition(mergedConflict, ctx.transition).attr("y",
|
|
2350
|
+
withTransition(mergedConflict, ctx.transition).attr("y", getYPos).attr("height", getHeight);
|
|
2351
|
+
layoutConstruction(ctx, true);
|
|
1603
2352
|
}
|
|
1604
2353
|
|
|
1605
2354
|
// src/renderers/fractures.renderer.ts
|
|
1606
|
-
var
|
|
2355
|
+
var d35 = __toESM(require("d3"), 1);
|
|
1607
2356
|
function wavyLine(rng, steps, baseY, jitter, startInset, endInset) {
|
|
1608
2357
|
const pts = [];
|
|
1609
2358
|
for (let i = 0; i < steps; i++) {
|
|
@@ -1615,7 +2364,6 @@ function wavyLine(rng, steps, baseY, jitter, startInset, endInset) {
|
|
|
1615
2364
|
return pts;
|
|
1616
2365
|
}
|
|
1617
2366
|
function drawFractures(ctx, data) {
|
|
1618
|
-
if (!data.length) return;
|
|
1619
2367
|
const {
|
|
1620
2368
|
groups: { fracturesGroup },
|
|
1621
2369
|
POCO_WIDTH,
|
|
@@ -1637,10 +2385,10 @@ function drawFractures(ctx, data) {
|
|
|
1637
2385
|
const merged = mergeEnter(entered, groups);
|
|
1638
2386
|
merged.attr(
|
|
1639
2387
|
"transform",
|
|
1640
|
-
(fracture) => `translate(0,${yScale(fracture.depth)}) rotate(${fracture.dip},${pocoCenterX},0)`
|
|
2388
|
+
(fracture) => `translate(0,${yScale(fracture.depth)}) rotate(${fractureDip(fracture.dip)},${pocoCenterX},0)`
|
|
1641
2389
|
);
|
|
1642
2390
|
merged.each(function(fracture) {
|
|
1643
|
-
const g =
|
|
2391
|
+
const g = d35.select(this);
|
|
1644
2392
|
g.selectAll("*").remove();
|
|
1645
2393
|
const rng = makeSeededPrng(fracture.depth, 7919);
|
|
1646
2394
|
const hitBuffer = fracture.swarm ? rf.hitBuffer.swarm : rf.hitBuffer.single;
|
|
@@ -1719,8 +2467,8 @@ function drawFractures(ctx, data) {
|
|
|
1719
2467
|
}
|
|
1720
2468
|
|
|
1721
2469
|
// src/renderers/highlights.renderer.ts
|
|
1722
|
-
var
|
|
1723
|
-
var
|
|
2470
|
+
var d36 = __toESM(require("d3"), 1);
|
|
2471
|
+
var import_utils6 = require("@welldot/utils");
|
|
1724
2472
|
function drawHighlightItem(ctx, group, x, y, w, h, label) {
|
|
1725
2473
|
if (h <= 0 || w <= 0) return;
|
|
1726
2474
|
const hlConfig = ctx.renderConfig.highlights;
|
|
@@ -1779,27 +2527,29 @@ function drawHighlights(ctx, hl) {
|
|
|
1779
2527
|
h.label
|
|
1780
2528
|
);
|
|
1781
2529
|
});
|
|
1782
|
-
const maxXVals = (0,
|
|
1783
|
-
const xScaleConstr =
|
|
2530
|
+
const maxXVals = (0, import_utils6.getProfileDiamValues)(ctx.constructionData);
|
|
2531
|
+
const xScaleConstr = d36.scaleLinear().domain([0, d36.max(maxXVals) || 0]).range([0, ctx.POCO_WIDTH]);
|
|
1784
2532
|
const constructionConfig = ctx.renderConfig.construction;
|
|
1785
|
-
if (hl.cement_pad && ctx.depthFrom
|
|
1786
|
-
const
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
const cpY = ctx.yScale(0) - ctx.yScale(
|
|
1790
|
-
cp.thickness * constructionConfig.cementPad.thicknessMultiplier
|
|
2533
|
+
if (hl.cement_pad && ctx.depthFrom <= 0 && ctx.depthTo > 0 && ctx.constructionData.cement_pad?.thickness) {
|
|
2534
|
+
const { opening, outer } = getPadDiameters(
|
|
2535
|
+
ctx.constructionData,
|
|
2536
|
+
constructionConfig.surfaceCase.diameterPaddingRatio
|
|
1791
2537
|
);
|
|
1792
|
-
const
|
|
1793
|
-
|
|
1794
|
-
|
|
2538
|
+
const pad = getCementPadRect(
|
|
2539
|
+
ctx.POCO_WIDTH,
|
|
2540
|
+
ctx.POCO_CENTER,
|
|
2541
|
+
ctx.yScale(0),
|
|
2542
|
+
constructionConfig.cementPad,
|
|
2543
|
+
xScaleConstr(opening),
|
|
2544
|
+
xScaleConstr(outer)
|
|
1795
2545
|
);
|
|
1796
2546
|
drawHighlightItem(
|
|
1797
2547
|
ctx,
|
|
1798
2548
|
ctx.groups.highlightsConstructionGroup,
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
2549
|
+
pad.x,
|
|
2550
|
+
pad.y,
|
|
2551
|
+
pad.width,
|
|
2552
|
+
pad.height,
|
|
1803
2553
|
hl.cement_pad.label
|
|
1804
2554
|
);
|
|
1805
2555
|
}
|
|
@@ -1875,8 +2625,12 @@ function drawHighlights(ctx, hl) {
|
|
|
1875
2625
|
// src/renderers/legend.renderer.ts
|
|
1876
2626
|
var d3module = __toESM(require("d3"), 1);
|
|
1877
2627
|
var import_defu = require("defu");
|
|
1878
|
-
var
|
|
1879
|
-
|
|
2628
|
+
var import_utils7 = require("@welldot/utils");
|
|
2629
|
+
var d37 = { ...d3module };
|
|
2630
|
+
var SYMBOL_WIDTH = 24;
|
|
2631
|
+
var SYMBOL_HEIGHT = 12;
|
|
2632
|
+
var SYMBOL_MARGIN = 2;
|
|
2633
|
+
function getWellLegendItems(profile, labels = INTERACTIVE_RENDER_CONFIG.legend.labels) {
|
|
1880
2634
|
const fractures = profile.fractures ?? [];
|
|
1881
2635
|
const caves = profile.caves ?? [];
|
|
1882
2636
|
const boreHoles = profile.bore_hole ?? [];
|
|
@@ -1896,6 +2650,8 @@ function drawWellLegend(selector, profile, options = {}) {
|
|
|
1896
2650
|
const hasWellCase = wellCases.length > 0;
|
|
1897
2651
|
const hasWellScreen = wellScreens.length > 0;
|
|
1898
2652
|
const hasReduction = reductions.length > 0;
|
|
2653
|
+
const hasCentralizer = (profile.centralizers ?? []).length > 0;
|
|
2654
|
+
const hasPump = (0, import_utils7.getCurrentPump)(profile)?.intake_depth !== void 0;
|
|
1899
2655
|
const hasCementPad = !!profile.cement_pad?.thickness;
|
|
1900
2656
|
const hasConflict = mergeConflicts(
|
|
1901
2657
|
[
|
|
@@ -1904,197 +2660,314 @@ function drawWellLegend(selector, profile, options = {}) {
|
|
|
1904
2660
|
],
|
|
1905
2661
|
1
|
|
1906
2662
|
).length > 0;
|
|
1907
|
-
const cfg = (0, import_defu.defu)(
|
|
1908
|
-
options.config ?? {},
|
|
1909
|
-
INTERACTIVE_RENDER_CONFIG.legend
|
|
1910
|
-
);
|
|
1911
|
-
const theme = (0, import_defu.defu)(options.theme ?? {}, DEFAULT_WELL_THEME);
|
|
1912
|
-
const cls = options.classNames ? { ...DEFAULT_COMPONENTS_CLASS_NAMES.legend, ...options.classNames } : DEFAULT_COMPONENTS_CLASS_NAMES.legend;
|
|
1913
2663
|
const items = [];
|
|
1914
2664
|
if (hasSimple)
|
|
1915
2665
|
items.push({
|
|
1916
2666
|
kind: "fracture",
|
|
1917
|
-
|
|
2667
|
+
key: "fractureSingle",
|
|
2668
|
+
label: labels.fractureSingle,
|
|
1918
2669
|
swarm: false,
|
|
1919
2670
|
water_intake: false
|
|
1920
2671
|
});
|
|
1921
2672
|
if (hasSwarm)
|
|
1922
2673
|
items.push({
|
|
1923
2674
|
kind: "fracture",
|
|
1924
|
-
|
|
2675
|
+
key: "fractureSwarm",
|
|
2676
|
+
label: labels.fractureSwarm,
|
|
1925
2677
|
swarm: true,
|
|
1926
2678
|
water_intake: false
|
|
1927
2679
|
});
|
|
1928
2680
|
if (hasWaterFx)
|
|
1929
2681
|
items.push({
|
|
1930
2682
|
kind: "fracture",
|
|
1931
|
-
|
|
2683
|
+
key: "fractureWater",
|
|
2684
|
+
label: labels.fractureWater,
|
|
1932
2685
|
swarm: false,
|
|
1933
2686
|
water_intake: true
|
|
1934
2687
|
});
|
|
1935
2688
|
if (hasCaveDry)
|
|
1936
2689
|
items.push({
|
|
1937
2690
|
kind: "cave",
|
|
1938
|
-
|
|
2691
|
+
key: "caveDry",
|
|
2692
|
+
label: labels.caveDry,
|
|
1939
2693
|
water_intake: false
|
|
1940
2694
|
});
|
|
1941
2695
|
if (hasCaveWet)
|
|
1942
|
-
items.push({
|
|
2696
|
+
items.push({
|
|
2697
|
+
kind: "cave",
|
|
2698
|
+
key: "caveWet",
|
|
2699
|
+
label: labels.caveWet,
|
|
2700
|
+
water_intake: true
|
|
2701
|
+
});
|
|
1943
2702
|
if (hasCementPad)
|
|
1944
2703
|
items.push({
|
|
1945
2704
|
kind: "construction",
|
|
1946
|
-
|
|
2705
|
+
key: "cementPad",
|
|
2706
|
+
label: labels.cementPad,
|
|
1947
2707
|
subKind: "cementPad"
|
|
1948
2708
|
});
|
|
1949
2709
|
if (hasBoreHole)
|
|
1950
2710
|
items.push({
|
|
1951
2711
|
kind: "construction",
|
|
1952
|
-
|
|
2712
|
+
key: "boreHole",
|
|
2713
|
+
label: labels.boreHole,
|
|
1953
2714
|
subKind: "boreHole"
|
|
1954
2715
|
});
|
|
1955
2716
|
if (hasSurfaceCase)
|
|
1956
2717
|
items.push({
|
|
1957
2718
|
kind: "construction",
|
|
1958
|
-
|
|
2719
|
+
key: "surfaceCase",
|
|
2720
|
+
label: labels.surfaceCase,
|
|
1959
2721
|
subKind: "surfaceCase"
|
|
1960
2722
|
});
|
|
1961
2723
|
if (hasHoleFillGravel)
|
|
1962
2724
|
items.push({
|
|
1963
2725
|
kind: "construction",
|
|
1964
|
-
|
|
2726
|
+
key: "holeFillGravel",
|
|
2727
|
+
label: labels.holeFillGravel,
|
|
1965
2728
|
subKind: "holeFillGravel"
|
|
1966
2729
|
});
|
|
1967
2730
|
if (hasHoleFillSeal)
|
|
1968
2731
|
items.push({
|
|
1969
2732
|
kind: "construction",
|
|
1970
|
-
|
|
2733
|
+
key: "holeFillSeal",
|
|
2734
|
+
label: labels.holeFillSeal,
|
|
1971
2735
|
subKind: "holeFillSeal"
|
|
1972
2736
|
});
|
|
1973
2737
|
if (hasWellCase)
|
|
1974
2738
|
items.push({
|
|
1975
2739
|
kind: "construction",
|
|
1976
|
-
|
|
2740
|
+
key: "wellCase",
|
|
2741
|
+
label: labels.wellCase,
|
|
1977
2742
|
subKind: "wellCase"
|
|
1978
2743
|
});
|
|
1979
2744
|
if (hasWellScreen)
|
|
1980
2745
|
items.push({
|
|
1981
2746
|
kind: "construction",
|
|
1982
|
-
|
|
2747
|
+
key: "wellScreen",
|
|
2748
|
+
label: labels.wellScreen,
|
|
1983
2749
|
subKind: "wellScreen"
|
|
1984
2750
|
});
|
|
1985
2751
|
if (hasReduction)
|
|
1986
2752
|
items.push({
|
|
1987
2753
|
kind: "construction",
|
|
1988
|
-
|
|
2754
|
+
key: "reduction",
|
|
2755
|
+
label: labels.reduction,
|
|
1989
2756
|
subKind: "reduction"
|
|
1990
2757
|
});
|
|
2758
|
+
if (hasCentralizer)
|
|
2759
|
+
items.push({
|
|
2760
|
+
kind: "construction",
|
|
2761
|
+
key: "centralizer",
|
|
2762
|
+
label: labels.centralizer,
|
|
2763
|
+
subKind: "centralizer"
|
|
2764
|
+
});
|
|
2765
|
+
if (hasPump)
|
|
2766
|
+
items.push({
|
|
2767
|
+
kind: "construction",
|
|
2768
|
+
key: "pump",
|
|
2769
|
+
label: labels.pump,
|
|
2770
|
+
subKind: "pump"
|
|
2771
|
+
});
|
|
1991
2772
|
if (hasConflict)
|
|
1992
2773
|
items.push({
|
|
1993
2774
|
kind: "construction",
|
|
1994
|
-
|
|
2775
|
+
key: "conflict",
|
|
2776
|
+
label: labels.conflict,
|
|
1995
2777
|
subKind: "conflict"
|
|
1996
2778
|
});
|
|
1997
|
-
|
|
2779
|
+
return items;
|
|
2780
|
+
}
|
|
2781
|
+
function drawLegendSymbol(symG, item, cx, rowSymY, { theme, cls, textures: legendTextures }) {
|
|
2782
|
+
const RC = "round";
|
|
2783
|
+
const rw = SYMBOL_WIDTH;
|
|
2784
|
+
const rh = SYMBOL_HEIGHT;
|
|
2785
|
+
if (item.kind === "fracture") {
|
|
2786
|
+
const color = item.water_intake ? theme.fracture.wetStroke : theme.fracture.dryStroke;
|
|
2787
|
+
if (item.swarm) {
|
|
2788
|
+
[-4, 0, 4].forEach((offset) => {
|
|
2789
|
+
symG.append("polyline").attr("class", cls.fracturePoly).attr(
|
|
2790
|
+
"points",
|
|
2791
|
+
`${cx},${rowSymY + offset} ${cx + 6},${rowSymY + offset - 1} ${cx + 12},${rowSymY + offset + 1} ${cx + 18},${rowSymY + offset - 0.5} ${cx + 24},${rowSymY + offset}`
|
|
2792
|
+
).attr("stroke", color).attr(
|
|
2793
|
+
"stroke-width",
|
|
2794
|
+
offset !== 0 ? theme.legend.fractureSideStrokeWidth : theme.legend.fractureStrokeWidth
|
|
2795
|
+
).attr("fill", "none").attr("stroke-linecap", RC).attr("stroke-linejoin", RC);
|
|
2796
|
+
});
|
|
2797
|
+
} else {
|
|
2798
|
+
symG.append("polyline").attr("class", cls.fracturePoly).attr(
|
|
2799
|
+
"points",
|
|
2800
|
+
`${cx},${rowSymY} ${cx + 5},${rowSymY - 1.5} ${cx + 11},${rowSymY + 1} ${cx + 17},${rowSymY - 0.5} ${cx + 24},${rowSymY}`
|
|
2801
|
+
).attr("stroke", color).attr("stroke-width", theme.legend.fractureStrokeWidth).attr("fill", "none").attr("stroke-linecap", RC).attr("stroke-linejoin", RC);
|
|
2802
|
+
}
|
|
2803
|
+
} else if (item.kind === "cave") {
|
|
2804
|
+
const color = item.water_intake ? theme.cave.wetStroke : theme.cave.dryStroke;
|
|
2805
|
+
const texture = item.water_intake ? legendTextures.cave_wet : legendTextures.cave_dry;
|
|
2806
|
+
symG.append("rect").attr("class", cls.caveFill).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", texture.url()).attr("stroke", color).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2807
|
+
} else if (item.subKind === "surfaceCase") {
|
|
2808
|
+
symG.append("rect").attr("class", cls.constructionRect).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", legendTextures.surface_case.url()).attr("stroke", "none");
|
|
2809
|
+
symG.append("line").attr("class", cls.constructionRect).attr("x1", cx).attr("x2", cx).attr("y1", rowSymY - rh / 2).attr("y2", rowSymY + rh / 2).attr("stroke", theme.surfaceCase.stroke).attr("stroke-width", 2);
|
|
2810
|
+
symG.append("line").attr("class", cls.constructionRect).attr("x1", cx + rw).attr("x2", cx + rw).attr("y1", rowSymY - rh / 2).attr("y2", rowSymY + rh / 2).attr("stroke", theme.surfaceCase.stroke).attr("stroke-width", 2);
|
|
2811
|
+
} else if (item.subKind === "centralizer") {
|
|
2812
|
+
const pipeW = rw * 0.4;
|
|
2813
|
+
const pipeL = cx + (rw - pipeW) / 2;
|
|
2814
|
+
const pipeR = pipeL + pipeW;
|
|
2815
|
+
const y1 = rowSymY - rh / 2;
|
|
2816
|
+
const y2 = rowSymY + rh / 2;
|
|
2817
|
+
const bowH = rh * 0.3;
|
|
2818
|
+
for (const x of [pipeL, pipeR]) {
|
|
2819
|
+
symG.append("line").attr("class", cls.constructionRect).attr("x1", x).attr("x2", x).attr("y1", y1).attr("y2", y2).attr("stroke", theme.wellCase.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2820
|
+
}
|
|
2821
|
+
for (const [from, to] of [
|
|
2822
|
+
[pipeL, cx],
|
|
2823
|
+
[pipeR, cx + rw]
|
|
2824
|
+
]) {
|
|
2825
|
+
symG.append("polyline").attr("class", cls.constructionRect).attr(
|
|
2826
|
+
"points",
|
|
2827
|
+
`${from},${rowSymY - bowH} ${to},${rowSymY} ${from},${rowSymY + bowH}`
|
|
2828
|
+
).attr("fill", theme.centralizer.fill).attr("stroke", theme.centralizer.stroke).attr("stroke-width", theme.centralizer.strokeWidth);
|
|
2829
|
+
}
|
|
2830
|
+
} else if (item.subKind === "pump") {
|
|
2831
|
+
const y1 = rowSymY - rh / 2;
|
|
2832
|
+
const y2 = rowSymY + rh / 2;
|
|
2833
|
+
const midX = cx + rw / 2;
|
|
2834
|
+
const riserHalf = rw * 0.12;
|
|
2835
|
+
const bodyHalf = rw * 0.28;
|
|
2836
|
+
const bodyTop = y1 + rh * 0.4;
|
|
2837
|
+
symG.append("rect").attr("class", cls.constructionRect).attr("x", midX - riserHalf).attr("y", y1).attr("width", 2 * riserHalf).attr("height", bodyTop - y1).attr("fill", theme.pump.riserFill).attr("stroke", "none");
|
|
2838
|
+
symG.append("path").attr("class", cls.constructionRect).attr("d", pipeWallsPath(midX - riserHalf, midX + riserHalf, y1, bodyTop)).attr("fill", "none").attr("stroke", theme.pump.riserStroke).attr("stroke-width", theme.pump.riserStrokeWidth);
|
|
2839
|
+
symG.append("path").attr("class", cls.constructionRect).attr(
|
|
2840
|
+
"d",
|
|
2841
|
+
`M${midX - bodyHalf},${bodyTop}H${midX + bodyHalf}V${y2}H${midX - bodyHalf}Z`
|
|
2842
|
+
).attr("fill", theme.pump.fill).attr("stroke", theme.pump.stroke).attr("stroke-width", theme.pump.strokeWidth);
|
|
2843
|
+
} else if (item.subKind === "reduction") {
|
|
2844
|
+
const topW = rw * 0.5;
|
|
2845
|
+
const y1 = rowSymY - rh / 2;
|
|
2846
|
+
const y2 = rowSymY + rh / 2;
|
|
2847
|
+
const midX = cx + rw / 2;
|
|
2848
|
+
const tl = `${midX - topW / 2},${y1}`;
|
|
2849
|
+
const tr = `${midX + topW / 2},${y1}`;
|
|
2850
|
+
symG.append("polygon").attr("class", cls.constructionRect).attr("points", `${tl} ${tr} ${cx + rw},${y2} ${cx},${y2}`).attr("fill", theme.reduction.fill).attr("stroke", "none");
|
|
2851
|
+
symG.append("path").attr("class", cls.constructionRect).attr("d", `M${tl}L${cx},${y2}M${tr}L${cx + rw},${y2}`).attr("fill", "none").attr("stroke", theme.reduction.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2852
|
+
} else if (item.subKind === "wellCase" || item.subKind === "wellScreen" || item.subKind === "boreHole") {
|
|
2853
|
+
const y1 = rowSymY - rh / 2;
|
|
2854
|
+
const y2 = rowSymY + rh / 2;
|
|
2855
|
+
const shoe = 3;
|
|
2856
|
+
const xL = cx + shoe;
|
|
2857
|
+
const xR = cx + rw - shoe;
|
|
2858
|
+
const style = {
|
|
2859
|
+
wellCase: { fill: theme.wellCase.fill, stroke: theme.wellCase.stroke },
|
|
2860
|
+
wellScreen: {
|
|
2861
|
+
fill: legendTextures.well_screen.url(),
|
|
2862
|
+
stroke: theme.wellScreen.stroke
|
|
2863
|
+
},
|
|
2864
|
+
boreHole: { fill: theme.boreHole.fill, stroke: theme.boreHole.stroke }
|
|
2865
|
+
}[item.subKind];
|
|
2866
|
+
symG.append("rect").attr("class", cls.constructionRect).attr("x", xL).attr("y", y1).attr("width", xR - xL).attr("height", rh).attr("fill", style.fill).attr("stroke", "none");
|
|
2867
|
+
const walls = symG.append("path").attr("class", cls.constructionRect).attr(
|
|
2868
|
+
"d",
|
|
2869
|
+
pipeWallsPath(xL, xR, y1, y2) + (item.subKind === "boreHole" ? `M${xL},${y2}H${xR}` : "")
|
|
2870
|
+
).attr("fill", "none").attr("stroke", style.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2871
|
+
if (item.subKind === "boreHole")
|
|
2872
|
+
walls.attr("stroke-dasharray", theme.boreHole.strokeDasharray);
|
|
2873
|
+
if (item.subKind === "wellCase")
|
|
2874
|
+
symG.append("path").attr("class", cls.constructionRect).attr("d", shoePath(xL, xR, y2, shoe)).attr("fill", style.stroke).attr("stroke", "none");
|
|
2875
|
+
if (item.subKind === "wellScreen")
|
|
2876
|
+
symG.append("path").attr("class", cls.constructionRect).attr(
|
|
2877
|
+
"d",
|
|
2878
|
+
screenEndPath(xL, xR, y1 + 0.5) + screenEndPath(xL, xR, y2 - 0.5)
|
|
2879
|
+
).attr("fill", "none").attr("stroke", style.stroke).attr("stroke-width", theme.wellScreen.endStrokeWidth).attr("stroke-dasharray", "2, 1.5");
|
|
2880
|
+
} else if (item.subKind === "cementPad") {
|
|
2881
|
+
const h = rh * 0.6;
|
|
2882
|
+
const { slabs } = getCementPadGeometry(
|
|
2883
|
+
rw,
|
|
2884
|
+
2 * cx + rw,
|
|
2885
|
+
rowSymY + h / 2,
|
|
2886
|
+
{ widthRatio: 1, height: h },
|
|
2887
|
+
rw * 0.3
|
|
2888
|
+
);
|
|
2889
|
+
for (const d of slabs)
|
|
2890
|
+
symG.append("path").attr("class", cls.constructionRect).attr("d", d).attr("fill", legendTextures.pad.url()).attr("stroke", theme.cementPad.stroke).attr("stroke-width", theme.legend.itemStrokeWidth).attr("stroke-linejoin", RC);
|
|
2891
|
+
} else {
|
|
2892
|
+
const symMap = {
|
|
2893
|
+
holeFillGravel: {
|
|
2894
|
+
fill: legendTextures.gravel_pack.url(),
|
|
2895
|
+
stroke: theme.holeFill.stroke
|
|
2896
|
+
},
|
|
2897
|
+
holeFillSeal: {
|
|
2898
|
+
fill: legendTextures.seal.url(),
|
|
2899
|
+
stroke: theme.holeFill.stroke
|
|
2900
|
+
},
|
|
2901
|
+
conflict: {
|
|
2902
|
+
fill: legendTextures.conflict.url(),
|
|
2903
|
+
stroke: theme.conflict.stroke
|
|
2904
|
+
}
|
|
2905
|
+
};
|
|
2906
|
+
const sym = symMap[item.subKind];
|
|
2907
|
+
const symRect = symG.append("rect").attr("class", cls.constructionRect).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", sym.fill).attr("stroke", sym.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2908
|
+
if (sym.dasharray) symRect.attr("stroke-dasharray", sym.dasharray);
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
function resolveStyle(options) {
|
|
2912
|
+
return {
|
|
2913
|
+
theme: (0, import_defu.defu)(options.theme ?? {}, DEFAULT_WELL_THEME),
|
|
2914
|
+
cls: options.classNames ? { ...DEFAULT_COMPONENTS_CLASS_NAMES.legend, ...options.classNames } : DEFAULT_COMPONENTS_CLASS_NAMES.legend,
|
|
2915
|
+
textures: createWellTextures(options.textures)
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
function drawWellLegendSymbol(selector, item, options = {}) {
|
|
2919
|
+
const style = resolveStyle(options);
|
|
2920
|
+
const svgEl = d37.select(selector);
|
|
2921
|
+
svgEl.selectAll("*").remove();
|
|
2922
|
+
svgEl.attr("width", SYMBOL_WIDTH + SYMBOL_MARGIN * 2).attr("height", SYMBOL_HEIGHT + SYMBOL_MARGIN * 2);
|
|
2923
|
+
Object.values(style.textures).forEach((t) => svgEl.call(t));
|
|
2924
|
+
const symG = svgEl.append("g").attr("class", style.cls.item);
|
|
2925
|
+
drawLegendSymbol(
|
|
2926
|
+
symG,
|
|
2927
|
+
item,
|
|
2928
|
+
SYMBOL_MARGIN,
|
|
2929
|
+
SYMBOL_MARGIN + SYMBOL_HEIGHT / 2,
|
|
2930
|
+
style
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
function drawWellLegend(selector, profile, options = {}) {
|
|
2934
|
+
const cfg = (0, import_defu.defu)(
|
|
2935
|
+
options.config ?? {},
|
|
2936
|
+
INTERACTIVE_RENDER_CONFIG.legend
|
|
2937
|
+
);
|
|
2938
|
+
const items = getWellLegendItems(profile, cfg.labels);
|
|
2939
|
+
const svgEl = d37.select(selector);
|
|
1998
2940
|
svgEl.selectAll("*").remove();
|
|
1999
2941
|
if (items.length === 0) {
|
|
2000
2942
|
svgEl.attr("width", 0).attr("height", 0);
|
|
2001
2943
|
return;
|
|
2002
2944
|
}
|
|
2003
|
-
const
|
|
2004
|
-
|
|
2945
|
+
const style = resolveStyle(options);
|
|
2946
|
+
const { theme, cls } = style;
|
|
2947
|
+
Object.values(style.textures).forEach((t) => svgEl.call(t));
|
|
2005
2948
|
const itemsPerRow = cfg.maxWidth ? Math.max(1, Math.floor((cfg.maxWidth - cfg.padding * 2) / cfg.itemWidth)) : items.length;
|
|
2006
2949
|
const numRows = Math.ceil(items.length / itemsPerRow);
|
|
2007
2950
|
const rowWidth = Math.min(items.length, itemsPerRow) * cfg.itemWidth;
|
|
2008
2951
|
const totalWidth = cfg.padding * 2 + rowWidth;
|
|
2009
2952
|
const totalHeight = numRows * cfg.height;
|
|
2010
2953
|
svgEl.attr("width", totalWidth).attr("height", totalHeight);
|
|
2011
|
-
const RC = "round";
|
|
2012
2954
|
const g = svgEl.append("g").attr("transform", `translate(${cfg.padding}, 2)`);
|
|
2013
2955
|
g.append("rect").attr("class", cls.border).attr("x", 0).attr("y", 0).attr("width", totalWidth - cfg.padding).attr("height", totalHeight - 4).attr("fill", "white").attr("rx", cfg.borderRadius).attr("stroke-width", theme.legend.borderStrokeWidth);
|
|
2014
2956
|
g.append("text").attr("class", cls.title).attr("x", 4).attr("y", 11).attr("font-size", theme.legend.fontSize).attr("font-family", theme.legend.fontFamily ?? "sans-serif").attr("font-weight", theme.legend.titleFontWeight ?? "bold").text(`${cfg.title}:`);
|
|
2015
|
-
const rw = 24;
|
|
2016
|
-
const rh = 12;
|
|
2017
2957
|
items.forEach((item, i) => {
|
|
2018
2958
|
const col = i % itemsPerRow;
|
|
2019
2959
|
const row = Math.floor(i / itemsPerRow);
|
|
2020
2960
|
const rowSymY = row * cfg.height + (cfg.height - 4) / 2;
|
|
2021
2961
|
const cx = col * cfg.itemWidth;
|
|
2022
2962
|
const symG = g.append("g").attr("class", cls.item);
|
|
2023
|
-
|
|
2024
|
-
const color = item.water_intake ? theme.fracture.wetStroke : theme.fracture.dryStroke;
|
|
2025
|
-
if (item.swarm) {
|
|
2026
|
-
[-4, 0, 4].forEach((offset) => {
|
|
2027
|
-
symG.append("polyline").attr("class", cls.fracturePoly).attr(
|
|
2028
|
-
"points",
|
|
2029
|
-
`${cx},${rowSymY + offset} ${cx + 6},${rowSymY + offset - 1} ${cx + 12},${rowSymY + offset + 1} ${cx + 18},${rowSymY + offset - 0.5} ${cx + 24},${rowSymY + offset}`
|
|
2030
|
-
).attr("stroke", color).attr(
|
|
2031
|
-
"stroke-width",
|
|
2032
|
-
offset !== 0 ? theme.legend.fractureSideStrokeWidth : theme.legend.fractureStrokeWidth
|
|
2033
|
-
).attr("fill", "none").attr("stroke-linecap", RC).attr("stroke-linejoin", RC);
|
|
2034
|
-
});
|
|
2035
|
-
} else {
|
|
2036
|
-
symG.append("polyline").attr("class", cls.fracturePoly).attr(
|
|
2037
|
-
"points",
|
|
2038
|
-
`${cx},${rowSymY} ${cx + 5},${rowSymY - 1.5} ${cx + 11},${rowSymY + 1} ${cx + 17},${rowSymY - 0.5} ${cx + 24},${rowSymY}`
|
|
2039
|
-
).attr("stroke", color).attr("stroke-width", theme.legend.fractureStrokeWidth).attr("fill", "none").attr("stroke-linecap", RC).attr("stroke-linejoin", RC);
|
|
2040
|
-
}
|
|
2041
|
-
} else if (item.kind === "cave") {
|
|
2042
|
-
const color = item.water_intake ? theme.cave.wetStroke : theme.cave.dryStroke;
|
|
2043
|
-
const texture = item.water_intake ? legendTextures.cave_wet : legendTextures.cave_dry;
|
|
2044
|
-
symG.append("rect").attr("class", cls.caveFill).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", texture.url()).attr("stroke", color).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2045
|
-
} else if (item.subKind === "surfaceCase") {
|
|
2046
|
-
symG.append("rect").attr("class", cls.constructionRect).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", legendTextures.surface_case.url()).attr("stroke", "none");
|
|
2047
|
-
symG.append("line").attr("class", cls.constructionRect).attr("x1", cx).attr("x2", cx).attr("y1", rowSymY - rh / 2).attr("y2", rowSymY + rh / 2).attr("stroke", theme.surfaceCase.stroke).attr("stroke-width", 2);
|
|
2048
|
-
symG.append("line").attr("class", cls.constructionRect).attr("x1", cx + rw).attr("x2", cx + rw).attr("y1", rowSymY - rh / 2).attr("y2", rowSymY + rh / 2).attr("stroke", theme.surfaceCase.stroke).attr("stroke-width", 2);
|
|
2049
|
-
} else if (item.subKind === "reduction") {
|
|
2050
|
-
const topW = rw * 0.5;
|
|
2051
|
-
const y1 = rowSymY - rh / 2;
|
|
2052
|
-
const y2 = rowSymY + rh / 2;
|
|
2053
|
-
const midX = cx + rw / 2;
|
|
2054
|
-
symG.append("polygon").attr("class", cls.constructionRect).attr(
|
|
2055
|
-
"points",
|
|
2056
|
-
`${midX - topW / 2},${y1} ${midX + topW / 2},${y1} ${cx + rw},${y2} ${cx},${y2}`
|
|
2057
|
-
).attr("fill", theme.reduction.fill).attr("stroke", theme.reduction.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2058
|
-
} else {
|
|
2059
|
-
const symMap = {
|
|
2060
|
-
boreHole: {
|
|
2061
|
-
fill: theme.boreHole.fill,
|
|
2062
|
-
stroke: theme.boreHole.stroke,
|
|
2063
|
-
dasharray: theme.boreHole.strokeDasharray
|
|
2064
|
-
},
|
|
2065
|
-
holeFillGravel: {
|
|
2066
|
-
fill: legendTextures.gravel_pack.url(),
|
|
2067
|
-
stroke: theme.holeFill.stroke
|
|
2068
|
-
},
|
|
2069
|
-
holeFillSeal: {
|
|
2070
|
-
fill: legendTextures.seal.url(),
|
|
2071
|
-
stroke: theme.holeFill.stroke
|
|
2072
|
-
},
|
|
2073
|
-
wellCase: { fill: theme.wellCase.fill, stroke: theme.wellCase.stroke },
|
|
2074
|
-
wellScreen: {
|
|
2075
|
-
fill: legendTextures.well_screen.url(),
|
|
2076
|
-
stroke: theme.wellScreen.stroke
|
|
2077
|
-
},
|
|
2078
|
-
cementPad: {
|
|
2079
|
-
fill: legendTextures.pad.url(),
|
|
2080
|
-
stroke: theme.cementPad.stroke
|
|
2081
|
-
},
|
|
2082
|
-
conflict: {
|
|
2083
|
-
fill: legendTextures.conflict.url(),
|
|
2084
|
-
stroke: theme.conflict.stroke
|
|
2085
|
-
}
|
|
2086
|
-
};
|
|
2087
|
-
const sym = symMap[item.subKind];
|
|
2088
|
-
const symRect = symG.append("rect").attr("class", cls.constructionRect).attr("x", cx).attr("y", rowSymY - rh / 2).attr("width", rw).attr("height", rh).attr("fill", sym.fill).attr("stroke", sym.stroke).attr("stroke-width", theme.legend.itemStrokeWidth);
|
|
2089
|
-
if (sym.dasharray) symRect.attr("stroke-dasharray", sym.dasharray);
|
|
2090
|
-
}
|
|
2963
|
+
drawLegendSymbol(symG, item, cx, rowSymY, style);
|
|
2091
2964
|
g.append("text").attr("class", cls.label).attr("x", cx + 28).attr("y", rowSymY + 3).attr("font-size", theme.legend.fontSize).attr("font-family", theme.legend.fontFamily ?? "sans-serif").attr("font-weight", theme.legend.labelFontWeight ?? 400).text(item.label);
|
|
2092
2965
|
});
|
|
2093
2966
|
}
|
|
2094
2967
|
|
|
2095
2968
|
// src/renderers/lithology.renderer.ts
|
|
2969
|
+
var d38 = __toESM(require("d3"), 1);
|
|
2096
2970
|
function drawLithology(ctx, data) {
|
|
2097
|
-
if (!data.length) return;
|
|
2098
2971
|
const {
|
|
2099
2972
|
groups: { lithologyGroup },
|
|
2100
2973
|
svg,
|
|
@@ -2118,10 +2991,219 @@ function drawLithology(ctx, data) {
|
|
|
2118
2991
|
const merged = mergeEnter(newLayers, rects);
|
|
2119
2992
|
withTransition(merged, transition).attr("y", getYPos).attr("height", getHeight).attr("fill", getLithologyFill(data, svg, ctx.theme.lithologyTexture));
|
|
2120
2993
|
}
|
|
2994
|
+
function drawLithologySwatch(selector, layer, options) {
|
|
2995
|
+
const { size, theme } = options;
|
|
2996
|
+
const svg = d38.select(selector);
|
|
2997
|
+
svg.selectAll("*").remove();
|
|
2998
|
+
svg.attr("width", size).attr("height", size);
|
|
2999
|
+
const fill = getLithologyFill([layer], svg, {
|
|
3000
|
+
...theme.lithologyTexture,
|
|
3001
|
+
// Denser pattern so a few strokes show inside the small square.
|
|
3002
|
+
size: Math.max(12, size * 3)
|
|
3003
|
+
});
|
|
3004
|
+
svg.append("rect").attr("x", 0.5).attr("y", 0.5).attr("width", size - 1).attr("height", size - 1).attr("fill", fill(layer)).attr("stroke", theme.lithology.stroke).attr("stroke-width", 0.5);
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
// src/renderers/markers.renderer.ts
|
|
3008
|
+
function drawMarkers(ctx, data) {
|
|
3009
|
+
const group = ctx.groups.markersGroup;
|
|
3010
|
+
group.selectAll("*").remove();
|
|
3011
|
+
const cfg = ctx.renderConfig.markers;
|
|
3012
|
+
const theme = ctx.theme.markers;
|
|
3013
|
+
const r = cfg.radius;
|
|
3014
|
+
if (cfg.lithology) {
|
|
3015
|
+
const cx = (ctx.geoXLeft + ctx.geoXRight) / 2;
|
|
3016
|
+
getLithologyMarkers(data.lithology, ctx.depthFrom, ctx.depthTo).forEach(
|
|
3017
|
+
(marker) => {
|
|
3018
|
+
const top = ctx.yScale(marker.from);
|
|
3019
|
+
const bottom = ctx.yScale(marker.to);
|
|
3020
|
+
if (bottom - top < r) return;
|
|
3021
|
+
const cy = bottom - top >= 2 * r + 4 ? top + r + 2 : (top + bottom) / 2;
|
|
3022
|
+
const g = group.append("g").attr("class", ctx.classes.markers.lithology);
|
|
3023
|
+
g.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", theme.fill).attr("stroke", theme.stroke).attr("stroke-width", theme.strokeWidth);
|
|
3024
|
+
g.append("text").attr("x", cx).attr("y", cy).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", theme.fontSize).attr("font-family", theme.fontFamily ?? "sans-serif").attr("font-weight", theme.fontWeight ?? 600).attr("fill", theme.color).text(String(marker.index));
|
|
3025
|
+
}
|
|
3026
|
+
);
|
|
3027
|
+
}
|
|
3028
|
+
if (cfg.fractures) {
|
|
3029
|
+
const x = ctx.pocoCenterX + ctx.POCO_WIDTH * ctx.renderConfig.fractures.widthMultiplier / 2 + 3;
|
|
3030
|
+
getFractureMarkers(data.fractures, ctx.depthFrom, ctx.depthTo).forEach(
|
|
3031
|
+
(marker) => {
|
|
3032
|
+
group.append("text").attr("class", ctx.classes.markers.fracture).attr("x", x).attr("y", ctx.yScale(marker.depth)).attr("dominant-baseline", "central").attr("font-size", theme.fontSize).attr("font-family", theme.fontFamily ?? "sans-serif").attr("font-weight", theme.fontWeight ?? 600).attr("fill", theme.color).text(marker.label);
|
|
3033
|
+
}
|
|
3034
|
+
);
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
// src/renderers/overlap.renderer.ts
|
|
3039
|
+
var import_textures3 = __toESM(require("textures"), 1);
|
|
3040
|
+
var import_utils8 = require("@welldot/utils");
|
|
3041
|
+
function drawOverlap(ctx) {
|
|
3042
|
+
const group = ctx.groups.overlapGroup;
|
|
3043
|
+
group.selectAll("*").remove();
|
|
3044
|
+
const { repeatedTo, depthFrom } = ctx;
|
|
3045
|
+
if (repeatedTo == null || repeatedTo <= depthFrom) return;
|
|
3046
|
+
const theme = ctx.theme.overlap;
|
|
3047
|
+
const { margins } = ctx.state;
|
|
3048
|
+
const overview = ctx.renderConfig.overview;
|
|
3049
|
+
const showsDescription = hasDescriptionColumn(ctx);
|
|
3050
|
+
const x0 = -margins.left + (overview.active ? overview.x + overview.width + 4 : 0);
|
|
3051
|
+
const x1 = showsDescription ? ctx.geoXRight + ctx.renderConfig.labels.descriptionXOffset - 4 : ctx.svgWidth - margins.left;
|
|
3052
|
+
const y0 = ctx.yScale(depthFrom);
|
|
3053
|
+
const y1 = ctx.yScale(repeatedTo);
|
|
3054
|
+
const hatch = import_textures3.default.lines().size(theme.size).strokeWidth(theme.strokeWidth).stroke(theme.stroke);
|
|
3055
|
+
ctx.svg.call(hatch);
|
|
3056
|
+
group.append("rect").attr("class", ctx.classes.overlap.band).attr("x", x0).attr("y", y0).attr("width", Math.max(0, x1 - x0)).attr("height", Math.max(0, y1 - y0)).attr("fill", hatch.url()).style("pointer-events", "none");
|
|
3057
|
+
group.append("line").attr("x1", x0).attr("x2", ctx.svgWidth - margins.left).attr("y1", y1).attr("y2", y1).attr("stroke", theme.ruleStroke).attr("stroke-width", 0.6).attr("stroke-dasharray", "3, 2");
|
|
3058
|
+
const whole = (m) => (0, import_utils8.formatNumber)(ctx.units.length === "ft" ? m * 3.28084 : m, {
|
|
3059
|
+
maximumFractionDigits: 0,
|
|
3060
|
+
locale: ctx.locale
|
|
3061
|
+
});
|
|
3062
|
+
const unit = getLengthUnit(ctx.units.length);
|
|
3063
|
+
const range = `${whole(depthFrom)}\u2013${whole(repeatedTo)} ${unit}`;
|
|
3064
|
+
group.append("text").attr("class", ctx.classes.overlap.label).attr("x", ctx.svgWidth - margins.left - 2).attr("y", y0 + theme.fontSize + 1).attr("text-anchor", "end").attr("font-size", theme.fontSize).attr("font-family", theme.fontFamily ?? "monospace").attr("fill", theme.labelColor).text(formatOverlapLabel(ctx.renderConfig.overlap.label, range));
|
|
3065
|
+
}
|
|
3066
|
+
|
|
3067
|
+
// src/renderers/overview.renderer.ts
|
|
3068
|
+
function drawOverview(ctx, lithology) {
|
|
3069
|
+
const group = ctx.groups.overviewGroup;
|
|
3070
|
+
group.selectAll("*").remove();
|
|
3071
|
+
const cfg = ctx.renderConfig.overview;
|
|
3072
|
+
if (!cfg.active || lithology.length === 0 || ctx.totalDepth <= 0) return;
|
|
3073
|
+
const theme = ctx.theme.overview;
|
|
3074
|
+
const height = Math.min(cfg.height, ctx.state.height);
|
|
3075
|
+
const { y, window } = getOverviewGeometry(
|
|
3076
|
+
ctx.totalDepth,
|
|
3077
|
+
height,
|
|
3078
|
+
ctx.depthFrom,
|
|
3079
|
+
ctx.depthTo
|
|
3080
|
+
);
|
|
3081
|
+
lithology.forEach((layer) => {
|
|
3082
|
+
group.append("rect").attr("class", ctx.classes.overview.item).attr("x", cfg.x).attr("y", y(layer.from)).attr("width", cfg.width).attr("height", Math.max(0, y(layer.to) - y(layer.from))).attr("fill", layer.color || theme.emptyFill);
|
|
3083
|
+
});
|
|
3084
|
+
group.append("rect").attr("x", cfg.x).attr("y", 0).attr("width", cfg.width).attr("height", y(ctx.totalDepth)).attr("fill", "none").attr("stroke", theme.stroke).attr("stroke-width", theme.strokeWidth);
|
|
3085
|
+
group.append("rect").attr("class", ctx.classes.overview.window).attr("x", cfg.x - 2).attr("y", window.y).attr("width", cfg.width + 4).attr("height", window.height).attr("fill", "none").attr("stroke", theme.windowStroke).attr("stroke-width", theme.windowStrokeWidth);
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
// src/renderers/pump.renderer.ts
|
|
3089
|
+
var d39 = __toESM(require("d3"), 1);
|
|
3090
|
+
var import_utils9 = require("@welldot/utils");
|
|
3091
|
+
function getPumpSpans(panelTop, panelBottom, bodyTop, intakeY) {
|
|
3092
|
+
const riserBottom = Math.min(Math.max(panelTop, bodyTop), panelBottom);
|
|
3093
|
+
const top = Math.max(bodyTop, panelTop);
|
|
3094
|
+
const bottom = Math.min(intakeY, panelBottom);
|
|
3095
|
+
return {
|
|
3096
|
+
riserBottom,
|
|
3097
|
+
body: bottom > top ? { top, bottom, cutTop: top > bodyTop, cutBottom: bottom < intakeY } : null
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
var riserBreakAmplitude = (width) => Math.min(2, width / 3);
|
|
3101
|
+
function getRiserTop(xLeft, xRight, y, broken) {
|
|
3102
|
+
if (!broken) return { edge: `H${xRight}`, breakLine: "" };
|
|
3103
|
+
const a = riserBreakAmplitude(xRight - xLeft);
|
|
3104
|
+
const w = xRight - xLeft;
|
|
3105
|
+
const zigzag = `L${xLeft + w / 3},${y - a}L${xLeft + 2 * w / 3},${y + a}L${xRight},${y}`;
|
|
3106
|
+
return { edge: zigzag, breakLine: `M${xLeft},${y}${zigzag}` };
|
|
3107
|
+
}
|
|
3108
|
+
var BODY_MAX_FILL = 0.85;
|
|
3109
|
+
var RISER_MAX_FILL = 0.7;
|
|
3110
|
+
function getPumpDiameters(intakeD, narrowestD, riserDiameter, cfg) {
|
|
3111
|
+
const maxBody = intakeD * BODY_MAX_FILL;
|
|
3112
|
+
const riser = Math.min(
|
|
3113
|
+
riserDiameter ?? intakeD * cfg.riserWidthRatio,
|
|
3114
|
+
narrowestD * RISER_MAX_FILL,
|
|
3115
|
+
maxBody * RISER_MAX_FILL
|
|
3116
|
+
);
|
|
3117
|
+
const body = Math.min(
|
|
3118
|
+
Math.max(intakeD * cfg.bodyWidthRatio, riser * 1.4),
|
|
3119
|
+
maxBody
|
|
3120
|
+
);
|
|
3121
|
+
return { riser, body };
|
|
3122
|
+
}
|
|
3123
|
+
function drawPump(ctx, pump) {
|
|
3124
|
+
const group = ctx.groups.pumpGroup;
|
|
3125
|
+
const cls = ctx.classes.pump;
|
|
3126
|
+
const cfg = ctx.renderConfig.construction.pump;
|
|
3127
|
+
const theme = ctx.theme.pump;
|
|
3128
|
+
const intake = pump?.intake_depth;
|
|
3129
|
+
const visible = !!pump && cfg.active && intake !== void 0 && intake > 0 && // the riser crosses this panel when the panel starts above the intake
|
|
3130
|
+
ctx.depthFrom < intake;
|
|
3131
|
+
const data = visible ? [pump] : [];
|
|
3132
|
+
const selection = group.selectAll(`g.${cls.item}`).data(data, (d) => d.id);
|
|
3133
|
+
selection.exit().remove();
|
|
3134
|
+
if (!visible) return;
|
|
3135
|
+
const maxXValue = d39.max((0, import_utils9.getProfileDiamValues)(ctx.constructionData)) || 0;
|
|
3136
|
+
const xScale = d39.scaleLinear().domain([0, maxXValue]).range([0, ctx.POCO_WIDTH]);
|
|
3137
|
+
const pipes = [
|
|
3138
|
+
...ctx.constructionData.well_case,
|
|
3139
|
+
...ctx.constructionData.well_screen
|
|
3140
|
+
];
|
|
3141
|
+
const casingD = diameterAt(pipes, intake) ?? diameterAt(ctx.constructionData.bore_hole, intake) ?? maxXValue;
|
|
3142
|
+
const narrowestD = Math.min(
|
|
3143
|
+
casingD,
|
|
3144
|
+
...[...pipes, ...ctx.constructionData.bore_hole].filter((i) => i.from < intake && i.to > 0).map((i) => i.diameter)
|
|
3145
|
+
);
|
|
3146
|
+
const { riser: riserD, body: bodyD } = getPumpDiameters(
|
|
3147
|
+
casingD,
|
|
3148
|
+
narrowestD,
|
|
3149
|
+
pump.riser_diameter,
|
|
3150
|
+
cfg
|
|
3151
|
+
);
|
|
3152
|
+
const riserLeft = (ctx.POCO_CENTER - xScale(riserD)) / 2;
|
|
3153
|
+
const riserRight = (ctx.POCO_CENTER + xScale(riserD)) / 2;
|
|
3154
|
+
const bodyLeft = (ctx.POCO_CENTER - xScale(bodyD)) / 2;
|
|
3155
|
+
const bodyRight = (ctx.POCO_CENTER + xScale(bodyD)) / 2;
|
|
3156
|
+
const yIntake = ctx.yScale(intake);
|
|
3157
|
+
const yBodyTop = yIntake - cfg.bodyHeight;
|
|
3158
|
+
const headDepth = Math.min(
|
|
3159
|
+
0,
|
|
3160
|
+
...pipes.filter((p) => p.from < 0).map((p) => p.from)
|
|
3161
|
+
);
|
|
3162
|
+
const headInPanel = ctx.depthFrom <= headDepth;
|
|
3163
|
+
const padOnHead = headDepth === 0 && !!ctx.constructionData.cement_pad?.thickness;
|
|
3164
|
+
const yRiserTop = headInPanel ? ctx.yScale(headDepth) - (padOnHead ? ctx.renderConfig.construction.cementPad.height - riserBreakAmplitude(xScale(riserD)) : 0) : ctx.yScale(ctx.depthFrom);
|
|
3165
|
+
const { riserBottom: yRiserBottom, body } = getPumpSpans(
|
|
3166
|
+
yRiserTop,
|
|
3167
|
+
ctx.yScale(ctx.depthTo),
|
|
3168
|
+
yBodyTop,
|
|
3169
|
+
yIntake
|
|
3170
|
+
);
|
|
3171
|
+
const r = Math.min(3, (bodyRight - bodyLeft) / 4);
|
|
3172
|
+
const entered = selection.enter().append("g").attr("class", cls.item).on("mouseover", ctx.tooltips.pump.show).on("mouseout", ctx.tooltips.pump.hide);
|
|
3173
|
+
entered.append("path").attr("class", `${cls.item}-riser-fill`);
|
|
3174
|
+
entered.append("path").attr("class", `${cls.item}-riser`);
|
|
3175
|
+
entered.append("path").attr("class", `${cls.item}-body`);
|
|
3176
|
+
entered.append("path").attr("class", `${cls.item}-intake`);
|
|
3177
|
+
const merged = entered.merge(selection);
|
|
3178
|
+
const top = getRiserTop(riserLeft, riserRight, yRiserTop, headInPanel);
|
|
3179
|
+
merged.select(`.${cls.item}-riser-fill`).attr(
|
|
3180
|
+
"d",
|
|
3181
|
+
yRiserBottom > yRiserTop ? `M${riserLeft},${yRiserTop}${top.edge}V${yRiserBottom}H${riserLeft}Z` : ""
|
|
3182
|
+
).attr("fill", theme.riserFill).attr("stroke", "none");
|
|
3183
|
+
merged.select(`.${cls.item}-riser`).attr(
|
|
3184
|
+
"d",
|
|
3185
|
+
yRiserBottom > yRiserTop ? `M${riserLeft},${yRiserTop}V${yRiserBottom}M${riserRight},${yRiserTop}V${yRiserBottom}${top.breakLine}` : ""
|
|
3186
|
+
).attr("stroke-linejoin", "round").attr("fill", "none").attr("stroke", theme.riserStroke).attr("stroke-width", theme.riserStrokeWidth);
|
|
3187
|
+
let bodyPath = "";
|
|
3188
|
+
if (body) {
|
|
3189
|
+
const rt = body.cutTop ? 0 : Math.min(r, (body.bottom - body.top) / 2);
|
|
3190
|
+
const rb = body.cutBottom ? 0 : Math.min(r, (body.bottom - body.top) / 2);
|
|
3191
|
+
const { top: top2, bottom } = body;
|
|
3192
|
+
bodyPath = `M${bodyLeft + rt},${top2}H${bodyRight - rt}Q${bodyRight},${top2} ${bodyRight},${top2 + rt}V${bottom - rb}Q${bodyRight},${bottom} ${bodyRight - rb},${bottom}H${bodyLeft + rb}Q${bodyLeft},${bottom} ${bodyLeft},${bottom - rb}V${top2 + rt}Q${bodyLeft},${top2} ${bodyLeft + rt},${top2}Z`;
|
|
3193
|
+
}
|
|
3194
|
+
merged.select(`.${cls.item}-body`).attr("d", bodyPath).attr("fill", theme.fill).attr("stroke", theme.stroke).attr("stroke-width", theme.strokeWidth);
|
|
3195
|
+
const hatchY = [
|
|
3196
|
+
yIntake - cfg.bodyHeight * 0.3,
|
|
3197
|
+
yIntake - cfg.bodyHeight * 0.15
|
|
3198
|
+
].filter((y) => body && y > body.top && y < body.bottom);
|
|
3199
|
+
merged.select(`.${cls.item}-intake`).attr(
|
|
3200
|
+
"d",
|
|
3201
|
+
hatchY.map((y) => `M${bodyLeft + 1.5},${y}H${bodyRight - 1.5}`).join("")
|
|
3202
|
+
).attr("fill", "none").attr("stroke", theme.stroke).attr("stroke-width", 0.8);
|
|
3203
|
+
}
|
|
2121
3204
|
|
|
2122
3205
|
// src/renderers/unit-labels.renderer.ts
|
|
2123
3206
|
function drawUnitLabels(ctx, data) {
|
|
2124
|
-
if (!ctx.renderConfig.unitLabels.active || !data.length) return;
|
|
2125
3207
|
const {
|
|
2126
3208
|
groups: { unitLabelsGroup },
|
|
2127
3209
|
depthFrom,
|
|
@@ -2132,6 +3214,7 @@ function drawUnitLabels(ctx, data) {
|
|
|
2132
3214
|
classes
|
|
2133
3215
|
} = ctx;
|
|
2134
3216
|
unitLabelsGroup.selectAll("*").remove();
|
|
3217
|
+
if (!renderConfig.unitLabels.active || !data.length) return;
|
|
2135
3218
|
const ru = renderConfig.unitLabels;
|
|
2136
3219
|
const rut = theme.unitLabels;
|
|
2137
3220
|
const sw = ru.stripWidth;
|
|
@@ -2212,7 +3295,7 @@ function buildSvgStyleBlock(theme) {
|
|
|
2212
3295
|
}
|
|
2213
3296
|
|
|
2214
3297
|
// src/Renderer.ts
|
|
2215
|
-
var
|
|
3298
|
+
var d310 = { ...d3module2, tip: import_d3_tip2.default };
|
|
2216
3299
|
var WellRenderer = class {
|
|
2217
3300
|
/**
|
|
2218
3301
|
* @param svgs - One entry per SVG panel; multi-entry for split-panel layouts.
|
|
@@ -2272,12 +3355,14 @@ var WellRenderer = class {
|
|
|
2272
3355
|
const { selector, height, width, margins } = inst;
|
|
2273
3356
|
const svgWidth = width + margins.left + margins.right;
|
|
2274
3357
|
const svgHeight = height + margins.top + margins.bottom;
|
|
2275
|
-
const svg =
|
|
3358
|
+
const svg = d310.select(selector);
|
|
2276
3359
|
svg.selectAll("*").remove();
|
|
2277
3360
|
svg.attr("height", svgHeight).attr("width", svgWidth);
|
|
2278
3361
|
const defs = svg.append("defs");
|
|
2279
3362
|
defs.append("style").text(buildSvgStyleBlock(this.theme));
|
|
2280
3363
|
defs.append("clipPath").attr("id", clipId).append("rect").attr("id", clipRectId).attr("x", 0).attr("y", 0).attr("width", 1e5).attr("height", 1e4);
|
|
3364
|
+
svg.append("g").attr("class", this.classes.overview.group).attr("transform", `translate(0, ${margins.top})`);
|
|
3365
|
+
svg.append("g").attr("class", this.classes.columnHeaders.group);
|
|
2281
3366
|
const poco = svg.append("g").attr("class", this.classes.wellGroup);
|
|
2282
3367
|
const geologic = poco.append("g").attr("class", this.classes.geologicGroup).attr("transform", `translate(${margins.left}, ${margins.top})`);
|
|
2283
3368
|
geologic.append("g").attr("class", this.classes.yAxis);
|
|
@@ -2292,6 +3377,7 @@ var WellRenderer = class {
|
|
|
2292
3377
|
);
|
|
2293
3378
|
const fracturesGroup = poco.append("g").attr("class", this.classes.fractures.group).attr("transform", `translate(${margins.left}, ${margins.top})`).attr("clip-path", `url(#${clipId})`);
|
|
2294
3379
|
fracturesGroup.append("g").attr("class", this.classes.highlights.fracturesGroup);
|
|
3380
|
+
poco.append("g").attr("class", this.classes.markers.group).attr("transform", `translate(${margins.left}, ${margins.top})`);
|
|
2295
3381
|
construction.append("g").attr("class", this.classes.cementPad.group);
|
|
2296
3382
|
construction.append("g").attr("class", this.classes.boreHole.group);
|
|
2297
3383
|
construction.append("g").attr("class", this.classes.surfaceCase.group);
|
|
@@ -2299,11 +3385,23 @@ var WellRenderer = class {
|
|
|
2299
3385
|
construction.append("g").attr("class", this.classes.wellCase.group);
|
|
2300
3386
|
construction.append("g").attr("class", this.classes.wellScreen.group);
|
|
2301
3387
|
construction.append("g").attr("class", this.classes.reduction.group);
|
|
3388
|
+
construction.append("g").attr("class", this.classes.pump.group);
|
|
3389
|
+
construction.append("g").attr("class", this.classes.centralizer.group);
|
|
2302
3390
|
construction.append("g").attr("class", this.classes.conflict.group);
|
|
2303
3391
|
construction.append("g").attr("class", this.classes.constructionLabels.group);
|
|
2304
3392
|
construction.append("g").attr("class", this.classes.highlights.constructionGroup);
|
|
3393
|
+
poco.append("g").attr("class", this.classes.overlap.group).attr("transform", `translate(${margins.left}, ${margins.top})`);
|
|
2305
3394
|
Object.values(this.textures).forEach((texture) => svg.call(texture));
|
|
2306
|
-
return {
|
|
3395
|
+
return {
|
|
3396
|
+
svg,
|
|
3397
|
+
height,
|
|
3398
|
+
width,
|
|
3399
|
+
margins,
|
|
3400
|
+
clipId,
|
|
3401
|
+
clipRectId,
|
|
3402
|
+
depthRange: inst.depthRange,
|
|
3403
|
+
repeatedTo: inst.repeatedTo
|
|
3404
|
+
};
|
|
2307
3405
|
}
|
|
2308
3406
|
/** Renders a standalone legend into the element matched by `selector`. */
|
|
2309
3407
|
renderLegend(selector, profile) {
|
|
@@ -2314,6 +3412,30 @@ var WellRenderer = class {
|
|
|
2314
3412
|
textures: this.renderConfig.textures
|
|
2315
3413
|
});
|
|
2316
3414
|
}
|
|
3415
|
+
/** Lists the legend entries `profile` needs, labeled from `renderConfig.legend.labels`. */
|
|
3416
|
+
getLegendItems(profile) {
|
|
3417
|
+
return getWellLegendItems(profile, this.renderConfig.legend.labels);
|
|
3418
|
+
}
|
|
3419
|
+
/**
|
|
3420
|
+
* Renders one legend entry's symbol (see {@link getLegendItems}) into its
|
|
3421
|
+
* own SVG matched by `selector`, with the textures it needs defined inside.
|
|
3422
|
+
*/
|
|
3423
|
+
renderLegendSymbol(selector, item) {
|
|
3424
|
+
drawWellLegendSymbol(selector, item, {
|
|
3425
|
+
theme: this.theme,
|
|
3426
|
+
classNames: this.classes.legend,
|
|
3427
|
+
textures: this.renderConfig.textures
|
|
3428
|
+
});
|
|
3429
|
+
}
|
|
3430
|
+
/**
|
|
3431
|
+
* Renders one lithology layer's fill as a `size`×`size` square into its
|
|
3432
|
+
* own SVG matched by `selector`, with its texture defined inside (e.g. for
|
|
3433
|
+
* a swatch in a PDF table). Call after `prepareSvg()`, which loads the
|
|
3434
|
+
* FGDC textures.
|
|
3435
|
+
*/
|
|
3436
|
+
renderLithologySwatch(selector, layer, size = 10) {
|
|
3437
|
+
drawLithologySwatch(selector, layer, { size, theme: this.theme });
|
|
3438
|
+
}
|
|
2317
3439
|
/**
|
|
2318
3440
|
* Multiplies the current zoom scale by `factor` (e.g. `1.25` to zoom in,
|
|
2319
3441
|
* `1 / 1.25` to zoom out) on every panel. No-op if both `renderConfig.zoom`
|
|
@@ -2330,7 +3452,7 @@ var WellRenderer = class {
|
|
|
2330
3452
|
* (defaults to `1`, i.e. the initial fit-to-container view).
|
|
2331
3453
|
*/
|
|
2332
3454
|
resetZoom() {
|
|
2333
|
-
const target =
|
|
3455
|
+
const target = d310.zoomIdentity.scale(this.renderConfig.zoomLevel ?? 1);
|
|
2334
3456
|
for (const state of this.instanceStates) {
|
|
2335
3457
|
if (!state.zoomNode) continue;
|
|
2336
3458
|
asSvgElement(state.svg).transition().call(state.zoomNode.transform, target);
|
|
@@ -2342,7 +3464,46 @@ var WellRenderer = class {
|
|
|
2342
3464
|
*/
|
|
2343
3465
|
getZoomScale() {
|
|
2344
3466
|
const node = this.instanceStates[0]?.svg.node();
|
|
2345
|
-
return node ?
|
|
3467
|
+
return node ? d310.zoomTransform(node).k : 1;
|
|
3468
|
+
}
|
|
3469
|
+
/**
|
|
3470
|
+
* Removes everything drawn on every panel (layers, labels, axis,
|
|
3471
|
+
* highlights) and keeps the structure `prepareSvg()` built, so the next
|
|
3472
|
+
* `draw()` needs no new `prepareSvg()`. `draw()` calls it for an empty well.
|
|
3473
|
+
*/
|
|
3474
|
+
clear() {
|
|
3475
|
+
const c = this.classes;
|
|
3476
|
+
const layerGroups = [
|
|
3477
|
+
c.overview.group,
|
|
3478
|
+
c.columnHeaders.group,
|
|
3479
|
+
c.yAxis,
|
|
3480
|
+
c.unitLabels.group,
|
|
3481
|
+
c.lithology.group,
|
|
3482
|
+
c.caves.group,
|
|
3483
|
+
c.labels.lithology.group,
|
|
3484
|
+
c.highlights.geologicGroup,
|
|
3485
|
+
c.highlights.constructionGroup,
|
|
3486
|
+
c.highlights.fracturesGroup,
|
|
3487
|
+
c.markers.group,
|
|
3488
|
+
c.cementPad.group,
|
|
3489
|
+
c.boreHole.group,
|
|
3490
|
+
c.surfaceCase.group,
|
|
3491
|
+
c.holeFill.group,
|
|
3492
|
+
c.wellCase.group,
|
|
3493
|
+
c.wellScreen.group,
|
|
3494
|
+
c.reduction.group,
|
|
3495
|
+
c.pump.group,
|
|
3496
|
+
c.centralizer.group,
|
|
3497
|
+
c.conflict.group,
|
|
3498
|
+
c.constructionLabels.group,
|
|
3499
|
+
c.overlap.group
|
|
3500
|
+
];
|
|
3501
|
+
for (const { svg } of this.instanceStates) {
|
|
3502
|
+
for (const cls of layerGroups) {
|
|
3503
|
+
svg.select(`.${cls}`).selectAll("*").interrupt().remove();
|
|
3504
|
+
}
|
|
3505
|
+
svg.select(`.${c.fractures.group}`).selectAll(`g.${c.fractures.item}`).interrupt().remove();
|
|
3506
|
+
}
|
|
2346
3507
|
}
|
|
2347
3508
|
/**
|
|
2348
3509
|
* Initialises the SVG DOM structure and preloads FGDC textures.
|
|
@@ -2355,14 +3516,19 @@ var WellRenderer = class {
|
|
|
2355
3516
|
);
|
|
2356
3517
|
}
|
|
2357
3518
|
/**
|
|
2358
|
-
* Renders the well profile into all configured SVG panels.
|
|
3519
|
+
* Renders the well profile into all configured SVG panels. Layers the
|
|
3520
|
+
* profile no longer has are removed; an empty well (`isWellEmpty`) clears
|
|
3521
|
+
* the panels (see {@link clear}).
|
|
2359
3522
|
* @param profile - The well data to render.
|
|
2360
3523
|
* @param options.units - Override the instance-level measurement units for this render.
|
|
2361
3524
|
* @param options.locale - Override the instance-level locale for this render.
|
|
2362
3525
|
* @param options.highlights - Highlight overlays to display on top of the profile.
|
|
2363
3526
|
*/
|
|
2364
3527
|
draw(profile, options = {}) {
|
|
2365
|
-
if ((0,
|
|
3528
|
+
if ((0, import_core4.isWellEmpty)(profile)) {
|
|
3529
|
+
this.clear();
|
|
3530
|
+
return;
|
|
3531
|
+
}
|
|
2366
3532
|
if (profile.version !== 2) {
|
|
2367
3533
|
console.warn(
|
|
2368
3534
|
`[WellRenderer] Received a .well file with version ${profile.version ?? "unknown"}. Only v2 is supported. Normalize with deserializeWell() from @welldot/core before rendering.`
|
|
@@ -2373,36 +3539,19 @@ var WellRenderer = class {
|
|
|
2373
3539
|
this.locale = options.locale;
|
|
2374
3540
|
}
|
|
2375
3541
|
const highlights = options.highlights ?? {};
|
|
2376
|
-
const maxValues = (0,
|
|
2377
|
-
const maxYValues =
|
|
2378
|
-
|
|
2379
|
-
this.
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
);
|
|
2386
|
-
|
|
2387
|
-
}
|
|
2388
|
-
const totalHeight = this.instanceStates.reduce((s, st) => s + st.height, 0) || 1;
|
|
2389
|
-
const yScaleGlobal = d37.scaleLinear().domain([0, maxYValues]).range([0, totalHeight]);
|
|
2390
|
-
let currentDepth = 0;
|
|
2391
|
-
for (const state of this.instanceStates) {
|
|
2392
|
-
const maxSvgDepth = yScaleGlobal.invert(
|
|
2393
|
-
yScaleGlobal(currentDepth) + state.height
|
|
2394
|
-
);
|
|
2395
|
-
this.drawLogToInstance(
|
|
2396
|
-
state,
|
|
2397
|
-
profile,
|
|
2398
|
-
currentDepth,
|
|
2399
|
-
maxSvgDepth,
|
|
2400
|
-
highlights
|
|
2401
|
-
);
|
|
2402
|
-
currentDepth = maxSvgDepth;
|
|
2403
|
-
}
|
|
3542
|
+
const maxValues = (0, import_utils10.getProfileLastItemsDepths)(profile);
|
|
3543
|
+
const maxYValues = d310.max(maxValues) || 0;
|
|
3544
|
+
const windows = resolvePanelWindows(
|
|
3545
|
+
this.instanceStates,
|
|
3546
|
+
maxYValues,
|
|
3547
|
+
getProfileTopDepth(profile)
|
|
3548
|
+
);
|
|
3549
|
+
this.instanceStates.forEach((state, i) => {
|
|
3550
|
+
const [from, to] = windows[i];
|
|
3551
|
+
this.drawLogToInstance(state, profile, from, to, maxYValues, highlights);
|
|
3552
|
+
});
|
|
2404
3553
|
}
|
|
2405
|
-
drawLogToInstance(state, profile, depthFrom, depthTo, highlights = {}) {
|
|
3554
|
+
drawLogToInstance(state, profile, depthFrom, depthTo, totalDepth, highlights = {}) {
|
|
2406
3555
|
const svg = state.svg;
|
|
2407
3556
|
const pocoGroup = svg.select(`.${this.classes.wellGroup}`);
|
|
2408
3557
|
const lithologyGroup = svg.select(`.${this.classes.lithology.group}`);
|
|
@@ -2419,6 +3568,8 @@ var WellRenderer = class {
|
|
|
2419
3568
|
const wellCaseGroup = svg.select(`.${this.classes.wellCase.group}`);
|
|
2420
3569
|
const wellScreenGroup = svg.select(`.${this.classes.wellScreen.group}`);
|
|
2421
3570
|
const reductionGroup = svg.select(`.${this.classes.reduction.group}`);
|
|
3571
|
+
const centralizerGroup = svg.select(`.${this.classes.centralizer.group}`);
|
|
3572
|
+
const pumpGroup = svg.select(`.${this.classes.pump.group}`);
|
|
2422
3573
|
const conflictGroup = svg.select(`.${this.classes.conflict.group}`);
|
|
2423
3574
|
const constructionLabelsGroup = svg.select(
|
|
2424
3575
|
`.${this.classes.constructionLabels.group}`
|
|
@@ -2433,13 +3584,19 @@ var WellRenderer = class {
|
|
|
2433
3584
|
`.${this.classes.highlights.fracturesGroup}`
|
|
2434
3585
|
);
|
|
2435
3586
|
const unitLabelsGroup = svg.select(`.${this.classes.unitLabels.group}`);
|
|
3587
|
+
const overviewGroup = svg.select(`.${this.classes.overview.group}`);
|
|
3588
|
+
const columnHeadersGroup = svg.select(
|
|
3589
|
+
`.${this.classes.columnHeaders.group}`
|
|
3590
|
+
);
|
|
3591
|
+
const markersGroup = svg.select(`.${this.classes.markers.group}`);
|
|
3592
|
+
const overlapGroup = svg.select(`.${this.classes.overlap.group}`);
|
|
2436
3593
|
const svgWidth = state.width + state.margins.left + state.margins.right;
|
|
2437
3594
|
const svgHeight = state.height + state.margins.top + state.margins.bottom;
|
|
2438
3595
|
const { pocoWidthRatio, pocoCenterRatio } = this.renderConfig.layout;
|
|
2439
3596
|
const POCO_WIDTH = svgWidth * pocoWidthRatio;
|
|
2440
3597
|
const POCO_CENTER = svgWidth * pocoCenterRatio;
|
|
2441
3598
|
const { duration, ease } = this.renderConfig.animation;
|
|
2442
|
-
const transition =
|
|
3599
|
+
const transition = d310.transition().duration(duration).ease(ease);
|
|
2443
3600
|
const tooltips = populateTooltips(
|
|
2444
3601
|
svg,
|
|
2445
3602
|
this.classes,
|
|
@@ -2464,14 +3621,15 @@ var WellRenderer = class {
|
|
|
2464
3621
|
well_case: profile.well_case,
|
|
2465
3622
|
well_screen: profile.well_screen,
|
|
2466
3623
|
reduction: profile.reduction,
|
|
3624
|
+
centralizers: profile.centralizers ?? [],
|
|
2467
3625
|
fractures: profile.fractures
|
|
2468
3626
|
};
|
|
2469
3627
|
const contentHeight = svgHeight - state.margins.top - state.margins.bottom;
|
|
2470
|
-
const yScaleLocal =
|
|
3628
|
+
const yScaleLocal = d310.scaleLinear().domain([depthFrom, depthTo]).range([0, contentHeight]);
|
|
2471
3629
|
const depthFactor = this.units.length === "ft" ? 3.28084 : 1;
|
|
2472
|
-
const yScaleAxis =
|
|
2473
|
-
const yAxis =
|
|
2474
|
-
(d) => `${(0,
|
|
3630
|
+
const yScaleAxis = d310.scaleLinear().domain([depthFrom * depthFactor, depthTo * depthFactor]).range([0, contentHeight]);
|
|
3631
|
+
const yAxis = d310.axisLeft(yScaleAxis).tickFormat(
|
|
3632
|
+
(d) => `${(0, import_utils10.formatNumber)(Number(d), {
|
|
2475
3633
|
maximumFractionDigits: this.units.length === "ft" ? 1 : 2,
|
|
2476
3634
|
locale: this.locale
|
|
2477
3635
|
})}${getLengthUnit(this.units.length)}`
|
|
@@ -2512,10 +3670,16 @@ var WellRenderer = class {
|
|
|
2512
3670
|
wellCaseGroup,
|
|
2513
3671
|
wellScreenGroup,
|
|
2514
3672
|
reductionGroup,
|
|
3673
|
+
centralizerGroup,
|
|
3674
|
+
pumpGroup,
|
|
2515
3675
|
conflictGroup,
|
|
2516
3676
|
highlightsGeologicGroup,
|
|
2517
3677
|
highlightsConstructionGroup,
|
|
2518
|
-
highlightsFracturesGroup
|
|
3678
|
+
highlightsFracturesGroup,
|
|
3679
|
+
overviewGroup,
|
|
3680
|
+
columnHeadersGroup,
|
|
3681
|
+
markersGroup,
|
|
3682
|
+
overlapGroup
|
|
2519
3683
|
};
|
|
2520
3684
|
const ctx = {
|
|
2521
3685
|
svg,
|
|
@@ -2529,6 +3693,8 @@ var WellRenderer = class {
|
|
|
2529
3693
|
geoXRight,
|
|
2530
3694
|
depthFrom,
|
|
2531
3695
|
depthTo,
|
|
3696
|
+
totalDepth,
|
|
3697
|
+
repeatedTo: state.repeatedTo,
|
|
2532
3698
|
yScale: yScaleLocal,
|
|
2533
3699
|
transition,
|
|
2534
3700
|
tooltips,
|
|
@@ -2542,6 +3708,7 @@ var WellRenderer = class {
|
|
|
2542
3708
|
groups
|
|
2543
3709
|
};
|
|
2544
3710
|
const inDepth = filterByDepth(depthFrom, depthTo);
|
|
3711
|
+
const currentPump = (0, import_utils10.getCurrentPump)(profile);
|
|
2545
3712
|
const filteredConstruction = {
|
|
2546
3713
|
...constructionData,
|
|
2547
3714
|
bore_hole: constructionData.bore_hole.filter(inDepth),
|
|
@@ -2549,7 +3716,8 @@ var WellRenderer = class {
|
|
|
2549
3716
|
surface_case: constructionData.surface_case.filter(inDepth),
|
|
2550
3717
|
well_case: constructionData.well_case.filter(inDepth),
|
|
2551
3718
|
well_screen: constructionData.well_screen.filter(inDepth),
|
|
2552
|
-
reduction: constructionData.reduction?.filter(inDepth) ?? []
|
|
3719
|
+
reduction: constructionData.reduction?.filter(inDepth) ?? [],
|
|
3720
|
+
centralizers: constructionData.centralizers?.filter(inDepth) ?? []
|
|
2553
3721
|
};
|
|
2554
3722
|
const zooming = (e) => {
|
|
2555
3723
|
const transform = e.transform;
|
|
@@ -2565,33 +3733,14 @@ var WellRenderer = class {
|
|
|
2565
3733
|
if (!d) return null;
|
|
2566
3734
|
return transform.k * spanH(d);
|
|
2567
3735
|
});
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
const sc = d;
|
|
2571
|
-
const g = d37.select(nodes[i]);
|
|
2572
|
-
const y = transform.applyY(spanY(sc));
|
|
2573
|
-
const h = transform.k * spanH(sc);
|
|
2574
|
-
g.select(".surface-case-fill").attr("y", y).attr("height", h);
|
|
2575
|
-
g.selectAll(".surface-case-side").attr("y1", y).attr("y2", y + h);
|
|
2576
|
-
});
|
|
2577
|
-
const maxXValsReduction = (0, import_utils6.getProfileDiamValues)(constructionData);
|
|
2578
|
-
const xScaleReduction = d37.scaleLinear().domain([0, d37.max(maxXValsReduction) || 0]).range([0, POCO_WIDTH]);
|
|
2579
|
-
reductionGroup.selectAll(`polygon.${this.classes.reduction.item}`).attr("points", (d) => {
|
|
2580
|
-
const r = d;
|
|
2581
|
-
const yTop = transform.applyY(spanY(r));
|
|
2582
|
-
const yBot = yTop + transform.k * spanH(r);
|
|
2583
|
-
const xTopLeft = (POCO_CENTER - xScaleReduction(r.diam_from)) / 2;
|
|
2584
|
-
const xTopRight = (POCO_CENTER + xScaleReduction(r.diam_from)) / 2;
|
|
2585
|
-
const xBotLeft = (POCO_CENTER - xScaleReduction(r.diam_to)) / 2;
|
|
2586
|
-
const xBotRight = (POCO_CENTER + xScaleReduction(r.diam_to)) / 2;
|
|
2587
|
-
return `${xTopLeft},${yTop} ${xTopRight},${yTop} ${xBotRight},${yBot} ${xBotLeft},${yBot}`;
|
|
2588
|
-
});
|
|
3736
|
+
layoutConstruction(zoomedCtx);
|
|
3737
|
+
drawCementPad(zoomedCtx, constructionData.cement_pad);
|
|
2589
3738
|
fracturesGroup.selectAll(`g.${this.classes.fractures.item}`).attr("transform", (d) => {
|
|
2590
3739
|
if (!d) return null;
|
|
2591
3740
|
const f = d;
|
|
2592
3741
|
const cx = pocoCenterX;
|
|
2593
3742
|
const cy = transform.applyY(yScaleLocal(f.depth));
|
|
2594
|
-
return `translate(0,${cy}) rotate(${f.dip},${cx},0)`;
|
|
3743
|
+
return `translate(0,${cy}) rotate(${fractureDip(f.dip)},${cx},0)`;
|
|
2595
3744
|
});
|
|
2596
3745
|
drawCaves(zoomedCtx, geologicData.caves?.filter(inDepth) ?? []);
|
|
2597
3746
|
drawUnitLabels(zoomedCtx, profile.lithology?.filter(inDepth) ?? []);
|
|
@@ -2602,10 +3751,17 @@ var WellRenderer = class {
|
|
|
2602
3751
|
) ?? [],
|
|
2603
3752
|
caves: profile.caves?.filter(inDepth) ?? []
|
|
2604
3753
|
});
|
|
3754
|
+
drawPump(zoomedCtx, currentPump);
|
|
3755
|
+
drawCentralizers(zoomedCtx, filteredConstruction);
|
|
2605
3756
|
drawConstructionLabels(zoomedCtx, {
|
|
2606
3757
|
well_case: constructionData.well_case.filter(inDepth),
|
|
2607
3758
|
well_screen: constructionData.well_screen.filter(inDepth)
|
|
2608
3759
|
});
|
|
3760
|
+
drawMarkers(zoomedCtx, {
|
|
3761
|
+
lithology: profile.lithology ?? [],
|
|
3762
|
+
fractures: profile.fractures ?? []
|
|
3763
|
+
});
|
|
3764
|
+
drawOverlap(zoomedCtx);
|
|
2609
3765
|
drawHighlights(zoomedCtx, highlights);
|
|
2610
3766
|
this.onZoom?.(transform.k);
|
|
2611
3767
|
};
|
|
@@ -2628,10 +3784,19 @@ var WellRenderer = class {
|
|
|
2628
3784
|
) ?? []
|
|
2629
3785
|
);
|
|
2630
3786
|
drawConstructive(ctx, filteredConstruction);
|
|
3787
|
+
drawPump(ctx, currentPump);
|
|
3788
|
+
drawCentralizers(ctx, filteredConstruction);
|
|
2631
3789
|
drawConstructionLabels(ctx, {
|
|
2632
3790
|
well_case: filteredConstruction.well_case,
|
|
2633
3791
|
well_screen: filteredConstruction.well_screen
|
|
2634
3792
|
});
|
|
3793
|
+
drawMarkers(ctx, {
|
|
3794
|
+
lithology: profile.lithology ?? [],
|
|
3795
|
+
fractures: profile.fractures ?? []
|
|
3796
|
+
});
|
|
3797
|
+
drawOverview(ctx, profile.lithology ?? []);
|
|
3798
|
+
drawColumnHeaders(ctx);
|
|
3799
|
+
drawOverlap(ctx);
|
|
2635
3800
|
svg.select(`#${state.clipRectId}`).attr("y", 0).attr("height", svgHeight);
|
|
2636
3801
|
drawHighlights(ctx, highlights);
|
|
2637
3802
|
};
|
|
@@ -2647,7 +3812,7 @@ var WellRenderer = class {
|
|
|
2647
3812
|
}
|
|
2648
3813
|
const { zoom: zoomEnabled, pan: panEnabled } = this.renderConfig;
|
|
2649
3814
|
if (zoomEnabled || panEnabled) {
|
|
2650
|
-
const zoomNode =
|
|
3815
|
+
const zoomNode = d310.zoom();
|
|
2651
3816
|
if (zoomEnabled || panEnabled) zoomNode.on("zoom", zooming);
|
|
2652
3817
|
zoomNode.scaleExtent(
|
|
2653
3818
|
zoomEnabled ? [
|
|
@@ -2663,7 +3828,7 @@ var WellRenderer = class {
|
|
|
2663
3828
|
if (initialZoom !== 1) {
|
|
2664
3829
|
asSvgElement(svg).call(
|
|
2665
3830
|
zoomNode.transform,
|
|
2666
|
-
|
|
3831
|
+
d310.zoomIdentity.scale(initialZoom)
|
|
2667
3832
|
);
|
|
2668
3833
|
}
|
|
2669
3834
|
}
|
|
@@ -2678,10 +3843,13 @@ var WellRenderer = class {
|
|
|
2678
3843
|
WellRenderer,
|
|
2679
3844
|
applyRenderLocale,
|
|
2680
3845
|
drawWellLegend,
|
|
3846
|
+
drawWellLegendSymbol,
|
|
2681
3847
|
formatDiameter,
|
|
2682
3848
|
formatLength,
|
|
2683
3849
|
getDiameterUnit,
|
|
2684
3850
|
getLengthUnit,
|
|
3851
|
+
getProfileTopDepth,
|
|
3852
|
+
getWellLegendItems,
|
|
2685
3853
|
importFgdcTextures,
|
|
2686
3854
|
resolveRenderLabel
|
|
2687
3855
|
});
|