将 Matplotlib 的填充等高线图 (contourf_plot) 转换为 GeoJSON

问题描述 投票:0回答:1

我正在开发一个项目,在 Google 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

问题:

contourf_plot 给出了这张图,它是期望的结果。

但是大叶可以:

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

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

python polygon geojson contour contourf
1个回答
0
投票

如果您在第一个图形上绘制等高线,您会发现等高线排列不正确。 您需要处理轮廓坐标,我建议使用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
:

© www.soinside.com 2019 - 2024. All rights reserved.