Пример #1
0
class Grass2Leaflet(object):
    def __init__(self, grassimg):
        self.grassimg = grassimg
        self.draw_control = None
        self.zoom = 15
        self.center = self.centermap()
        self.m = Map(default_tiles=TileLayer(opacity=1.0),
                     center=self.center,
                     zoom=self.zoom)

    def centermap(self):
        centerlat = []
        centerlon = []
        for i in self.grassimg:
            centerlat.append(self.grassimg[i]['C'][0])
            centerlon.append(self.grassimg[i]['C'][1])
        center = (sum(centerlat) / float(len(centerlat)),
                  sum(centerlon) / float(len(centerlon)))
        return center

    def imgoverlays(self):
        self.leafletimg = OrderedDict()
        for i in self.grassimg:
            layer = ImageOverlay(url=self.grassimg[i]['raster'],
                                 bounds=(self.grassimg[i]['LL'],
                                         self.grassimg[i]['UR']))
            self.leafletimg[i] = layer

    def render(self, draw_control=None):
        self.imgoverlays()
        self.dc = None
        options = ['None']
        self.m.add_layer(self.leafletimg[list(self.grassimg.keys())[-1]])
        if len(self.grassimg) >= 2:
            self.maplist = widgets.Dropdown(
                options=options + list(self.grassimg.keys()),
                value=list(self.grassimg.keys())[-1],
                description='Select Layer:',
            )
            self.maplist.observe(self.on_value_change, names='value')
            display(self.maplist)
        if draw_control:
            self.dc = DrawControl()
            self.dc.on_draw(handle_draw)
            self.m.add_control(self.dc)
        display(self.m)
        return {'map': self.m, 'drawer': self.dc}

    def on_value_change(self, layername):
        self.m.clear_layers()
        self.m.add_layer(TileLayer(opacity=1.0))
        if self.maplist.value != 'None':
            self.m.add_layer(self.leafletimg[layername['new']])

    def main(self):
        self.imgoverlays()
        self.render()
Пример #2
0
def create_map(normalized_image: np.ndarray) -> Map:
    """
    Creates leaflet map with given image
    :param normalized_image: Image data normalized to 0-255 8-bit integer
    :return: Leaflet map
    """
    width = normalized_image.shape[0]
    height = normalized_image.shape[1]
    bounds = [(-width / 2, -height / 2), (width / 2, height / 2)]

    layer = ImageOverlay(url=serialize_to_url(normalized_image), bounds=bounds)
    leaflet = Map(center=[0, 0], zoom=1, interpolation='nearest')
    leaflet.clear_layers()
    leaflet.add_layer(layer)

    return leaflet
