我正在尝试解决这个问题如何与 TikZ 和 Pgfplots 保持一致性?本质上,需要一种将坐标保存为宏(或者可能是全局键?)的方法,然后可以<x>,<y>
在正常节点/路径和 pgfplots 图中使用它来代替通常的对。
澄清一下:我希望能够定义一个宏\PointA
,每当需要语法时都可以调用它(<x>,<y>)
。这可能是在节点定义中使用\node at (<x>,<y>) {};
,或者在 pgfplots 图中使用\addplot coordinates { (0,0) (<x>,<y>) (1,1) };
对于普通节点和路径,仅使用就\def\<name>{<x>,<y>}
可以正常工作,但是当我尝试将其用作 pgfplots 图中的坐标时,它会失败并显示错误消息:
File ended while scanning use of \pgfplots@foreach@plot@coord@NEXT.
又是扩展问题?还是我应该采用完全不同的方法?
\documentclass{article}
\usepackage{pgfplots}
\def\PointA{1,2}
\begin{document}
\begin{tikzpicture}
\draw [gray] (0,0) grid (3,3);
\fill (\PointA) circle (2pt); % Works
\begin{axis}[xshift=3.5cm,width=6cm,xmin=0,xmax=3,ymin=0,ymax=3,grid=both]
\fill [orange] (axis cs:\PointA) circle (4pt); % Works
\addplot coordinates { (0,0) (1,2) (2,2) }; % Works
% \addplot coordinates { (0,0) (\PointA) (2,2) }; % Fails
\end{axis}
\end{tikzpicture}
\end{document}
答案1
实现此目的的一种方法是修补负责读取坐标的内部宏。检测到开口后将调用\pgfplots@foreach@plot@coord@NEXT
in并从输入流中读取。在您的示例中,您有,因此被视为 X 和Y 部分。想法是修补此宏以展开下一个标记以显示其中的。这可以使用以下代码完成:pgfplotscoordprocessing.code.tex
(
(#1,#2)
(\PointA) (2,2)
\PointA) (2
2
(
,
\documentclass{article}
\usepackage{pgfplots}
\def\PointA{1,2}
\makeatletter
\let\orig@pgfplots@foreach@plot@coord@NEXT\pgfplots@foreach@plot@coord@NEXT
\def\pgfplots@foreach@plot@coord@NEXT{%
\expandafter\orig@pgfplots@foreach@plot@coord@NEXT\expandafter
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw [gray] (0,0) grid (3,3);
\fill (\PointA) circle (2pt); % Works
\begin{axis}[xshift=3.5cm,width=6cm,xmin=0,xmax=3,ymin=0,ymax=3,grid=both]
\fill [orange] (axis cs:\PointA) circle (4pt); % Works
% \addplot coordinates { (0,0) (1,2) (2,2) }; % Works
\addplot coordinates { (0,0) (\PointA) (2,2) }; % Works now!!
\end{axis}
\end{tikzpicture}
\end{document}
另一种方法是修补负责读取{ }
之后的宏coordinate
,以便在进一步处理该参数之前完全扩展该参数。这样做的好处是,您可以包含保存多个坐标的宏或其他无法使用上述代码扩展的宏。调用有问题的宏\pgfplots@addplotimpl@coordinates@
并将坐标读取为#3
。以下代码使用扩展该参数\edef
:
\documentclass{article}
\usepackage{pgfplots}
\def\PointA{1,2}
\def\mycoordinates{ (1,0) (2,1) (3,0) }
\makeatletter
\long\def\pgfplots@addplotimpl@coordinates@#1#2#3#4{%
\pgfplots@start@plot@with@behavioroptions{#1,/pgfplots/.cd,#2}%
\pgfplots@PREPARE@COORD@STREAM{#4}%
\begingroup
\edef\@tempa{{#3}}%
\ifpgfplots@curplot@threedim
\expandafter\endgroup\expandafter
\pgfplots@coord@stream@foreach@threedim\@tempa
\else
\expandafter\endgroup\expandafter
\pgfplots@coord@stream@foreach\@tempa
\fi
}%
\makeatother
\begin{document}
\begin{tikzpicture}
\draw [gray] (0,0) grid (3,3);
\fill (\PointA) circle (2pt); % Works
\begin{axis}[xshift=3.5cm,width=6cm,xmin=0,xmax=3,ymin=0,ymax=3,grid=both]
\fill [orange] (axis cs:\PointA) circle (4pt); % Works
% \addplot coordinates { (0,0) (1,2) (2,2) }; % Works
\addplot coordinates { (0,0) (\PointA) (2,2) }; % Works now!!
\addplot coordinates \mycoordinates; % Works as well!!
\addplot coordinates { (0,1) \mycoordinates (6,7) }; % Works as well!!
\end{axis}
\end{tikzpicture}
\end{document}
或者,您可以定义\PointAX
然后\PointAY
写入(\PointAX,\PointAY)
哪些也应该可以在没有任何补丁的情况下工作。
答案2
您可以单独存储每个坐标或定义一个表:
\documentclass{article}
\usepackage{pgfplots}
\def\PointAx{1}
\def\PointAy{2}
\def\PointA{\PointAx,\PointAy}
\pgfplotstableread{%
2 2
}{\PointB}
\begin{document}
\begin{tikzpicture}
\draw [gray] (0,0) grid (3,3);
\fill (\PointA) circle (2pt); % Works
\begin{axis}[xshift=3.5cm,width=6cm,xmin=0,xmax=3,ymin=0,ymax=3,grid=both]
\fill [orange] (axis cs:\PointA) circle (4pt); % Works
\addplot coordinates { (1,2) }; % Works
\addplot coordinates { (\PointAx,\PointAy) }; % Works
\addplot table {\PointB}; % Works
\end{axis}
\end{tikzpicture}
\end{document}
答案3
换个角度来看这个问题:
\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\def\PointA{1,2}
\def\PointB{coordinates {(3,3)}}
\begin{document}
\begin{tikzpicture}
\draw [gray] (0,0) grid (3,3);
\fill (\PointA) circle (2pt); % Works
\begin{axis}[xshift=3.5cm,width=6cm,xmin=0,xmax=3,ymin=0,ymax=3,grid=both]
\fill [orange] (axis cs:\PointA) circle (4pt); % Works
\expandafter\addplot\PointB; % Works
\end{axis}
\end{tikzpicture}
\end{document}
这是一个简单干净的解决方案。可以对其进行修改。例如,您可以定义一个宏:
\def\Coordinates#1#2{%
\def\A{#1}
\def\B{#2}
\def\PointB{coordinates {(\A,\B)}}
\expandafter\addplot\PointB;
}
这也可以起作用,只需从内部调用它\begin{axis}
...。\end{axis}