Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I couldn't really think of a reasonable title for this question; but anyhow, here goes:

I saw a very interesting question and solution today here:

\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}

From this solution I would like to know if it was possible to copy this diagram n times by simply referring to the code shown. For example, if I was drawing a field, drawn as a simple horizontal line:

\begin{tikzpicture}
\draw(0,0) -- (10,0);
\end{tikzpicture}

Could I then repeat the tree drawn, say 4 times along this line to represent a portion of a forest, scaled accordingly? For example:

Obviously these can be created by a simple for loop, however, I guess I'm just trying to find a way of re-applying the code for the tree numerous times.

share|improve this question
1  
You can save the picture in a savebox and reuse the content of the saved box later on. Personally, I'd be against that idea because generating randomly shaped trees is much nicer! –  Marc van Dongen Mar 6 '13 at 19:11
    
could you provide an example :) –  KatyB Mar 6 '13 at 19:15

2 Answers 2

up vote 11 down vote accepted

As Marc van Dongen commented you could save the picure in a \savebox and reuse that. But, then all the pictures will be identical. Instead, you can define a command for the tikzpicture and reuse it which yields a different tree for each instance, or define a macro to be useable within a \tikzpicture environment.

1. Reuse entire tikzpicture:

enter image description here

Notes:

  • If you wish to reuse the same \Tree code within a tikzpicture then define a macro that only contains the two foreach loops, and either use a `scope to shift each instance to the right, or provide a parameter which controls where the drawing is done.

Code:

\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. Using scope:

If you wish to reuse the same \Tree code within a tikzpicture you could define a macro that only contains the two foreach loops, and use a `scope to shift each instance to the right

Code:

\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. Parametrized Version:

Another way of reusing the same code within a tikzpicture would be to define a macro which contains the two foreach loops, and takes a parameter which controls where the drawing is done.

Code:

\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. Fancy Version

If you are parametrizing the macro, might as well add optional parameters to be able to control the draw options for the treetop and trunk as well:

enter image description here

Notes:

  • My color choices were based on Pandora, but I have been told that on Earth, well at least in the UK :-), trees in nature do not exhibit these kind of colors. Perhaps someone who can chose more aesthetically pleasing colors can edit the choices here.

Code:

\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}
share|improve this answer

All previous answers were (and still are) valid with TiKZ versions previous to v3.0. But TikZ 3.0 introduced a new tool called pics (more information in pgfmanual's section 18. Pics: Small Pictures on Paths) which can be used to declare and reuse complex figures without having to use new shapes.

With this tool, any group of commands can be declared inside a 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);
     }
   }

and used afterwards with drawing commands like \pic at (x,y) {my tree}; or \path (x,y) pic {my tree};.

If pics are declared with arguments, another declaration syntax is needed:

   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);
          }
       }
   }

An example using both syntax could be:

\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}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.