我真的想不出这个问题的合理标题;但无论如何,标题如下:
今天看到一个很有意思的题目和解答这里:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\thispagestyle{empty}
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\begin{tikzpicture}
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop] ellipse (\n/1.5 and \n);
}
\end{tikzpicture}
\end{document}
从这个解决方案中,我想知道是否可以n
通过简单地引用显示的代码来复制此图表。例如,如果我正在绘制一个字段,将其绘制为一条简单的水平线:
\begin{tikzpicture}
\draw(0,0) -- (10,0);
\end{tikzpicture}
那么我是否可以重复绘制这棵树,比如4
沿着这条线多次来表示森林的一部分,并进行相应的缩放?例如:
显然,这些可以通过一个简单的 for 循环来创建,但是,我想我只是想找到一种多次重新应用树的代码的方法。
答案1
正如 Marc van Dongen 所评论的,您可以将图片保存在 a 中\savebox
并重复使用。但是,这样所有的图片都会相同。相反,您可以为 定义一个命令tikzpicture
并重复使用它,这会为每个实例生成一个不同的树,或者定义一个可在环境中使用的宏\tikzpicture
。
1. 重复使用全部tikzpicture
:
笔记:
- 如果你想重复使用相同的
\Tree
代码之内然后tikzpicture
定义一个仅包含两个foreach
循环的宏,并使用“范围”将每个实例向右移动,或者提供一个控制绘图完成位置的参数。
代码:
\documentclass{article}
\usepackage{tikz}
\thispagestyle{empty}
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\newcommand*{\Tree}{%
\begin{tikzpicture}
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop] ellipse (\n/1.5 and \n);
}
\end{tikzpicture}}%
\begin{document}
\Tree \Tree \Tree \Tree
\end{document}
2.使用scope
:
如果你想重复使用相同的\Tree
代码之内你tikzpicture
可以定义一个只包含两个foreach
循环的宏,并使用 `scope 将每个实例向右移动
代码:
\documentclass{article}
\usepackage{tikz}
\thispagestyle{empty}
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\newcommand*{\Tree}{%
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop] ellipse (\n/1.5 and \n);
}
}%
\begin{document}
\begin{tikzpicture}
\Tree
\begin{scope}[xshift=2cm]
\Tree
\end{scope}
\begin{scope}[xshift=4cm]
\Tree
\end{scope}
\begin{scope}[xshift=6cm]
\Tree
\end{scope}
\end{tikzpicture}
\end{document}
3.参数化版本:
重复使用相同代码的另一种方法tikzpicture
是定义一个包含两个foreach
循环的宏,并采用控制绘图位置的参数。
代码:
\documentclass{article}
\usepackage{tikz}
\thispagestyle{empty}
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\newcommand*{\Tree}[2]{%
% #1 = origin coordinate
\begin{scope}[xshift=#1 cm, yshift=#2 cm]
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop] ellipse (\n/1.5 and \n);
}
\end{scope}
}%
\begin{document}
\begin{tikzpicture}
\Tree{0}{0}
\Tree{2}{0}
\Tree{4}{0}
\Tree{6}{0}
\end{tikzpicture}
\end{document}
4. 花式版本
如果您正在参数化宏,不妨添加可选参数,以便能够控制树梢和树干的绘制选项:
笔记:
- 我的颜色选择是基于潘多拉星球的,但有人告诉我,在地球上,至少在英国 :-),大自然中的树木不会呈现出这种颜色。也许有人可以选择更美观的颜色,可以在这里编辑这些选择。
代码:
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\thispagestyle{empty}
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\NewDocumentCommand{\Tree}{%
O{green!\f!black}% #1 = tree top options
O{brown!\f!black}% #2 = trunk options
m% #3 = xshift
m% #4 = yshift
}{%
\begin{scope}[xshift=#3 cm, yshift=#4 cm]
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [#2, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [#1, treetop] ellipse (\n/1.5 and \n);
}
\end{scope}
}%
\begin{document}
\begin{tikzpicture}
\Tree{0}{0}
\Tree[orange!\f!black][gray!\f!blue]{2}{0}
\Tree[olive!\f!cyan][orange!\f!violet]{4}{0}
\Tree[orange!\f!red][brown!\f!black]{6}{0}
\end{tikzpicture}
\end{document}
答案2
TiKZ
所有先前的答案对于 v3.0 之前的版本都是有效的(现在仍然有效) 。但是TikZ 3.0
pics
引入了一个名为(更多信息请参阅 pgfmanual 的第 18 节)的新工具。图片:路径上的小图片) 可用于声明和重用复杂图形,而无需使用 new shapes
。
使用此工具,可以在pic
my tree/.pic={
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (-\w/2,0) rectangle +(\w,3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop](0,3) ellipse (\n/1.5 and \n);
}
}
\pic at (x,y) {my tree};
然后与或等绘图命令一起使用\path (x,y) pic {my tree};
。
如果使用参数声明图片,则需要另一种声明语法:
pics/second tree/.style 2 args={
code={
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [#2, trunk] (-\w/2,0) rectangle +(\w,3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [#1, treetop](0,3) ellipse (\n/1.5 and \n);
}
}
}
使用这两种语法的示例可能是:
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{decorations.pathmorphing,calc,shapes,shapes.geometric,patterns}
\begin{document}
\tikzset{treetop/.style = {decoration={random steps, segment length=0.4mm},decorate},trunk/.style = {decoration={random steps, segment length=2mm, amplitude=0.2mm},decorate}}
\tikzset{
my tree/.pic={
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (-\w/2,0) rectangle +(\w,3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop](0,3) ellipse (\n/1.5 and \n);
}
}
}
\begin{tikzpicture}
\pic at (2,0) {my tree};
\draw (4,0) pic {my tree};
\path (6,0) pic {second tree={red!\f}{purple!\f}};
\pic at (0,0) {second tree={orange!\f!black}{gray!\f!blue}};
\end{tikzpicture}
\end{document}