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

use ipyleaflet to edit vector through leafmap and observate "ghost" polygon #1173

Open
suredream opened this issue Jan 20, 2024 · 0 comments

Comments

@suredream
Copy link

I use leafmap but this issue issem root from other package, any suggestions are appreciated!

Description

  • A widget for the user to select polygon from a list to edit,
  • however, after adding one polygon, the next one doesn't appear but the 3rd go back.
  • seems one polygon has been "eaten".

How to replicate

$ pip install solara leafmap
$ solara run example.py

import solara
import solara as sl
from solara import Reactive, reactive
import leafmap
import os, tempfile, sys
from io import BytesIO
from typing import Union
import random, numpy as np
from ipywidgets import widgets

import geojson, json
from shapely.geometry import shape
import shapely.wkt
import pandas as pd
import time

BUTTON_KWARGS = dict(color="primary", text=True, outlined=True)

class State:
    zoom = reactive(20)
    center = reactive((None, None))
    enroll_wkt = reactive(None)

def wkt_to_featurecollection(wkt):
    geom = shapely.wkt.loads(wkt)
    return {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {},
                "geometry": geom.__geo_interface__,
            }
        ],
    }

aoi = 'POLYGON ((-91.16138525535435 37.81442211215915, -91.16138525535435 37.73515728531591, -90.85526326612401 37.73515728531591, -90.85526326612401 37.81442211215915, -91.16138525535435 37.81442211215915))'
wkt_list = ['POLYGON ((-91.15796462083297 37.806056428087615, -91.15796462083297 37.79771581956473, -90.86679686670833 37.79771581956473, -90.86679686670833 37.806056428087615, -91.15796462083297 37.806056428087615))', 
        'POLYGON ((-91.11222224140039 37.792622288824845, -91.11222224140039 37.76260439211525, -91.02064573377882 37.76260439211525, -91.02064573377882 37.792622288824845, -91.11222224140039 37.792622288824845))',
        'POLYGON ((-91.00305251600666 37.79041596911006, -91.0496745431024 37.79041596911006, -91.0496745431024 37.74730356543847, -91.00305251600666 37.74730356543847, -91.00305251600666 37.79041596911006)))']

def widget_droplist(options, desc, width = "270px", padding = "0px 0px 0px 5px", **kwargs):
    return widgets.Dropdown(
        options=[""] + options,
        description=desc,
        style={"description_width": "initial"},
        layout=widgets.Layout(width=width, padding=padding),
        **kwargs)

def add_widgets(m, padding = "0px 0px 0px 5px"):
    style = {"description_width": "initial"}

    geom_sel = widget_droplist(['1','2','3'], "geometry:")
    export_button = widgets.Button(description="Click 'Save' before Export", layout=widgets.Layout(width="200px"))
    
    reset_button = widgets.Button(
        description="clear", layout=widgets.Layout(width="50px"), button_style="info"
    )

    func_box = widgets.HBox([export_button, reset_button])
    output = widgets.Output()


    # zoom to the footprint
    m.add_geojson(
        wkt_to_featurecollection(aoi),
        layer_name="Footprint",
        zoom_to_layer=True,
        # hover_style={'opacity':0.9},
        style_callback=lambda feat: {"color": "red","opacity":0.9, 'hover_style':{'opacity':0.9}},
    )

    def select_boundary(change):
        m.remove_layer(m.find_layer("Footprint"))
        m.draw_control.clear()
        m.draw_features = []
        # m.user_rois = None
        # m.user_roi = None
        # time.sleep(0.1) 

        if change.new == "1":
            feature_collection = wkt_to_featurecollection(wkt_list[0])
            m.edit_vector(feature_collection)#, layer_name="Footprint")
        elif change.new == "2":
            feature_collection = wkt_to_featurecollection(wkt_list[1])
            m.edit_vector(feature_collection)#, layer_name="Footprint2")
        elif change.new == "3":
            feature_collection = wkt_to_featurecollection(wkt_list[2])
            m.edit_vector(feature_collection)#, layer_name="Footprint2")
        else: # "empty"
            # m.draw_control.clear()
            pass
        # output.append_stdout(State.series_df.value.iloc[0]['mask'])
        output.append_stdout(change.new)
    geom_sel.observe(select_boundary, names="value")

    def export_wkt(e):
        # -1: latest saved edits
        g1 = shape(m.draw_features[-1]['geometry'])
        output.outputs = ()
        output.append_stdout(g1.wkt)

    export_button.on_click(export_wkt)

    def reset_output(e):
        output.outputs = ()
    reset_button.on_click(reset_output)

    box = widgets.VBox(
        [
            geom_sel,
            func_box,
            output,
        ]
    )
    m.add_widget(box, position="topright", add_header=False)

class Map(leafmap.Map):
    def __init__(self, **kwargs):
        kwargs["toolbar_control"] = False
        super().__init__(**kwargs)
        basemap = {
            "url": "https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
            "attribution": "Google",
            "name": "Google Satellite",
        }
        self.add_tile_layer(**basemap, shown=True)
        add_widgets(self)

@sl.component
def Page() -> None:
    solara.Markdown("""- A widget for the user to select polygon from a list to edit, \n- however, after adding one polygon, the next one doesn't appear but the 3rd go back.\n- seems leafmap "eats" one polygon""")
    Map.element(  # type: ignore
        zoom=State.zoom.value,
        scroll_wheel_zoom=True,
        toolbar_ctrl=False,
        data_ctrl=False,
        height="780px",
    )
if __name__ == "__main__":
    Page()

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

No branches or pull requests

1 participant