定义 TikZ 常量的首选方法是什么?

定义 TikZ 常量的首选方法是什么?

我正在绘制一个 TikZ 图形,需要几个可以在编译之间轻松更改的常数,例如主半径、比例、线数等。定义这些的首选方法是什么?

它不只是一个\draw命令,所以我想我不能使用let

答案1

使用\newcommand\pgfmathsetmacro

由于您只打算更改.tex包含的最深文件中的参数tikzpicture,因此我将使用\newcommand*{\Name}{}%它来设置值并使用\Name来访问它们。

但是,如果某些参数的值是通过数学方法从另一个参数计算出来的,那么我建议使用\pgfmathsetmacro{\NewName}{}。例如:

\newcommand*{\Diameter}{3.0}%
\pgfmathsetmacro{\Radius}{\Diameter/2}%
\pgfmathsetmacro{\Circumference}{2*pi*\Radius}%

当计算稍微复杂一些时,这将非常有用。

但是,如果您想考虑从父文档更改它们,您可以改为在文档\providecommand{}{}中使用tikzpicture来设置参数。这样您就可以在父文档中更改参数。这种方法的一个缺点是,存在在其他地方定义该值的风险,也不会在中触发任何错误tikzpicture

使用\pgfmathsetnewmacro

正如评论中指出的\pgfmathsetmacro那样,使用,\def因此如果您覆盖现有的宏名称,则不会产生错误。因此,您可以改为使用\pgfmathsetnewmacro如下定义 -\newcommand在调用之前,这会发出一个来检查宏是否不存在\pgfmathsetmacro

\newcommand*{\pgfmathsetnewmacro}[2]{%
    \newcommand*{#1}{}% Error if already defined
    \pgfmathsetmacro{#1}{#2}%
}%

如果您正在定义其中的值tikzpicture并且不担心覆盖任何先前定义的值,那么您可以使用\def\pgfmathsetmacro

更新:使用问题\def

评论建议,如果你定义这些常量之内环境中,任何通过或tikzpicture意外覆盖现有宏的情况都会\def\pgfmathsetmacro不是导致任何外部问题,tikzpicture因为重新定义只会在tikzpicture环境本地进行。这是不是完全准确,因为它导致tikzpicture环境内部出现问题,这是我经过几个小时的调试后才发现的。

随着错误的考虑到在本地范围内使用没有问题\def,我决定更改难以阅读(如果在开头添加其他参数则难以修改)的宏,例如:

\newcommand*{\DrawXAxis}[3][]{%
    \draw [ultra thick, #1] (#2,0) -- (#3,0)%
}%

像这样:

\newcommand*{\DrawXAxisReadable}[3][]{%
    \def\XAxisStyle{#1}
    \def\XAxisMin{#2}
    \def\XAxisMax{#3}
    \draw [ultra thick, \XAxisStyle] (\XAxisMin,0) -- (\XAxisMax,0)%
}%

我认为如果我在这个宏内覆盖则没有问题,\XAxisMin因为我不需要以前设置的任何内容,并且无论如何它都会在这个宏结束时恢复。

嗯,这没问题最多案件——但是不好如果某个父宏已定义\XAxisMin并将其作为参数传递给此宏。下面的代码说明了这一点。它按原样编译得很好,但如果你取消注释,最后一个则tikzpicture似乎pdflatex陷入了无限循环。


测试代码:

\documentclass{standalone}
\usepackage{tikz}

%\def\Diameter{}% Error from \newcommand if this is uncommented
%\def\Radius{}% Error from \pgfmathsetnewmacro if this is uncommented
%\def\Circumference{}% Error from \pgfmathsetnewmacro if this is uncommented


% This bascially automates a \newcommand{<name>}{} to ensure
% that a command with the given <name> does not already exist
\newcommand*{\pgfmathsetnewmacro}[2]{%
    \newcommand*{#1}{}% Error if already defined
    \pgfmathsetmacro{#1}{#2}%
}%

\begin{document}
\newcommand*{\Diameter}{3.0}%

\pgfmathsetnewmacro{\Radius}{\Diameter/2}%
\pgfmathsetnewmacro{\Circumference}{2*pi*\Radius}%

\newcommand{\Origin}{(0,0)}%

\begin{tikzpicture}
    \draw \Origin circle (\Radius);
\end{tikzpicture}
\end{document}

代码:使用时出现\def问题tikzpicture

\documentclass{article}
\usepackage{tikz}

\newcommand*{\XAxisMin}{0}%
\newcommand*{\XAxisMax}{5}%

\newcommand*{\DrawXAxis}[3][]{%
    \draw [ultra thick, #1] (#2,0) -- (#3,0)%
}%

\newcommand*{\DrawXAxisReadable}[3][]{%
    \def\XAxisStyle{#1}
    \def\XAxisMin{#2}
    \def\XAxisMax{#3}
    \draw [ultra thick, \XAxisStyle] (\XAxisMin,0) -- (\XAxisMax,0)%
}%

\begin{document}
\begin{tikzpicture}
    \DrawXAxis[black]{\XAxisMin}{\XAxisMax};
\end{tikzpicture}

\begin{tikzpicture}
    \DrawXAxisReadable[blue]{0}{5};
\end{tikzpicture}

%%% Un comment this to see the problem
%\begin{tikzpicture}
%   \DrawXAxisReadable[red]{\XAxisMin}{\XAxisMax};
%\end{tikzpicture}
\end{document}

答案2

使用\def

我通常更喜欢\def比更短的\newcommand问题是, \def不检查是否已经存在,所以可能被覆盖.但我\def只使用 initions里面 {tikzpicture}并且可能的覆盖仅存在于当前组中{tikzpicture}

\documentclass[border=1cm]{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
   \def\radius{1cm}
   \draw circle (\radius);
\end{tikzpicture}
\end{document}

在上面的例子中,\radius仅在其内部定义{tikzpicture}并且只能在其内部使用。

下一个示例显示\def可能会产生不理想的结果

\documentclass[border=1cm]{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
   \def\bfseries{1mm}
   \draw [line width=\bfseries] circle (2cm);
   \node {\bfseries That's the problem.};
\end{tikzpicture}
\end{document}

使用\newcommand

如果我需要一个全局变量,我更喜欢它,\newcommand因为如果我尝试使用已经存在的宏名,它会出现错误。

\documentclass[border=1cm]{standalone}

\usepackage{tikz}

\newcommand\radius{1cm}

\begin{document}
\begin{tikzpicture}
   \draw circle (\radius);
\end{tikzpicture}

\begin{tikzpicture}
   \draw [red] circle (\radius);
\end{tikzpicture}
\end{document}

与“使用”中的第二个示例相同,\def但使用\newcommand。如果我们现在尝试使用现有命令(\bfseries)作为 TikZ 变量,我们会收到已定义的错误消息\bfseries。因此,用户必须决定是否重新定义它或使用其他名称,这是本例中的推荐方法。

\documentclass[border=1cm]{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
   \newcommand\bfseries{1mm}
   \draw [line width=\bfseries] circle (2cm);
   \node {\bfseries That's the problem.};
\end{tikzpicture}
\end{document}

相关内容