Пример #3
0
def clickablemap(center=[48.790153, 2.327395],
                 zoom=13,
                 layout=ipywidgets.Layout(width='100%', height='500px')):
    # look at: http://leaflet.github.io/Leaflet.draw/docs/examples/basic.html

    import json

    from ipyleaflet import (Map, Rectangle, Polygon, TileLayer, ImageOverlay,
                            DrawControl, GeoJSON)

    #%matplotlib inline
    #   %matplotlib notebook

    # google tileserver
    # https://stackoverflow.com/questions/9394190/leaflet-map-api-with-google-satellite-layer
    mosaicsTilesURL = 'https://mt1.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}'  # Hybrid: s,h; Satellite: s; Streets: m; Terrain: p;

    # Map Settings
    # Define colors
    colors = {'blue': "#009da5"}
    # Define initial map center lat/long
    #center = [48.790153, 2.327395]
    # Define initial map zoom level
    #zoom = 13
    # Create the map
    m = Map(center=center, zoom=zoom, scroll_wheel_zoom=True, layout=layout)

    # using custom basemap
    m.clear_layers()
    m.add_layer(TileLayer(url=mosaicsTilesURL))

    # Define the draw tool type options
    polygon = {'shapeOptions': {'color': colors['blue']}}
    rectangle = {'shapeOptions': {'color': colors['blue']}}

    ## Create the draw controls
    ## @see https://github.com/ellisonbg/ipyleaflet/blob/master/ipyleaflet/leaflet.py#L293
    #dc = DrawControl(
    #    polygon = polygon,
    #    rectangle = rectangle
    #)
    dc = DrawControl(
        polygon={'shapeOptions': {
            'color': '#0000FF'
        }},
        polyline={'shapeOptions': {
            'color': '#0000FF'
        }},
        circle={'shapeOptions': {
            'color': '#0000FF'
        }},
        rectangle={'shapeOptions': {
            'color': '#0000FF'
        }},
    )

    # Initialize an action counter variable
    m.actionCount = 0
    m.AOIs = []

    # Register the draw controls handler
    def handle_draw(self, action, geo_json):
        # Increment the action counter
        #global actionCount
        m.actionCount += 1
        # Remove the `style` property from the GeoJSON
        geo_json['properties'] = {}
        # Convert geo_json output to a string and prettify (indent & replace ' with ")
        geojsonStr = json.dumps(geo_json, indent=2).replace("'", '"')
        m.AOIs.append(json.loads(geojsonStr))

    # Attach the draw handler to the draw controls `on_draw` event
    dc.on_draw(handle_draw)
    m.add_control(dc)

    # add a custom function to create and add a Rectangle layer
    # (LESS USEFUL THAN add_geojson)
    def add_rect(*args, **kwargs):
        r = Rectangle(*args, **kwargs)
        return m.add_layer(r)

    m.add_rectangle = add_rect

    # add a custom function to create and add a Polygon layer
    def add_geojson(*args, **kwargs):
        # ugly workaround to call without data=aoi
        if 'data' not in kwargs:
            kwargs['data'] = args[0]
            args2 = [i for i in args[1:-1]]
        else:
            args2 = args

        r = GeoJSON(*args2, **kwargs)
        return m.add_layer(r)

    m.add_GeoJSON = add_geojson

    # Display
    return m
