コード例 #1
0
def mk_map_region_selector(height='600px', **kwargs):
    from ipyleaflet import Map, WidgetControl, FullScreenControl, DrawControl
    from ipywidgets.widgets import Layout, Button, HTML
    from types import SimpleNamespace

    state = SimpleNamespace(selection=None, bounds=None, done=False)

    btn_done = Button(description='done', layout=Layout(width='5em'))
    btn_done.style.button_color = 'green'
    btn_done.disabled = True

    html_info = HTML(
        layout=Layout(flex='1 0 20em', width='20em', height='3em'))

    def update_info(txt):
        html_info.value = '<pre style="color:grey">' + txt + '</pre>'

    m = Map(**kwargs) if len(kwargs) else Map(zoom=2)
    m.scroll_wheel_zoom = True
    m.layout.height = height

    widgets = [
        WidgetControl(widget=btn_done, position='topright'),
        WidgetControl(widget=html_info, position='bottomleft'),
    ]
    for w in widgets:
        m.add_control(w)

    draw = DrawControl()

    draw.circle = {}
    draw.polyline = {}
    draw.circlemarker = {}

    shape_opts = {
        "fillColor": "#fca45d",
        "color": "#000000",
        "fillOpacity": 0.1
    }
    draw.rectangle = {"shapeOptions": shape_opts}
    poly_opts = {"shapeOptions": dict(**shape_opts)}
    poly_opts["shapeOptions"]["original"] = dict(**shape_opts)
    poly_opts["shapeOptions"]["editing"] = dict(**shape_opts)

    draw.polygon = poly_opts
    draw.edit = True
    draw.remove = True
    m.add_control(draw)
    m.add_control(FullScreenControl())

    def on_done(btn):
        state.done = True
        btn_done.disabled = True
        m.remove_control(draw)
        for w in widgets:
            m.remove_control(w)

    def bounds_handler(event):
        (lat1, lon1), (lat2, lon2) = event['new']
        txt = 'lat: [{:.{n}f}, {:.{n}f}]\nlon: [{:.{n}f}, {:.{n}f}]'.format(
            lat1, lat2, lon1, lon2, n=4)
        update_info(txt)
        state.bounds = dict(lat=(lat1, lat2), lon=(lon1, lon2))

    def on_draw(event):
        v = event['new']
        action = event['name']
        if action == 'last_draw':
            state.selection = v['geometry']
        elif action == 'last_action' and v == 'deleted':
            state.selection = None

        btn_done.disabled = state.selection is None

    draw.observe(on_draw)
    m.observe(bounds_handler, ('bounds', ))
    btn_done.on_click(on_done)

    return m, state
コード例 #2
0
ファイル: show.py プロジェクト: ashiquebiniqbal/stackstac
 def __init__(self, map: ipyleaflet.Map) -> None:
     self.layers: Dict[ipyleaflet.TileLayer, TileManager] = {}
     self.map = map
     map.observe(self, names=["window_url", "bounds", "layers"])
