假设我想绘制无穷符号的变体(主要是因为我不会画鸭子,尽管鸭子可以很好地完成 MWE)。我找不到使用 pgf/tikz 键以简洁的方式操纵 tikz 图片绘制方式的简单示例。查看我自己的代码库,似乎我自己对这个主题也相当困惑。
要求 :
让我们允许通过 和 键改变形状的大小width
,并使用和height
键使叶片能够摆动。最重要的是,我们要在各种书法笔之间进行选择,这必须通过代码进行设置。这通过选择和 'right' 来控制。inner target
outer target
left
pen
代码 :
对于此示例,您将需要spath
和calligraphy
样式文件,可用这里,可作为spath3
包和 tikzcalligraphy
库使用。
\documentclass[tikz]{standalone}
\usepackage{spath}
\usepackage{calligraphy}
\usetikzlibrary{calc}
\makeatletter
\tikzset{
infinity/.is family,
infinity/.pic = {
% This is the curve we wish to have drawn
\calligraphy let \p1=(0,0) in
(\p1) .. controls (-\infty@upper*\infty@width, \infty@height) and (-\infty@lower*\infty@width,-\infty@height) ..
(\p1) .. controls ( \infty@lower*\infty@width, \infty@height) and ( \infty@upper*\infty@width,-\infty@height) .. cycle;;
% This curve is simply here as a backup
\draw[line width=0.1, blue] let \p1=(0,0) in
(\p1) .. controls (-\infty@upper*\infty@width, \infty@height) and (-\infty@lower*\infty@width,-\infty@height) ..
(\p1) .. controls ( \infty@lower*\infty@width, \infty@height) and ( \infty@upper*\infty@width,-\infty@height) .. cycle;;
},
infinity,
pen/.is choice,
pen/left/.code={\pen (-.01,.01) -- (.01,-.01);},
pen/right/.code={\pen (-.01,-.01) -- (.01,.01);},
pen/.default=left,
pen/.initial=left,
width/.store in=\infty@width,
height/.store in=\infty@height,
inner target/.store in=\infty@upper,
outer target/.store in=\infty@lower,
}
\tikzset{
infinity,
width = 1 em,
height = 1 em,
inner target = 0.2 em,
outer target = 0.8 em,
}
%\tikzset{ % Fails to set the properties before the infinity/.code is executed.
% infinity/.style={width=1em, height=1em, inner target =0.2, outer target =0.8},
%}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw pic {infinity};
\end{tikzpicture}
\begin{tikzpicture}
\draw pic[infinity/pen=left] {infinity};
\end{tikzpicture}
\end{document}
概述
我正在尝试按如下方式构造代码。将所有内容归类到infinity
系列下。infinity
还充当 tikz 图片,其几何形状由尺寸控制\infty@DIMENSION
,其中是和DIMENSION
之一,控制大小,和控制摆动。如上所述选择。width
height
upper
lower
pen
问题) :
如何设置 pic 设置的默认值?设置几何键对
infinity/.style
我来说失败了。因此,我在第二次\tikzset{}
调用时定义了它们,以便 MWE 可以立即编译。我还必须明确设置要显示的书法曲线的值 pen。这是否也应该成为 的一部分
infinity/.style
?这一点与上面的 1 和 2 有关。下面的尺寸设置失败,因为它在执行
infinity/.style
之前没有设置任何尺寸。infinity/.code
\tikzset{ infinity/.style={...}, }
在其他一些代码中,我使用
DIMENISON/.get
处理程序而不是“DIMENSION/.store in”处理程序。我应该在这里这样做吗?在第二个
tikzpicture
环境中,我明确设置了 pen 使用infinity/pen=...
有没有办法简单地书写pen=...
? 那么是否还需要infinity/.search also=/tikz/
在第一个\tikzset
环境中指定我定义的位置infinity
?
背景 :
Ryan Reich 就这些问题给出了很好的答案,但我现在找不到了。我读完了 pgfmanual 的 pgfkeys 部分,对我来说,它更像是一份 API 文档,我发现我需要一个示例来串联这些点,因此提出了这个问题。
更新 :
我提出这个问题的初衷是被软件包更新所利用,这在某种“哦,该死”的方式下真的很好。
答案1
这基本的使用密钥的规则(也有例外)是您需要执行以下操作:
- 初始化一个密钥,
- 定义一个键,
- 使用钥匙。
总体而言,我发现一旦进入pgfkeys
生态系统,最好就留在那里。因此,值height
、width
、upper
和lower
可以存储在键中,而不需要辅助宏。
对于笔,当您使用一个.code
键时,该代码将在调用时执行,因此与存储值以供以后使用略有不同。您想要的是决定使用哪支笔,然后在调用内部pic
安装它所需的代码。这意味着将该键的设置和获取分开,因为您想在选项中设置该键,pic
但在实际代码中使用它。这意味着设置一个选项来说明以后要使用哪支笔会更容易pen
。事实上,您可以在文档开头定义笔并在代码中使用它们。
使用
infinity/.style
意味着您以三种不同的方式使用infinity
密钥:作为 pgfkeys 系列、作为图片和作为样式。这可能会让用户感到困惑。使用密钥时,没有必要同时使用样式。您可以使用密钥.initial
处理程序为密钥设置初始值。通过将笔设置为一个值而不是显式代码,我们也可以使用
.initial
键处理程序来实现这一点。infinity/.style
不做任何事情的原因是您从未使用它。使用密钥本身可以避免需要
.store in
或.get
处理程序。您可以将
pen
其设置为别名,infinity/pen
如下面的代码所示。
这是有效代码,欢迎在评论中提出后续问题:
\documentclass[tikz]{standalone}
%\url{http://tex.stackexchange.com/q/315412/86}
\usetikzlibrary{calc,calligraphy}
\makeatletter
%
% This is a shorthand for getting the value of a relevant key, purely
% to save typing
%
\def\inf@key#1{%
\pgfkeysvalueof{/tikz/infinity/#1}%
}
\AtBeginDocument{
%
% Put these in a box to throw away so that it takes up no space
%
\setbox0=\vbox{%
\definepen[pen name=left] (-.01,.01) -- (.01,-.01);
\definepen[pen name=right] (-.01,-.01) -- (.01,.01);
}%
}
\tikzset{
%
% So that we can use the pen outside the infinity tree
%
pen/.style={
infinity/pen=#1,
},
infinity/.is family,
infinity/.pic = {
%
% The calligraphy/spath3 library currently has some issues with the
% cycle coordinate. Oops.
%
\calligraphy[pen name=\inf@key{pen}] let \p1=(0,0) in
(\p1) .. controls (-\inf@key{inner target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{outer target}*\inf@key{width},-\inf@key{height}) ..
(\p1) .. controls ( \inf@key{outer target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{inner target}*\inf@key{width},-\inf@key{height}) .. (\p1);
% This curve is simply here as a backup
\draw[line width=0.1, blue] let \p1=(0,0) in
(\p1) .. controls (-\inf@key{inner target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{outer target}*\inf@key{width},-\inf@key{height}) ..
(\p1) .. controls ( \inf@key{outer target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{inner target}*\inf@key{width},-\inf@key{height}) .. (\p1);
},
infinity,
pen/.initial=left,
width/.initial=1em,
height/.initial=1em,
inner target/.initial=0.2,
outer target/.initial=0.8
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw pic[infinity/width=2em] {infinity};
\end{tikzpicture}
\begin{tikzpicture}
\draw pic[infinity/pen=right] {infinity};
\end{tikzpicture}
\begin{tikzpicture}
\draw[pen=right] pic {infinity};
\end{tikzpicture}
\end{document}
顺便说一句,该库已被CTAN 提供的库spath
所取代,并且可在所有优秀的 TeX 发行版中使用。spath3
答案2
坚持使用旧软件包,我能够解决我好奇的问题。即如何在指定图片时选择性地更改笔。
遵循 @Loop Space 提供的建议,即不要将所有键都放在一个路径下,而是使用您定义的样式,将值存储在 pgf 树中并提供包装器宏来检索它们。结果如下,尽管他的答案略显冗长。
\documentclass[tikz]{standalone}
\usepackage{spath}
\usepackage{calligraphy}
\usetikzlibrary{calc}
\makeatletter
\def\inf@key#1{%
\pgfkeysvalueof{/tikz/infinity dimensions/#1}%
}
\tikzset{
% Dimensions
infinity dimensions/.is family,
infinity dimensions/width/.initial =1 em,
infinity dimensions/height/.initial=1 em,
infinity dimensions/upper target/.initial=0.2,
infinity dimensions/lower target/.initial=0.8,
% Options
infinity options/.is family,
infinity options/pen/.is choice,
infinity options/pen/left/.code = {\pen (-.01, .01) -- ( .01,-.01);},
infinity options/pen/right/.code = {\pen (-.01,-.01) -- ( .01, .01);},
infinity options/pen/.default=left,
% Style
infinity style/.style={/tikz/infinity options/.cd, pen=#1},
% Pic/Symbol
infinity symbol/.pic = {
% This is the curve we wish to have drawn
\calligraphy[infinity style=#1] let \p1=(0,0) in
(\p1) .. controls (-\inf@key{upper target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{lower target}*\inf@key{width},-\inf@key{height}) ..
(\p1) .. controls ( \inf@key{lower target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{upper target}*\inf@key{width},-\inf@key{height}) .. cycle;
% This curve is simply here as a backup
\draw[line width=0.1, blue] let \p1=(0,0) in
(\p1) .. controls (-\inf@key{upper target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{lower target}*\inf@key{width},-\inf@key{height}) ..
(\p1) .. controls ( \inf@key{lower target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{upper target}*\inf@key{width},-\inf@key{height}) .. cycle;
},
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw pic {infinity symbol};
\end{tikzpicture}
\begin{tikzpicture}
\draw pic {infinity symbol=right};
\end{tikzpicture}
\end{document}
不同之处在于我故意保留了.is choice
处理程序,设置了.style
和重要的使用它。(EZKeys 提供了替代方法)。 这魔法发生在启用 中指定的可选参数的行infinity style/.style={...}
和上。它们一起作用,将参数传递到 pgfkeys 中的正确分支/名称空间。然后在跟踪书法路径之前调用代码,这在原始问题中没有发生。\calligraphy[infinity style=#1] ...
\draw pic {infinity symbol= ...}
\pen ...;
我还没能解决传递的pic actions
问题infinity dimensions
。
最好有一个将所有键“混合”在一起进行比较的版本,因为处理程序通常不会发生冲突,所以这是可能的。它还可以避免命名分支,例如infinity symbol/options/dimensions
,它实际上应该属于infinity
子树/分支。
这更像是一种练习,但它很有用,因为它允许图片的“类别”。例如,如果我指定了一系列与汽车相关的图片,我可以提供一个默认图片,比如 volla(甲壳虫),但\draw pic {car};
允许选择其他图片, \draw pic {car=ALTERNATE};
例如改装车、轿车或掀背车。