Ejemplo n.º 1
0
def load_map(area, datafile, generate_ids, return_html=True):
    """
    Create a map for a bouldering zone that shows the GEOJSON data, names and
    links to video playlists of its sectors as well as the parking areas. All
    this data should be provided via a JSON file
    """
    generate_ids.reset_seed()
    area_data = {}
    with open(datafile, encoding='utf-8') as data:
        area_data = json.load(data)

    area_map = folium.Map(
        location=[area_data['latitude'], area_data['longitude']],
        zoom_start=area_data['zoom'])
    area_map._id = generate_ids.next_id()  # reassign id
    for child in area_map._children.values():
        child._id = generate_ids.next_id()
    tile_layer = folium.TileLayer(
        tiles=
        'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        name='Satellite',
        attr=
        'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
    )
    tile_layer._id = generate_ids.next_id()  # reassign id
    tile_layer.add_to(area_map)

    # Add fullscreen button to map
    fs = Fullscreen()
    fs._id = generate_ids.next_id()
    fs.add_to(area_map)

    sectors = area_data['sectors']
    # Create a Folium feature group for this layer, since we will be displaying multiple layers
    sector_lyr = folium.FeatureGroup(name='Zone Markers')
    sector_lyr._id = generate_ids.next_id()  # reassign id

    for sector in sectors:
        if not sector['sector_data'] or not sector['link']:
            continue
        sector_map = folium.GeoJson(
            os.path.dirname(os.path.abspath(datafile)) + sector['sector_data'],
            name=sector['name'],
            tooltip=sector['name'],
            style_function=lambda x: {
                'color': x['properties']['stroke'],
                'weight': x['properties']['stroke-width'],
                'opacity': SECTOR_OPACITY,
                'fillColor': x['properties']['stroke'],
            })
        sector_map._id = generate_ids.next_id()  # reassign id
        sector_html = utils.js_helpers.generate_sector_html(
            sector['name'], sector['link'])
        sector_popup = folium.Popup(sector_html,
                                    max_width=POPUP_WIDTH,
                                    min_width=POPUP_WIDTH)
        sector_popup._id = generate_ids.next_id()  # reassign id
        for child in sector_popup._children.values():
            child._id = generate_ids.next_id()

        sector_map.add_child(sector_popup)

        sector_lyr.add_child(sector_map)

    # Parking areas
    for parking in area_data['parkings']:
        parking_icon = CustomIcon('static/images/icons/parking.png',
                                  icon_size=(ICON_SIZE, ICON_SIZE))
        parking_icon._id = generate_ids.next_id()  # reassign id
        parking_marker = folium.Marker(
            location=[
                parking['parking_latitude'], parking['parking_longitude']
            ],
            popup=utils.js_helpers.generate_parking_html(
                [parking['parking_latitude'], parking['parking_longitude']]),
            tooltip='Parking',
            icon=parking_icon)
        parking_marker._id = generate_ids.next_id()  # reassign id
        for child in parking_marker._children.values():
            child._id = generate_ids.next_id()

        sector_lyr.add_child(parking_marker)

    # Approximation
    if area_data.get('approximation', None) is not None:
        import gpxpy
        import gpxpy.gpx

        approximation_geojson = {
            'type': 'Feature',
            'properties': {
                'stroke': '#1f1a95',
                'stroke-opacity': 1,
                'stroke-width': 2
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': []
            }
        }

        gpx_path = 'data/zones/' + area + '/' + area_data.get('approximation')
        with open(gpx_path, 'r') as gpx_file:
            gpx = gpxpy.parse(gpx_file)
            for track in gpx.tracks:
                for segment in track.segments:
                    for point in segment.points:
                        approximation_geojson['geometry'][
                            'coordinates'].append(
                                [point.longitude, point.latitude])

        zone_approximation = folium.GeoJson(
            approximation_geojson,
            name='Approximation',
            tooltip=APPROX_PLACEHOLDER,
            style_function=lambda x: {
                'color': x['properties']['stroke'],
                'weight': x['properties']['stroke-width'],
                'opacity': SECTOR_OPACITY,
                'fillColor': x['properties']['stroke'],
            })
        zone_approximation._id = generate_ids.next_id()  # reassign id

        zone_approx_html = utils.js_helpers.generate_file_download_html(
            area, area_data.get('approximation'), 'Track')

        track_popup = folium.Popup(zone_approx_html,
                                   max_width=POPUP_WIDTH,
                                   min_width=POPUP_WIDTH)
        track_popup._id = generate_ids.next_id()  # reassign id

        for child in track_popup._children.values():
            child._id = generate_ids.next_id()

        zone_approximation.add_child(track_popup)

        sector_lyr.add_child(zone_approximation)

    # Sectors
    zoomed_out_lyr = folium.FeatureGroup(name='Sector Markers')
    zoomed_out_lyr._id = generate_ids.next_id()  # reassign id
    zoomed_out_icon = CustomIcon('static/images/marker/marker.png',
                                 icon_size=(MARKER_SIZE, MARKER_SIZE))
    zoomed_out_icon._id = generate_ids.next_id()  # reassign id
    sectors_marker = folium.Marker(
        location=[area_data['latitude'], area_data['longitude']],
        tooltip=area_data['name'],
        icon=zoomed_out_icon)
    sectors_marker._id = generate_ids.next_id()  # reassign id
    zoomed_out_lyr.add_child(sectors_marker)

    area_map.add_child(zoomed_out_lyr)
    area_map.add_child(sector_lyr)

    layer_control = folium.LayerControl()
    layer_control._id = generate_ids.next_id()  # reassign id
    layer_control.add_to(area_map)

    # Since folium does not support all the functionalities we need
    # we obtain them by injecting JavaScript code in the map html
    map_html = area_map.get_root().render()
    map_html = utils.js_helpers.make_layer_that_hides(map_html,
                                                      area_map.get_name(),
                                                      sector_lyr.get_name(),
                                                      DEFAULT_AREA_ZOOM)
    map_html = utils.js_helpers.make_layer_that_hides(
        map_html, area_map.get_name(), zoomed_out_lyr.get_name(),
        DEFAULT_AREA_ZOOM, False, True)
    # Zoom into area when clicking
    map_html = utils.js_helpers.zoom_on_click(map_html, area_map.get_name(),
                                              sectors_marker.get_name(),
                                              DEFAULT_AREA_ZOOM + 1)

    map_html = utils.js_helpers.enable_links_from_iframe(map_html)
    map_html = utils.js_helpers.replace_maps_placeholder(map_html)
    map_html = utils.js_helpers.replace_approx_placeholders_for_translations(
        map_html, APPROX_PLACEHOLDER)
    # Avoid zooming in when clicking on a sector area
    map_html = utils.js_helpers.remove_geojson_zoom_on_click(map_html)
    # replace the ids of all the html tags
    map_html = utils.js_helpers.replace_tag_ids(map_html, ['html'],
                                                generate_ids)
    return map_html if return_html else area_map
