matplotlib Python:在球体上绘制点和圆

de90aj5v  于 2023-02-19  发布在  Python
关注(0)|答案(1)|浏览(264)

我在大学里做过一个项目,我尝试用Python来重建地球,用它来绘制地球表面的特定位置,以及不同方向的圆圈,这样它们就可以与卫星数据对齐。我必须从数据集中给出一个飞机在给定时间的位置。
我从简单地绘制一个线框开始,并在线框上绘制我需要的点(所有这些都是为了缩放地球及其地理位置)。
我遇到的问题是,当我把地球的图像叠加在一个类似球体的物体上时,当球体旋转经过某个点时,这些点就会消失。所以,最初的问题是:我怎样才能阻止他们消失呢?
其次;我似乎找不到任何方法来绘制以球体为中心的圆--例如,一个围绕赤道的圆,然后运用同样的想法在球体表面绘制圆,得到如下所示的图像:

我知道这是从谷歌Map,但我很好奇,如果这可以在Python中完成(我假设)。
我的当前代码是:

import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from itertools import product, combinations
    import PIL
    
    #Plot the Earth
    f = plt.figure(1, figsize=(13,13))
    ax = f.add_subplot(111, projection='3d')
    u, v = np.mgrid[0:2*np.pi:30j, 0:np.pi:20j]
    x=6371*np.cos(u)*np.sin(v)
    y=6371*np.sin(u)*np.sin(v)
    z=6371*np.cos(v)
    ax.plot_wireframe(x, y, z, color="b")
    
    #GES ground station @ Perth & AES @ KLIA
    
    ax.scatter([-2368.8],[4881.1],[-3342.0],color="r",s=100)
    ax.scatter([-1293.0],[6238.3],[303.5],color="k",s=100)
    
    #Load earthmap with PIL
    bm = PIL.Image.open('earthmap.jpg')
    #It's big, so I'll rescale it, convert to array, and divide by 256 to get RGB values that matplotlib accept 
    bm = np.array(bm.resize([d/3 for d in bm.size]))/256.
    
    #d/1 is normal size, anything else is smaller - faster loading time on Uni HPC
    
    #Coordinates of the image - don't know if this is entirely accurate, but probably close
    lons = np.linspace(-180, 180, bm.shape[1]) * np.pi/180 
    lats = np.linspace(-90, 90, bm.shape[0])[::-1] * np.pi/180 
    
    #Repeat code specifying face colours 
    
    x = np.outer(6371*np.cos(lons), np.cos(lats)).T
    y = np.outer(6371*np.sin(lons), np.cos(lats)).T
    z = np.outer(6371*np.ones(np.size(lons)), np.sin(lats)).T
    ax.plot_surface(x, y, z, rstride=4, cstride=4, facecolors = bm)
    
    plt.show()

如果有任何方法我可以得到它,使点停止消失和绘图,甚至只是一个圆在赤道上,这将是伟大的!
谢谢!

kxkpmulp

kxkpmulp1#

我相信第一部分的问题已大致解决。至于第二部分的问题,大致上你可以尝试以下方法:

%matplotlib ipympl
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Creating an arbitrary sphere
f = plt.figure(1, figsize=(10, 10))
ax = f.add_subplot(111, projection='3d')
u, v = np.mgrid[0:2*np.pi:100j, 0:np.pi:100j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=np.cos(v)
ax.plot_surface(x, y, z, color="b", alpha=0.3) #low alpha value allows for better visualization of scatter points


def draw_circle_on_sphere(p:float, a:float, v:float):
    '''
        Parametric equation determined by the radius and angular positions (both polar and azimuthal relative to the z-axis) of the circle on the spherical surface
        Parameters:
            p (float): polar angle
            a (float): azimuthal angle
            v (float): radius is controlled by sin(v)
            
        Returns:
            Circular scatter points on a spherical surface
    '''
    
    u = np.mgrid[0:2*np.pi:30j]
    
    x = np.sin(v)*np.cos(p)*np.cos(a)*np.cos(u) + np.cos(v)*np.sin(p)*np.cos(a) - np.sin(v)*np.sin(a)*np.sin(u)
    y = np.sin(v)*np.cos(p)*np.sin(a)*np.cos(u) + np.cos(v)*np.sin(p)*np.sin(a) + np.sin(v)*np.cos(a)*np.sin(u)
    z = -np.sin(v)*np.sin(p)*np.cos(u) + np.cos(v)*np.cos(p)

    return ax.scatter(x, y, z, color="r")

_ = draw_circle_on_sphere(3*np.pi/2, np.pi/4, np.pi/4) # example

结果

View result

相关问题