Пример #4
0
def overlaymap(aoiY,
               imagesurls,
               zoom=13,
               layout=ipywidgets.Layout(width='100%', height='500px')):

    import json
    import numpy as np

    from ipyleaflet import (
        Map,
        Rectangle,
        Polygon,
        TileLayer,
        ImageOverlay,
        DrawControl,
    )

    ## handle the case of imageurls not a list
    if type(imagesurls) != list:
        imagesurls = [imagesurls]

    number_of_images = len(imagesurls)

    ## handle both kinds of calls with aoi, or aoi['coordinates']
    if 'coordinates' in aoiY:
        aoiY = aoiY['coordinates'][0]

    # create the Map object
    # google tileserver
    # https://stackoverflow.com/questions/9394190/leaflet-map-api-with-google-satellite-layer
    mosaicsTilesURL = 'https://mt1.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}'  # Hybrid: s,h; Satellite: s; Streets: m; Terrain: p;
    m = Map(
        center=aoiY[0][::-1],
        zoom=zoom,
        scroll_wheel_zoom=True,
        layout=layout,
    )

    # using custom basemap
    m.clear_layers()
    m.add_layer(TileLayer(url=mosaicsTilesURL, opacity=1.00))

    #vlayer = VideoOverlay(videoUrl, videoBounds )
    #m.add_layer(vlayer)

    ### this shows an animated gif
    #m.add_layer(layer)

    # display map (this show)
    #display(m)

    ############## ADD INTERACTIVE LAYER
    from ipywidgets import interact, interactive, fixed, interact_manual
    import ipywidgets as widgets

    # meke sure that the images have unique names
    imagesurls = [
        '%s?%05d' % (i, np.random.randint(10000)) for i in imagesurls
    ]

    # draw bounding polygon
    y = [a[::-1] for a in aoiY]
    p = Polygon(locations=y, weight=2, fill_opacity=0.25)
    m.add_layer(p)

    # create image
    layer = ImageOverlay(url='%s' % (imagesurls[0]),
                         bounds=[
                             list(np.max(aoiY, axis=0)[::-1]),
                             list(np.min(aoiY, axis=0)[::-1])
                         ])

    m.add_layer(layer)

    # callback fro flipping images
    def showim(i):
        if (i < len(imagesurls)):
            #      -----       FLICKERS ----
            #             layer.url='%s'%(imagesurls[i])
            #             layer.visible = False
            #             layer.visible = True

            #    ALTERNATIVE:  add a new layer
            layer = ImageOverlay(url='%s' % (imagesurls[i]),
                                 bounds=[
                                     list(np.max(aoiY, axis=0)[::-1]),
                                     list(np.min(aoiY, axis=0)[::-1])
                                 ])
            m.add_layer(layer)
            # remove old ones
            if len(m.layers) > 30:  # image buffer
                for l in (m.layers[1:-1]):
                    m.remove_layer(l)

    # build the UI
    #interact(showim,i=len(imagesurls)-1)
    #interact(showim, i=widgets.IntSlider(min=0,max=len(imagesurls),step=1,value=0));
    play = widgets.Play(
        interval=200,  #ms
        value=0,
        min=0,
        max=len(imagesurls) - 1,
        step=1,
        description="Press play",
        disabled=False,
    )
    slider = widgets.IntSlider(min=0,
                               max=len(imagesurls) - 1,
                               description='Frame:')
    label = widgets.Label(value="")

    def on_value_change(change):
        label.value = imagesurls[change['new']]
        showim(change['new'])

    slider.observe(on_value_change, 'value')
    b1 = widgets.Button(description='fw', layout=widgets.Layout(width='auto'))
    b2 = widgets.Button(description='bw', layout=widgets.Layout(width='auto'))
    b3 = widgets.Button(description='hide',
                        layout=widgets.Layout(width='auto'))
    b4 = widgets.Button(description='hidePoly',
                        layout=widgets.Layout(width='auto'))

    def clickfw(b):
        slider.value = slider.value + 1

    def clickbw(b):
        slider.value = slider.value - 1

    def clickhide(b):
        if layer.visible:
            layer.visible = False
        else:
            layer.visible = True

    def clickhidePoly(b):
        if p.visible:
            p.visible = False
        else:
            p.visible = True

    b1.on_click(clickfw)
    b2.on_click(clickbw)
    b3.on_click(clickhide)
    b4.on_click(clickhidePoly)

    # add a custom function to create and add a Polygon layer
    def add_geojson(*args, **kwargs):
        # ugly workaround to call without data=aoi
        if 'data' not in kwargs:
            kwargs['data'] = args[0]
            args2 = [i for i in args[1:-1]]
        else:
            args2 = args

        r = GeoJSON(*args2, **kwargs)
        return m.add_layer(r)

    m.add_GeoJSON = add_geojson

    widgets.jslink((play, 'value'), (slider, 'value'))
    if number_of_images > 1:
        return widgets.VBox(
            [widgets.HBox([play, b2, b1, b3, b4, slider, label]), m])
    else:
        return widgets.VBox([widgets.HBox([b3, b4, label]), m])
