ipyleaflet icon indicating copy to clipboard operation
ipyleaflet copied to clipboard

Drawing polygons with different colors

Open odhondt opened this issue 1 year ago • 0 comments

I am trying to draw polygons where the polygon color is determined by ipywidget.widgets.RadioButtons

This is what I got so far (inspired by https://github.com/jupyter-widgets/ipyleaflet/issues/425)

import ipywidgets as widgets
from ipyleaflet import Map, GeomanDrawControl, basemaps

# Radio buttons for class selection
class_selector = widgets.RadioButtons(
    options=["Water", "Crop", "Urban"], description="Class:", disabled=False
)

# Function to return different colors based on class
def get_class_color(polygon_class):
    if polygon_class == "Water":
        return "#0000FF"  # Blue
    elif polygon_class == "Crop":
        return "#008800"  # Green
    elif polygon_class == "Urban":
        return "#FF0000"  # Red
    return "#000000"  # Default black

m = Map(center=(51.0, 0.0), zoom=12, basemap=basemaps.OpenStreetMap.Mapnik)

class LabelTool:
    def __init__(self, m):
        self.m = m
        self.current_polygon = None

        # Initial color is blue for "Water"
        initial_color = get_class_color(class_selector.value)

        # Geoman Draw control
        self.draw_control = GeomanDrawControl(
            circle={},
            polyline={},
            polygon={"shapeOptions": {"color": initial_color}},  # Initial color
        )
        self.m.add_control(self.draw_control)

        # Set up event listeners
        self.draw_control.on_draw(self.handle_draw)
        class_selector.observe(self.update_draw_color, 'value')

    # Draw event handler
    def handle_draw(self, target, action, geo_json):
        if action == 'create':
            self.current_polygon = geo_json
            polygon_class = class_selector.value
            color = get_class_color(polygon_class)

            # Update drawn polygon's color by recreating the control with the new color
            self.update_draw_color({'new': polygon_class})

    # Update polygon color based on the selected class
    def update_draw_color(self, change):
        polygon_class = class_selector.value
        color = get_class_color(polygon_class)

        # Remove and recreate draw control with updated color
        self.m.remove_control(self.draw_control)
        self.draw_control = GeomanDrawControl(
            circle={},
            polyline={},
            polygon={"shapeOptions": {"color": color}},  # Updated color
        )
        self.m.add_control(self.draw_control)

        # Reattach the draw event handler
        self.draw_control.on_draw(self.handle_draw)

# Display map and widgets
l = LabelTool(m)


widgets.VBox([m, class_selector])

The problem is that when the radio value is changed, the next create action draws several superimposed identical polygons (see the following screenshot, I slighly shifted the polygons for visualization)

Screenshot 2024-10-09 at 09 27 30

Any idea how to fix that?

odhondt avatar Oct 09 '24 07:10 odhondt