给定一系列经度和纬度,如何在球体上绘制热图?

Jon*_*onK 5 python 3d wolfram-mathematica heatmap

我有超过500点的列表,以纬度和经度给出。这些点表示火山口,我想绘制这些火山口的热图。例如,我希望将具有大量陨石坑的区域视为“热”,而将较少陨石坑的区域视为“冷”。我已经使用SciPy查看了KDE,还尝试在Mathematica中使用ListSliceDensityPlot3D,但是我无法创建足够的图。

我将每个点从纬度/经度转换为笛卡尔[x,y,z]坐标,并将其绘制在球体的表面上,但是我不知道如何获取点列表并计算给定的密度区域,然后将其绘制在3D曲面上。

我的想法是得到一个类似Ceres的图片

在此先感谢您,如果需要的话请提出问题,如果我最初发布的信息不足,请抱歉。

mik*_*ski 6

这是一种蛮力方法,但它在一定程度上起作用。如果您使网格非常精细或有数千个陨石坑,这将是有问题的。如果 bin 大小足够小,则表面上的距离和 3D 距离之间没有太大差异,因此我采用后者,因为它更容易计算,但可能需要更改此设置。

代码如下:

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


def random_point( r=1 ):
    ct = 2*np.random.rand() - 1
    st = np.sqrt( 1 - ct**2 )
    phi = 2* np.pi *  np.random.rand()
    x = r * st * np.cos( phi)
    y = r * st * np.sin( phi)
    z = r * ct
    return np.array( [x, y, z ] )

def near( p, pntList, d0 ):
    cnt=0
    for pj in pntList:
        dist=np.linalg.norm( p - pj )
        if dist < d0:
            cnt += 1 - dist/d0
    return cnt


"""
/sf/ask/1549023661/
"""

pointList = np.array([ random_point( 10.05 ) for i in range( 65 ) ] )

fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1, projection='3d')

u = np.linspace( 0, 2 * np.pi, 120)
v = np.linspace( 0, np.pi, 60 )

# create the sphere surface
XX = 10 * np.outer( np.cos( u ), np.sin( v ) )
YY = 10 * np.outer( np.sin( u ), np.sin( v ) )
ZZ = 10 * np.outer( np.ones( np.size( u ) ), np.cos( v ) )

WW = XX.copy()
for i in range( len( XX ) ):
    for j in range( len( XX[0] ) ):
        x = XX[ i, j ]
        y = YY[ i, j ]
        z = ZZ[ i, j ]
        WW[ i, j ] = near(n p.array( [x, y, z ] ), pointList, 3)
WW = WW / np.amax( WW )
myheatmap = WW

# ~ ax.scatter( *zip( *pointList ), color='#dd00dd' )
ax.plot_surface( XX, YY,  ZZ, cstride=1, rstride=1, facecolors=cm.jet( myheatmap ) )
plt.show() 
Run Code Online (Sandbox Code Playgroud)

结果是这样的:

密度球

您还可以修改距离函数以考虑陨石坑的大小。