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

如何基于三维轨迹集生成2D及3D热力图?

解决方案:基于3D轨迹生成热力图(统计跨网格轨迹数)

嘿,我来给你梳理一下如何实现这个需求——从独立文件的3D轨迹出发,生成统计穿过每个网格的不同轨迹数量的2D(XY/XZ)和3D热力图,顺便把你提到的额外矩阵用法讲清楚~

核心思路先明确

我们要统计的不是轨迹点的密度,而是「有多少条不同的轨迹穿过了某个网格」——哪怕一条轨迹来回穿同一个网格十次,也只算1次。所以核心步骤是:

  1. 把整个空间(比如你说的100×100,实际480×640)划分成10×10的网格单元(X/Y/Z轴各分10段,2D对应10×10个网格,3D对应10×10×10个)。
  2. 对每条轨迹,找出它穿过的所有网格,去重后给对应网格的计数+1。
  3. 用计数矩阵生成热力图。

你需要的3个矩阵(对应不同维度)

  • xy_grid_count:(10,10)的2D矩阵,存储XY平面每个网格被多少条不同轨迹穿过。
  • xz_grid_count:(10,10)的2D矩阵,对应XZ平面的统计结果。
  • xyz_grid_count:(10,10,10)的3D矩阵,统计3D空间每个网格的轨迹穿过数(用来做3D热力图)。

具体实现步骤

第一步:预处理轨迹数据

  • 先把每个轨迹文件的3D点序列(比如(x1,y1,z1), (x2,y2,z2), ...)读进内存,给每条轨迹分配唯一ID(比如从0开始递增)——这样方便后续去重和计数。
  • 坐标映射(可选):如果要把实际的480×640映射到100×100的讨论范围,用简单的线性缩放就行,比如x_scaled = x * 100 / 480,Y轴同理。当然也可以直接用实际尺寸划分网格(X轴每48单位一个网格,Y轴每64单位一个),结果是一致的。

第二步:判断轨迹穿过的网格(关键!)

对每条轨迹,我们要找出它在不同平面/空间穿过的所有网格:

以XY平面为例:

  1. 遍历轨迹的连续两个点(x_i,y_i)和(x_{i+1},y_{i+1}),计算这条线段穿过了哪些XY网格。这里可以用Bresenham算法的扩展版(专门处理线段穿网格),或者更简单的:先算出线段的包围盒覆盖的所有网格,再逐个判断线段是否穿过该网格。
  2. 把这条轨迹穿过的所有XY网格存在一个集合里(自动去重,避免同一条轨迹多次穿同一个网格重复计数)。
  3. 遍历这个集合,给xy_grid_count中对应网格的数值加1。

XZ平面和3D网格的判断逻辑完全同理:

  • XZ平面:把Y坐标换成Z,重复上述步骤,更新xz_grid_count。
  • 3D网格:判断线段穿过的3D空间网格,去重后更新xyz_grid_count。

第三步:生成2D热力图(XY/XZ)

用Python的seaborn或者matplotlib就能快速实现,举个例子:

import seaborn as sns
import matplotlib.pyplot as plt

# 假设xy_grid_count是已经填充好的(10,10)矩阵
plt.figure(figsize=(8,8))
# 热力图+标注数值,颜色用橙红渐变
sns.heatmap(xy_grid_count, annot=True, cmap='YlOrRd', xticklabels=10, yticklabels=10)
plt.title('XY平面热力图(穿过网格的不同轨迹数)')
plt.xlabel('X轴网格编号')
plt.ylabel('Y轴网格编号')
plt.show()

把xy_grid_count换成xz_grid_count,改一下坐标轴标签,就能得到XZ平面的热力图。

第四步:生成3D热力图

3D热力图可以用plotly做交互式体素图,或者matplotlib做3D散点可视化:

用Plotly做交互式3D体素图:

import plotly.graph_objects as go
import numpy as np

# 假设xyz_grid_count是(10,10,10)的3D矩阵
x, y, z = np.meshgrid(np.arange(10), np.arange(10), np.arange(10))

fig = go.Figure(data=go.Volume(
    x=x.flatten(),
    y=y.flatten(),
    z=z.flatten(),
    value=xyz_grid_count.flatten(),
    isomin=1,
    isomax=xyz_grid_count.max(),
    opacity=0.3, # 调整透明度,方便看内部
    surface_count=20, # 控制表面精细度
    colorscale='YlOrRd'
))
fig.update_layout(title='3D热力图(穿过网格的不同轨迹数)')
fig.show()

用Matplotlib做3D散点图(更轻量化):

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

# 遍历每个3D网格
for i in range(10):
    for j in range(10):
        for k in range(10):
            count = xyz_grid_count[i][j][k]
            if count > 0:
                # 取网格中心坐标
                x_center = i*10 + 5
                y_center = j*10 + 5
                z_center = k*10 + 5
                # 用点的大小表示轨迹数量,颜色深浅辅助
                ax.scatter(x_center, y_center, z_center, s=count*15, c='darkred', alpha=0.6)

ax.set_title('3D热力图(轨迹数可视化)')
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
plt.show()

几个实用小提示

  • 去重必须重视:一定要用集合存储每条轨迹穿过的网格,不然同一条轨迹穿同一个网格多次会重复计数,结果就不准了。
  • 效率优化:如果轨迹数量特别多,用numpy矩阵存储计数(比Python列表快N倍);判断线段穿网格的算法可以用快速的射线法,避免遍历所有网格浪费时间。
  • 坐标对齐:确保所有轨迹的坐标系统一,不然划分网格后统计会乱套。

内容的提问来源于stack exchange,提问作者Philip Bal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:09:54