在 TikZ 中检查一个点是否位于另一个点的右侧或左侧

在 TikZ 中检查一个点是否位于另一个点的右侧或左侧

尝试实现一种方便的方法来检查一个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负载的包)。

这是我的问题:

  1. 在注释的代码中,\ifnum扩展中究竟发生了什么,导致编译失败?
  2. 我该如何修复该\isRight命令以便能够与其一起使用\ifnum
  3. 如果问题 2 很棘手,我该如何影响\ifnum扩展以实现我的愿望?
  4. 有没有pgf更聪明/更直接的方法来检查一个TikZ点是否在另一个点的左侧/右侧?我的最终目标是仅当一个点在另一个点的右侧/左侧时才绘制某些东西。

附加问题:

  1. 如何(以及在​​哪里)\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}

 

    在此处输入图片描述

相关内容