可以通过组合shift
、x
和y
键(或仅使用通用cm
键来设置坐标矩阵和移位)在 TikZ 中执行一般仿射坐标变换。这允许人们编写自然的代码来绘制例如移位、倾斜、倾斜的抛物线:
\tikzset{shift = {(2,3)}, x = {(1,-2)}, y = {(5,1)}}
\draw plot (\x, \x^2);
我不使用 TikZ 来绘制函数,因为绘制轴和处理缩放很麻烦;我使用pgfplots
。不幸的是,因为该包实现缩放问题解决方案的方式,其坐标与周围 TikZ 图片的坐标之间没有直接联系,这意味着这些相同的键在内部传递时不会产生预期的效果axis
。
现在,我知道有 和 这样的东西axis cs
,axis 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)}
在一个轴或者一个范围内。