コード例 #3
0
    def __init__(
        self,
        a_map: Map,
        description: str = "H3",
        position: str = "topright",
    ):
        """Instantiate a tile grid tool and place it on a map.
        """
        self._max_zoom_delta = -1

        self.tile_id = ""
        self.level = int(a_map.zoom)
        style = {"color": "#888888", "weight": 1, "fillOpacity": 0}
        hover_style = {"weight": 3, "fillOpacity": 0.1}
        self.gj = GeoJSON(data=geojson.Feature(),
                          name=description,
                          style=style,
                          hover_style=hover_style)

        min_, max_ = 0, int(a_map.zoom) + self._max_zoom_delta
        self.slider = IntSlider(description=description,
                                min=min_,
                                max=max_,
                                value=self.level)
        self.ht = HTML(f"ID: {self.tile_id} Map zoom: {int(a_map.zoom)}")
        self.close_btn = Button(
            icon="times",
            button_style="info",
            tooltip="Close the widget",
            layout=Layout(width="32px"),
        )
        self.widget = HBox([self.slider, self.ht, self.close_btn])

        def hover(event, feature, **kwargs):
            if event == "mouseover":
                self.tile_id = feature["id"]
                self.ht.value = f"{self.tile_id} Map zoom: {int(a_map.zoom)}"

        def slider_moved(event):
            if event["type"] == "change" and event["name"] == "value":
                self.level = event["new"]

                # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer,
                # but not in the LayersControl!
                self.gj.name = f"H3"  # level {self.level}"

                self.tile_id = ""
                map_interacted({
                    "type": "change",
                    "name": "bounds",
                    "owner": a_map
                })

        self.slider.observe(slider_moved)

        def map_interacted(event):
            if event["type"] == "change" and event["name"] == "bounds":
                self.ht.value = f"{self.tile_id}, Map zoom: {int(a_map.zoom)}"
                self.slider.max = int(a_map.zoom) + self._max_zoom_delta
                m = event["owner"]

                b_poly = list(m.bounds_polygon)
                b_poly += [tuple(b_poly[0])]
                # m += Polyline(locations=b_poly)
                poly = geojson.Polygon(coordinates=[[(p[0], p[1])
                                                     for p in b_poly]])
                hexagons = list(h3.polyfill(dict(poly), self.slider.value))
                fc = geojson.FeatureCollection(features=[
                    geojson.Polygon(coordinates=h3.h3_set_to_multi_polygon(
                        [h], geo_json=True)[0],
                                    id=h) for h in hexagons
                ])
                self.gj.data = fc

                # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer,
                # but not in the LayersControl!
                self.gj.name = f"H3"  # level {self.level}"

                self.gj.on_hover(hover)

        def close_click(change):
            self.widget.children = []
            self.widget.close()

        self.close_btn.on_click(close_click)

        a_map += self.gj
        a_map.observe(map_interacted)
        map_interacted({"type": "change", "name": "bounds", "owner": a_map})

        self.widget_control = WidgetControl(widget=self.widget,
                                            position=position)
        a_map.add_control(self.widget_control)
コード例 #4
0
    def __init__(
        self,
        a_map: Map,
        description: str = "Mercator",
        position: str = "topright",
    ):
        """Instantiate a tile grid tool and place it on a map.
        """
        self._max_zoom_delta = 4

        self.tile_id = ""
        self.level = int(a_map.zoom)
        style = {"color": "#888888", "weight": 1, "fillOpacity": 0}
        hover_style = {"weight": 3, "fillOpacity": 0.1}
        self.gj = GeoJSON(data=geojson.Feature(),
                          name=description,
                          style=style,
                          hover_style=hover_style)

        min, max = 0, int(a_map.zoom) + self._max_zoom_delta
        self.slider = IntSlider(description=description,
                                min=min,
                                max=max,
                                value=self.level)
        self.ht = HTML(f"ID: {self.tile_id} Map zoom: {int(a_map.zoom)}")
        self.close_btn = Button(
            icon="times",
            button_style="info",
            tooltip="Close the widget",
            layout=Layout(width="32px"),
        )
        self.widget = HBox([self.slider, self.ht, self.close_btn])

        def hover(event, feature, **kwargs):
            if event == "mouseover":
                self.tile_id = feature["id"]
                self.ht.value = f"{self.tile_id} Map zoom: {int(a_map.zoom)}"

        def slider_moved(event):
            if event["type"] == "change" and event["name"] == "value":
                self.level = event["new"]

                # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer,
                # but not in the LayersControl!
                self.gj.name = f"Mercator"  # level {self.level}"

                self.tile_id = ""
                map_interacted({
                    "type": "change",
                    "name": "bounds",
                    "owner": a_map
                })

        self.slider.observe(slider_moved)

        def map_interacted(event):
            if event["type"] == "change" and event["name"] == "bounds":
                self.ht.value = f"{self.tile_id}, Map zoom: {int(a_map.zoom)}"
                self.slider.max = int(a_map.zoom) + self._max_zoom_delta

                m = event["owner"]
                ((south, west), (north, east)) = m.bounds

                b_poly = list(m.bounds_polygon)
                b_poly += [tuple(b_poly[0])]
                # m += Polyline(locations=b_poly)

                # Attention in the order of west, south, east, north!
                tiles = mercantile.tiles(west,
                                         south,
                                         east,
                                         north,
                                         zooms=self.level)

                features = [mercantile.feature(t) for t in tiles]
                self.gj.data = geojson.FeatureCollection(features=features)

                # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer,
                # but not in the LayersControl!
                self.gj.name = f"Mercator"  # level {self.level}"

                self.gj.on_hover(hover)

        def close_click(change):
            self.widget.children = []
            self.widget.close()

        self.close_btn.on_click(close_click)

        a_map += self.gj
        a_map.observe(map_interacted)
        map_interacted({"type": "change", "name": "bounds", "owner": a_map})

        self.widget_control = WidgetControl(widget=self.widget,
                                            position=position)
        a_map.add_control(self.widget_control)
