jupyter-widgets / ipyleaflet

A Jupyter - Leaflet.js bridge
https://ipyleaflet.readthedocs.io
MIT License
1.48k stars 363 forks source link

DrawControl edited event: which shape was edited? #849

Open sradomski opened 3 years ago

sradomski commented 3 years ago

Hey there,

as far as I can see the DrawControl will only store the last_action and the last_drawn geometry in the Python representation on the server side, whereas last_draw is also set prior to sending the delete action. This allows to keep track about the created and delete geometries.

However, I can not figure out how to know, which geometry was edited, when receiving the respective event. I do know the new geometry after the changes from last_draw, but I do not know the original geometry that was edited, which makes it impossible to know the shape of geometries currently on the map.

Am I missing something or is this functionality not implemented? Stefan

giswqs commented 3 years ago

As far as I know, ipyleaflet does not support this yet. See a relevant issue https://github.com/jupyter-widgets/ipyleaflet/issues/672

sradomski commented 3 years ago

First of all, thank you for your answer!

Yes, that issue is related and if it were solved, getting the edited and the original shape would not be necessary to keep track as you could just list all shapes.

So there is currently no way of knowing the set of shapes that were established with the DrawControl widget when shape editing is enabled? Because one is supposed to keep track of shapes via the on_draw handler but the edited event only carries information about the new shape, not the original one that was changed, making it impossible to keep track.

Is there some way to "hack" it? I tried to change the various objects in self when on_draw is called (e.g. last_draw) but changes would not be persisted, nor was it possible to introduce any kind of dynamic shape identifiers in the GeoJSON properties via draw_handler.polygon['shapeOptions'].

giswqs commented 2 years ago

I was able to hack it to keep track of the edited geometries. You can inspect the leafmap source code to see how I implemented it. All geometries are stored in draw_control.data as a list of features. Whenever a feature is edited, the draw_control.data is updated. The challenging part is that draw_control.data is not updated within the on_draw handler. It is only updated once the program gets out of the on_draw handler. So you will need something else outside the on_draw handler to figure out the edited geometries.

Some relevant source in leafmap that handles this:

Notebook: https://leafmap.org/notebooks/46_edit_vector/

Demo:

https://user-images.githubusercontent.com/5016453/151686842-2b29440c-42f3-45ef-b226-37d18c87dfb9.mp4

0x000eHx commented 2 years ago

Did someone find an ipyleaflet/ipywidget event which gets called after on_draw, meaning the the DrawControl.data property is updated by then? It's weird to access DrawControl.data within another methode for finally accepting all drawn geometries, if keeping track of all geometries/markers could get updated with every change (on its own). But on_draw sadly doesn't do the trick...