pgfplots + animate:旋转 3D 轴系统并保持大小不变

pgfplots + animate:旋转 3D 轴系统并保持大小不变
  • 目标:我想旋转完整的 3D 图表(轴系统),同时保持“感知大小”不变。
  • 我的当前版本(参见 MWE)原则上有效。
  • 问题:问题在于图表一直在“改变大小”(它正在“呼吸”/“抽水”)。
  • 问题:我怎样才能保持尺寸不变(从人类的角度来看)?
  • 我想我几年前看到过一篇相关的帖子,但我没有找到它。

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{animate}

\begin{document}

\begin{animateinline}[controls]{20}
\multiframe{200}{rAngle=25+1}{
    \begin{tikzpicture}
    \begin{axis}[
        view = {\rAngle}{30}, % <-- Rotate View
        scale only axis,
        unit vector ratio = 1 1 1,
        ]
    \addplot3[surf, mesh/rows=3] coordinates {
    (0,0,0) (1,0,0) (2,0,0) (3,0,0)
    (0,1,0) (1,1,0.6) (2,1,0.7) (3,1,0.5)
    (0,2,0) (1,2,0.7) (2,2,0.8) (3,2,0.5)
    };
    \end{axis}
    \end{tikzpicture}
}
\end{animateinline}

\end{document}

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述

答案1

Tikz 会自动计算图片中图形元素的边界框,从而确定其最终的整体大小。从不同角度观看时,投影在画布上的轴框的大小会发生变化,从而导致观察到的“抽吸”。

解决此问题的方法是放置一个图形对象,该对象在旋转时不会改变其在画布上的 2d 投影,并且包含绘图的所有部分。最适合此目的的是轴与旋转轴对齐的边界圆柱体。

边界圆柱隐藏 ( draw=none):

在此处输入图片描述

图示气缸:

在此处输入图片描述

\documentclass[export]{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{animate}

\begin{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% fix axes to these ranges (depending on the data to be plotted, of course)
\def\xmin{-0.2}
\def\xmax{3.2}
\def\ymin{-0.2}
\def\ymax{2.2}
\def\zmin{-0.2}
\def\zmax{1.2}
% bounding cylinder based on axes ranges with some scaling and z-offsets to also
% include tick labels
\def\scaleCylRadius{1.25}
\pgfmathsetmacro\cylCentreX{0.5*(\xmin+\xmax)}
\pgfmathsetmacro\cylCentreY{0.5*(\ymin+\ymax)}
\pgfmathsetmacro\cylRadius{\scaleCylRadius*sqrt((\xmax-\xmin)^2+(\ymax-\ymin)^2))/2}
\pgfmathsetmacro\cylZMin{\zmin - 0.02}
\pgfmathsetmacro\cylZMax{\zmax + 0.0}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{animateinline}[controls]{20}
\multiframe{60}{rAngle=25+6}{
  \begin{tikzpicture}
  \begin{axis}[
    view = {\rAngle}{30}, % <-- Rotate View
    unit vector ratio = 1 1 1,
    trig format plots=rad,
    xmin=\xmin,xmax=\xmax,
    ymin=\ymin,ymax=\ymax,
    zmin=\zmin,zmax=\zmax,
    clip=false, % don't clip cylinder circles to axes ranges
  ]
    % lower circle
    \addplot3[
      draw=none, % comment out to see cylinder circles
      domain=0:2*pi,samples=60]({\cylCentreX+\cylRadius*sin(x)},{\cylCentreY+\cylRadius*cos(x)},\cylZMin);
    % data
    \addplot3[surf, mesh/rows=3] coordinates {
    (0,0,0) (1,0,0) (2,0,0) (3,0,0)
    (0,1,0) (1,1,0.6) (2,1,0.7) (3,1,0.5)
    (0,2,0) (1,2,0.7) (2,2,0.8) (3,2,0.5)
    };
    % upper circle
    \addplot3[
      draw=none,
      domain=0:2*pi,samples=60]({\cylCentreX+\cylRadius*sin(x)},{\cylCentreY+\cylRadius*cos(x)},\cylZMax);
  \end{axis}
  \end{tikzpicture}
}
\end{animateinline}

\end{document}

答案2

这让我想起:使用 tikz 在球体上绘制抛物线莫比乌斯地图

@Fritz 用旋转坐标系给出了答案。我不明白代码,但也许定义viewport就是用于这个目的!?

这是我的初步尝试:

\documentclass{article}
\usepackage{animate}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\tikzset{viewport/.style 2 args={
x={({cos(-#1)*1cm},{sin(-#1)*sin(#2)*1cm})},
y={({-sin(-#1)*1cm},{cos(-#1)*sin(#2)*1cm})},
z={(0,{cos(#2)*1cm})}
}}
\begin{document}
\begin{animateinline}[controls]{20}
\multiframe{200}{rAngle=25+1}{
\begin{tikzpicture}
\useasboundingbox (0,0) circle[radius=4];
\begin{axis}[
view = {\rAngle}{30},
disabledatascaling,  
anchor=origin,  
viewport={\rAngle}{30},
]
\addplot3[surf, mesh/rows=3] coordinates {
(0,0,0) (1,0,0) (2,0,0) (3,0,0)
(0,1,0) (1,1,0.6) (2,1,0.7) (3,1,0.5)
(0,2,0) (1,2,0.7) (2,2,0.8) (3,2,0.5)
};
\end{axis}
\end{tikzpicture}
}
\end{animateinline}
\end{document}

所有框架都相互叠置:

插入多帧表面图

需要进行更多的实验并理解代码。

相关内容