-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
boiler template for lasso layer implementation (#1300)
* 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
1 parent
ab49598
commit 78bf0b0
Showing
7 changed files
with
259 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
react/src/lib/components/DeckGLMap/layers/LassoLayer/lassoLayer.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
115
react/src/lib/components/DeckGLMap/layers/LassoLayer/lassoLayer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters