广义:访问 TikZ 坐标的逻辑值

广义:访问 TikZ 坐标的逻辑值

在另一个关于访问逻辑坐标的问题中

访问 TikZ 坐标的逻辑值

我使用了这些函数,直到我得到一个缩放的 tikzpicture,然后它就关闭了。我现在为缩放添加了一个因子,但我正在寻找一种使其通用的方法。这意味着 xcoord/ycoord 将通过 tikz/pgf 变量考虑图片的缩放。

\makeatletter
\newcommand\xcoord[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathprintnumber{\pgfmathresult}%
}}
\newcommand\ycoord[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@y/\pgf@yy}%
  \pgfmathprintnumber{\pgfmathresult}%
 }}
 \makeatother

有这方面的建议吗?

MWE 是:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgffor}

\makeatletter
\newcommand\xcoorda[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathprintnumber{\pgfmathresult}%
}}

\makeatletter
\newcommand\xcoord[2][center]{{%
 \pgfpointanchor{#2}{#1}%
 \pgfmathparse{\pgf@x/\pgf@xx/.17}%
 \pgfmathprintnumber{\pgfmathresult}%
}}

\newcommand\ycoorda[2][center]{{%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@y/\pgf@yy}%
  \pgfmathprintnumber{\pgfmathresult}%
}}
\makeatother

\usetikzlibrary{intersections}


\begin{document}

\begin{tikzpicture}[domain=-0.01:0.55,xscale=17,yscale=0.01] 
% the scaling is also in xcoord
\draw[-stealth,name path=xline] (0,0) -- (0.55,0);
\draw[stealth-stealth,name path=yline] (0,-220) -- (0,220);
\draw[color=blue,name path=func] (0,200) parabola bend (.25,-50) (.50,200);
\path[name intersections={of=func and xline,by={i1,i2}}];
\node[above=15pt] (i1label) at(i1) {\xcoord{i1}\%};
\draw[-stealth,green] (i1label.south) -- (i1);
\node[below=20pt,text width=2cm,align=center,draw,fill=red!25] (i1label_a) 
 at(i1) {\xcoorda{i1}\%\\ sans scaling \\ wrong!};
\draw[-stealth,red] (i1label_a.north) -- (i1);
\node[above=15pt] (i2label) at(i2) {\xcoord{i2}\%};
\draw[-stealth,green] (i2label.south) -- (i2);
\node[below=20pt,text width=2cm,draw,align=center,fill=red!25] (i2label_a) 
 at(i2) {\xcoorda{i2}\%\\ sans scaling \\ wrong!};
\draw[-stealth,red] (i2label_a.north) -- (i2);
\foreach \t in {10,20,...,50} {
\pgfmathparse{\t/100}\edef\v{\pgfmathresult}
  \draw[thin] (\v,10) -- (\v,-10) node[below] {\t\%};
}
\foreach \t in {-200,-100,...,200} {
 \draw[thin] (.010,\t) -- (-0.01,\t) node[left] {\small\t};
}
\end{tikzpicture}

\end{document}

我在 MWE 中使用了抛物线,并在两种情况下标记了缩放和未缩放的 xcoord。

答案1

问题出现是因为\xcoorda在节点内部调用了 ,这会重置变换矩阵,因此\pgf@xx无法正确缩放。要避免这种情况,您可以做的是在 using 开始时将变换矩阵保存到宏中tikzpicture\pgfgettransform{<macro>}然后在\xcoorda宏 using中设置它\pgfsettransform{<macro>}。为了在表达式中使用结果坐标\pgfmathparse,我建议将宏转换为pgfmath函数。我已在下面的代码中包含了这种方法。

获取逻辑坐标

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections}

\makeatletter
\newcommand\xcoorda[2][center]{{%
%
% Set the transformation matrix that was saved at the beginning of the tikzpicture
%
  \pgfsettransform{\transform}%
  \pgfpointanchor{#2}{#1}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
  \pgfmathresult%
}}

\pgfmathdeclarefunction{xcoord}{1}{
  \pgfsettransform{\transform}%
  \pgfpointanchor{#1}{center}%
  \pgfmathparse{\pgf@x/\pgf@xx}%
}

\makeatother

\begin{document}

\begin{tikzpicture}[domain=-0.01:0.55,xscale=17,yscale=0.01] 

% Save the transformation matrix
\pgfgettransform{\transform}

\draw[-stealth,name path=xline] (0,0) -- (0.55,0);
\draw[stealth-stealth,name path=yline] (0,-220) -- (0,220);
\draw[color=blue,name path=func] (0,200) parabola bend (.25,-50) (.50,200);
\path[name intersections={of=func and xline,by={i1,i2}}];
\node[below=20pt,text width=2cm,align=center,draw,fill=green!25] (i1label_a) 
 at(i1) {\xcoorda{i1}\\correct};
\draw[-stealth,red] (i1label_a.north) -- (i1);
\node[below=20pt,text width=2cm,draw,align=center,fill=green!25] (i2label_a) 
 at(i2) {\pgfmathparse{xcoord("i2")*100}\pgfmathprintnumber{\pgfmathresult}\,\%\\ correct};
\draw[-stealth,red] (i2label_a.north) -- (i2);
\foreach \t in {10,20,...,50} {
\pgfmathsetmacro\v{\t/100}
  \draw[thin] (\v,10) -- (\v,-10) node[below] {\t\%};
}
\foreach \t in {-200,-100,...,200} {
 \draw[thin] (.010,\t) -- (-0.01,\t) node[left] {\small\t};
}
\end{tikzpicture}

\end{document}

如果您使用 PGFplots,则可以避免手动保存和恢复坐标转换,因为在这种情况下,您可以使用\pgfplotsunitxlength,它保存 x 单位向量的长度乘以 1000,以及\pgfplotspointaxisorigin,它保存当前轴的点 (0,0):

pgfplots 逻辑坐标

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{intersections}

\newcommand\xcoord[2][center]{{%
    \pgfpointanchor{#2}{#1}%
    \pgfgetlastxy{\ix}{\iy}%
    \pgfplotspointaxisorigin%
    \pgfgetlastxy{\ox}{\oy}
    \pgfmathparse{(\ix-\ox)/\pgfplotsunitxlength/1000}
    \pgfmathprintnumber{\pgfmathresult}}
}

\begin{document}

\vspace{1cm}
\begin{tikzpicture}
\begin{axis}[
    domain=0:0.5,
    samples=100,
    no markers,
    axis lines=middle,
    enlarge x limits=upper,
    enlarge y limits=true,
    xticklabel=\pgfmathparse{\tick*100}\pgfmathprintnumber{\pgfmathresult}\,\%,
    x axis line style={{name path global=xaxis}}
    ]
\addplot +[name path global=plot] {4000*(x-0.25)^2-50};

\pgfplotsextra{
\fill [name intersections={of=xaxis and plot, name=i, total=\t}] 
    [red, every node/.style={black}] 
    (i-1) circle (2pt) node [pin={\xcoord{i-1}}] {}
    (i-2) circle (2pt) node [pin={\xcoord{i-2}}] {};
}
\end{axis}
\end{tikzpicture}
\end{document}

相关内容