代码之家  ›  专栏  ›  技术社区  ›  John Smith

将Matplotlib的填充轮廓图(contourf_plot)转换为GeoJSON

  •  0
  • John Smith  · 技术社区  · 1 年前

    我正在进行一个项目,我在谷歌Colab环境中使用Matplotlib中的plt.contourf成功生成了填充轮廓图。现在,我正试图将这些填充的轮廓多边形转换为GeoJSON,以便与Folium无缝集成。

    import numpy as np
    import folium
    from folium import plugins
    import matplotlib.pyplot as plt
    from matplotlib.colors import to_hex, Normalize
    
    # Specify the URL of the NetCDF file
    url = "https://www.star.nesdis.noaa.gov/socd/mecb/sar/AKDEMO_products/APL_winds/tropical/2024/SH052024_BELAL/STAR_SAR_20240116013937_SH052024_05S_MERGED_FIX_3km.nc"
    
    # Download the NetCDF file content
    response = requests.get(url)
    nc_content = BytesIO(response.content)
    # Open the NetCDF file using xarray
    dataset = xr.open_dataset(nc_content)
    
    # Access the 'sar_wind' variable
    sar_wind = dataset['sar_wind'].values
    
    # Access the 'latitude' and 'longitude' variables
    latitude = dataset['latitude'].values
    longitude = dataset['longitude'].values
    # Set iso values for filled contours
    iso_values_filled = np.linspace(np.min(sar_wind), np.max(sar_wind), 11)  # One extra value for filling the background
    
    # Create a filled contour plot
    contourf_plot = plt.contourf(longitude, latitude, sar_wind, levels=iso_values_filled, cmap='viridis')
    
    # Convert filled contour polygons to GeoJSON
    geojson_data_polygon = {"type": "FeatureCollection", "features": []}
    
    # Normalize iso values for colormap mapping
    norm = Normalize(vmin=np.min(iso_values_filled), vmax=np.max(iso_values_filled))
    
    for level, collection in zip(iso_values_filled, contourf_plot.collections):
        for path in collection.get_paths():
            coordinates = path.vertices.tolist()
            # Close the polygon by repeating the first vertex
            coordinates.append(coordinates[0])
            color_hex = to_hex(plt.cm.viridis(norm(level)))  # Map normalized iso value to colormap
            geojson_data_polygon["features"].append({
                "type": "Feature",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [coordinates]
                },
                "properties": {
                    "level": level,
                    "color": color_hex
                }
            })
    
    # Create a Folium map centered on the average latitude and longitude
    center_lat, center_lon = np.mean(latitude), np.mean(longitude)
    mymap_polygon = folium.Map(location=[center_lat, center_lon], zoom_start=8)
    
    # Add filled contour polygons as GeoJSON overlay with colored areas
    folium.GeoJson(
        geojson_data_polygon,
        style_function=lambda feature: {
            'fillColor': feature['properties']['color'],
            'color': feature['properties']['color'],
            'weight': 2,
            'fillOpacity': 0.7
        }
    ).add_to(mymap_polygon)
    
    # Display the map with filled contour polygons
    mymap_polygon
    

    问题:

    Contourfplot给出了这个映射,这是期望的结果。 enter image description here

    但叶子给出了:

    enter image description here

    我们可以看到多边形没有被构建。

    目标: 我的目标是将填充的轮廓多边形从contourf_plot转换为GeoJSON格式,以便我可以在Folium中显示它们。

    0 回复  |  直到 1 年前
        1
  •  2
  •   HMH1013    1 年前

    如果你在第一个图上绘制等高线,你会发现等高线排列不正确。 enter image description here 你需要处理轮廓坐标,我建议使用 geojsoncontour .

    只需更改行后的代码 contourf_plot = ... 致:

    import geojsoncontour
    import branca
    
    # Create geogson strings
    geojson = geojsoncontour.contourf_to_geojson(
        contourf=contourf_plot,
        min_angle_deg=3.0,
        ndigits=5,
        stroke_width=1,
        fill_opacity=0.7)
    
    # Normalize iso values for colormap mapping
    norm = Normalize(vmin=np.min(iso_values_filled), vmax=np.max(iso_values_filled))
    # Covert float to hex colors
    color_hex = []
    for level in iso_values_filled: 
        color_hex.append( to_hex(plt.cm.viridis(norm(level))))
    
    # Create a Folium map centered on the average latitude and longitude
    center_lat, center_lon = np.mean(latitude), np.mean(longitude)
    mymap_polygon = folium.Map(location=[center_lat, center_lon], zoom_start=8)
    
    # Creat colormap
    cm = branca.colormap.LinearColormap(color_hex)
    
    # Add filled contour polygons as GeoJSON overlay with colored areas
    folium.GeoJson(
        geojson,
        style_function=lambda x: {
            'color':     x['properties']['stroke'],
            'weight':    x['properties']['stroke-width'],
            'fillColor': x['properties']['fill'],
            'fillOpacity':   0.7,
        }).add_to(mymap_polygon)
    
    # Update color map 
    mymap_polygon.add_child(cm)
    

    你会得到结果的 mymap_polygon :

    enter image description here