Skip to content

Commit d27bcc1

Browse files
authored
feat: Well labels tool tip (#2523)
Well names will show up in the tooltip when hovering over a well label and also in the readout
1 parent 06834f7 commit d27bcc1

File tree

6 files changed

+131
-6
lines changed

6 files changed

+131
-6
lines changed

typescript/packages/subsurface-viewer/src/components/InfoCard.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
PropertyDataType,
1818
} from "../layers/utils/layerTools";
1919
import { rgb } from "d3-color";
20+
import { WellLabelLayer } from "../layers/wells/layers/wellLabelLayer";
2021

2122
Icon.add({ arrow_drop_up, arrow_drop_down });
2223

@@ -161,6 +162,32 @@ const InfoCard: React.FC<InfoCardProps> = (props: InfoCardProps) => {
161162
setInfoCardData(null);
162163
return;
163164
}
165+
166+
if (
167+
(props.pickInfos[0].layer?.constructor === WellLabelLayer ||
168+
props.pickInfos[0].sourceLayer?.constructor ===
169+
WellLabelLayer) &&
170+
props.pickInfos[0].object?.wellLabels
171+
) {
172+
// Cluster of well labels.
173+
const info_card_data: InfoCardDataType[] = [];
174+
const xy_properties: PropertyDataType[] = [];
175+
props.pickInfos[0].object.wellLabels.forEach((label: string) => {
176+
xy_properties.push({
177+
name: label,
178+
value: "",
179+
});
180+
});
181+
182+
info_card_data.push({
183+
layerName: "Well(s)",
184+
properties: xy_properties,
185+
});
186+
187+
setInfoCardData(info_card_data);
188+
return;
189+
}
190+
164191
const topObject = props.pickInfos[0];
165192
if (
166193
topObject.coordinate === undefined ||

typescript/packages/subsurface-viewer/src/components/Map.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import type { ViewportType } from "../views/viewport";
7777
import { useVerticalScale } from "../views/viewport";
7878

7979
import mergeRefs from "merge-refs";
80+
import { WellLabelLayer } from "../layers/wells/layers/wellLabelLayer";
8081

8182
export type { BoundingBox2D, BoundingBox3D, Point2D, Point3D };
8283
/**
@@ -401,7 +402,13 @@ export interface MapProps {
401402
}
402403

403404
function defaultTooltip(info: PickingInfo) {
404-
if ((info as WellsPickInfo)?.logName) {
405+
if (
406+
(info.layer?.constructor === WellLabelLayer ||
407+
info.sourceLayer?.constructor === WellLabelLayer) &&
408+
info.object?.wellLabels
409+
) {
410+
return info.object.wellLabels?.join("\n");
411+
} else if ((info as WellsPickInfo)?.logName) {
405412
return (info as WellsPickInfo)?.logName;
406413
} else if (info.layer?.id === "drawing-layer") {
407414
return (info as LayerPickInfo).propertyValue?.toFixed(2);
@@ -640,7 +647,7 @@ const Map: React.FC<MapProps> = ({
640647
const onHover = useCallback(
641648
(pickInfo: PickingInfo, event: MjolnirEvent) => {
642649
const infos = getPickingInfos(pickInfo, event);
643-
setHoverInfo(infos); // for InfoCard pickInfos
650+
setHoverInfo(infos);
644651
callOnMouseEvent?.("hover", infos, event);
645652
},
646653
[callOnMouseEvent, getPickingInfos]

typescript/packages/subsurface-viewer/src/layers/wells/layers/wellLabelLayer.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Color } from "@deck.gl/core";
1+
import type { Color, PickingInfo } from "@deck.gl/core";
22
import { type DefaultProps, type UpdateParameters } from "@deck.gl/core";
33
import type { TextLayerProps } from "@deck.gl/layers";
44
import type { Feature, Position } from "geojson";
@@ -67,6 +67,7 @@ const DEFAULT_PROPS: DefaultProps<WellLabelLayerProps> = {
6767
backgroundPadding: [3, 1, 3, 1],
6868
getBorderColor: [0, 0, 0, 255],
6969
getBorderWidth: 1,
70+
pickable: true,
7071

7172
transitions: {
7273
// Animate label position transitions in order to help tracking when labels are moving
@@ -325,6 +326,15 @@ export class WellLabelLayer extends MergedTextLayer<
325326
// Default to well head of no valid position is found in viewport
326327
return [0, trajectory[0] as Position3D];
327328
}
329+
330+
getPickingInfo({ info }: { info: PickingInfo }) {
331+
const name = info.object?.properties?.name ?? "";
332+
const pos = this.state.labelPositions.get(name)!;
333+
const names = this.state.clusters.get(pos);
334+
335+
info.object = { ...info.object, wellLabels: names };
336+
return info;
337+
}
328338
}
329339

330340
WellLabelLayer.defaultProps = DEFAULT_PROPS as DefaultProps<

typescript/packages/subsurface-viewer/src/layers/wells/wellsLayer.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export default class WellsLayer extends CompositeLayer<WellsLayerProps> {
384384
...this.props.wellLabel,
385385
id: SubLayerId.LABELS,
386386
data,
387-
387+
pickable: true,
388388
// Z is always increasing upwards at this stage
389389
zIncreasingDownwards: false,
390390

@@ -645,7 +645,14 @@ export default class WellsLayer extends CompositeLayer<WellsLayerProps> {
645645
}
646646

647647
getPickingInfo({ info }: { info: PickingInfo }): WellsPickInfo {
648-
if (!info.object) return { ...info, properties: [], logName: "" };
648+
const noLog = {
649+
properties: [],
650+
logName: "",
651+
};
652+
653+
if (!info.object || info.sourceLayer?.constructor === WellLabelLayer) {
654+
return { ...info, ...noLog };
655+
}
649656

650657
const features = this.getWellDataState()?.features ?? [];
651658
const coordinate: Position = info.coordinate || [0, 0, 0];

typescript/packages/subsurface-viewer/src/storybook/layers/WellLabelLayer.stories.tsx

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
WellFeature,
1414
WellFeatureCollection,
1515
} from "../../layers/wells/types";
16-
import type { ViewsType } from "../../SubsurfaceViewer";
16+
import type { ViewStateType, ViewsType } from "../../SubsurfaceViewer";
1717
import SubsurfaceViewer from "../../SubsurfaceViewer";
1818
import {
1919
LABEL_ORIENTATION_ARGTYPES,
@@ -23,6 +23,7 @@ import {
2323
} from "../constant/argTypes";
2424
import type { TrajectorySimulationProps } from "../types/trajectory";
2525
import { getRgba } from "../util/color";
26+
import { fireEvent, userEvent } from "@storybook/test";
2627

2728
type WellCount = { wellCount: number };
2829

@@ -317,6 +318,79 @@ export const Default: StoryObj<WellCount> = {
317318
},
318319
};
319320

321+
export const WellLabelPicking: StoryObj<typeof SubsurfaceViewer> = {
322+
render: () => {
323+
const camera: ViewStateType = {
324+
target: [458305, 6785369, 0],
325+
zoom: 0,
326+
rotationX: 0,
327+
rotationOrbit: 40,
328+
};
329+
330+
const data = getSyntheticWells(10);
331+
332+
const wellLayer = new WellsLayer({
333+
...WELL_LAYER_PROPS,
334+
data,
335+
});
336+
337+
const labelLayer = new WellLabelLayer({
338+
...DEFAULT_LABEL_PROPS,
339+
data: data.features,
340+
background: true,
341+
getSize: 100,
342+
});
343+
344+
const propsWithLayers = {
345+
id: "default",
346+
cameraPosition: camera,
347+
layers: [...AXES_LAYERS, wellLayer, labelLayer],
348+
views: {
349+
layout: [1, 1],
350+
viewports: [
351+
{
352+
id: "view_1",
353+
show3D: false,
354+
layerIds: [
355+
"well-layer",
356+
"axes-layer-3d",
357+
"well-labels",
358+
],
359+
},
360+
],
361+
} as ViewsType,
362+
};
363+
364+
return <SubsurfaceViewer {...propsWithLayers} />;
365+
},
366+
play: async () => {
367+
const delay = 500;
368+
const canvas = document.querySelector("canvas");
369+
370+
if (canvas) {
371+
await userEvent.click(canvas, { delay });
372+
}
373+
374+
if (!canvas) {
375+
return;
376+
}
377+
378+
const leftViewCenterPosition = {
379+
x: canvas.clientLeft + canvas.clientWidth / 2,
380+
y: canvas.clientTop + canvas.clientHeight / 2,
381+
};
382+
383+
await userEvent.hover(canvas, { delay });
384+
385+
await fireEvent.mouseMove(canvas, { clientX: 0, clientY: 0, delay });
386+
await fireEvent.mouseMove(canvas, {
387+
clientX: leftViewCenterPosition.x,
388+
clientY: leftViewCenterPosition.y,
389+
delay,
390+
});
391+
},
392+
};
393+
320394
export const LabelPosition: StoryObj<
321395
WellCount & WellLabelLayerProps & TrajectorySimulationProps
322396
> = {

0 commit comments

Comments
 (0)