[英]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#Axes3D和https://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.