You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为3D绘图的Lat-Long平面添加背景图并保持2D宽高比

需求:将2D背景图融合到3D散点图的经纬度平面(保留宽高比)

现有2D可视化代码(带高度约束的经纬度-温度图)

该代码基于高度范围筛选数据,在金星地图背景上绘制经纬度点,用颜色表示温度,并根据背景图宽高比设置画布尺寸:

import os
import pandas as pd
import matplotlib.pyplot as plt

# 路径设置
combo_folder = '/home/dev/Desktop/Venus/Data/combo'

# 约束参数
height_min = 40
height_max = 60
venus_radius = 6051.8

# 读取背景图并计算宽高比
image = plt.imread('/home/dev/Desktop/Venus/Images/venmap.gif')
image_aspect_ratio = image.shape[1] / image.shape[0]

# 根据宽高比设置画布尺寸
width = 30
height = width / image_aspect_ratio
fig, ax = plt.subplots(figsize=(width, height))

# 绘制背景图
ax.imshow(image, extent=[0, 360, -90, 90], aspect='auto')

# 遍历并绘制CSV数据
for filename in os.listdir(combo_folder):
    if filename.endswith('.csv'):
        file_path = os.path.join(combo_folder, filename)
        df = pd.read_csv(file_path)
        
        # 提取字段并计算高度
        latitude = df['LATITUDE']
        longitude = df['LONGITUDE']
        temperature = df['TEMPERATURE_MEDIUM_TEMPERATURE_AT_BOUNDARY']
        height = df['RADIUS'] - venus_radius
        
        # 高度范围筛选
        mask = (height >= height_min) & (height <= height_max)
        latitude = latitude[mask]
        longitude = longitude[mask]
        temperature = temperature[mask]
        
        # 绘制散点图
        scatter = ax.scatter(longitude, latitude, c=temperature, s=200, cmap='viridis', alpha=0.7)
        ax.set_xlabel('Longitude')
        ax.set_ylabel('Latitude')
        ax.set_title(f'Latitude and Longitude with Temperature (Height: {height_min} to {height_max})')

# 添加温度色标
cbar = fig.colorbar(scatter, ax=ax, label='Temperature (°C)')

plt.show()

现有3D可视化代码(经纬度-高度-温度散点图)

该代码在3D空间展示经纬度、高度与温度的关系,同样应用了高度范围约束:

import os
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 路径设置
combo_folder = '/home/dev/Desktop/Venus/Data/combo'

# 约束参数
height_min = 40
height_max = 60
venus_radius = 6051.8

# 创建3D画布
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 设置轴范围
ax.set_xlim(0, 360)
ax.set_ylim(-90, 90)
ax.set_zlim(0, 90)

# 遍历并绘制CSV数据
for filename in os.listdir(combo_folder):
    if filename.endswith('.csv'):
        file_path = os.path.join(combo_folder, filename)
        df = pd.read_csv(file_path)
        
        # 提取字段并计算高度
        latitude = df['LATITUDE']
        longitude = df['LONGITUDE']
        temperature = df['TEMPERATURE_MEDIUM_TEMPERATURE_AT_BOUNDARY']
        height = df['RADIUS'] - venus_radius
        
        # 高度范围筛选
        mask = (height >= height_min) & (height <= height_max)
        latitude = latitude[mask]
        longitude = longitude[mask]
        temperature = temperature[mask]
        height = height[mask]
        
        # 绘制3D散点图
        scatter = ax.scatter(longitude, latitude, height, c=temperature, cmap='viridis', alpha=0.7)
        ax.set_xlabel('Longitude')
        ax.set_ylabel('Latitude')
        ax.set_zlabel('Height')
        ax.set_title(f'Latitude, Longitude, and Height with Temperature (Height: {height_min} to {height_max})')

# 添加温度色标
cbar = fig.colorbar(scatter, ax=ax, label='Temperature (°C)')

plt.show()

目标需求

  • 保留2D绘图中基于背景图宽高比设置画布尺寸的逻辑
  • 将金星背景图添加到3D散点图的**经纬度平面(z=0)**上
  • 融合后保留3D散点的温度色标与交互功能

融合后的实现代码

import os
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 路径设置
combo_folder = '/home/dev/Desktop/Venus/Data/combo'
background_img_path = '/home/dev/Desktop/Venus/Images/venmap.gif'

# 约束参数
height_min = 40
height_max = 60
venus_radius = 6051.8

# ---------------------- 保留2D图的宽高比设置逻辑 ----------------------
# 读取背景图并计算宽高比
image = plt.imread(background_img_path)
image_aspect_ratio = image.shape[1] / image.shape[0]

# 根据宽高比设置画布尺寸
width = 30
height = width / image_aspect_ratio
fig = plt.figure(figsize=(width, height))
ax = fig.add_subplot(111, projection='3d')

# ---------------------- 设置3D轴属性 ----------------------
ax.set_xlim(0, 360)
ax.set_ylim(-90, 90)
ax.set_zlim(0, 90)
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
ax.set_zlabel('Height')
ax.set_title(f'Latitude, Longitude, Height with Temperature (Height: {height_min} to {height_max})')

# ---------------------- 在经纬度平面(z=0)添加背景图 ----------------------
# 创建覆盖经纬度范围的网格,固定z=0
x_range = [0, 360]
y_range = [-90, 90]
X, Y = plt.meshgrid(x_range, y_range)
Z = X * 0  # z坐标固定为0

# 将背景图贴到z=0平面,匹配经纬度范围并保持图像比例
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=image, shade=False,
                extent=[0, 360, -90, 90], aspect='auto')

# ---------------------- 绘制筛选后的3D散点数据 ----------------------
scatter = None
for filename in os.listdir(combo_folder):
    if filename.endswith('.csv'):
        file_path = os.path.join(combo_folder, filename)
        df = pd.read_csv(file_path)
        
        # 提取并计算所需字段
        lat = df['LATITUDE']
        lon = df['LONGITUDE']
        temp = df['TEMPERATURE_MEDIUM_TEMPERATURE_AT_BOUNDARY']
        height = df['RADIUS'] - venus_radius
        
        # 高度范围筛选
        mask = (height >= height_min) & (height <= height_max)
        scatter = ax.scatter(lon[mask], lat[mask], height[mask], 
                             c=temp[mask], cmap='viridis', alpha=0.7, s=200)

# ---------------------- 添加温度色标 ----------------------
if scatter is not None:
    cbar = fig.colorbar(scatter, ax=ax, label='Temperature (°C)')

plt.show()

关键修改说明

  1. 保留宽高比逻辑:完全沿用2D图中读取背景图、计算宽高比并设置画布尺寸的代码,保证画布比例与背景图一致
  2. 3D平面贴背景图:使用plot_surface在z=0的平面上绘制背景图,通过facecolors参数将图像作为纹理贴附,extent匹配经纬度范围,aspect='auto'避免图像拉伸变形
  3. 兼容原3D逻辑:保留了原3D散点的筛选与绘制逻辑,仅调整变量名避免冲突
  4. 鲁棒性处理:添加了色标绘制的判断,避免无数据时出现报错

内容的提问来源于stack exchange,提问作者Keshav Aggarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:57:00