使用键向 tikz pic 传入多个命名参数

使用键向 tikz pic 传入多个命名参数

我正在向 传递一个参数,pic像这样pic[n=3]。我这样做对吗?那么传递几个参数怎么样,比如说两个,像这样pic[n=3, r=1]

我真的很喜欢能够将参数明确地写在方括号内,而不是说pic{3}{1}(很难记住参数的顺序)。我尝试重复我对\pgfkeysgetvalue{/tikz/n}\nfor 的操作\r并添加.pic 2 args ={or .pic n args = {2}{,但失败了。

    \documentclass[class=article,border=2mm,tikz]{standalone}
    \usetikzlibrary{calc}

    \tikzset{%
      circle pyramid/.pic ={
        \begin{scope}
          \pgfkeysgetvalue{/tikz/n}\n
          \foreach \x in {\n,...,1} {
            \draw[fill=white]
              \ifnum\x=\n
                (0,0)
              \else
                (row)++(60:2)
              \fi
              coordinate (row)%
                \foreach \y in {1,...,\x} {
                  circle[radius=1]++(2,0)% circles of radius 1, would like to make it \r
                };
            }
        \end{scope}
      },
      n/.initial=2
    }

    % radius of the circumscribed circle in terms of the smaller circle r
    % R = r (3+2*(n-1)*sqrt(3))/3, and we set r = 1
    \newcommand{\radius}[1]{\pgfmathparse{(3+2*(#1-1)*sqrt(3))/3}}%

    \begin{document}
    \begin{tikzpicture}
      \radius{3}%
      \draw[fill=black] circle[radius=\pgfmathresult cm];
      \path (-2,-1.16) pic[n=3]{circle pyramid}; % inelegant tweak of the center
    \end{tikzpicture}

    \end{document}

圆形金字塔的代码借用自斯基尔蒙。我尝试将其减少到我需要的最小元素。但正如您从屏幕截图中看到的那样,右侧有一些不需要的空白。我也想修复它。

在此处输入图片描述

答案1

出现空间过大的问题是因为代码在

circle[radius=1]++(2,0)

不应将其添加++(2,0)到最后一个坐标中。 也可以(-2,-1.16)从第一原理计算,它是极坐标(-150:R-r),其中R是大背景圆的半径和r小圆的半径。 至于将参数传递给图片的问题,我使用了来自https://tex.stackexchange.com/a/534355但它也与什么相当相似Andrew Stacey 的回答除了我在这里使用 之外\pgfkeysvalueof,它避免了定义许多额外的宏(例如,\n可能会与calc您加载的 的语法发生冲突,但在本例中不需要)。至于半径函数,我只需使用declare function来定义cpradius。背景圆已添加到图片中,但可以使用开关将其关闭。以下是带有许多示例的代码:

\documentclass[class=article,border=2mm,tikz]{standalone}
%\usetikzlibrary{calc}
\newif\iftikzcirclepyramiddrawbackgroundcircle
\tikzset{%
  declare function={cpradius(\x)=(3+2*(\x-1)*sqrt(3))/3;},
  pics/circle pyramid/.style={code={%
      \tikzset{circle pyramid/.cd,#1}%
      \def\pv##1{\pgfkeysvalueof{/tikz/circle pyramid/##1}}%
      \iftikzcirclepyramiddrawbackgroundcircle
       \path[circle pyramid/bg circle] circle[radius={\pv{r}*cpradius(\pv{n})}];
      \fi
      \foreach \x in {\pv{n},...,1} {
        \draw[circle pyramid/fg circle]
          \ifnum\x=\pv{n}
            (-150:{\pv{r}*cpradius(\pv{n})-\pv{r}})
          \else
            (row)++(60:2*\pv{r})
          \fi
          coordinate (row)%
            \ifnum\x>1
            foreach \y in {1,...,\the\numexpr\x-1} {
              circle[radius=\pv{r}]++(2*\pv{r},0)% circles of radius 1, would like to make it \r
            }
            \fi
            circle[radius=\pv{r}];
        }
    }  
 },
  circle pyramid/.cd,n/.initial=2,r/.initial=1,
  background circle/.is if=tikzcirclepyramiddrawbackgroundcircle,
  background circle=true,bg circle/.style={draw,fill=black},
  fg circle/.style={draw,fill=white},
}


\begin{document}
\begin{tikzpicture}
  \path pic{circle pyramid={r=1,n=3}} 
   (9,-3) pic{circle pyramid={r=1.5,n=3}}
   (0,-7) pic{circle pyramid={r=0.8,n=4}}
   (8,-10) pic{circle pyramid={r=0.6,n=2,background circle=false}}
   (11,-10) pic{circle pyramid={r=0.6,n=2,bg circle/.style={fill=blue},
    fg circle/.style={fill=orange}}}; 
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

一种方法是将一组键值对作为单个参数传递给 pic,然后由 pgfkeys 重新解析。我发现将这些键放在系列中有助于避免重复使用它们的问题。我所做的另一项更改是,正如评论中提到的,您设置外圆半径的方法并不可靠(在非 TeX 意义上),因为任何中间计算都会覆盖结果。以下代码产生与问题相同的结果。

(我确实对背景圆圈感到好奇——它应该是图片的一部分吗?)


    \documentclass[class=article,border=2mm,tikz]{standalone}
    \usetikzlibrary{calc}

    \tikzset{%
      circle pyramid/.pic ={
        \begin{scope}[circle pyramid options/.cd,#1]
          \pgfkeysgetvalue{/tikz/circle pyramid options/n}\n
          \pgfkeysgetvalue{/tikz/circle pyramid options/r}\r
          \foreach \x in {\n,...,1} {
            \draw[fill=white]
              \ifnum\x=\n
                (0,0)
              \else
                (row)++(60:2)
              \fi
              coordinate (row)%
                \foreach \y in {1,...,\x} {
                  circle[radius=\r]++(2,0)% circles of radius 1, would like to make it \r
                };
            }
        \end{scope}
      },
      circle pyramid options/.is family,
      circle pyramid options/.cd,
      n/.initial=2,
      r/.initial=1
    }

    % radius of the circumscribed circle in terms of the smaller circle r
    % R = r (3+2*(n-1)*sqrt(3))/3, and we set r = 1
    \newcommand{\radius}[1]{((3+2*(#1-1)*sqrt(3))/3)}%

    \begin{document}
    \begin{tikzpicture}
      \draw[fill=black] circle[radius=\radius{3}];
      \path (-2,-1.16) pic{circle pyramid={n=3,r=1}}; % inelegant tweak of the center
    \end{tikzpicture}

    \end{document}

相关内容