# Avoid repetition of blocks of code for the same picture in TikZ

As a follow-up to my previous question (US Abilene Topology in Tikz: How can I further improve the picture), I want to optimise the code in the previous post (Segment 2). It contains a repetition of the same block of code (for the set of chains) to realise three such pictures. I came across some questions closely related to the problem I have but I want to realise all three blocks on one image just like I have done in the previous post but not repeat the code so much. Incase, I have to depict 10 or 20 such chains, I don't want to copy paste the same block 20 times. I tried using \tikzset command but I faced some troubles with that too.

• You could define a bunch of macros like \yslant and \rotate, which would actually make you code less opaque. – John Kormylo Oct 25 '16 at 14:05
• Do you know the pic concept? tex.stackexchange.com/a/151772/1952, tex.stackexchange.com/a/289620/1952 – Ignasi Oct 26 '16 at 7:27
• I checked it out but I don't know how to adapt it to my case as I additionally define coordinates for my nodes. So, that was exactly where I was stuck. Infact, the post is a nice reference. Could I ask your help to adapt my code in such a way? – crypto Oct 26 '16 at 7:34

I'm not sure why you define macros whose sole purpose seems to be to pass their arguments as keys to a tikz command. As far as I can tell, most of what this achieves is to obfuscate the code. If you want to use a command like this, it is probably best to follow percusse's advice and use pgfkeys to pass most of the arguments as keywords. However, in your case most of the arguments seem to be fixed anyway, so I'm not sure why you're passing them as arguments rather than hard coding them into the macros.

Instead of defining macros, I would probably just define a single style that you can use for all of your nodes:

\tikzset{mynode/.style = {draw, drop shadow={opacity=.15}, minimum height=7, minimum width=30, %
xslant=-2, yslant=0, inner color=#1!20, outer color=#1!45, color=#1!50!black}}


You can always overwrite any parts of this which do not apply to a particular node, but this gives a good default starting place to avoid copy/pasted code.

Another thing you can do to avoid repeated code is use pgf's \foreach loops, which are quite flexible. I recommend looking at the documentation (section 83 of the tikz/pgf manual) for more features of \foreach.

Overall, I might write your second segment as

\documentclass[tikz, border=5]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows, automata}

\tikzset{mynode/.style = {draw, drop shadow={opacity=.15}, minimum height=7, minimum width=30, %
xslant=-2, yslant=0, inner color=#1!20, outer color=#1!45, color=#1!50!black}}
\begin{document}
\begin{tikzpicture}[auto, outer sep=3pt, node distance=2cm, >=latex']

% Background
\node[mynode=gray,drop shadow={opacity=.35},minimum height=100,minimum width=450, inner color=white, outer color=gray!30] {}; %

\foreach \x/\y/\edgestyle in {0.4/0/dashed, 2.8/-1.2/, 5.2/-2.4/dotted}{
\begin{scope}[xshift=\x cm, yshift=\y cm]

% Start
\path (-9.7,1.20) node[mynode=red] (l) {} node {\tiny $\textit{e}_1$}; %

% Middle
\foreach \vx/\vy [count=\n] in {-7.2/1.20, -2.7/1.50, -4.2/0.90, -0.2/0.90, 2.00/1.20}{
\path (\vx,\vy) node[mynode=blue] (vl\n) {} node {\tiny $\textit{vnf}_\n$}; %
}

% End
\path (4.2,1.20) node[mynode=red] (r) {} node {\tiny $\textit{e}_2$}; %

% Edges
\foreach \u/\v in {l/vl1, vl1/vl2, vl1/vl3, vl3/vl4, vl2/vl5, vl4/vl5, vl5/r}{
\draw [<->, thick, \edgestyle] (\u) -- (\v);
}
\end{scope}
}
\end{tikzpicture}

\end{document}


You could Schönfinkel the definitions of macros and their usage. For example, for the macros, you would have:

\def\comn#1[#2,#3,#4,#5,#6,#7,#8]#9{%
\node[#1,draw,drop shadow={opacity=.15},minimum height=#2,minimum width=#3,xslant=#4,yslant=#5] (#7) at #8 {}; %
\node[anchor=#6, inner sep=2pt] at(#7.#6) {#9};}
\def\layr{\comn{inner color=white!40,outer color=gray!30,color=gray!50!black}}
\def\endr{\comn{inner color=red!20,outer color=red!45,color=red!50!black}}
\def\vnfr{\comn{inner color=blue!20,outer color=blue!45,color=blue!50!black}}


This would be done also for the repeating blocks in the drawing itself.

Abstracting out a repeating block requires one hidden argument to be added each time. Nothing else changes. If you run out of arguments (say you need more than nine) in the base macro, then you could the code from here.

• pgfkeys is invented to avoid this – percusse Oct 25 '16 at 14:06
• It would be safer to avoid \def in any case. But this really cries out for a key-value interface! – cfr Nov 24 '16 at 22:22