Пример #5
0
class Grass2Leaflet(object):
    def __init__(self, grassimg):
        self.grassimg = grassimg
        self.draw_control = None
        self.zoom = 15
        self.center = self.centermap()
        self.m = Map(default_tiles=TileLayer(opacity=1.0),
                     center=self.center,
                     zoom=self.zoom)

    def centermap(self):
        centerlat = []
        centerlon = []
        for i in self.grassimg:
            centerlat.append(self.grassimg[i]['C'][0])
            centerlon.append(self.grassimg[i]['C'][1])
        center = (sum(centerlat) / float(len(centerlat)),
                  sum(centerlon) / float(len(centerlon)))
        return center

    def imgoverlays(self):
        self.leafletimg = OrderedDict()
        for i in self.grassimg:
            layer = ImageOverlay(url=self.grassimg[i]['raster'],
                                 bounds=(self.grassimg[i]['LL'],
                                         self.grassimg[i]['UR']))
            self.leafletimg[i] = layer

    def render(self, draw_control=None, caption=None):
        self.out = widgets.Output()
        self.imgoverlays()
        self.dc = None
        options = ['None']
        self.m.add_layer(self.leafletimg[list(self.grassimg.keys())[-1]])
        if len(self.grassimg) >= 2:
            self.maplist = widgets.Dropdown(
                options=options + list(self.grassimg.keys()),
                value=list(self.grassimg.keys())[-1],
                description='Select Layer:',
            )
            self.maplist.observe(self.on_value_change, names='value')
            display(self.maplist)
        if draw_control:
            self.dc = DrawControl()
            self.dc.on_draw(handle_draw)
            self.m.add_control(self.dc)
        display(self.m)
        self.lastdraw = widgets.Button(
            description='Print last draw',
            disabled=False,
            button_style='',  # 'success', 'info', 'warning', 'danger' or ''
            tooltip='Print last draw',
            #icon='check'
        )
        self.lastdraw.on_click(self.on_button_clicked1)
        if not draw_control:
            self.lastdraw.disabled = True
        display(widgets.HBox([self.lastdraw, self.out]))
        if caption:
            display(
                HTML("<center><b>Figure %s:</b> %s<center>" %
                     (caption[0], caption[1])))
        return {'map': self.m, 'drawer': self.dc}

    def on_value_change(self, layername):
        self.m.clear_layers()
        self.m.add_layer(TileLayer(opacity=1.0))
        if self.maplist.value != 'None':
            self.m.add_layer(self.leafletimg[layername['new']])

    def on_button_clicked1(self, b):
        with self.out:
            clear_output()
            display(self.dc.last_draw)
            new_draw = GeoJSON(data=self.dc.last_draw)
            self.m.add_layer(new_draw)
            #display(dir(self.dc.layer))

    def handle_draw_output(self, json):
        display(json.dumps(geo_json))

    def main(self):
        self.imgoverlays()
        self.render()
Пример #6
0
class UbxMap():
    def __init__(self,
                 basemapName="Mapnik",
                 animate=False,
                 zoom=16,
                 width="100%",
                 height="720px"):
        """Parse the UBX File and put it into a DataFrame"""
        self.OnLocationChanged = None
        self.OnDataLoaded = None
        self.OnDataFileChanged = None
        self._animate = animate

        # map
        self._basemaps = {
            "Mapnik": basemaps.OpenStreetMap.Mapnik,
            "Satellite": basemaps.Esri.WorldImagery,
            "WorldStreetMap": basemaps.Esri.WorldStreetMap,
            "BlackAndWhite": basemaps.OpenStreetMap.BlackAndWhite,
            "France": basemaps.OpenStreetMap.France,
            "HOT": basemaps.OpenStreetMap.HOT,
            "OpenTopoMap": basemaps.OpenTopoMap,
            "WorldTopoMap": basemaps.Esri.WorldTopoMap,
        }
        self._basemapName = basemapName
        self._basemap = self._basemaps[self._basemapName]
        self._zoom = zoom
        self._startLocation = (49, 8)
        self._m = Map(basemap=self._basemap,
                      center=self._startLocation,
                      zoom=self._zoom,
                      close_popup_on_click=False)
        self._m.layout.width = width
        self._m.layout.height = height

        self._addControls()
        # parser
        self._parser = UbxParser()

        # GUI elements
        self._fileSelector = widgets.Dropdown(value=self.UbxFiles[0],
                                              placeholder="Log Files",
                                              options=self.UbxFiles,
                                              description="Log File",
                                              ensureoption=False,
                                              disabled=False)
        self._fileSelector.observe(self._on_filename_changed, names='value')

        self._waypointSlider = widgets.IntSlider(
            value=0,
            description="Waypoint",
            min=0,
            max=0,
            layout=widgets.Layout(width='50%'))
        self._waypointSlider.observe(self._on_waypoint_changed, names='value')

        self._mapSelector = widgets.Dropdown(value=self._basemapName,
                                             options=list(
                                                 self._basemaps.keys()),
                                             description="Map",
                                             ensureoption=True,
                                             disabled=False)
        self._mapSelector.observe(self._on_mapstyle_changed, names='value')

        self._upload = FileUpload(accept='.pubx', multiple=True)
        self._upload.observe(self._on_file_upload_changed, names="value")

        self._header = HTML(
            "<b><font size='2' color='orange'>pixelmaps</font></b>")

        self._gui = widgets.VBox([
            widgets.HBox([
                self._header, self._fileSelector, self._waypointSlider,
                self._mapSelector, self._upload
            ]), self._m
        ])

    @property
    def CurrentLocation(self):
        return self._waypointMarker.location

    @property
    def RouteLine(self):
        return self._routeLine

    @property
    def Map(self):
        return self._m

    @property
    def WaypointSliderWidget(self):
        return self._waypointSlider

    @property
    def FileSelectorWidget(self):
        return self._fileSelector

    @property
    def MaxNumberOfWaypoints(self):
        return len(self._df) - 1

    @property
    def UbxFiles(self):
        ubxFiles = []
        dir = os.listdir()
        ubxFiles = []
        for file in dir:
            if file.endswith(".pubx"):
                ubxFiles.append(file)
        if len(ubxFiles) == 0:
            ubxFiles.append("<NoLogFiles>")
        return ubxFiles

    def setCurrentWaypoint(self, value):
        self._currentWaypoint = value
        row = self._df.iloc[self._currentWaypoint]
        speed = row["groundspeed"]
        gz = row["gravityz"]
        ml = row["miclevel"]
        lat = row["latitude"]
        lng = row["longitude"]
        head = row["headingofmotion"]
        self._waypointMessage.value = f"Moving {self._parser.direction(head)} with {speed:.0f} Km/h"
        #self._waypointMarker.rotation_angle = head
        self._waypointMarker.location = (lat, lng)
        self._center()

    def Append(self, filename):
        self._filename = filename
        self._df = self._df.append(
            DataFrame.from_dict(self._parser.read(self._filename)))
        self._updateData()

    def Load(self, filename="<First>"):
        if filename == "<First>":
            self._filename = self.UbxFiles[0]
            if self._filename == "<NoLogFiles>":
                return
        else:
            self._filename = filename
        self._df = DataFrame.from_dict(self._parser.read(self._filename))
        self._updateData()
        self._clearLayers()

    def _updateData(self):
        # Get the start location
        self._startLocation = (self._df.at[0, 'latitude'],
                               self._df.at[0, 'longitude'])

        # Calculate the route average speed
        self._averageSpeed = self._df["groundspeed"].mean()
        self._minSpeed = self._df["groundspeed"].min()
        self._maxSpeed = self._df["groundspeed"].max()
        self._averageHOF = self._df["headingofmotion"].mean()
        # Get the route points to draw the route
        self._routePoints = self._df.loc[:, ["latitude", "longitude"
                                             ]].values.tolist()

        self._waypointSlider.max = self.MaxNumberOfWaypoints

        if self.OnDataLoaded:
            self.OnDataLoaded(self)

    def _addControls(self):
        # Add Controls
        self._m.add_control(
            MeasureControl(position='bottomleft',
                           active_color='orange',
                           primary_length_unit='kilometers'))
        self._m.add_control(FullScreenControl())
        self._m.add_control(ScaleControl(position='bottomleft'))
        searchMarker = Marker(icon=AwesomeIcon(
            name="check", marker_color='green', icon_color='darkred'))
        self._m.add_control(
            SearchControl(
                position="topleft",
                url=
                'https://nominatim.openstreetmap.org/search?format=json&q={s}',
                zoom=self._zoom,
                marker=searchMarker))

    def Display(self):
        self._fileSelector.options = self.UbxFiles
        self._waypointSlider.max = self.MaxNumberOfWaypoints
        return self._gui

    def move(self, location):
        self._waypointMarker.location = location

    def _on_filename_changed(self, change):
        newFile = change["new"]
        self.Load(newFile)
        self.DrawRoute()
        if self.OnDataFileChanged:
            self.OnDataFileChanged(self, change["new"])

    def _on_file_upload_changed(self, change):
        newFile = change["new"]
        with open(newFile, 'wb') as output_file:
            for uploaded_filename in self._upload.value:
                content = self._upload.value[uploaded_filename]['content']
                output_file.write(content)

    def _on_mapstyle_changed(self, change):
        self._basemapName = change["new"]
        self._m.layers = [basemap_to_tiles(self._basemaps[self._basemapName])]
        self.DrawRoute()

    def _on_waypoint_changed(self, change):
        self._currentWaypoint = int(change['new'])
        self.setCurrentWaypoint(self._currentWaypoint)

    def _on_location_changed(self, event):
        # Do some computation given the new marker location, accessible from `event['new']
        print(event["new"])

    def _addWaypoint(self):
        # Waypoint
        self._waypointMarker = Marker(location=self._startLocation,
                                      draggable=False)
        self._waypointMarker.observe(self._on_location_changed, 'location')
        self._m.add_layer(self._waypointMarker)

        # Waypoint Popup Message
        self._waypointMessage = HTML()
        self._waypointMarker.popup = self._waypointMessage

    def DrawRoute(self):
        # Draw the route
        #self._clearLayers()
        self._routeLine = AntPath(
            locations=self._routePoints,
            dash_array=[1, int(self._averageSpeed)],
            delay=int(self._averageSpeed * 500),
            color="red",
            pulse_color="blue")  #color='#7590ba',pulse_color='#3f6fba')
        self._m.add_layer(self._routeLine)
        self._addWaypoint()
        self._center()
        self._addStats()
        if self._animate:
            self._center()

    def _center(self):
        self._m.center = self._waypointMarker.location

    def _centerTo(self, location):
        self._m.center = location

    def _clearLayers(self):
        self._m.clear_layers()
        self._m.layers = [basemap_to_tiles(self._basemap)]

    def calcSpeedZGravityThreshold(self, speed, grvityz):
        threshold = 10.5
        if speed < 6:  #walking
            threshold = 12.5
        elif speed >= 6 and speed < 10:  # running
            threshold = 14.5
        elif speed > 10 and speed < 25:  # bike
            threshold = 16.5
        return threshold

    def _addStats(self):
        oldloc = (0, 0)
        # Iterate through the route points
        for index, row in self._df.iterrows():
            # Get various row info
            speed = row["groundspeed"]
            gz = row["gravityz"]
            ml = row["miclevel"]
            lat = row["latitude"]
            lng = row["longitude"]
            loc = (lat, lng)

            # Add speed markers
            if speed < 2 and self._parser.distance(loc, oldloc) > 0.01:
                #m.add_layer(Marker(location=loc, draggable=False, title="Stopped"))
                self._m.add_layer(
                    Circle(location=loc,
                           radius=5,
                           color="green",
                           fill_color="green"))
                oldloc = loc
                if self._animate:
                    self._centerTo(loc)

            # Add Z Gravity markers (bumps)
            if gz > self.calcSpeedZGravityThreshold(speed, gz):
                self._m.add_layer(
                    Circle(location=loc,
                           radius=int(gz / 2),
                           color="red",
                           fill_color="red"))
                if self._animate:
                    self._centerTo(loc)

            # Add Sound Markers
            if ml >= 1.5:
                self._m.add_layer(
                    Circle(location=loc,
                           radius=int(ml * 5),
                           color="orange",
                           fill_color="orange"))
                if self._animate:
                    self._centerTo(loc)