Ejemplo n.º 2
0
def load_general_map(datafiles, generate_ids, return_html=True):
    """
    Create a map that contains all the zones provided by the list of datafiles
    i.e. all areas combined in one map. This map only shows the markers that 
    indicate an existing area.
    """
    generate_ids.reset_seed()
    area_map = folium.Map(location=[-23.0390625, -18.299051014581817],
                          zoom_start=2)
    area_map._id = generate_ids.next_id()  # reassign id
    for child in area_map._children.values():
        child._id = generate_ids.next_id()

    tile_layer = folium.TileLayer(
        tiles=
        'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        name='Satellite',
        attr=
        'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
    )
    tile_layer._id = generate_ids.next_id()  # reassign id
    tile_layer.add_to(area_map)

    # Add fullscreen button to map
    fs = Fullscreen()
    fs._id = generate_ids.next_id()
    fs.add_to(area_map)

    # layers = []
    sectors_markers = []
    placeholders = []

    # Sectors layer
    zoomed_out_lyr = folium.FeatureGroup(name='Sector Markers')
    zoomed_out_lyr._id = generate_ids.next_id()  # reassign id
    areas_cluster = MarkerCluster()
    areas_cluster._id = generate_ids.next_id()  # reassign id

    for areadatafile in datafiles:
        area_data = {}
        with open(areadatafile, encoding='utf-8') as data:
            area_data = json.load(data)

        # sectors = area_data['sectors']
        # # Create a Folium feature group for this layer, since we will be displaying multiple layers
        # sector_lyr = folium.FeatureGroup(name='sectors_layer')
        # for sector in sectors:
        #     sector_map = folium.GeoJson(
        #         os.path.dirname(os.path.abspath(areadatafile)) +
        #         sector['sector_data'],
        #         name=sector['name'],
        #         tooltip=sector['name'],
        #         style_function=lambda x: {
        #             'color': x['properties']['stroke'],
        #             'weight': x['properties']['stroke-width'],
        #             'opacity': SECTOR_OPACITY,
        #             'fillColor': x['properties']['stroke'],
        #         }
        #     )
        #     sector_html = helpers.generate_sector_html(
        #         sector['name'], sector['link'])
        #     sector_map.add_child(folium.Popup(
        #         sector_html, max_width=POPUP_WIDTH, min_width=POPUP_WIDTH))

        #     sector_lyr.add_child(sector_map)

        # Parking
        # for parking in area_data['parkings']:
        #     parking_marker = folium.Marker(
        #         location=[parking['parking_latitude'],
        #                   parking['parking_longitude']],
        #         popup=helpers.generate_parking_html([parking['parking_latitude'],
        #                                              parking['parking_longitude']]),
        #         tooltip='Parking',
        #         icon=folium.Icon(color='red', icon='info-sign')
        #     )

        #     sector_lyr.add_child(parking_marker)

        zoomed_out_icon = CustomIcon('static/images/marker/marker.png',
                                     icon_size=(MARKER_SIZE, MARKER_SIZE))
        zoomed_out_icon._id = generate_ids.next_id()  # reassign id
        html_redirect, _ = os.path.splitext(
            os.path.basename(os.path.normpath(areadatafile)))
        area_name = os.path.splitext(os.path.basename(areadatafile))[0]
        placeholder = area_name + PLACEHOLDER
        popup_html = folium.Html(utils.js_helpers.generate_area_popup_html(
            area_data['name'], area_name, html_redirect, placeholder),
                                 script=True)
        popup_html._id = generate_ids.next_id()  # reassign id
        zone_popup = folium.Popup(
            popup_html,
            max_width=max(len(area_data['name']), len(BETA_VIDEOS_TEXT)) * 10)
        zone_popup._id = generate_ids.next_id()  # reassign id
        placeholders.append(placeholder)

        sectors_marker = folium.Marker(
            location=[area_data['latitude'], area_data['longitude']],
            tooltip=area_data['name'],
            icon=zoomed_out_icon,
            popup=zone_popup,
        )
        sectors_marker._id = generate_ids.next_id()  # reassign id
        sectors_markers += [sectors_marker]
        # Group areas' markers when zoomed out
        areas_cluster.add_child(sectors_marker)
        zoomed_out_lyr.add_child(areas_cluster)

        area_map.add_child(zoomed_out_lyr)
        # area_map.add_child(sector_lyr)
        # layers += [(sector_lyr, zoomed_out_lyr)]

    layer_control = folium.LayerControl()
    layer_control._id = generate_ids.next_id()  # reassign id
    layer_control.add_to(area_map)

    # Since folium does not support all the functionalities we need
    # we obtain them by injecting or editing JavaScript code in the map html
    map_html = area_map.get_root().render()
    # for sector_lyr, zoomed_out_lyr in layers:
    #     # Hide or show layers depending on the zoom level
    #     map_html = helpers.make_layer_that_hides(
    #         map_html, area_map.get_name(), sector_lyr.get_name(), DEFAULT_AREA_ZOOM, False, False)
    #     map_html = helpers.make_layer_that_hides(
    #         map_html, area_map.get_name(), zoomed_out_lyr.get_name(), DEFAULT_AREA_ZOOM, True, True)
    #     # Zoom into area when clicking
    #     for marker in sectors_markers:
    #         map_html = helpers.zoom_on_click(
    #             map_html, area_map.get_name(), marker.get_name(), DEFAULT_AREA_ZOOM+1)
    map_html = utils.js_helpers.replace_custom_placeholders(
        map_html, placeholders)
    map_html = utils.js_helpers.replace_tag_ids(map_html, ['html'],
                                                generate_ids)
    return map_html if return_html else area_map