参数图片:无限的变化

参数图片:无限的变化

假设我想绘制无穷符号的变体(主要是因为我不会画鸭子,尽管鸭子可以很好地完成 MWE)。我找不到使用 pgf/tikz 键以简洁的方式操纵 tikz 图片绘制方式的简单示例。查看我自己的代码库,似乎我自己对这个主题也相当困惑。

要求 :

让我们允许通过 和 键改变形状的大小width,并使用和height键使叶片能够摆动。最重要的是,我们要在各种书法笔之间进行选择,这必须通过代码进行设置。这通过选择和 'right' 来控制。inner targetouter targetleftpen

代码 :

对于此示例,您将需要spathcalligraphy样式文件,可用这里,可作为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之一,控制大小,和控制摆动。如上所述选择。widthheightupperlowerpen

问题) :

  1. 如何设置 pic 设置的默认值?设置几何键对infinity/.style我来说失败了。因此,我在第二次\tikzset{}调用时定义了它们,以便 MWE 可以立即编译。

  2. 我还必须明确设置要显示的书法曲线的值 pen。这是否也应该成为 的一部分infinity/.style

  3. 这一点与上面的 1 和 2 有关。下面的尺寸设置失败,因为它在执行infinity/.style之前没有设置任何尺寸。infinity/.code

    \tikzset{ infinity/.style={...}, }

  4. 在其他一些代码中,我使用DIMENISON/.get处理程序而不是“DIMENSION/.store in”处理程序。我应该在这里这样做吗?

  5. 在第二个tikzpicture环境中,我明确设置了 pen 使用infinity/pen=...有没有办法简单地书写pen=...? 那么是否还需要infinity/.search also=/tikz/在第一个\tikzset环境中指定我定义的位置infinity

背景 :

Ryan Reich 就这些问题给出了很好的答案,但我现在找不到了。我读完了 pgfmanual 的 pgfkeys 部分,对我来说,它更像是一份 API 文档,我发现我需要一个示例来串联这些点,因此提出了这个问题。

更新 :

我提出这个问题的初衷是被软件包更新所利用,这在某种“哦,该死”的方式下真的很好。

答案1

基本的使用密钥的规则(也有例外)是您需要执行以下操作:

  1. 初始化一个密钥,
  2. 定义一个键,
  3. 使用钥匙。

总体而言,我发现一旦进入pgfkeys生态系统,最好就留在那里。因此,值heightwidthupperlower可以存储在键中,而不需要辅助宏。

对于笔,当您使用一个.code键时,该代码将在调用时执行,因此与存储值以供以后使用略有不同。您想要的是决定使用哪支笔,然后在调用内部pic安装它所需的代码。这意味着将该键的设置和获取分开,因为您想在选项中设置该键,pic但在实际代码中使用它。这意味着设置一个选项来说明以后要使用哪支笔会更容易pen。事实上,您可以在文档开头定义笔并在代码中使用它们。

  1. 使用infinity/.style意味着您以三种不同的方式使用infinity密钥:作为 pgfkeys 系列、作为图片和作为样式。这可能会让用户感到困惑。使用密钥时,没有必要同时使用样式。您可以使用密钥.initial处理程序为密钥设置初始值。

  2. 通过将笔设置为一个值而不是显式代码,我们也可以使用.initial键处理程序来实现这一点。

  3. infinity/.style不做任何事情的原因是您从未使用它。

  4. 使用密钥本身可以避免需要.store in.get处理程序。

  5. 您可以将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};例如改装车、轿车或掀背车。

相关内容