27

If I have two tikzpictures drawn:

\documentclass{article}
\usepackage[margin = 1in]{geometry}
\usepackage{tikz}
\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}}

\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{tikzpicture}
\shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
\end{tikzpicture}

\end{document}

enter image description here

How could I use the first tikz picture within the second? Can I define the first picture as some variable and then place this variable within the second picture and have the option of defining its exact location (x,y) and its size? For example, if I wanted to place the tree in the middle of the rectangle (5,5) but make the size of the tree half its current size. How would I do this

2
  • Can it be a duplicate of tex.stackexchange.com/questions/37823/…
    – percusse
    Jul 31, 2013 at 8:01
  • How about using the background canvas via ´\begin{scope}[background] ... \end{scope}´ for the second image? (I am still a beginner.)
    – Jan
    Apr 3, 2018 at 9:53

4 Answers 4

19

I would define a specific key for the tree and one for the position:

% to get the positions of last x,y
\newdimen\xval
\newdimen\yval

\pgfkeys{/tikz/.cd,
   at/.initial={(0,0)},
   at/.get=\coordpos,
   at/.store in=\coordpos,   
   my tree/.code={
     \foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
       \fill [brown!\f!black, trunk] \coordpos ++(-\w/2,0) rectangle +(\w,-3);
     }
     \pgfgetlastxy{\xval}{\yval};
     \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](\xval,\yval) ellipse (\n/1.5 and \n);
     }
   }
}

so that in the final picture you can use:

\begin{tikzpicture}
\shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
\node[at={(2.5,5)},my tree]{};
\node[at={(5,5)},my tree]{};
\node[at={(7.5,5)},my tree]{};
\end{tikzpicture}

The complete code:

\documentclass{article}
\usepackage[margin = 1in]{geometry}
\usepackage{tikz}
\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}}

% to get the positions of last x,y
\newdimen\xval
\newdimen\yval

\pgfkeys{/tikz/.cd,
   at/.initial={(0,0)},
   at/.get=\coordpos,
   at/.store in=\coordpos,   
   my tree/.code={
     \foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
       \fill [brown!\f!black, trunk] \coordpos ++(-\w/2,0) rectangle +(\w,-3);
     }
     \pgfgetlastxy{\xval}{\yval};
     \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](\xval,\yval) ellipse (\n/1.5 and \n);
     }
   }
}

\begin{tikzpicture}
\shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
\node[at={(2.5,5)},my tree]{};
\node[at={(5,5)},my tree]{};
\node[at={(7.5,5)},my tree]{};
\end{tikzpicture}

\end{document}

The result:

enter image description here

3
  • 1
    +1 Much more elegant solution than mine. I need to get up to speed on pgfkeys!
    – jub0bs
    Jul 31, 2013 at 8:17
  • @Jubobs: definitely ;) Jul 31, 2013 at 8:37
  • +100 This is brilliant. You just helped me save hundreds of lines of code as I had lots of variations on the same image throughout a document. I don't know if it's correct or not, but specifying coordinates within a node works as well.
    – Robbie
    Oct 31, 2016 at 5:13
40

TiKZ 3.0.0 introduces pic a "short picture" which can be inserted in any place of a tikzpicture. A possible solution with 'pic' would be:

\documentclass{standalone}
\usepackage[margin = 1in]{geometry}
\usepackage{tikz}
\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}
\shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
\pic at (2,2) {my tree};
\pic at (4,2.5) {my tree};
\pic at (6,1.75) {my tree};
\end{tikzpicture}

\end{document}

enter image description here

3
  • You deserve more upvotes. This is the most elegant variant.
    – Ingo
    Jan 11, 2014 at 12:06
  • Is there anyway of adding a parameter to control features, such as the size?
    – mattdns
    May 2, 2016 at 17:43
  • @mattdns you can try with \pic[scale=0.8] at (...) {my tree};
    – Ignasi
    May 2, 2016 at 18:32
6

Let us define a newcommand:

\newcommand\myfig[2]{%
    \begin{scope}[xshift=#1cm,yshift=#2cm]
        \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}
}

And use it like this:

\documentclass{article}
\usepackage[margin = 1in]{geometry}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing,calc,shapes,shapes.geometric,patterns}

\newcommand\myfig[2]{%
    \begin{scope}[xshift=#1cm,yshift=#2cm]
        \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}
\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}
    \myfig{0}{0}
\end{tikzpicture}

\begin{tikzpicture}
    \shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
    \myfig{2.5}{5}
    \myfig{5}{5}
    \myfig{7.5}{5}    
\end{tikzpicture}

\end{document}

enter image description here

1
  • I think, this is very elegant, too. And---just in case---it solved my actual problem very well! Thank you!
    – Jan
    Apr 3, 2018 at 9:56
5

Yes, it can be done with a pgfonlayer environment within the tikzpicture and a new command (called \treedrawing below) that takes as argument the coordinates (of the form x,y) of the tree and draws it there. Just make sure to call \treedrawing after the pgfonlayer environment, or your trees will be behind the background.

enter image description here

\documentclass{article}
\usepackage[margin = 1in]{geometry}
\usepackage{tikz}
\usetikzlibrary{%
    backgrounds,%
    decorations.pathmorphing,%
    calc,%
    shapes,%
    shapes.geometric,%
    patterns,%
}

\begin{document}

\newcommand\treedrawing[1]{%
    \tikzset{%
        treetop/.style = {decoration    = {random steps, segment length=0.4mm},decorate},%
        trunk/.style = {decoration={random steps, segment length=2mm, amplitude=0.2mm},decorate}%
    }
\begin{scope}[shift={(#1)}]
    \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{tikzpicture}
    \begin{pgfonlayer}{background}
        \shade[bottom color=cyan!60!black, top color=blue!20!white] (0,0) rectangle (10,10);
    \end{pgfonlayer}
    \treedrawing{2,5}
    \treedrawing{5,5}
    \treedrawing{8,5}
\end{tikzpicture}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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