Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select data by bounding box #148

Open
Tracked by #313
kylebarron opened this issue Oct 25, 2023 · 3 comments
Open
Tracked by #313

Select data by bounding box #148

kylebarron opened this issue Oct 25, 2023 · 3 comments
Assignees
Labels
javascript Relates to JS bindings

Comments

@kylebarron
Copy link
Member

kylebarron commented Oct 25, 2023

A user draws a bounding box to select an array of feature indices that fall within the bounding box. The features are highlighted on the map and selected in the geodataframe.

Useful for exploratory data analysis.

Kyle to add details.

@kylebarron kylebarron added the javascript Relates to JS bindings label Oct 25, 2023
@kylebarron
Copy link
Member Author

The idea here is to let the user draw a box on the screen and select items from their visualization. The items may either be highlighted on the JS side in the map or, also, the row indexes can be sent back from JS to Python so that the user can call gdf.iloc[layer.selected_indexes].

The predominant question is: how do you draw a bounding box in deck.gl?

Option 1: "Manual" approach

Deck has a pickObjects method on the map class to find the objects that intersect with the box. I believe the input box should be in screen space, as it's described to be pixels. This means that what we need to do is enable a selection tool and access the pixel range of the map canvas from that selection. I don't know how to do this myself, and maybe nebula.gl would help with this, or maybe it's better to read up on how e.g. leaflet-draw works.

Option 2: Nebula.gl

nebula.gl is a library that works with deck.gl to enable editing of geospatial data. In theory, this should solve the problem for us using its SelectionLayer, but the library seems to be no longer maintained.


Once we have the data from pickObjects, we can take those row indexes and update them on the widget state to send the data back to Python.

@hanbyul-here
Copy link

Some related findings discussions we had today.

For 'Drawing-bbox' UI part

Existing options - Nebula.gl

As mentioned, Nebula.gl seems to be not maintained anymore.

Use react-map-gl-draw

I was hoping we could use react-map-gl-draw plugin with ReactMapGL's useControl hook. However, the current way of using Mapbox (Inside of as a child of ) seems to confuse the plugin. I could not draw anything with the control added on. I can't pinpoint why, maybe DeckGL layer is interfering the interaction between mapbox-gl-draw and mapbox gl? or mapbox-gl-draw cannot reach Mapbox?

We discussed using the DeckGL layer as a MapboxOverlay, which will give a better integration with other Mapbox controls. Considering this will change how all the layers will work internally, it seems not worth the risk.

For passing the data to layer part

pickObjects method belongs to DeckGL instance. (So the layer doesn't have access to these objects.) To expose the selected indices in a coherent way (attaching selected objects to the layer level), We would need to associate selected indices to each layer. Since selected objects have the layer that they belong to, we can use that info and attach it to the layers? Maybe using Submodelstates which have the layers?:

lonboard/src/index.tsx

Lines 68 to 73 in 96611f5

let [subModelState, setSubModelState] = useState<
Record<string, BaseLayerModel>
>({});
let model = useModel();
let [childLayerIds] = useModelState<string[]>("layers");

@batpad
Copy link
Member

batpad commented Mar 23, 2024

@kylebarron and I started hacking on this a bit when we met last week, many thanks to @isaacbrodsky for the initial PR that was a great starting point.

This is the PR where I've been working: #417

Here's a screen recording of what the interaction looks like currently:

BboxScreengrab.mp4

The bit to get working is passing the selected indexes back to Python, but that should be reasonably straightforward. And the code needs a bunch of cleanups.

It would also be nice to get some design help :)

Seeing how complex this could get in the future (do we support drawing arbitrary polygons, etc) - @kylebarron, am wondering how this code should be structured -- I'll leave further comments on the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
javascript Relates to JS bindings
Projects
None yet
Development

No branches or pull requests

3 participants