@webviz/subsurface-viewer 0.0.1-alpha.1 → 0.0.2-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/dist/package.json +5 -2
  2. package/package.json +6 -3
  3. package/src/DashSubsurfaceViewer.tsx +0 -270
  4. package/src/SubsurfaceViewer.stories.tsx +0 -449
  5. package/src/SubsurfaceViewer.test.tsx +0 -98
  6. package/src/SubsurfaceViewer.tsx +0 -356
  7. package/src/__snapshots__/SubsurfaceViewer.test.tsx.snap +0 -178
  8. package/src/assets/glTF/north_arrow/scene.bin +0 -0
  9. package/src/assets/glTF/north_arrow/scene.gltf +0 -315
  10. package/src/assets/glTF/north_arrow/textures/Arrow5_baseColor.png +0 -0
  11. package/src/assets/glTF/north_arrow/textures/Arrow5_metallicRoughness.png +0 -0
  12. package/src/assets/glTF/north_arrow/textures/Arrow5_normal.png +0 -0
  13. package/src/components/ColorLegend.test.tsx +0 -32
  14. package/src/components/ColorLegend.tsx +0 -80
  15. package/src/components/ColorLegends.test.tsx +0 -97
  16. package/src/components/ColorLegends.tsx +0 -46
  17. package/src/components/DistanceScale.stories.tsx +0 -28
  18. package/src/components/DistanceScale.test.tsx +0 -36
  19. package/src/components/DistanceScale.tsx +0 -84
  20. package/src/components/InfoCard.test.tsx +0 -110
  21. package/src/components/InfoCard.tsx +0 -263
  22. package/src/components/Map.test.tsx +0 -142
  23. package/src/components/Map.tsx +0 -1435
  24. package/src/components/StatusIndicator.test.tsx +0 -14
  25. package/src/components/StatusIndicator.tsx +0 -38
  26. package/src/components/ViewAnnotation.tsx +0 -16
  27. package/src/components/ViewFooter.test.tsx +0 -12
  28. package/src/components/ViewFooter.tsx +0 -30
  29. package/src/components/__snapshots__/ColorLegends.test.tsx.snap +0 -15
  30. package/src/components/__snapshots__/DistanceScale.test.tsx.snap +0 -33
  31. package/src/components/__snapshots__/InfoCard.test.tsx.snap +0 -561
  32. package/src/components/__snapshots__/Map.test.tsx.snap +0 -119
  33. package/src/components/__snapshots__/StatusIndicator.test.tsx.snap +0 -3
  34. package/src/components/__snapshots__/ViewFooter.test.tsx.snap +0 -7
  35. package/src/components/settings/DrawModeSelector.test.tsx +0 -45
  36. package/src/components/settings/DrawModeSelector.tsx +0 -58
  37. package/src/components/settings/DrawModeSelector_performance.test.tsx +0 -35
  38. package/src/components/settings/LayerProperty.test.tsx +0 -35
  39. package/src/components/settings/LayerProperty.tsx +0 -153
  40. package/src/components/settings/LayerProperty_performance.test.tsx +0 -39
  41. package/src/components/settings/LayerSettingsButton.test.tsx +0 -133
  42. package/src/components/settings/LayerSettingsButton.tsx +0 -95
  43. package/src/components/settings/LayersButton.test.tsx +0 -102
  44. package/src/components/settings/LayersButton.tsx +0 -97
  45. package/src/components/settings/NumericInput.test.tsx +0 -25
  46. package/src/components/settings/NumericInput.tsx +0 -67
  47. package/src/components/settings/Settings.tsx +0 -71
  48. package/src/components/settings/SliderInput.test.tsx +0 -28
  49. package/src/components/settings/SliderInput.tsx +0 -71
  50. package/src/components/settings/ToggleButton.test.tsx +0 -25
  51. package/src/components/settings/ToggleButton.tsx +0 -53
  52. package/src/components/settings/__snapshots__/DrawModeSelector.test.tsx.snap +0 -124
  53. package/src/components/settings/__snapshots__/LayerProperty.test.tsx.snap +0 -124
  54. package/src/components/settings/__snapshots__/LayerSettingsButton.test.tsx.snap +0 -36
  55. package/src/components/settings/__snapshots__/LayersButton.test.tsx.snap +0 -83
  56. package/src/components/settings/__snapshots__/NumericInput.test.tsx.snap +0 -123
  57. package/src/components/settings/__snapshots__/SliderInput.test.tsx.snap +0 -244
  58. package/src/components/settings/__snapshots__/ToggleButton.test.tsx.snap +0 -182
  59. package/src/custom.d.ts +0 -9
  60. package/src/index.ts +0 -5
  61. package/src/inputSchema/ColorTables.json +0 -51
  62. package/src/inputSchema/FaultPolygons.json +0 -80
  63. package/src/inputSchema/Grid.json +0 -39
  64. package/src/inputSchema/PieChart.json +0 -72
  65. package/src/inputSchema/WellLog.json +0 -126
  66. package/src/inputSchema/WellLogTemplate.json +0 -136
  67. package/src/inputSchema/WellLogs.json +0 -5
  68. package/src/inputSchema/Wells.json +0 -106
  69. package/src/inputSchema/schemaValidationUtil.tsx +0 -55
  70. package/src/inputSchema/validator.tsx +0 -72
  71. package/src/inputSchema/wellCompletions.json +0 -108
  72. package/src/layers/BoxSelectionLayer/boxSelectionLayer.stories.tsx +0 -172
  73. package/src/layers/BoxSelectionLayer/boxSelectionLayer.tsx +0 -136
  74. package/src/layers/axes/axes-fragment.glsl.ts +0 -15
  75. package/src/layers/axes/axesLayer.stories.tsx +0 -87
  76. package/src/layers/axes/axesLayer.ts +0 -692
  77. package/src/layers/axes/boxLayer.ts +0 -71
  78. package/src/layers/axes/grid-vertex.glsl.ts +0 -14
  79. package/src/layers/axes2d/axes2DLayer.stories.tsx +0 -150
  80. package/src/layers/axes2d/axes2DLayer.ts +0 -841
  81. package/src/layers/axes2d/font-atlas.png +0 -0
  82. package/src/layers/axes2d/label-fragment.glsl.js +0 -37
  83. package/src/layers/axes2d/label-vertex.glsl.js +0 -20
  84. package/src/layers/axes2d/line-fragment.glsl.js +0 -14
  85. package/src/layers/axes2d/line-vertex.glsl.js +0 -13
  86. package/src/layers/colormap/colormap.fs.glsl.ts +0 -42
  87. package/src/layers/colormap/colormapLayer.ts +0 -247
  88. package/src/layers/drawing/drawingLayer.tsx +0 -256
  89. package/src/layers/fault_polygons/faultPolygonsLayer.ts +0 -54
  90. package/src/layers/grid3d/fragment.fs.glsl.ts +0 -109
  91. package/src/layers/grid3d/fragment_lines.glsl.ts +0 -21
  92. package/src/layers/grid3d/grid3dLayer.stories.tsx +0 -172
  93. package/src/layers/grid3d/grid3dLayer.ts +0 -248
  94. package/src/layers/grid3d/privateLayer.ts +0 -292
  95. package/src/layers/grid3d/vertex.glsl.ts +0 -43
  96. package/src/layers/grid3d/vertex_lines.glsl.ts +0 -15
  97. package/src/layers/grid3d/webworker.ts +0 -173
  98. package/src/layers/hillshading2d/hillshading2d.fs.glsl.ts +0 -62
  99. package/src/layers/hillshading2d/hillshading2dLayer.ts +0 -172
  100. package/src/layers/index.ts +0 -35
  101. package/src/layers/intersection/intersectionView.stories.tsx +0 -294
  102. package/src/layers/intersection/unfoldedGeoJsonLayer.ts +0 -92
  103. package/src/layers/map/fragment.fs.glsl.ts +0 -127
  104. package/src/layers/map/fragment_lines.glsl.ts +0 -21
  105. package/src/layers/map/mapLayer.stories.tsx +0 -1369
  106. package/src/layers/map/mapLayer.ts +0 -470
  107. package/src/layers/map/privateMapLayer.ts +0 -317
  108. package/src/layers/map/vertex.glsl.ts +0 -45
  109. package/src/layers/map/vertex_lines.glsl.ts +0 -15
  110. package/src/layers/map/webworker.ts +0 -479
  111. package/src/layers/northarrow/northArrow.stories.tsx +0 -108
  112. package/src/layers/northarrow/northArrow3DLayer.ts +0 -204
  113. package/src/layers/northarrow/northarrow-fragment.glsl.js +0 -14
  114. package/src/layers/northarrow/northarrow-vertex.glsl.js +0 -13
  115. package/src/layers/piechart/fragment.glsl.js +0 -42
  116. package/src/layers/piechart/pieChartLayer.ts +0 -246
  117. package/src/layers/piechart/vertex.glsl.js +0 -42
  118. package/src/layers/points/pointsLayer.stories.tsx +0 -141
  119. package/src/layers/points/pointsLayer.ts +0 -143
  120. package/src/layers/polylines/polylinesLayer.stories.tsx +0 -144
  121. package/src/layers/polylines/polylinesLayer.ts +0 -263
  122. package/src/layers/selectable_geojson/selectableGeoJsonLayer.ts +0 -25
  123. package/src/layers/shader_modules/decoder.fs.glsl.ts +0 -41
  124. package/src/layers/shader_modules/decoder.ts +0 -46
  125. package/src/layers/shader_modules/index.ts +0 -1
  126. package/src/layers/terrain/map3DLayer.stories.tsx +0 -340
  127. package/src/layers/terrain/map3DLayer.ts +0 -556
  128. package/src/layers/terrain/terrainMapLayer.ts +0 -334
  129. package/src/layers/terrain/terrainmap.fs.glsl.ts +0 -134
  130. package/src/layers/triangle/fragment.fs.glsl.ts +0 -126
  131. package/src/layers/triangle/fragment_lines.glsl.ts +0 -21
  132. package/src/layers/triangle/privateTriangleLayer.ts +0 -203
  133. package/src/layers/triangle/test_data/surfacePoints.ts +0 -4344
  134. package/src/layers/triangle/test_data/surfaceTriangles.ts +0 -7392
  135. package/src/layers/triangle/triangleLayer.stories.tsx +0 -191
  136. package/src/layers/triangle/triangleLayer.ts +0 -273
  137. package/src/layers/triangle/vertex.glsl.ts +0 -35
  138. package/src/layers/triangle/vertex_lines.glsl.ts +0 -15
  139. package/src/layers/triangle/webworker.ts +0 -165
  140. package/src/layers/utils/glsl.d.ts +0 -4
  141. package/src/layers/utils/layerTools.ts +0 -182
  142. package/src/layers/utils/propertyMapTools.ts +0 -43
  143. package/src/layers/wells/utils/spline.ts +0 -318
  144. package/src/layers/wells/wellsLayer.stories.tsx +0 -625
  145. package/src/layers/wells/wellsLayer.ts +0 -1377
  146. package/src/redux/actions.ts +0 -8
  147. package/src/redux/reducer.ts +0 -43
  148. package/src/redux/store.ts +0 -15
  149. package/src/redux/types.ts +0 -114
  150. package/src/storybook/SubsurfaceViewer.stories.jsx +0 -644
  151. package/src/storybook/components/InfoCard.stories.jsx +0 -39
  152. package/src/storybook/components/colorLegends/ContinuousLegend.stories.jsx +0 -32
  153. package/src/storybook/components/colorLegends/DiscreteLegend.stories.jsx +0 -33
  154. package/src/storybook/components/colorLegends/IndividualScaleForMap.stories.jsx +0 -99
  155. package/src/storybook/components/colorLegends/SingleScaleForMap.stories.jsx +0 -120
  156. package/src/storybook/components/settings/LayerSettingsButton.stories.jsx +0 -34
  157. package/src/storybook/components/settings/NumericInput.stories.jsx +0 -17
  158. package/src/storybook/components/settings/ToggleButton.stories.jsx +0 -16
  159. package/src/storybook/schemaValidation/sampleData.js +0 -177
  160. package/src/storybook/schemaValidation/schemaValidation.stories.jsx +0 -91
  161. package/src/test/TestWrapper.tsx +0 -13
  162. package/src/utils/configuration.ts +0 -61
  163. package/src/utils/fit-bounds.js +0 -85
  164. package/src/utils/measurement.ts +0 -61
  165. package/src/utils/northArrow.ts +0 -4
  166. package/src/utils/specExtractor.ts +0 -36
  167. package/src/viewports/index.js +0 -1
  168. package/src/viewports/intersectionViewport.ts +0 -137
  169. package/src/views/index.js +0 -1
  170. package/src/views/intersectionView.ts +0 -38
  171. package/tsconfig.json +0 -7
