繁体   English   中英

如何在 Matplotlib 上注释 3d plot?

[英]How to annotate 3d plot on Matplotlib?

I am trying to annotate a word text on my 3d plot diagram, I know ax.text is able to plot the text on my 3d plot however, the plt.annotate does a better job at that as it arrows the text to the coordinate which是我需要的。 有没有办法在 3d 图上使用 plt.annotate 到 plot ? 我只知道它适用于二维。 请让我知道解决方案。

plt.annotate(s='pppppp', xy=(1.5,0), xytext=(1.5,0)) //doesnt work on 3d
ax.text(1.5,0,0,'pppppp')

如果查看源代码: https://matplotlib.org/3.1.1/_modules/mpl_toolkits/mplot3d/axes3d.html#Axes3Dhttps://matplotlib.org/_modules/matxeslib/_axes. ,您将看到 3d 图没有ax.annotate()方法。 因此, ax.annotate() get 被称为Axes方法。 因此,它没有适合 3d 图的转换。 解决这个问题的一种方法是按照这篇文章的说明Matplotlib: Annotating a 3D scatter plot

以下是使用帖子解决方案的示例:

from mpl_toolkits.mplot3d.proj3d import proj_transform
from matplotlib.text import Annotation
import matplotlib as mpl
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(projection="3d")

class Annotation3D(Annotation):
    '''Annotate the point xyz with text s'''

    def __init__(self, s, xyz, *args, **kwargs):
        Annotation.__init__(self,s, xy=(0,0), *args, **kwargs)
        self._verts3d = xyz        

    def draw(self, renderer):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj_transform(xs3d, ys3d, zs3d, renderer.M)
        self.xy=(xs,ys)
        Annotation.draw(self, renderer)

def annotate3D(ax, s, *args, **kwargs):
    '''add anotation text s to to Axes3d ax'''

    tag = Annotation3D(s, *args, **kwargs)
    ax.add_artist(tag)
    return tag

annotate3D(ax, "HEllo world", [1, 1, 1])
plt.show()

这是我对 p479h 答案的修改。

  • 它公开Annotation3D.xy以供公众访问; 遵循Annotation.xy的性质。

  • annotateND根据ax的类型返回 2D 或 3D 注释


from typing import Optional, Tuple, Union

from matplotlib.text import Annotation
from matplotlib import pyplot as plt
from mpl_toolkits import mplot3d as plt3d

class Annotation3D(Annotation):
    """
    Annotation for 3D axes

    Args:
        text: text to display as annotation
        xyz: annotation co-ordinates
        *args: passed to `matplotlib.text.Annotation`
        **kwargs: passed to `matplotlib.text.Annotation`
    """
    def __init__(self, text: str, xyz: Tuple[float, float, float], *args,
                 **kwargs):
        Annotation.__init__(self, text, xy=(0, 0), *args, **kwargs)

        # 3D position
        self._xyz = xyz

        # Hard-set 2D projection
        self._xy: Optional[Tuple[float, float]] = None

    @property
    def xy(self):
        if self._xy is not None:
            return self._xy
        *xy2d, _ = plt3d.proj3d.proj_transform(*self._xyz, self.axes.M)
        return xy2d

    @xy.setter
    def xy(self, val):
        # publicly set
        self._xy = val

    @xy.deleter
    def xy(self):
        self._xy = None

# replace ax.annotate(*args, **kwargs) by annotateND(ax, *args, **kwargs)
def annotateND(ax: Union[plt.Axes, plt3d.axes3d.Axes3D], text: str,
               xy: Tuple[float, ...], *args, **kwargs) -> Union[Annotation3D, Annotation]:
    """
    Add annotation to 3D axes

    Args:
        ax: target (parent) axes
        text: Annotation text
        xy: annotation co-ordinates
        *args: passed to `matplotlib.text.Annotation`
        **kwargs: passed to `matplotlib.text.Annotation`

    Returns:
        AnnotationD
    """

    if isinstance(ax, plt3d.axes3d.Axes3D):
        a = Annotation3D(text, xy, *args, **kwargs)
        ax.add_artist(a)
        return a
    return ax.annotate(text, xy, *args, **kwargs)


向 2D 或 3D 轴的annotateND(ax, *args, **kwargs)无缝替换所有ax.annotate(*args, **kwargs)迈出了一步。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM