@webviz/subsurface-viewer
Version:
3D visualization component for subsurface reservoir data
189 lines • 8.35 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import _ from "lodash";
import { distance } from "mathjs";
function hasPropertiesArray(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
obj) {
return obj && Array.isArray(obj.properties);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function hasSingleProperty(obj) {
return (obj && "propertyValue" in obj && typeof obj.propertyValue === "number");
}
function getUniqueInfoPickId(pick) {
var _a;
return `${pick.index}::${(_a = pick.layer) === null || _a === void 0 ? void 0 : _a.id}`;
}
export class MultiViewPickingInfoAssembler {
constructor(deckGL, options = {
multiPicking: false,
pickDepth: 1,
}) {
this._deckGl = null;
this._subscribers = new Set();
this._deckGl = deckGL;
this._options = options;
}
setDeckGL(deckGL) {
this._deckGl = deckGL;
}
subscribe(callback) {
this._subscribers.add(callback);
return () => {
this._subscribers.delete(callback);
};
}
publish(info, activeViewportId) {
for (const subscriber of this._subscribers) {
subscriber(info, activeViewportId);
}
}
getMultiViewPickingInfo(hoverEvent) {
var _a, _b, _c;
if (!((_a = this._deckGl) === null || _a === void 0 ? void 0 : _a.deck)) {
return;
}
const viewports = (_b = this._deckGl.deck) === null || _b === void 0 ? void 0 : _b.getViewports();
if (!viewports) {
return;
}
if (hoverEvent.infos.length === 0) {
return;
}
const activeViewportId = (_c = hoverEvent.infos[0].viewport) === null || _c === void 0 ? void 0 : _c.id;
if (!activeViewportId) {
return;
}
const eventScreenCoordinate = [
hoverEvent.infos[0].x,
hoverEvent.infos[0].y,
];
this.assembleMultiViewPickingInfo(eventScreenCoordinate, activeViewportId, viewports).then((info) => {
this.publish(info, activeViewportId);
});
}
pickAtCoordinate(x, y) {
var _a;
const deck = (_a = this._deckGl) === null || _a === void 0 ? void 0 : _a.deck;
if (!deck)
return [];
if (this._options.multiPicking) {
// ! For some reason, multi-pick pads the array up to pick-depth length, repeating the last element
const multPickResult = deck.pickMultipleObjects({
depth: this._options.pickDepth,
unproject3D: true,
x,
y,
});
// Ensure the top-most element is processed first by sorting based on distance to camera
return _.sortBy(multPickResult, (pick) => {
var _a;
if (!((_a = pick.viewport) === null || _a === void 0 ? void 0 : _a.cameraPosition))
return -1;
if (!pick.coordinate)
return -1;
return distance(pick.coordinate, pick.viewport.cameraPosition);
});
}
else {
const obj = deck.pickObject({
unproject3D: true,
x,
y,
});
return obj ? [obj] : [];
}
}
assembleMultiViewPickingInfo(eventScreenCoordinate, activeViewportId, viewports) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
var _a;
if (!((_a = this._deckGl) === null || _a === void 0 ? void 0 : _a.deck)) {
reject("DeckGL not initialized");
return;
}
const activeViewport = viewports.find((el) => el.id === activeViewportId);
if (!activeViewport) {
reject("Active viewport not found");
return;
}
const activeViewportRelativeScreenCoordinates = [
eventScreenCoordinate[0] - activeViewport.x,
eventScreenCoordinate[1] - activeViewport.y,
];
const worldCoordinate = activeViewport.unproject(activeViewportRelativeScreenCoordinates);
const collectedPickingInfo = {};
for (const viewport of viewports) {
const [relativeScreenX, relativeScreenY] = viewport.project(worldCoordinate);
const pickingInfo = this.pickAtCoordinate(relativeScreenX + viewport.x, relativeScreenY + viewport.y);
if (pickingInfo) {
const layerInfoDict = {};
const processedPickIds = [];
for (const info of pickingInfo) {
const uniquePickId = getUniqueInfoPickId(info);
const hasMultipleProperties = hasPropertiesArray(info);
const hasOneProperty = hasSingleProperty(info);
// General guard clauses
if (!info.layer)
continue;
if (processedPickIds.includes(uniquePickId))
continue;
if (!hasMultipleProperties && !hasOneProperty)
continue;
processedPickIds.push(uniquePickId);
const layerId = info.layer.id;
const layerProps = info.layer
.props;
const layerName = layerProps.name;
if (!layerInfoDict[layerId]) {
layerInfoDict[layerId] = {
layerId,
layerName,
properties: [],
};
}
const layerPickingInfo = layerInfoDict[layerId];
if (hasOneProperty) {
layerPickingInfo.properties.push({
name: "Value",
value: info.propertyValue,
color: undefined,
});
}
else if (hasMultipleProperties) {
const properties = info.properties;
for (const property of properties) {
layerPickingInfo.properties.push({
name: property.name,
value: property.value,
color: property.color,
});
}
}
}
collectedPickingInfo[viewport.id] = {
coordinates: worldCoordinate,
layerPickingInfo: Object.values(layerInfoDict),
};
}
else {
collectedPickingInfo[viewport.id] = {
coordinates: worldCoordinate,
layerPickingInfo: [],
};
}
}
resolve(collectedPickingInfo);
});
});
}
}
//# sourceMappingURL=MultiViewPickingInfoAssembler.js.map