尝试实现一种方便的方法来检查一个TikZ
点是在另一个点的右边还是左边,我想出了以下 MWE。
\documentclass[border=1mm, tikz]{standalone}
\makeatletter
% prints 1 if #1.center is right than #2.center, 0 otherwise
\newcommand{\isRight}[2]{
%\pgfpointdiff{a}{b} gives b-a
\pgfpointdiff{\pgfpointanchor{#2}{center}}{\pgfpointanchor{#1}{center}}
\pgfmathparse{greater(\pgf@x,0)}\pgfmathresult
}
% 1 if #1.center is left than #2.center, 0 otherwise -> result in \pgfmathresult
\newcommand{\checkIfLeft}[2]{
%\pgfpointdiff{a}{b} gives b-a
\pgfpointdiff{\pgfpointanchor{#2}{center}}{\pgfpointanchor{#1}{center}}%
\pgfmathparse{less(\pgf@x,0)}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[draw] (A) at (0,0) {A};
\node[draw] (B) at (1,0) {B};
\checkIfLeft{A}{B}
\ifnum\pgfmathresult=1
\node at (0.5,1){A is left of B};
\fi
%\ifnum\isRight{B}{A}=1
% \node at (0.5,-1){B is right of A};
%\fi
\end{tikzpicture}
\end{document}
但我对此很不满意。我希望拥有的是可以在构造中使用的东西\ifnum ... \fi
,如注释代码中所示(并且我不想使用超出pgf
负载的包)。
这是我的问题:
- 在注释的代码中,
\ifnum
扩展中究竟发生了什么,导致编译失败? - 我该如何修复该
\isRight
命令以便能够与其一起使用\ifnum
? - 如果问题 2 很棘手,我该如何影响
\ifnum
扩展以实现我的愿望? - 有没有
pgf
更聪明/更直接的方法来检查一个TikZ
点是否在另一个点的左侧/右侧?我的最终目标是仅当一个点在另一个点的右侧/左侧时才绘制某些东西。
附加问题:
- 如何(以及在哪里)
\pdfstrcmp{}{}
实现,因为在构造中使用它是无害的\ifnum ... \fi
?
答案1
以下是一些基于的低级代码这个答案不使用calc
。
\documentclass[tikz,border=7pt]{standalone}
\newif\ifleft
\makeatletter
\def\isleft(#1)of(#2)?{%
\tikz@scan@one@point\pgfutil@firstofone(#1)\relax%
\pgf@xa=\pgf@x%
\tikz@scan@one@point\pgfutil@firstofone(#2)\relax%
\ifdim\pgf@xa<\pgf@x\relax\lefttrue\else\leftfalse\fi
}
\makeatother
\begin{document}
\begin{tikzpicture}[nodes=circle]
\node[draw] (A) at (0,0) {A};
\node[draw] (B) at (2,1) {right of A};
\isleft(A)of(B)?
\path (A) \ifleft edge[latex-] (B) \else edge[-latex] (B) \fi ;
\foreach~in{1,...,70}
\path[ultra thin] ({180*rand}:1) coordinate(N)
\pgfextra{\isleft(N)of(A)?}
\ifleft [red] \else [blue] \fi node[scale=2]{.}
(N) \ifleft edge[latex-] (A) \else edge[-latex] (A) \fi;
\end{tikzpicture}
\end{document}
答案2
怎么样
\documentclass[border=1mm, tikz]{standalone}
\usetikzlibrary{calc}
\tikzset{if left/.style n args={4}{insert path={%
let \p1=($#1-#2$) in \ifdim\x1<0pt
#3
\else
#4
\fi}}}
\begin{document}
\begin{tikzpicture}
\node[draw] (A) at (0,0) {A};
\node[draw] (B) at (1,0) {B};
\path[if left={(A)}{(B)}{(0.5,1) node {A is left of B}}{}];
\path[if left={(B)}{(A)}{(0.5,-1) node {B is left of A}}{}];
\end{tikzpicture}
\end{document}
答案3
仅供将来参考,我想分享一下 Kpym 在他的回答中所建议的一点细节。为了避免出现\newif
,可以为宏提供另外两个参数。当然,使用 可以\ifleft
提供多种使用方式(正如 Kpym 的回答中很好地展示的那样),但也许这并不是真正需要的(就像我的情况一样)。
\documentclass[border=1mm, tikz]{standalone}
\makeatletter
\long\def\IfLeft(#1)of(#2)#3#4{%
\tikz@scan@one@point\pgfutil@firstofone(#1)\relax%
\pgf@xa=\pgf@x%
\tikz@scan@one@point\pgfutil@firstofone(#2)\relax%
\ifdim\pgf@xa<\pgf@x\relax#3\else#4\fi
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[draw] (A) at (0,0) {A};
\node[draw] (B) at (1,0) {B};
\node[draw] (C) at (2,0) {C};
\IfLeft(A)of(B){%
\foreach \n in {10,20,...,90}{
\fill[red!\n!yellow] (0.5,0) ++(\n/100,0.5) circle(1mm);
}
}{%
\foreach \n in {10,20,...,90}{
\fill[black!\n!gray] (0.5,0) ++(\n/100,-0.5) circle(1mm);
}
}
\IfLeft(C)of(B){%
\foreach \n in {10,20,...,90}{
\fill[black!\n!gray] (0.5,0) ++(\n/100,0.5) circle(1mm);
}
}{%
\foreach \n in {10,20,...,90}{
\fill[blue!\n!magenta] (0.5,0) ++(\n/100,-0.5) circle(1mm);
}
}
\end{tikzpicture}
\end{document}