Skip to content

Commit

Permalink
boiler template for lasso layer implementation (#1300)
Browse files Browse the repository at this point in the history
* boiler template for lasso layer implementation

* implement lasso layer

* resolve issue

* resolve comments

* fix

* fix

* update

* fix comments

* fix comments

* fix comments

* fix comments

* fix comments

Co-authored-by: shengwei zhang <[email protected]>
Co-authored-by: Håvard Bjerke <[email protected]>
  • Loading branch information
3 people authored Nov 30, 2022
1 parent ab49598 commit 78bf0b0
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 2 deletions.
2 changes: 1 addition & 1 deletion react/src/lib/components/DeckGLMap/components/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ const Map: React.FC<MapProps> = ({
else enumerations.push({ editedData: {} });

setDeckGLLayers(jsonToObject(layers, enumerations) as LayersList);
}, [st_layers, resources, editedData]);
}, [st_layers, resources, editedData, layers]);

useEffect(() => {
const layers = deckRef.current?.deck?.props.layers;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { FormControlLabel, makeStyles, Switch } from "@material-ui/core";
import { ComponentMeta, ComponentStory } from "@storybook/react";
import React from "react";
import DeckGLMap from "../../DeckGLMap";

export default {
component: DeckGLMap,
title: "DeckGLMap / Lasso Layer",
} as ComponentMeta<typeof DeckGLMap>;

const useStyles = makeStyles({
main: {
height: 500,
border: "1px solid black",
position: "relative",
},
legend: {
width: 100,
position: "absolute",
top: "0",
right: "0",
},
});

export const lassoSelection: ComponentStory<typeof DeckGLMap> = (args) => {
const [editedData, setEditedData] = React.useState(args.editedData);
const [argsState, setArgsState] =
React.useState<Record<string, unknown>>(enableLassoArgs);
const [state, setState] = React.useState<boolean>(true);

const handleChange = React.useCallback(() => {
const lassoLayer = enableLassoArgs.layers.filter(
(item) => item["@@type"] === "LassoLayer"
);
if (lassoLayer[0].visible !== undefined) {
lassoLayer[0].visible = !lassoLayer[0].visible;
}
if (lassoLayer[0].visible) {
setArgsState(enableLassoArgs);
} else {
setArgsState(disableLassoArgs);
}
setState(!state);
}, [state]);

React.useEffect(() => {
setEditedData(args.editedData);
}, [args.editedData]);

return (
<>
<div className={useStyles().main}>
<DeckGLMap
id={"DeckGL-Map"}
{...argsState}
editedData={editedData}
setProps={(updatedProps) => {
setEditedData(updatedProps);
}}
legend={{ visible: false }}
/>
</div>
<div style={{ textAlign: "center" }}>
<FormControlLabel
control={
<Switch
checked={state}
onChange={handleChange}
color="primary"
name="checkedB"
inputProps={{ "aria-label": "primary checkbox" }}
/>
}
label="Display Lasso Selection"
/>
</div>
</>
);
};

const disableLassoArgs = {
id: "DeckGL-Map",
resources: {
wellsData: "./volve_wells.json",
},
bounds: [432205, 6475078, 437720, 6481113],
layers: [
{
"@@type": "WellsLayer",
data: "@@#resources.wellsData",
},
{
"@@type": "LassoLayer",
visible: false,
data: "@@#resources.wellsData",
},
],
editedData: {},
views: {
layout: [1, 1],
showLabel: false,
viewports: [
{
id: "view_1",
show3D: false,
layerIds: [],
},
],
},
};

const enableLassoArgs = {
...disableLassoArgs,
layers: [
{
"@@type": "WellsLayer",
data: "@@#resources.wellsData",
},
{
"@@type": "LassoLayer",
visible: true,
data: "@@#resources.wellsData",
},
],
};
115 changes: 115 additions & 0 deletions react/src/lib/components/DeckGLMap/layers/LassoLayer/lassoLayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { CompositeLayer, PickingInfo, LayersList } from "@deck.gl/core/typed";
import { FeatureCollection } from "@nebula.gl/edit-modes";
import { layersDefaultProps } from "../layersDefaultProps";
import { SelectionLayer } from "@nebula.gl/layers";
import { GeoJsonLayer } from "@deck.gl/layers/typed";
import { ExtendedLayerProps } from "../utils/layerTools";
import { getSize } from "../wells/wellsLayer";
import { Color } from "@deck.gl/core/typed";
import { Feature } from "geojson";
export interface LassoLayerProps<D> extends ExtendedLayerProps<D> {
mode: string; // One of modes in MODE_MAP
selectedFeatureIndexes: number[];
pickingInfos: PickingInfo[];
refine: boolean;
pointRadiusScale: number;
lineWidthScale: number;
lineStyle: LineStyleAccessor;
wellHeadStyle: WellHeadStyleAccessor;
}

type StyleAccessorFunction = (
object: Feature,
objectInfo?: Record<string, unknown>
) => StyleData;

type NumberPair = [number, number];
type DashAccessor = boolean | NumberPair | StyleAccessorFunction | undefined;
type ColorAccessor = Color | StyleAccessorFunction | undefined;
type SizeAccessor = number | StyleAccessorFunction | undefined;
type StyleData = NumberPair | Color | number;

type LineStyleAccessor = {
color?: ColorAccessor;
dash?: DashAccessor;
width?: SizeAccessor;
};

type WellHeadStyleAccessor = {
color?: ColorAccessor;
size?: SizeAccessor;
};

// Composite layer that contains an Selection Lyaer from nebula.gl
// See https://nebula.gl/docs/api-reference/layers/selection-layer
export default class LassoLayer extends CompositeLayer<
LassoLayerProps<FeatureCollection>
> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setMultiSelection(pickingInfos: any[]): void {
if (this.internalState) {
const data = pickingInfos
.map((item) => item.object)
.filter((item) => item.type === "Feature");
this.setState({
pickingInfos: pickingInfos,
data: data,
});
}
}

renderLayers(): LayersList {
if (this.props.visible == false) {
return [];
}

const LINE = "line";
const POINT = "point";
const isOrthographic =
this.context.viewport.constructor.name === "OrthographicViewport";
const positionFormat = isOrthographic ? "XY" : "XYZ";

const geoJsonLayer = new GeoJsonLayer({
id: "geoJson",
data: this.state["data"],
pickable: false,
stroked: false,
positionFormat,
pointRadiusUnits: "pixels",
lineWidthUnits: "pixels",
pointRadiusScale: this.props.pointRadiusScale
? this.props.pointRadiusScale
: 1,
lineWidthScale: this.props.lineWidthScale
? this.props.lineWidthScale
: 1,
getLineWidth: getSize(LINE, this.props.lineStyle?.width, -1),
getPointRadius: getSize(POINT, this.props.wellHeadStyle?.size, 2),
getFillColor: [255, 140, 0],
getLineColor: [255, 140, 0],
});
const selectionLayer = new SelectionLayer(
// @ts-expect-error: EditableGeoJsonLayer from nebula.gl has no typing
this.getSubLayerProps({
id: "selection",
selectionType: "rectangle",
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onSelect: ({ pickingInfos }: any) => {
this.setMultiSelection(pickingInfos);
},
layerIds: ["wells-layer"],
getTentativeFillColor: () => [255, 0, 255, 100],
getTentativeLineColor: () => [0, 0, 255, 255],
getTentativeLineDashArray: () => [0, 0],
lineWidthMinPixels: 3,
})
);
// @ts-expect-error: EditableGeoJsonLayer from nebula.gl has no typing
return [selectionLayer, geoJsonLayer];
}
}

LassoLayer.layerName = "LassoLayer";
LassoLayer.defaultProps = layersDefaultProps[
"LassoLayer"
] as LassoLayerProps<FeatureCollection>;
2 changes: 2 additions & 0 deletions react/src/lib/components/DeckGLMap/layers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export { default as SelectableGeoJsonLayer } from "./selectable_geojson/selectab
export { default as NorthArrow3DLayer } from "./northarrow/northArrow3DLayer";
export { default as UnfoldedGeoJsonLayer } from "./intersection/unfoldedGeoJsonLayer";
export { default as Grid3DLayer } from "./grid3d/grid3dLayer";
export { default as LassoLayer } from "./LassoLayer/lassoLayer";

export { AxesLayerProps } from "./axes/axesLayer";
export { Axes2DLayerProps } from "./axes2d/axes2DLayer";
Expand All @@ -27,3 +28,4 @@ export { PieChartLayerProps } from "./piechart/pieChartLayer";
export { Map3DLayerProps } from "./terrain/map3DLayer";
export { WellsLayerProps } from "./wells/wellsLayer";
export { Grid3DLayerProps } from "./grid3d/grid3dLayer";
export { LassoLayerProps } from "./LassoLayer/lassoLayer";
14 changes: 14 additions & 0 deletions react/src/lib/components/DeckGLMap/layers/layersDefaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@ export const layersDefaultProps: Record<string, unknown> = {
features: [],
},
},
LassoLayer: {
"@@type": "LassoLayer",
name: "Lasso",
id: "lasso-layer",
pickable: true,
visible: false,

// Props used to get/set data in the drawing layer.
selectedFeatureIndexes: [] as number[],
data: {
type: "FeatureCollection",
features: [],
},
},
Grid3DLayer: {
"@@type": "Grid3DLayer",
name: "Grid 3D",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export type NewLayersList = LayersList & {

type prop = {
data: wellData;
visible: boolean;
};

type wellData = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function getColor(accessor: ColorAccessor) {
};
}

function getSize(
export function getSize(
type: string,
accessor: SizeAccessor,
offset = 0
Expand Down

0 comments on commit 78bf0b0

Please sign in to comment.