我最近尝试编写(在 ChatGPT 的帮助下)一个 python 代码,绘制一个由 3D 球体表示的行星及其从互联网上获取的表面图像。 代码有效,但不是我想要的:绘制了带有行星表面的 3D 球体,但结果是不可接受的,正如您在图像中发现的那样,网格不够精细,无法清晰地表示表面. 这是图片: 在函数中,我只能添加到地球表面的链接。
这是函数:
import numpy as np
import imageio
'''
plot_planet - returns a 3d sphere with all the planets belong to the solar system and the sun.
Prototype: plot_planet('planet', ax)
AUTHOR: Giovanni Facchinetti, 2023
'''
def plot_planet(planet_name, ax):
# Define planet properties
planets = {
'sun': {
'radius': 695700.0, # km
'color': 'yellow',
'texture': '...'
},
'mercury': {
'radius': 2439.7, # km
'color': 'gray',
'texture': '...'
},
'venus': {
'radius': 6051.8, # km
'color': 'orange',
'texture': '...'
},
'earth': {
'radius': 6371.0, # km
'color': 'blue',
'texture': 'https://www.solarsystemscope.com/textures/download/8k_earth_daymap.jpg'
},
'mars': {
'radius': 3389.5, # km
'color': 'red',
'texture': '...'
},
'jupiter': {
'radius': 69911.0, # km
'color': 'brown',
'texture': '...'
},
'saturn': {
'radius': 58232.0, # km
'color': 'goldenrod',
'texture': '...'
},
'uranus': {
'radius': 25362.0, # km
'color': 'cyan',
'texture': '...'
},
'neptune': {
'radius': 24622.0, # km
'color': 'blueviolet',
'texture': '...'
},
'pluto': {
'radius': 1188.3, # km
'color': 'gray',
},
}
# Get planet properties
planet = planets.get(planet_name)
if planet is None:
raise ValueError(f'Invalid planet name: {planet_name}')
# Create planet
u, v = np.mgrid[0:2 * np.pi:100j, 0:np.pi:100j]
x = planet['radius'] * np.cos(u) * np.sin(v)
y = planet['radius'] * np.sin(v) * np.sin(u)
z = planet['radius'] * np.cos(v)
if 'texture' in planet:
# Load the image from the internet URL
image_url = planet['texture']
image = imageio.imread(image_url)
# Flip the image vertically
image = np.flipud(image)
# Set the texture coordinates based on the sphere coordinates
phi = np.arctan2(y, x)
theta = np.arccos(z / planet['radius'])
# Convert texture coordinates to pixel coordinates
texture_x = (phi + np.pi) / (2 * np.pi) * image.shape[1]
texture_y = (np.pi - theta) / np.pi * (image.shape[0] - 1)
# Make sure the image array is large enough
image = np.pad(image,
[(max(0, int(texture_y.max() - image.shape[0])) // 2,
max(0, int(texture_y.max() - image.shape[0])) // 2 + max(0, int(texture_y.max() - image.shape[
0])) % 2),
(0, max(0, int(texture_x.max() - image.shape[1]))),
(0, 0)], mode='edge')
# Sample the texture at the given coordinates
texture = image[np.clip(texture_y.astype(int), 0, image.shape[0] - 1), np.clip(texture_x.astype(int), 0,
image.shape[1] - 1)]
# Plot the textured sphere
ax.plot_surface(x, y, z, facecolors=texture / 255.0, shade=True)
else:
# Plot the solid-colored sphere
ax.plot_surface(x, y, z, rstride=1, cstride=1, color=planet['color'], alpha=0.5)
要绘制地球,您可以尝试运行此代码:
from plot_planet import plot_planet
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(13, 18))
# Plot the orbit
ax1 = fig.add_subplot(projection='3d')
plot_planet('earth', ax1)
ax1.axis('equal')
plt.show()
请注意,我已经尝试增加网格数,但这不是正确的做法,因为:
我想要的是在表面上可视化从互联网上拍摄的相同图像(即 8k 质量)。
非常感谢任何建议