コード例 #5
0
def mk_map_region_selector(map=None, height="600px", **kwargs):
    from ipyleaflet import Map, WidgetControl, FullScreenControl, DrawControl
    from ipywidgets.widgets import Layout, Button, HTML
    from types import SimpleNamespace

    state = SimpleNamespace(selection=None, bounds=None, done=False)

    btn_done = Button(description="done", layout=Layout(width="5em"))
    btn_done.style.button_color = "green"
    btn_done.disabled = True

    html_info = HTML(layout=Layout(flex="1 0 20em", width="20em", height="3em"))

    def update_info(txt):
        html_info.value = '<pre style="color:grey">' + txt + "</pre>"

    def render_bounds(bounds):
        (lat1, lon1), (lat2, lon2) = bounds
        txt = "lat: [{:.{n}f}, {:.{n}f}]\nlon: [{:.{n}f}, {:.{n}f}]".format(
            lat1, lat2, lon1, lon2, n=4
        )
        update_info(txt)

    if map is None:
        m = Map(**kwargs) if len(kwargs) else Map(zoom=2)
        m.scroll_wheel_zoom = True
        m.layout.height = height
    else:
        m = map
        render_bounds(m.bounds)

    widgets = [
        WidgetControl(widget=btn_done, position="topright"),
        WidgetControl(widget=html_info, position="bottomleft"),
    ]
    for w in widgets:
        m.add_control(w)

    draw = DrawControl()

    draw.circle = {}
    draw.polyline = {}
    draw.circlemarker = {}

    shape_opts = {"fillColor": "#fca45d", "color": "#000000", "fillOpacity": 0.1}
    draw.rectangle = {"shapeOptions": shape_opts, "metric": ["km", "m"]}
    poly_opts = {"shapeOptions": dict(**shape_opts)}
    poly_opts["shapeOptions"]["original"] = dict(**shape_opts)
    poly_opts["shapeOptions"]["editing"] = dict(**shape_opts)

    draw.polygon = poly_opts
    draw.edit = True
    draw.remove = True
    m.add_control(draw)
    m.add_control(FullScreenControl())

    def on_done(btn):
        state.done = True
        btn_done.disabled = True
        m.remove_control(draw)
        for w in widgets:
            m.remove_control(w)

    def bounds_handler(event):
        bounds = event["new"]
        render_bounds(bounds)
        (lat1, lon1), (lat2, lon2) = bounds
        state.bounds = dict(lat=(lat1, lat2), lon=(lon1, lon2))

    def on_draw(event):
        v = event["new"]
        action = event["name"]
        if action == "last_draw":
            state.selection = v["geometry"]
        elif action == "last_action" and v == "deleted":
            state.selection = None

        btn_done.disabled = state.selection is None

    draw.observe(on_draw)
    m.observe(bounds_handler, ("bounds",))
    btn_done.on_click(on_done)

    return m, state