沿三维曲线移动的箭头

0 投票
1 回答
46 浏览
提问于 2025-04-14 16:32

我想知道如何在3D图中沿着一条路径放置一个箭头。

这里有一个例子。

import matplotlib.pyplot as plt
import numpy as np

z = np.linspace(0,10,100)
x = np.sin(z)
y = np.cos(z)

ax = plt.figure().add_subplot(projection='3d')
ax.plot(x, y, z, label='parametric curve')

我尝试使用 FancyArrowPatch 来实现这个功能,具体可以查看这个链接:https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.FancyArrowPatch.html。但是,path 参数只接受 (x,y) 的输入。请问如何将这个转换到3D呢?

1 个回答

2

这里是基于@CT Zhu(来自 在3D图中给向量加箭头)和@Ruli的内容,后者解决了新版 matplotlib 中的 attribute error 问题。我们可以把 Arrow3D 的逻辑应用到一个包含 xyz 最后两个值的 listtuple 上,这样箭头的头部就能沿着路径或线条的曲线移动:

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d

class Arrow3D(FancyArrowPatch):
    def __init__(self, xs, ys, zs, *args, **kwargs):
        super().__init__((0, 0), (0, 0), *args, **kwargs)
        self._verts3d = xs, ys, zs

    def do_3d_projection(self, renderer=None):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
        self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))

        return np.min(zs)

z = np.linspace(0, 10, 100)
x = np.sin(z)
y = np.cos(z)

ax = plt.figure().add_subplot(projection='3d')
ax.plot(x, y, z, label='parametric curve', color='r')
arrow_prop_dict = dict(mutation_scale=20, arrowstyle='-|>', color='r', shrinkA=0, shrinkB=0)
arrow_head = (x[-2:], y[-2:], z[-2:])
a = Arrow3D(*arrow_head, **arrow_prop_dict)
ax.add_artist(a)

plt.show()

输出结果:

在这里输入图片描述

其实应该感谢@CT Zhu(和@Ruli),他们基本上完成了所有的工作。

撰写回答