如何在 pgfplots 中进行仿射坐标变换?

如何在 pgfplots 中进行仿射坐标变换?

可以通过组合shiftxy键(或仅使用通用cm键来设置坐标矩阵和移位)在 TikZ 中执行一般仿射坐标变换。这允许人们编写自然的代码来绘制例如移位、倾斜、倾斜的抛物线:

\tikzset{shift = {(2,3)}, x = {(1,-2)}, y = {(5,1)}}
\draw plot (\x, \x^2);

我不使用 TikZ 来绘制函数,因为绘制轴和处理缩放很麻烦;我使用pgfplots。不幸的是,因为该包实现缩放问题解决方案的方式,其坐标与周围 TikZ 图片的坐标之间没有直接联系,这意味着这些相同的键在内部传递时不会产生预期的效果axis

现在,我知道有 和 这样的东西axis csaxis direction cs我也知道“TikZ 互操作性”部分的内容,但两者都不是我想要的。如果我正在绘制蒂克兹图片,后者让我负责轴的大小。使用,比如说,shift = {(axis direction cs:2,3)}实际上并没有放置计算原点(与轴原点相比,轴原点有更好的保持在原始位置(0,0)!)在轴坐标处(2,3)(其他两个明显的替代坐标系也不如此)。我想要以下内容:

  • 一种方法是局部坐标变换在 内部,根据仿射变换scope移动通过 给出的图。\addplot

  • pgfplots这个变化的透明度:我希望能够毫不费力地使用它的缩放坐标。

如果可用的选项中有仿射变换就太好了,data cs但它只做极坐标变换。我也不热衷于弄清楚如何使用\pgfplotsdefinecstransform它来做这个简单的事情。

下面是一个可以采用这种解决方案的示例:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}

\begin{tikzpicture}\begin{axis}

% What I want to write
\begin{scope}[ % Equivalent of:
  % shift = {(0.5,0.5)},
  % x = {(1,-1)},
  % y = {(2, 1)},
  %% Other options, such as:
  /pgfplots/every axis plot/.append style = {very thick}
]
 \addplot ({0.5*exp(x)}, {0.75*exp(-x)});
\end{scope}

% What I now have to write
\begin{scope}[
  /pgfplots/every axis plot/.append style = {very thick}
]
 \addplot ({0.5 + 0.5*exp(x) + 0.75*2*exp(-x)},
           {0.5 + 0.5*-1*exp(x) + 0.75*exp(-x)});
\end{scope}

\end{axis}\end{tikzpicture}

\end{document}

我想您能明白我为什么想要这个。(对于好奇的人,我正在绘制一些线性微分方程组解的轨迹。)

答案1

Pgfplots 有几个不同的坐标映射。这里你需要的是filter point:它接受输入/data point/x/data point/y可以修改每个输入值。

你的示例可以变成:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\thispagestyle{empty}

\begin{tikzpicture}\begin{axis}

% What I want to write
\begin{scope}[ % Equivalent of:
  % shift = {(0.5,0.5)},
  % x = {(1,-1)},
  % y = {(2, 1)},
  %% Other options, such as:
  /pgfplots/every axis plot/.append style = {very thick},
  /pgfplots/filter point/.code={%
    \pgfkeysgetvalue{/data point/x}\X
    \pgfkeysgetvalue{/data point/y}\Y
    %
    \def\eXX{1}%
    \def\eXY{-1}%
    %
    \def\eYX{2}%
    \def\eYY{1}%
    %
    \def\sX{0.5}%
    \def\sY{0.5}%
    %
    \pgfmathparse{\X * \eXX + \Y * \eYX + \sX}%
    \let\outX=\pgfmathresult
    %
    \pgfmathparse{\X * \eXY + \Y * \eYY + \sY}%
    \let\outY=\pgfmathresult
    %
    \pgfkeyslet{/data point/x}\outX
    \pgfkeyslet{/data point/y}\outY
  },
]
 \addplot ({0.5*exp(x)}, {0.75*exp(-x)});
\end{scope}
\end{axis}\end{tikzpicture}

\begin{tikzpicture}\begin{axis}

% What I now have to write
\begin{scope}[
  /pgfplots/every axis plot/.append style = {very thick}
]
 \addplot ({0.5 + 0.5*exp(x) + 0.75*2*exp(-x)},
           {0.5 + 0.5*-1*exp(x) + 0.75*exp(-x)});
\end{scope}

\end{axis}\end{tikzpicture}

\end{document}

在此处输入图片描述

我意识到不同的坐标变换在参考手册中有很好的参考,但它们的关系和顺序没有记录。我添加了一个部分“变换的相互作用”(将作为 pgfplots 不稳定的手册提供http://pgfplots.sourceforge.net/在接下来的几天里)。

答案2

为了补充 Christian 的回答,以下是我实际在做的事情。代码相同,但更加精致/可重复使用。

\def\pt(#1,#2)#3{%
  \expandafter\def\csname#3X\endcsname{#1}
  \expandafter\def\csname#3Y\endcsname{#2}
}%
\pgfplotsset{
  % x-vec, y-vec, shift
  affine cs/.style n args = {3}{
    /pgfplots/filter point/.code = {
      \pgfkeysgetvalue{/data point/x}\X
      \pgfkeysgetvalue{/data point/y}\Y
      \pt#1{xvec}
      \pt#2{yvec}
      \pt#3{shift}
      \pgfmathparse{\xvecX*\X+\yvecX*\Y+\shiftX}
      \pgfkeyslet{/data point/x}\pgfmathresult
      \pgfmathparse{\xvecY*\X+\yvecY*\Y+\shiftY}
      \pgfkeyslet{/data point/y}\pgfmathresult
    }
  },
}

也许我选择的名字\pt不太好。但它确实有在代码中创建一长行 's 的有益效果\p:) 然后可以通过以下方式使用密钥

/pgfplots/affine cs = {(x-vec)}{(y-vec)}{(shift-vec)}

在一个轴或者一个范围内。

相关内容