lonboard icon indicating copy to clipboard operation
lonboard copied to clipboard

Select data by bounding box

Open kylebarron opened this issue 2 years ago • 3 comments

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 avatar Oct 25 '23 16:10 kylebarron

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.

kylebarron avatar Jan 11 '24 21:01 kylebarron

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 <Deck>) 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?: https://github.com/developmentseed/lonboard/blob/96611f50764a6d09f1326023d28a684a89e15fe1/src/index.tsx#L68-L73

hanbyul-here avatar Jan 29 '24 23:01 hanbyul-here

@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: https://github.com/developmentseed/lonboard/pull/417

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

https://github.com/developmentseed/lonboard/assets/72280/c7e85f75-e9eb-4bdc-be74-21cc40059b91

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.

batpad avatar Mar 23 '24 03:03 batpad