检测是否在 tikzpicture 内

检测是否在 tikzpicture 内

我想定义\DrawLine下面的宏,以便可以从中调用它之内环境{tikzpicture}或来自外部

\newcommand*{\DrawLine}[1]{%
  \IfInTikzPic{}{\tikzpicture[remember picture]}
      \draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};
  \IfInTikzPic{}{\endtikzpicture}%
}

当从 内部调用时,此方法可以正常工作{tikzpicture},但从外部调用时则不行(MWE 中注释了该行)。从外部调用会产生错误:

缺少插入的 \endgroup。

在此处输入图片描述

下面的 MWE 使用下面的第一个引用。其他两个引用也在注释掉的测试用例上失败了。

参考:

代码:

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand{\IfInTikzPic}[2]{% https://tex.stackexchange.com/a/121309/4301
  \ifx\pgfpictureid\@undefined#2\else#1\fi%
}
\makeatother

\newcommand*{\DrawLine}[1]{%
  \IfInTikzPic{}{\tikzpicture[remember picture]}
      \draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};
  \IfInTikzPic{}{\endtikzpicture}%
}

\begin{document}
%%% The commented out code here is to show that \IfInTikzPic works as desired
%%% (in a tikzpicture, outside of a \node).
%%%

%\textbf{IfInTikzPic}\par
%\IfInTikzPic{inside}{outside}
%
%\begin{tikzpicture}
%  \IfInTikzPic{\draw [red, ultra thick]}{\draw [blue, ultra thick]} (0,0) -- (1,0);
%\end{tikzpicture}
%
%\medskip% --------------------------
\textbf{DrawLine}: Actual Output\par

%\DrawLine{blue}% <---- How do I get this case to work?

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}

\medskip% --------------------------
\textbf{DrawLine}: Desired Output\par

\begin{tikzpicture}
  \DrawLine{blue}
\end{tikzpicture}

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}
\end{document}

答案1

下面的示例定义了\IfInTikzPic检查current environmenttikzpicture并相应地定义\tikzstart...\tikzend对:

在此处输入图片描述

\documentclass{article}

\usepackage{tikz}

\makeatletter
\def\@tikzenvironment{tikzpicture}

\newcommand{\IfInTikzPic}{%
  \edef\tikzstart{%
    \ifx\@currenvir\@tikzenvironment\else
      \noexpand\tikzpicture[remember picture]%
    \fi
  }%
  \edef\tikzend{%
    \ifx\@currenvir\@tikzenvironment\else
      \noexpand\endtikzpicture%
    \fi
  }%
}

\newcommand*{\DrawLine}[1]{%
  \IfInTikzPic
  \tikzstart
    \draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};
  \tikzend%
}
\makeatother

\begin{document}

\textbf{DrawLine}: Actual Output\par

\DrawLine{blue}

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}

\medskip% --------------------------

\textbf{DrawLine}: Desired Output\par

\begin{tikzpicture}
  \DrawLine{blue}
\end{tikzpicture}

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}

\end{document}

tikzpicture如果需要,您还可以对其进行分组:

\newcommand{\IfInTikzPic}{%
  \edef\tikzstart{%
    \ifx\@currenvir\@tikzenvironment\else
      \noexpand\begin{tikzpicture}[remember picture]%
    \fi
  }%
  \edef\tikzend{%
    \ifx\@currenvir\@tikzenvironment\else
      \noexpand\end{tikzpicture}%
    \fi
  }%
}

答案2

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand{\IfInTikzPic}{% https://tex.stackexchange.com/a/121309/4301
  \ifx\pgfpictureid\@undefined
    \expandafter\@firstoftwo
     \else
    \expandafter\@secondoftwo
    \fi
}
\makeatother

\newcommand*{\DrawLine}[1]{%
  \IfInTikzPic
   {\begin{tikzpicture}[remember picture]
    \draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};
   \end{tikzpicture}}%
    {\draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};}%
}

\begin{document}
%%% The commented out code here is to show that \IfInTikzPic works as desired
%%% (in a tikzpicture, outside of a \node).
%%%

\textbf{IfInTikzPic}\par
\IfInTikzPic{inside}{outside}

\begin{tikzpicture}
  \IfInTikzPic{\draw [red, ultra thick]}{\draw [blue, ultra thick]} (0,0) -- (1,0);
\end{tikzpicture}

\medskip% --------------------------
\textbf{DrawLine}: Actual Output\par

\DrawLine{blue}% <---- How do I get this case to work?

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}

\medskip% --------------------------
\textbf{DrawLine}: Desired Output\par

\begin{tikzpicture}
  \DrawLine{blue}
\end{tikzpicture}

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}
\end{document}

或者这个版本直接强制 tikz,而不是使用 if-then-else 构造

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand{\ensuretikz}{% https://tex.stackexchange.com/a/121309/4301
  \ifx\pgfpictureid\@undefined
    \expandafter\tikzify
     \else
    \expandafter\@firstofone
    \fi
}
\makeatother

\def\tikzify#1{\begin{tikzpicture}#1\end{tikzpicture}}

\newcommand*{\DrawLine}[1]{%
    \ensuretikz
    {\draw[ultra thick, ->, #1] (0,) -- (1,1) node [right] {output of DrawLine};}%
}

\begin{document}
%%% The commented out code here is to show that \IfInTikzPic works as desired
%%% (in a tikzpicture, outside of a \node).
%%%




\medskip% --------------------------
\textbf{DrawLine}: Actual Output\par

\DrawLine{blue}% <---- How do I get this case to work?

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}

\medskip% --------------------------
\textbf{DrawLine}: Desired Output\par

\begin{tikzpicture}
  \DrawLine{blue}
\end{tikzpicture}

\begin{tikzpicture}
  \DrawLine{orange}
\end{tikzpicture}
\end{document}

相关内容