我正在向 传递一个参数,pic
像这样pic[n=3]
。我这样做对吗?那么传递几个参数怎么样,比如说两个,像这样pic[n=3, r=1]
?
我真的很喜欢能够将参数明确地写在方括号内,而不是说pic{3}{1}
(很难记住参数的顺序)。我尝试重复我对\pgfkeysgetvalue{/tikz/n}\n
for 的操作\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}