@@ -1,1435 +0,0 @@
1
- import { JSONConfiguration, JSONConverter } from "@deck.gl/json/typed";
2
- import DeckGL, { DeckGLRef } from "@deck.gl/react/typed";
3
- import {
4
- Color,
5
- Deck,
6
- Layer,
7
- LayersList,
8
- LayerProps,
9
- LayerContext,
10
- View,
11
- Viewport,
12
- PickingInfo,
13
- OrthographicView,
14
- OrbitView,
15
- } from "@deck.gl/core/typed";
16
- import { Feature, FeatureCollection } from "geojson";
17
- import React, { useEffect, useState, useCallback, useRef } from "react";
18
- import JSON_CONVERTER_CONFIG from "../utils/configuration";
19
- import { WellsPickInfo } from "../layers/wells/wellsLayer";
20
- import InfoCard from "./InfoCard";
21
- import DistanceScale from "./DistanceScale";
22
- import StatusIndicator from "./StatusIndicator";
23
- import { colorTablesArray } from "@emerson-eps/color-tables/";
24
- import fitBounds from "../utils/fit-bounds";
25
- import {
26
- validateColorTables,
27
- validateLayers,
28
- } from "../inputSchema/schemaValidationUtil";
29
- import { LayerPickInfo } from "../layers/utils/layerTools";
30
- import { getLayersByType } from "../layers/utils/layerTools";
31
- import { getWellLayerByTypeAndSelectedWells } from "../layers/utils/layerTools";
32
- import { WellsLayer, Axes2DLayer, NorthArrow3DLayer } from "../layers";
33
-
34
- import { isEmpty, isEqual } from "lodash";
35
- import { cloneDeep } from "lodash";
36
-
37
- import { colorTables } from "@emerson-eps/color-tables";
38
- import { getModelMatrixScale } from "../layers/utils/layerTools";
39
- import { OrbitController, OrthographicController } from "@deck.gl/core/typed";
40
- import { MjolnirEvent, MjolnirPointerEvent } from "mjolnir.js";
41
- import IntersectionView from "../views/intersectionView";
42
- import { Unit } from "convert-units";
43
-
44
- type BoundingBox = [number, number, number, number, number, number];
45
- type NumberQuad = [number, number, number, number];
46
-
47
- function addBoundingBoxes(b1: BoundingBox, b2: BoundingBox): BoundingBox {
48
- const boxDefault: BoundingBox = [0, 0, 0, 1, 1, 1];
49
-
50
- if (typeof b1 === "undefined" || typeof b2 === "undefined") {
51
- return boxDefault;
52
- }
53
-
54
- if (isEqual(b1, boxDefault)) {
55
- return b2;
56
- }
57
-
58
- const xmin = Math.min(b1[0], b2[0]);
59
- const ymin = Math.min(b1[1], b2[1]);
60
- const zmin = Math.min(b1[2], b2[2]);
61
-
62
- const xmax = Math.max(b1[3], b2[3]);
63
- const ymax = Math.max(b1[4], b2[4]);
64
- const zmax = Math.max(b1[5], b2[5]);
65
- return [xmin, ymin, zmin, xmax, ymax, zmax];
66
- }
67
-
68
- function boundingBoxCenter(box: BoundingBox): [number, number, number] {
69
- const xmin = box[0];
70
- const ymin = box[1];
71
- const zmin = box[2];
72
-
73
- const xmax = box[3];
74
- const ymax = box[4];
75
- const zmax = box[5];
76
- return [
77
- xmin + 0.5 * (xmax - xmin),
78
- ymin + 0.5 * (ymax - ymin),
79
- zmin + 0.5 * (zmax - zmin),
80
- ];
81
- }
82
-
83
- export type BoundsAccessor = () => [number, number, number, number];
84
-
85
- export type TooltipCallback = (
86
- info: PickingInfo
87
- ) => string | Record<string, unknown> | null;
88
-
89
- export interface ViewportType {
90
- /**
91
- * Viewport id
92
- */
93
- id: string;
94
-
95
- /**
96
- * Viewport name
97
- */
98
- name?: string;
99
-
100
- /**
101
- * If true, displays map in 3D view, default is 2D view (false)
102
- */
103
- show3D?: boolean;
104
-
105
- /**
106
- * Layers to be displayed on viewport
107
- */
108
- layerIds?: string[];
109
-
110
- target?: [number, number];
111
- zoom?: number;
112
- rotationX?: number;
113
- rotationOrbit?: number;
114
- isSync?: boolean;
115
- }
116
-
117
- export interface ViewsType {
118
- /**
119
- * Layout for viewport in specified as [row, column]
120
- */
121
- layout: [number, number];
122
-
123
- /**
124
- * Number of pixels used for the margin in matrix mode.
125
- * Defaults to 0.
126
- */
127
- marginPixels?: number;
128
-
129
- /**
130
- * Show views label
131
- */
132
- showLabel?: boolean;
133
-
134
- /**
135
- * Layers configuration for multiple viewport
136
- */
137
- viewports: ViewportType[];
138
- }
139
-
140
- export interface ViewStateType {
141
- target: number[];
142
- zoom: number;
143
- rotationX: number;
144
- rotationOrbit: number;
145
- }
146
-
147
- interface marginsType {
148
- left: number;
149
- right: number;
150
- top: number;
151
- bottom: number;
152
- }
153
-
154
- export interface DeckGLLayerContext extends LayerContext {
155
- userData: {
156
- setEditedData: (data: Record<string, unknown>) => void;
157
- colorTables: colorTablesArray;
158
- };
159
- }
160
-
161
- export type EventCallback = (event: MapMouseEvent) => void;
162
-
163
- export interface MapProps {
164
- /**
165
- * The ID of this component, used to identify dash components
166
- * in callbacks. The ID needs to be unique across all of the
167
- * components in an app.
168
- */
169
- id: string;
170
-
171
- /**
172
- * Resource dictionary made available in the DeckGL specification as an enum.
173
- * The values can be accessed like this: `"@@#resources.resourceId"`, where
174
- * `resourceId` is the key in the `resources` dict. For more information,
175
- * see the DeckGL documentation on enums in the json spec:
176
- * https://deck.gl/docs/api-reference/json/conversion-reference#enumerations-and-using-the--prefix
177
- */
178
- resources?: Record<string, unknown>;
179
-
180
- /* List of JSON object containing layer specific data.
181
- * Each JSON object will consist of layer type with key as "@@type" and
182
- * layer specific data, if any.
183
- */
184
- layers?: LayersList;
185
-
186
- /**
187
- * Coordinate boundary for the view defined as [left, bottom, right, top].
188
- */
189
- bounds?: [number, number, number, number] | BoundsAccessor;
190
-
191
- /**
192
- * Views configuration for map. If not specified, all the layers will be
193
- * displayed in a single 2D viewport
194
- */
195
- views?: ViewsType;
196
-
197
- /**
198
- * Parameters for the InfoCard component
199
- */
200
- coords?: {
201
- visible?: boolean | null;
202
- multiPicking?: boolean | null;
203
- pickDepth?: number | null;
204
- };
205
-
206
- /**
207
- * Parameters for the Distance Scale component
208
- */
209
- scale?: {
210
- visible?: boolean | null;
211
- incrementValue?: number | null;
212
- widthPerUnit?: number | null;
213
- cssStyle?: Record<string, unknown> | null;
214
- };
215
-
216
- coordinateUnit?: Unit;
217
-
218
- /**
219
- * Parameters to control toolbar
220
- */
221
- toolbar?: {
222
- visible?: boolean | null;
223
- };
224
-
225
- /**
226
- * Prop containing color table data
227
- */
228
- colorTables?: colorTablesArray;
229
-
230
- /**
231
- * Prop containing edited data from layers
232
- */
233
- editedData?: Record<string, unknown>;
234
-
235
- /**
236
- * For reacting to prop changes
237
- */
238
- setEditedData?: (data: Record<string, unknown>) => void;
239
-
240
- /**
241
- * Validate JSON datafile against schema
242
- */
243
- checkDatafileSchema?: boolean;
244
-
245
- /**
246
- * For get mouse events
247
- */
248
- onMouseEvent?: EventCallback;
249
-
250
- getCameraPosition?: (input: ViewStateType) => void;
251
-
252
- /**
253
- * If changed will reset camera to default position.
254
- */
255
- triggerHome?: number;
256
- triggerResetMultipleWells?: number;
257
- selection?: {
258
- well: string | undefined;
259
- selection: [number | undefined, number | undefined] | undefined;
260
- };
261
-
262
- children?: React.ReactNode;
263
-
264
- getTooltip?: TooltipCallback;
265
- cameraPosition?: ViewStateType;
266
- }
267
-
268
- export interface MapMouseEvent {
269
- type: "click" | "hover" | "contextmenu";
270
- infos: PickingInfo[];
271
- // some frequently used values extracted from infos[]:
272
- x?: number;
273
- y?: number;
274
- // Only for one well. Full information is available in infos[]
275
- wellname?: string;
276
- wellcolor?: Color; // well color
277
- md?: number;
278
- tvd?: number;
279
- }
280
-
281
- export function useHoverInfo(): [PickingInfo[], EventCallback] {
282
- const [hoverInfo, setHoverInfo] = React.useState<PickingInfo[]>([]);
283
- const callback = React.useCallback((pickEvent: MapMouseEvent) => {
284
- setHoverInfo(pickEvent.infos);
285
- }, []);
286
- return [hoverInfo, callback];
287
- }
288
-
289
- function defaultTooltip(info: PickingInfo) {
290
- if ((info as WellsPickInfo)?.logName) {
291
- return (info as WellsPickInfo)?.logName;
292
- } else if (info.layer?.id === "drawing-layer") {
293
- return (info as LayerPickInfo).propertyValue?.toFixed(2);
294
- }
295
- const feat = info.object as Feature;
296
- return feat?.properties?.["name"];
297
- }
298
-
299
- function adjustCameraTarget(
300
- viewStates: Record<string, ViewStateType>,
301
- scale: number,
302
- newScale: number
303
- ): Record<string, ViewStateType> {
304
- const vs = cloneDeep(viewStates);
305
- for (const key in vs) {
306
- if (typeof vs[key].target !== "undefined") {
307
- const t = vs[key].target;
308
- const z = newScale * (t[2] / scale);
309
- vs[key].target = [t[0], t[1], z];
310
- }
311
- }
312
- return vs;
313
- }
314
-
315
- const Map: React.FC<MapProps> = ({
316
- id,
317
- layers,
318
- bounds,
319
- views,
320
- coords,
321
- scale,
322
- coordinateUnit,
323
- colorTables,
324
- setEditedData,
325
- checkDatafileSchema,
326
- onMouseEvent,
327
- selection,
328
- children,
329
- getTooltip = defaultTooltip,
330
- cameraPosition,
331
- getCameraPosition,
332
- triggerHome,
333
- triggerResetMultipleWells,
334
- }: MapProps) => {
335
- const isCameraPositionDefined =
336
- typeof cameraPosition !== "undefined" &&
337
- Object.keys(cameraPosition).length !== 0;
338
-
339
- const deckRef = useRef<DeckGLRef>(null);
340
-
341
- const bboxInitial: BoundingBox = [0, 0, 0, 1, 1, 1];
342
-
343
- const boundsInitial = React.useMemo(
344
- () => bounds ?? ([0, 0, 1, 1] as NumberQuad),
345
- [bounds]
346
- );
347
-
348
- // state for views prop of DeckGL component
349
- const [viewsProps, setViewsProps] = useState<ViewportType[]>([]);
350
- const [alteredLayers, setAlteredLayers] = useState<LayersList>([]);
351
-
352
- const [viewPortMargins, setViewPortMargins] = useState<marginsType>({
353
- left: 0,
354
- right: 0,
355
- top: 0,
356
- bottom: 0,
357
- });
358
-
359
- const [didUserChangeCamera, setDidUserChangeCamera] =
360
- useState<boolean>(false);
361
-
362
- const [reportedBoundingBox, setReportedBoundingBox] =
363
- useState<BoundingBox>(bboxInitial);
364
- const [reportedBoundingBoxAcc, setReportedBoundingBoxAcc] =
365
- useState<BoundingBox>(bboxInitial);
366
-
367
- const initialViewState = getViewState(
368
- viewPortMargins,
369
- boundsInitial,
370
- boundingBoxCenter(reportedBoundingBoxAcc),
371
- views,
372
- 0,
373
- deckRef.current?.deck
374
- );
375
-
376
- // Local help function.
377
- const calcDefaultViewStates = useCallback(
378
- (boundingBox: BoundingBox, input?: ViewportType[]) => {
379
- const center = boundingBoxCenter(
380
- boundingBox // note this may include axesLayer
381
- );
382
-
383
- const updatedViewProps = input ? input : viewsProps;
384
-
385
- const isBoundsDefined = typeof bounds !== "undefined";
386
- const viewStateMap = updatedViewProps.map((item, index) => {
387
- const is3D = views?.viewports?.[index]?.show3D ?? false;
388
-
389
- const viewState = isBoundsDefined
390
- ? getViewState(
391
- viewPortMargins,
392
- boundsInitial,
393
- center,
394
- views,
395
- index,
396
- deckRef.current?.deck
397
- )
398
- : getViewState3D(
399
- is3D,
400
- boundingBox,
401
- views?.viewports?.[index].zoom,
402
- deckRef.current?.deck
403
- );
404
-
405
- const minZoom = is3D ? -12 : -12;
406
- const maxZoom = is3D ? +12 : +4;
407
-
408
- return [item.id, { ...viewState, minZoom, maxZoom }];
409
- });
410
-
411
- const tempViewStates = Object.fromEntries(viewStateMap);
412
-
413
- setDidUserChangeCamera(false);
414
- setViewStates(tempViewStates);
415
- },
416
- [bounds, boundsInitial, views, viewPortMargins, viewsProps]
417
- );
418
-
419
- // set initial view state based on supplied bounds and zoom in viewState
420
- const [viewStates, setViewStates] = useState<Record<string, ViewStateType>>(
421
- {
422
- "main-view_2D": cameraPosition ?? ({} as ViewStateType),
423
- }
424
- );
425
- const [firstViewStateId, setFirstViewStatesId] =
426
- useState<string>("main-view_2D");
427
-
428
- useEffect(() => {
429
- let tempViewStates: Record<string, ViewStateType> = {};
430
- if (isCameraPositionDefined) {
431
- tempViewStates = Object.fromEntries(
432
- viewsProps.map((item) => [item.id, cameraPosition])
433
- ) as unknown as Record<string, ViewStateType>;
434
- } else {
435
- const isBoundsDefined = typeof bounds !== "undefined";
436
-
437
- tempViewStates = Object.fromEntries(
438
- viewsProps.map((item, index) => {
439
- let viewState = viewStates[item.id];
440
- if (typeof viewState === "undefined") {
441
- viewState = isBoundsDefined
442
- ? getViewState(
443
- viewPortMargins,
444
- boundsInitial,
445
- boundingBoxCenter(reportedBoundingBoxAcc),
446
- views,
447
- index,
448
- deckRef.current?.deck
449
- )
450
- : getViewState3D(
451
- views?.viewports?.[index]?.show3D ?? false,
452
- reportedBoundingBoxAcc,
453
- views?.viewports?.[index].zoom,
454
- deckRef.current?.deck
455
- );
456
- }
457
-
458
- return [item.id, viewState];
459
- })
460
- );
461
- }
462
- if (viewsProps[0] !== undefined) {
463
- setFirstViewStatesId(viewsProps[0].id);
464
- }
465
- setViewStates(tempViewStates);
466
- // eslint-disable-next-line react-hooks/exhaustive-deps
467
- }, [
468
- boundsInitial,
469
- cameraPosition,
470
- isCameraPositionDefined,
471
- viewPortMargins,
472
- views?.viewports,
473
- viewsProps,
474
- ]);
475
-
476
- // calculate view state on deckgl context load (based on viewport size)
477
- const onLoad = useCallback(() => {
478
- let tempViewStates: Record<string, ViewStateType> = {};
479
- if (isCameraPositionDefined) {
480
- tempViewStates = Object.fromEntries(
481
- viewsProps.map((item) => [item.id, cameraPosition])
482
- ) as unknown as Record<string, ViewStateType>;
483
- } else {
484
- tempViewStates = Object.fromEntries(
485
- viewsProps.map((item, index) => [
486
- item.id,
487
- getViewState(
488
- viewPortMargins,
489
- boundsInitial,
490
- boundingBoxCenter(reportedBoundingBoxAcc),
491
- views,
492
- index,
493
- deckRef.current?.deck
494
- ),
495
- ])
496
- );
497
- if (viewsProps[0] !== undefined) {
498
- setFirstViewStatesId(viewsProps[0].id);
499
- }
500
- setViewStates(tempViewStates);
501
- }
502
- }, [
503
- isCameraPositionDefined,
504
- viewsProps,
505
- cameraPosition,
506
- viewPortMargins,
507
- boundsInitial,
508
- reportedBoundingBoxAcc,
509
- views,
510
- ]);
511
-
512
- useEffect(() => {
513
- if (typeof triggerHome !== "undefined") {
514
- calcDefaultViewStates(reportedBoundingBoxAcc);
515
- }
516
- // eslint-disable-next-line react-hooks/exhaustive-deps
517
- }, [triggerHome]);
518
-
519
- useEffect(() => {
520
- const union_of_reported_bboxes = addBoundingBoxes(
521
- reportedBoundingBoxAcc,
522
- reportedBoundingBox
523
- );
524
- setReportedBoundingBoxAcc(union_of_reported_bboxes);
525
-
526
- // If "bounds" or "cameraPosition" is not defined "viewState" will be
527
- // calculated based on the union of the reported bounding boxes from each layer.
528
- if (!didUserChangeCamera && !isCameraPositionDefined) {
529
- calcDefaultViewStates(union_of_reported_bboxes);
530
- }
531
- // eslint-disable-next-line react-hooks/exhaustive-deps
532
- }, [reportedBoundingBox]);
533
-
534
- // react on bounds prop change
535
- useEffect(() => {
536
- const isBoundsDefined = typeof bounds !== "undefined";
537
-
538
- let tempViewStates: Record<string, ViewStateType> = {};
539
- if (!isCameraPositionDefined) {
540
- tempViewStates = Object.fromEntries(
541
- viewsProps.map((item, index) => [
542
- item.id,
543
- isBoundsDefined
544
- ? getViewState(
545
- viewPortMargins,
546
- boundsInitial,
547
- boundingBoxCenter(reportedBoundingBoxAcc),
548
- views,
549
- index,
550
- deckRef.current?.deck
551
- )
552
- : getViewState3D(
553
- views?.viewports?.[index]?.show3D ?? false,
554
- reportedBoundingBoxAcc,
555
- views?.viewports?.[index].zoom,
556
- deckRef.current?.deck
557
- ),
558
- ])
559
- );
560
- if (viewsProps[0] !== undefined) {
561
- setFirstViewStatesId(viewsProps[0].id);
562
- }
563
- setViewStates(tempViewStates);
564
- }
565
- // eslint-disable-next-line react-hooks/exhaustive-deps
566
- }, [boundsInitial, cameraPosition, views?.viewports, viewsProps]);
567
-
568
- // react on cameraPosition prop change
569
- useEffect(() => {
570
- let tempViewStates: Record<string, ViewStateType> = {};
571
- if (isCameraPositionDefined) {
572
- tempViewStates = Object.fromEntries(
573
- viewsProps.map((item) => [item.id, cameraPosition])
574
- ) as unknown as Record<string, ViewStateType>;
575
- setViewStates(tempViewStates);
576
- if (viewsProps[0] !== undefined) {
577
- setFirstViewStatesId(viewsProps[0].id);
578
- }
579
- }
580
- if (cameraPosition === null) {
581
- tempViewStates = Object.fromEntries(
582
- viewsProps.map((item) => [item.id, initialViewState])
583
- );
584
- setViewStates(tempViewStates);
585
- }
586
- // eslint-disable-next-line react-hooks/exhaustive-deps
587
- }, [cameraPosition, viewsProps]);
588
-
589
- // Used for scaling in z direction using arrow keys.
590
- const [scaleZ, setScaleZ] = useState<number>(1);
591
- const [scaleZUp, setScaleZUp] = useState<number>(1);
592
- const [scaleZDown, setScaleZDown] = useState<number>(1);
593
-
594
- const scaleUpFunction = () => {
595
- setScaleZUp(Math.random());
596
- };
597
-
598
- const scaleDownFunction = () => {
599
- setScaleZDown(Math.random());
600
- };
601
-
602
- useEffect(() => {
603
- const newScaleZ = scaleZ * 1.05;
604
- setScaleZ(newScaleZ);
605
- // Make camera target follow the scaling.
606
- const vs = adjustCameraTarget(viewStates, scaleZ, newScaleZ);
607
- setViewStates(vs);
608
- // eslint-disable-next-line react-hooks/exhaustive-deps
609
- }, [scaleZUp]);
610
-
611
- useEffect(() => {
612
- const newScaleZ = scaleZ * 0.95;
613
- setScaleZ(newScaleZ);
614
- // Make camera target follow the scaling.
615
- const vs = adjustCameraTarget(viewStates, scaleZ, newScaleZ);
616
- setViewStates(vs);
617
- // eslint-disable-next-line react-hooks/exhaustive-deps
618
- }, [scaleZDown]);
619
-
620
- useEffect(() => {
621
- const viewProps = getViews(views) as ViewportType[];
622
-
623
- setViewsProps(viewProps);
624
-
625
- if (!bounds) {
626
- calcDefaultViewStates(reportedBoundingBoxAcc);
627
- }
628
- // eslint-disable-next-line react-hooks/exhaustive-deps
629
- }, [views]);
630
-
631
- useEffect(() => {
632
- if (layers == undefined) return;
633
-
634
- // Margins on the viewport are extracted from a potenial axes2D layer.
635
- const axes2DLayer = layers?.find((e) => {
636
- return e?.constructor === Axes2DLayer;
637
- }) as Axes2DLayer;
638
-
639
- const left =
640
- axes2DLayer && axes2DLayer.props.isLeftRuler
641
- ? axes2DLayer.props.marginH
642
- : 0;
643
- const right =
644
- axes2DLayer && axes2DLayer.props.isRightRuler
645
- ? axes2DLayer.props.marginH
646
- : 0;
647
- const top =
648
- axes2DLayer && axes2DLayer.props.isTopRuler
649
- ? axes2DLayer.props.marginV
650
- : 0;
651
- const bottom =
652
- axes2DLayer && axes2DLayer.props.isBottomRuler
653
- ? axes2DLayer.props.marginV
654
- : 0;
655
-
656
- setViewPortMargins({ left, right, top, bottom });
657
-
658
- const m = getModelMatrixScale(scaleZ);
659
-
660
- const layers_copy = layers.map((item) => {
661
- if (item?.constructor.name === NorthArrow3DLayer.name) return item;
662
-
663
- const layer = item as Layer;
664
-
665
- // Set "modelLayer" matrix to reflect correct z scaling.
666
- const scaledLayer = layer.clone({ modelMatrix: m });
667
-
668
- // Inject "setReportedBoundingBox" function into layer for it to report
669
- // back its respective bounding box.
670
- const boundedLayer = scaledLayer.clone({
671
- setReportedBoundingBox: setReportedBoundingBox,
672
- });
673
-
674
- return boundedLayer ?? scaledLayer;
675
- });
676
-
677
- setAlteredLayers(layers_copy);
678
- }, [scaleZ, layers /*dispatch*/]);
679
-
680
- const [deckGLLayers, setDeckGLLayers] = useState<LayersList>([]);
681
-
682
- useEffect(() => {
683
- setDeckGLLayers(alteredLayers);
684
- }, [alteredLayers]);
685
-
686
- useEffect(() => {
687
- const layers = deckRef.current?.deck?.props.layers;
688
- if (layers) {
689
- const wellslayer = getLayersByType(
690
- layers,
691
- WellsLayer.name
692
- )?.[0] as WellsLayer;
693
-
694
- wellslayer?.setSelection(selection?.well, selection?.selection);
695
- }
696
- }, [selection]);
697
-
698
- // multiple well layers
699
- const [multipleWells, setMultipleWells] = useState<string[]>([]);
700
- const [selectedWell, setSelectedWell] = useState<string>("");
701
- const [shiftHeld, setShiftHeld] = useState(false);
702
-
703
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
704
- function downHandler({ key }: any) {
705
- if (key === "Shift") {
706
- setShiftHeld(true);
707
- }
708
- }
709
-
710
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
711
- function upHandler({ key }: any) {
712
- if (key === "Shift") {
713
- setShiftHeld(false);
714
- }
715
- }
716
-
717
- useEffect(() => {
718
- window.addEventListener("keydown", downHandler);
719
- window.addEventListener("keyup", upHandler);
720
- return () => {
721
- window.removeEventListener("keydown", downHandler);
722
- window.removeEventListener("keyup", upHandler);
723
- };
724
- }, []);
725
-
726
- useEffect(() => {
727
- const layers = deckRef.current?.deck?.props.layers;
728
- if (layers) {
729
- const wellslayer = getWellLayerByTypeAndSelectedWells(
730
- layers,
731
- "WellsLayer",
732
- selectedWell
733
- )?.[0] as WellsLayer;
734
- wellslayer?.setMultiSelection(multipleWells);
735
- }
736
- }, [multipleWells, selectedWell]);
737
-
738
- useEffect(() => {
739
- if (typeof triggerResetMultipleWells !== "undefined") {
740
- setMultipleWells([]);
741
- }
742
- }, [triggerResetMultipleWells]);
743
-
744
- const getPickingInfos = useCallback(
745
- (
746
- pickInfo: PickingInfo,
747
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
748
- event: any
749
- ): PickingInfo[] => {
750
- if (coords?.multiPicking && pickInfo.layer?.context.deck) {
751
- const pickInfos =
752
- pickInfo.layer.context.deck.pickMultipleObjects({
753
- x: event.offsetCenter.x,
754
- y: event.offsetCenter.y,
755
- depth: coords.pickDepth ? coords.pickDepth : undefined,
756
- }) as LayerPickInfo[];
757
- pickInfos.forEach((item) => {
758
- if (item.properties) {
759
- let unit = (
760
- item.sourceLayer?.props
761
- .data as unknown as FeatureCollection & {
762
- unit: string;
763
- }
764
- )?.unit;
765
- if (unit == undefined) unit = " ";
766
- item.properties.forEach((element) => {
767
- if (
768
- element.name.includes("MD") ||
769
- element.name.includes("TVD")
770
- ) {
771
- element.value =
772
- Number(element.value)
773
- .toFixed(2)
774
- .toString() +
775
- " " +
776
- unit;
777
- }
778
- });
779
- }
780
- });
781
- return pickInfos;
782
- }
783
- return [pickInfo];
784
- },
785
- [coords?.multiPicking, coords?.pickDepth]
786
- );
787
-
788
- /**
789
- * call onMouseEvent callback
790
- */
791
- const callOnMouseEvent = useCallback(
792
- (
793
- type: "click" | "hover",
794
- infos: PickingInfo[],
795
- event: MjolnirEvent
796
- ): void => {
797
- if (!onMouseEvent) return;
798
- const ev = handleMouseEvent(type, infos, event);
799
- onMouseEvent(ev);
800
- },
801
- [onMouseEvent]
802
- );
803
-
804
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
805
- const [hoverInfo, setHoverInfo] = useState<any>([]);
806
- const onHover = useCallback(
807
- (pickInfo: PickingInfo, event: MjolnirEvent) => {
808
- const infos = getPickingInfos(pickInfo, event);
809
- setHoverInfo(infos); // for InfoCard pickInfos
810
- callOnMouseEvent?.("hover", infos, event);
811
- },
812
- [callOnMouseEvent, getPickingInfos]
813
- );
814
-
815
- const onClick = useCallback(
816
- (pickInfo: PickingInfo, event: MjolnirEvent) => {
817
- const infos = getPickingInfos(pickInfo, event);
818
- callOnMouseEvent?.("click", infos, event);
819
- },
820
- [callOnMouseEvent, getPickingInfos]
821
- );
822
-
823
- const [isLoaded, setIsLoaded] = useState<boolean>(false);
824
- const onAfterRender = useCallback(() => {
825
- if (deckGLLayers) {
826
- const state = deckGLLayers.every(
827
- (layer) => (layer as Layer).isLoaded
828
- );
829
- setIsLoaded(state);
830
- }
831
- }, [deckGLLayers]);
832
-
833
- // validate layers data
834
- const [errorText, setErrorText] = useState<string>();
835
- useEffect(() => {
836
- const layers = deckRef.current?.deck?.props.layers as Layer[];
837
- // this ensures to validate the schemas only once
838
- if (checkDatafileSchema && layers && isLoaded) {
839
- try {
840
- validateLayers(layers);
841
- colorTables && validateColorTables(colorTables);
842
- } catch (e) {
843
- setErrorText(String(e));
844
- }
845
- } else setErrorText(undefined);
846
- }, [
847
- checkDatafileSchema,
848
- colorTables,
849
- deckRef?.current?.deck?.props.layers,
850
- isLoaded,
851
- ]);
852
-
853
- const layerFilter = useCallback(
854
- (args: { layer: Layer; viewport: Viewport }): boolean => {
855
- // display all the layers if views are not specified correctly
856
- if (!views || !views.viewports || !views.layout) return true;
857
-
858
- const cur_view = views.viewports.find(
859
- ({ id }) => args.viewport.id && id === args.viewport.id
860
- );
861
- if (cur_view?.layerIds && cur_view.layerIds.length > 0) {
862
- const layer_ids = cur_view.layerIds;
863
- return layer_ids.some((layer_id) => {
864
- const t = layer_id === args.layer.id;
865
- return t;
866
- });
867
- } else {
868
- return true;
869
- }
870
- },
871
- [views]
872
- );
873
-
874
- const onViewStateChange = useCallback(
875
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
876
- ({ viewId, viewState }: { viewId: string; viewState: any }) => {
877
- const viewports = views?.viewports || [];
878
- const isSyncIds = viewports
879
- .filter((item) => item.isSync)
880
- .map((item) => item.id);
881
- if (isSyncIds?.includes(viewId)) {
882
- const viewStateTable = views?.viewports
883
- .filter((item) => item.isSync)
884
- .map((item) => [item.id, viewState]);
885
- const tempViewStates = Object.fromEntries(viewStateTable ?? []);
886
- setViewStates((currentViewStates) => ({
887
- ...currentViewStates,
888
- ...tempViewStates,
889
- }));
890
- } else {
891
- setViewStates((currentViewStates) => ({
892
- ...currentViewStates,
893
- [viewId]: viewState,
894
- }));
895
- }
896
- if (getCameraPosition) {
897
- getCameraPosition(viewState);
898
- }
899
- setFirstViewStatesId(viewsProps[0]?.id);
900
- setDidUserChangeCamera(true);
901
- },
902
- [getCameraPosition, views?.viewports, viewsProps]
903
- );
904
-
905
- const deckGLViews = React.useMemo(() => {
906
- return createViews(
907
- views,
908
- scaleUpFunction,
909
- scaleDownFunction,
910
- deckRef.current?.deck
911
- );
912
- // eslint-disable-next-line react-hooks/exhaustive-deps
913
- }, [views, views, deckRef.current?.deck]);
914
-
915
- if (!deckGLViews || isEmpty(deckGLViews) || isEmpty(deckGLLayers))
916
- return null;
917
- return (
918
- <div onContextMenu={(event) => event.preventDefault()}>
919
- <DeckGL
920
- id={id}
921
- viewState={viewStates}
922
- views={deckGLViews}
923
- layerFilter={layerFilter}
924
- layers={deckGLLayers}
925
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
926
- // @ts-expect-error
927
- userData={{
928
- setEditedData: (updated_prop: Record<string, unknown>) => {
929
- setSelectedWell(updated_prop["selectedWell"] as string);
930
- if (
931
- Object.keys(updated_prop).includes("selectedWell")
932
- ) {
933
- if (shiftHeld) {
934
- if (
935
- multipleWells.includes(
936
- updated_prop["selectedWell"] as string
937
- )
938
- ) {
939
- const temp = multipleWells.filter(
940
- (item) =>
941
- item !==
942
- updated_prop["selectedWell"]
943
- );
944
- setMultipleWells(temp);
945
- } else {
946
- const temp = multipleWells.concat(
947
- updated_prop["selectedWell"] as string
948
- );
949
- setMultipleWells(temp);
950
- }
951
- } else {
952
- setMultipleWells([]);
953
- }
954
- }
955
- setEditedData?.(updated_prop);
956
- },
957
- colorTables: colorTables,
958
- }}
959
- getCursor={({ isDragging }): string =>
960
- isDragging ? "grabbing" : "default"
961
- }
962
- getTooltip={getTooltip}
963
- ref={deckRef}
964
- onViewStateChange={onViewStateChange}
965
- onHover={onHover}
966
- onClick={onClick}
967
- onLoad={onLoad}
968
- onAfterRender={onAfterRender}
969
- >
970
- {children}
971
- </DeckGL>
972
- {scale?.visible ? (
973
- <DistanceScale
974
- {...scale}
975
- zoom={
976
- viewStates[firstViewStateId] === undefined
977
- ? -5
978
- : viewStates[firstViewStateId].zoom
979
- }
980
- scaleUnit={coordinateUnit}
981
- style={scale.cssStyle ?? {}}
982
- />
983
- ) : null}
984
- <StatusIndicator layers={deckGLLayers} isLoaded={isLoaded} />
985
- {coords?.visible ? <InfoCard pickInfos={hoverInfo} /> : null}
986
- {errorText && (
987
- <pre
988
- style={{
989
- flex: "0, 0",
990
- color: "rgb(255, 64, 64)",
991
- backgroundColor: "rgb(255, 255, 192)",
992
- }}
993
- >
994
- {errorText}
995
- </pre>
996
- )}
997
- </div>
998
- );
999
- };
1000
-
1001
- Map.defaultProps = {
1002
- coords: {
1003
- visible: true,
1004
- multiPicking: true,
1005
- pickDepth: 10,
1006
- },
1007
- scale: {
1008
- visible: true,
1009
- incrementValue: 100,
1010
- widthPerUnit: 100,
1011
- cssStyle: { top: 10, left: 10 },
1012
- },
1013
- toolbar: {
1014
- visible: false,
1015
- },
1016
- coordinateUnit: "m",
1017
- views: {
1018
- layout: [1, 1],
1019
- showLabel: false,
1020
- viewports: [{ id: "main-view", show3D: false, layerIds: [] }],
1021
- },
1022
- colorTables: colorTables,
1023
- checkDatafileSchema: false,
1024
- };
1025
-
1026
- export default Map;
1027
-
1028
- // ------------- Helper functions ---------- //
1029
-
1030
- // Add the resources as an enum in the Json Configuration and then convert the spec to actual objects.
1031
- // See https://deck.gl/docs/api-reference/json/overview for more details.
1032
- export function jsonToObject(
1033
- data: Record<string, unknown>[] | LayerProps[],
1034
- enums: Record<string, unknown>[] | undefined = undefined
1035
- ): LayersList | View[] {
1036
- if (!data) return [];
1037
-
1038
- const configuration = new JSONConfiguration(JSON_CONVERTER_CONFIG);
1039
- enums?.forEach((enumeration) => {
1040
- if (enumeration) {
1041
- configuration.merge({
1042
- enumerations: {
1043
- ...enumeration,
1044
- },
1045
- });
1046
- }
1047
- });
1048
- const jsonConverter = new JSONConverter({ configuration });
1049
-
1050
- // remove empty data/layer object
1051
- const filtered_data = data.filter(
1052
- (value) => Object.keys(value).length !== 0
1053
- );
1054
- return jsonConverter.convert(filtered_data);
1055
- }
1056
-
1057
- // return viewstate with computed bounds to fit the data in viewport
1058
- function getViewState(
1059
- viewPortMargins: marginsType,
1060
- bounds_accessor: [number, number, number, number] | BoundsAccessor,
1061
- centerOfData: [number, number, number],
1062
- views: ViewsType | undefined,
1063
- viewPortIndex: number,
1064
- deck?: Deck
1065
- ): ViewStateType {
1066
- let bounds = [0, 0, 1, 1];
1067
- if (typeof bounds_accessor == "function") {
1068
- bounds = bounds_accessor();
1069
- } else {
1070
- bounds = bounds_accessor;
1071
- }
1072
-
1073
- let w = bounds[2] - bounds[0]; // right - left
1074
- let h = bounds[3] - bounds[1]; // top - bottom
1075
-
1076
- const z = centerOfData[2];
1077
-
1078
- const fb = fitBounds({ width: w, height: h, bounds });
1079
- let fb_target = [fb.x, fb.y, z];
1080
- let fb_zoom = fb.zoom;
1081
-
1082
- if (deck) {
1083
- // If there are margins/rulers in the viewport (axes2DLayer) we have to account for that.
1084
- // Camera target should be in the middle of viewport minus the rulers.
1085
- const w_bounds = w;
1086
- const h_bounds = h;
1087
-
1088
- const ml = viewPortMargins.left;
1089
- const mr = viewPortMargins.right;
1090
- const mb = viewPortMargins.bottom;
1091
- const mt = viewPortMargins.top;
1092
-
1093
- // Subtract margins.
1094
- const marginH = (ml > 0 ? ml : 0) + (mr > 0 ? mr : 0);
1095
- const marginV = (mb > 0 ? mb : 0) + (mt > 0 ? mt : 0);
1096
-
1097
- w = deck.width - marginH; // width of the viewport minus margin.
1098
- h = deck.height - marginV;
1099
-
1100
- // Special case if matrix views.
1101
- // Use width and heigt for a subview instead of full viewport.
1102
- if (typeof views?.layout !== "undefined") {
1103
- const [nY, nX] = views.layout;
1104
- const isMatrixViews = nX !== 1 || nY !== 1;
1105
- if (isMatrixViews) {
1106
- const mPixels = views?.marginPixels ?? 0;
1107
-
1108
- const w_ = 99.5 / nX; // Using 99.5% of viewport to avoid flickering of deckgl canvas
1109
- const h_ = 99.5 / nY;
1110
-
1111
- const marginHorPercentage =
1112
- 100 * 100 * (mPixels / (w_ * deck.width)); //percentage of sub view
1113
- const marginVerPercentage =
1114
- 100 * 100 * (mPixels / (h_ * deck.height));
1115
-
1116
- const sub_w = (w_ / 100) * deck.width;
1117
- const sub_h = (h_ / 100) * deck.height;
1118
-
1119
- w = sub_w * (1 - 2 * (marginHorPercentage / 100)) - marginH;
1120
- h = sub_h * (1 - 2 * (marginVerPercentage / 100)) - marginV;
1121
- }
1122
- }
1123
-
1124
- const port_aspect = h / w;
1125
- const bounds_aspect = h_bounds / w_bounds;
1126
-
1127
- const m_pr_pixel =
1128
- bounds_aspect > port_aspect ? h_bounds / h : w_bounds / w;
1129
-
1130
- let translate_x = 0;
1131
- if (ml > 0 && mr === 0) {
1132
- // left margin and no right margin
1133
- translate_x = 0.5 * ml * m_pr_pixel;
1134
- } else if (ml === 0 && mr > 0) {
1135
- // no left margin but right margin
1136
- translate_x = -0.5 * mr * m_pr_pixel;
1137
- }
1138
-
1139
- let translate_y = 0;
1140
- if (mb > 0 && mt === 0) {
1141
- translate_y = 0.5 * mb * m_pr_pixel;
1142
- } else if (mb === 0 && mt > 0) {
1143
- translate_y = -0.5 * mt * m_pr_pixel;
1144
- }
1145
-
1146
- const fb = fitBounds({ width: w, height: h, bounds });
1147
- fb_target = [fb.x - translate_x, fb.y - translate_y, z];
1148
- fb_zoom = fb.zoom;
1149
- }
1150
-
1151
- const target = views?.viewports?.[viewPortIndex]?.target;
1152
- const zoom = views?.viewports?.[viewPortIndex]?.zoom;
1153
-
1154
- const target_ = target ?? fb_target;
1155
- const zoom_ = zoom ?? fb_zoom;
1156
-
1157
- const view_state: ViewStateType = {
1158
- target: target_,
1159
- zoom: zoom_,
1160
- rotationX: 90, // look down z -axis
1161
- rotationOrbit: 0,
1162
- };
1163
- return view_state;
1164
- }
1165
-
1166
- ///////////////////////////////////////////////////////////////////////////////////////////
1167
- // return viewstate with computed bounds to fit the data in viewport
1168
- function getViewState3D(
1169
- is3D: boolean,
1170
- bounds: [number, number, number, number, number, number],
1171
- zoom?: number,
1172
- deck?: Deck
1173
- ): ViewStateType {
1174
- const xMin = bounds[0];
1175
- const yMin = bounds[1];
1176
- const zMin = bounds[2];
1177
-
1178
- const xMax = bounds[3];
1179
- const yMax = bounds[4];
1180
- const zMax = bounds[5];
1181
-
1182
- let width = xMax - xMin;
1183
- let height = yMax - yMin;
1184
- if (deck) {
1185
- width = deck.width;
1186
- height = deck.height;
1187
- }
1188
-
1189
- const target = [
1190
- xMin + (xMax - xMin) / 2,
1191
- yMin + (yMax - yMin) / 2,
1192
- is3D ? zMin + (zMax - zMin) / 2 : 0,
1193
- ];
1194
- const bounds2D = [xMin, yMin, xMax, yMax];
1195
- const fitted_bound = fitBounds({
1196
- width,
1197
- height,
1198
- bounds: bounds2D,
1199
- });
1200
- const view_state: ViewStateType = {
1201
- target,
1202
- zoom: zoom ?? fitted_bound.zoom * 1.2,
1203
- rotationX: 45, // look down z -axis at 45 degrees
1204
- rotationOrbit: 0,
1205
- };
1206
- return view_state;
1207
- }
1208
-
1209
- // construct views object for DeckGL component
1210
- function createViews(
1211
- views: ViewsType | undefined,
1212
- scaleUpFunction: { (): void; (): void },
1213
- scaleDownFunction: { (): void; (): void },
1214
- deck?: Deck
1215
- ): View[] {
1216
- // Use modified controller to handle key events.
1217
- class ZScaleOrbitController extends OrbitController {
1218
- handleEvent(event: MjolnirEvent): boolean {
1219
- if (event.type === "keydown" && event.key === "ArrowUp") {
1220
- scaleUpFunction();
1221
- return true;
1222
- } else if (event.type === "keydown" && event.key === "ArrowDown") {
1223
- scaleDownFunction();
1224
- return true;
1225
- }
1226
-
1227
- return super.handleEvent(event);
1228
- }
1229
- }
1230
- const deckgl_views: View[] = [];
1231
-
1232
- const widthViewPort = deck?.width;
1233
- const heightViewPort = deck?.height;
1234
-
1235
- const isDeckDefined =
1236
- typeof widthViewPort !== "undefined" &&
1237
- typeof heightViewPort !== "undefined";
1238
-
1239
- const mPixels = views?.marginPixels ?? 0;
1240
-
1241
- // if props for multiple viewport are not proper, return 2d view
1242
- if (!views || !views.viewports || !views.layout || !isDeckDefined) {
1243
- deckgl_views.push(
1244
- new OrthographicView({
1245
- id: "main",
1246
- controller: { doubleClickZoom: false },
1247
- x: "0%",
1248
- y: "0%",
1249
- width: "100%",
1250
- height: "100%",
1251
- flipY: false,
1252
- far: +99999,
1253
- near: -99999,
1254
- })
1255
- );
1256
- } else {
1257
- let yPos = 0;
1258
- const [nY, nX] = views.layout;
1259
- const w = 99.5 / nX; // Using 99.5% of viewport to avoid flickering of deckgl canvas
1260
- const h = 99.5 / nY;
1261
-
1262
- const singleView = nX === 1 && nY === 1;
1263
-
1264
- const marginHorPercentage = singleView // percentage of sub view
1265
- ? 0
1266
- : 100 * 100 * (mPixels / (w * widthViewPort));
1267
- const marginVerPercentage = singleView
1268
- ? 0
1269
- : 100 * 100 * (mPixels / (h * heightViewPort));
1270
-
1271
- for (let y = 1; y <= nY; y++) {
1272
- let xPos = 0;
1273
- for (let x = 1; x <= nX; x++) {
1274
- if (
1275
- views.viewports == undefined ||
1276
- deckgl_views.length >= views.viewports.length
1277
- ) {
1278
- return deckgl_views;
1279
- }
1280
-
1281
- const currentViewport: ViewportType =
1282
- views.viewports[deckgl_views.length];
1283
-
1284
- const ViewType = currentViewport.show3D
1285
- ? OrbitView
1286
- : currentViewport.id === "intersection_view"
1287
- ? IntersectionView
1288
- : OrthographicView;
1289
-
1290
- const far = 9999;
1291
- const near = currentViewport.show3D ? 0.1 : -9999;
1292
-
1293
- const Controller = currentViewport.show3D
1294
- ? ZScaleOrbitController
1295
- : OrthographicController;
1296
-
1297
- const controller = {
1298
- type: Controller,
1299
- doubleClickZoom: false,
1300
- };
1301
-
1302
- deckgl_views.push(
1303
- new ViewType({
1304
- id: currentViewport.id,
1305
- controller: controller,
1306
-
1307
- x: xPos + marginHorPercentage / nX + "%",
1308
- y: yPos + marginVerPercentage / nY + "%",
1309
-
1310
- width: w * (1 - 2 * (marginHorPercentage / 100)) + "%",
1311
- height: h * (1 - 2 * (marginVerPercentage / 100)) + "%",
1312
-
1313
- flipY: false,
1314
- far,
1315
- near,
1316
- })
1317
- );
1318
- xPos = xPos + w;
1319
- }
1320
- yPos = yPos + h;
1321
- }
1322
- }
1323
- return deckgl_views;
1324
- }
1325
-
1326
- // construct views object for DeckGL component
1327
- function getViews(views: ViewsType | undefined): ViewportType[] {
1328
- const deckgl_views = [];
1329
-
1330
- // if props for multiple viewport are not proper, return 2d view
1331
- if (!views || !views.viewports || !views.layout) {
1332
- deckgl_views.push({
1333
- id: "main",
1334
- });
1335
- } else {
1336
- const [nY, nX] = views.layout;
1337
- for (let y = 1; y <= nY; y++) {
1338
- for (let x = 1; x <= nX; x++) {
1339
- if (
1340
- views.viewports == undefined ||
1341
- deckgl_views.length >= views.viewports.length
1342
- )
1343
- return deckgl_views;
1344
-
1345
- const cur_viewport: ViewportType =
1346
- views.viewports[deckgl_views.length];
1347
-
1348
- deckgl_views.push({
1349
- id: cur_viewport.id,
1350
- });
1351
- }
1352
- }
1353
- }
1354
- return deckgl_views;
1355
- }
1356
-
1357
- function handleMouseEvent(
1358
- type: "click" | "hover",
1359
- infos: PickingInfo[],
1360
- event: MjolnirEvent
1361
- ) {
1362
- const ev: MapMouseEvent = {
1363
- type: type,
1364
- infos: infos,
1365
- };
1366
- if (ev.type === "click") {
1367
- if ((event as MjolnirPointerEvent).rightButton) ev.type = "contextmenu";
1368
- }
1369
- for (const info of infos as LayerPickInfo[]) {
1370
- if (info.coordinate) {
1371
- ev.x = info.coordinate[0];
1372
- ev.y = info.coordinate[1];
1373
- }
1374
- if (info.layer && info.layer.id === "wells-layer") {
1375
- // info.object is Feature or WellLog;
1376
- {
1377
- // try to use Object info (see DeckGL getToolTip callback)
1378
- const feat = info.object as Feature;
1379
- const properties = feat?.properties;
1380
- if (properties) {
1381
- ev.wellname = properties["name"];
1382
- ev.wellcolor = properties["color"];
1383
- }
1384
- }
1385
-
1386
- if (!ev.wellname)
1387
- if (info.object) {
1388
- ev.wellname = info.object.header?.["well"]; // object is WellLog
1389
- }
1390
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1391
- if (info.properties) {
1392
- for (const property of info.properties) {
1393
- if (!ev.wellcolor) ev.wellcolor = property.color;
1394
- let propname = property.name;
1395
- if (propname) {
1396
- const sep = propname.indexOf(" ");
1397
- if (sep >= 0) {
1398
- if (!ev.wellname) {
1399
- ev.wellname = propname.substring(sep + 1);
1400
- }
1401
- propname = propname.substring(0, sep);
1402
- }
1403
- }
1404
- const names_md = [
1405
- "DEPTH",
1406
- "DEPT",
1407
- "MD" /*Measured Depth*/,
1408
- "TDEP" /*"Tool DEPth"*/,
1409
- "MD_RKB" /*Rotary Relly Bushing*/,
1410
- ]; // aliases for MD
1411
- const names_tvd = [
1412
- "TVD" /*True Vertical Depth*/,
1413
- "TVDSS" /*SubSea*/,
1414
- "DVER" /*"VERtical Depth"*/,
1415
- "TVD_MSL" /*below Mean Sea Level*/,
1416
- ]; // aliases for MD
1417
-
1418
- if (names_md.find((name) => name == propname))
1419
- ev.md = parseFloat(property.value as string);
1420
- else if (names_tvd.find((name) => name == propname))
1421
- ev.tvd = parseFloat(property.value as string);
1422
-
1423
- if (
1424
- ev.md !== undefined &&
1425
- ev.tvd !== undefined &&
1426
- ev.wellname !== undefined
1427
- )
1428
- break;
1429
- }
1430
- }
1431
- break;
1432
- }
1433
- }
1434
- return ev;
1435
- }