pythonpython-3.xgeopandasfolium

Filling outside a PolyLine in Leaflet


I have a set of coordinates that gives a closed polygon. Using the folium.PolyLine() function in Python I can easily fill "inside" but not "outside". The actual output is left, the desired one right in figure.

enter image description here

The code used in Python (in order to obtain image on the left) is the following, where I decided to use leafmap.folium.Map() object.

import folium
import leafmap.foliumap as leafmap
m = leafmap.Map(
    layers_control=True,
    draw_control=False,
    measure_control=False,
    fullscreen_control=False,
    center=(map_center_x,map_center_y),
    zoom=z_start
)
m.add_basemap('OpenTopoMap')
folium.PolyLine(
    locations=coords,
    fill_color="#D3D3D3",
    color="#00B0F0",
    weight=line_weight,
    opacity=fill_opacity
).add_to(m)

I want to revert the area of filling, but I cannot find a way. Is there a way, using folium.PolyLine() to obtain the result on the right instead?


Solution

  • You can create a polygon that covers the entire extent of the coordinate system and add an inner ring (or hole) within the polygon. When you apply a fillOpacity to the polygon, the inner ring remains unaffected, making it fully transparent and clearly visible against the filled outer polygon.

    import folium
    import leafmap.foliumap as leafmap
    from shapely.geometry import Polygon, mapping
    
    map_center_x = 51.1657
    map_center_y = 10.4515
    z_start = 5
    
    m = leafmap.Map(
        layers_control=True,
        draw_control=False,
        measure_control=False,
        fullscreen_control=False,
        center=(map_center_x, map_center_y),
        zoom=z_start
    )
    m.add_basemap('OpenTopoMap')
    
    # Define the extent of the outer polygon (global coordinates)
    x_min, y_min = -180, -90
    x_max, y_max = 180, 90
    
    # create the outer polygon
    outer_polygon = Polygon([
        [y_min, x_min], [y_min, x_max], [y_max, x_max], [y_max, x_min], [y_min, x_min]
    ])
    
    # Define the inner polygon
    hole = Polygon([
        [8.5, 50.5], [11.5, 50.5], [11.5, 51.5], [8.5, 51.5], [8.5, 50.5]
    ])
    
    polygon_with_hole = Polygon(outer_polygon.exterior.coords, [hole.exterior.coords])
    
    geojson_data = mapping(polygon_with_hole)
    
    folium.GeoJson(
        geojson_data,
        name="Polygon with hole",
        style_function=lambda feature: {
            'fillColor': 'grey',
            'color': 'black',
            'weight': 1,
            'fillOpacity': 0.8
        }
    ).add_to(m)
    
    m
    
    

    Resulting Map:

    Resulting Map