28

Context
I want to create several diagrams to illustrate processes. They are not technically complex. However, they consist of several nested elements. First, macro-elements are relatively positioned. These macro-elements are made up of sub-elements, which are themselves made-up of sub-sub-elements. Moreover, I finally draw additional elements relatively to macro-, sub-, and/or sub-sub-elements.

Question
My question is thus what is the best way to design such pictures with nested elements using TikZ?

My requirements are:

  1. I want to position sub-elements relatively to their parent-element (and if possible relatively to sub-elements of other macro-elements too);
  2. At a given level, I want to be able to access elements of this levels and of any sub-levels;
  3. I would like to be able to use relative coordinate in each element. This means that each element would have its own (0,0) coordinate. Its position would be computed relatively to the the achor of the element, and the position of the anchor relatively to the (0,0) of the global picture;
  4. I don't care about properties inheritance: each [sub]element is unambiguously defined.

Possible solutions

  • The solution I currently use is to nest tikzpictures. Even if it works most of the time, I know that is is not a recommended solution (Nesting “tikzpicture” within “tikzpicture” elements - Good or bad practice?). I am thus looking for a more robust way to do it.
  • I have though of pic, but it is said that one cannot access pic later on ("Unlike nodes, pics cannot be referenced later on." PGF manual §18.1).
  • scope environments does not seem to work neither, since I want to "dynamically" position elements (i.e. not with constants, but relatively to the others).
  • Lastly, if Matrices might solve the positioning of macro-elements, however, each cell acts as a node and thus cannot be nested In TikZ, is it possible to nest matrices?).

Example

Note: This example is a concrete case, showing code I'd like to improve. However I am rather interested in general guidelines for structuring such diagrams, than in a specific code-review. Or in other word, what strategy should be used to create similar diagrams.

enter image description here

  • This picture is made up of major elements (green), which are positioned relatively the one to the other: enter image description here

  • Most elements constitutes in a group of sub-elements (blue). The latter are also positioned relatively the one to the other: enter image description here

  • These sub-elements are also made-up of sub-sub-elements (orange): enter image description here

  • Finally, some additional elements are drawn in top of the rest (red): enter image description here

MWE
(for the purpose of the MWE, I've removed included images. I know this code is far from minimal, but I've tried to find a balance between a representative example, and a minimal one.)

\documentclass[10pt, margin=10pt]{standalone}
    \usepackage{graphicx}
    \usepackage{tikz}
        \usetikzlibrary{calc}
        \usetikzlibrary{positioning}
        \usetikzlibrary{arrows.meta}
    \usepackage{calc}

\begin{document}
%% Constants definition %%
    %Length and coefficient%
    \newlength{\eboXbigUnit}
        \setlength{\eboXbigUnit}{5em}
    \newlength{\eboYbigUnit}
        \setlength{\eboYbigUnit}{6\baselineskip}
    \newlength{\eboInterlabelDistance}
        \setlength{\eboInterlabelDistance}{2.5\baselineskip}
    \newlength{\eboIconsUnit}
        \setlength{\eboIconsUnit}{\baselineskip}
    \newlength{\eboInterArrowLength}
        \setlength{\eboInterArrowLength}{1.5\baselineskip}
    \newlength{\eboLineWidth}
        \setlength{\eboLineWidth}{.33ex}

    \newcommand{\coefBoxWidth}{6.2}
    \newcommand{\coefBoxHeight}{3}
    %Colors%
    \definecolor{eboOrange}{RGB}{250,179,52}
    \definecolor{eboOrange21}{RGB}{253,215,145}
    \definecolor{eboOrange22}{RGB}{249,163,13}

    \definecolor{eboGrey20}{RGB}{235,234,233}
    \definecolor{eboGrey21}{RGB}{173,171,172}
    \definecolor{eboGrey22}{RGB}{118,115,116}

    \definecolor{eboBlack}{RGB}{35,31,32}

\begin{tikzpicture}[
    remember picture,
    inner sep=0pt,
    outer sep=0pt,
    eboStepLabel/.style={
        font={\sffamily\scriptsize},
        text=eboOrange,
        align=center,
        anchor=base,
    },
    eboMiddleArrow/.style={
        ->,
        draw=eboGrey21,
        line width=\eboLineWidth,
        line cap=round,
        line join = round,
        >={Straight Barb[line cap=round, line join=miter, angle=45:4*\the\eboLineWidth]}
    },
    iconGrey/.style={
        text=eboBlack,
    },
]

%%% TOP LABELS %%%  
% Label 1
    \node[
    eboStepLabel,
    ] 
    (1-caption)
    at (0,0)
    {1. Lorem ipsum\\
        dolor sit amet\strut};

% Label 2
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 1-caption.east,
    anchor=west,
    ] 
    (2-caption)
    {2. consectetur adipiscing elit.\\
        Mauris eu varius eros\strut};

% Label 3
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 2-caption.east,
    anchor=west,
    ] 
    (3-caption)
    {3. Ut convallis\\
        accumsan porttitor\strut};

% Label 4
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 3-caption.east,
    anchor=west,
    ] 
    (4-caption)
    {4. Donec mollis in\\
        erat id sollicitudin\strut};

%%% ILLUSTRATIONS%%%    
% Illustration step 0
    \node (0-picture)[
        below left = \eboYbigUnit and 2.75\eboInterlabelDistance of 1-caption.south, 
        anchor=center
    ]
    {\includegraphics[width=2\baselineskip]{example-image-a}};

% Define center coordinate for illustration of steps 2 to 4
    \coordinate [below = \eboYbigUnit of 2-caption.south](2-center);
    \coordinate [below = \eboYbigUnit of 3-caption.south](3-center);
    \coordinate [below = \eboYbigUnit of 4-caption.south](4-center);

% Illustration step 2       
    \node (2-picture) at (2-center)[
        anchor=base,
    ]
    {%
        \begin{tikzpicture}[
            inner sep=0pt, 
            remember picture, 
            baseline=(2-methodology.base)
        ]
        %true positive
        \node[
            fill = eboOrange21,
            draw = eboOrange22,
            anchor=north east,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth
        ] (2-truepositive)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-truepositive.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboOrange22,
        ](2-truepositive-label)
        {Duis tempus};

        \coordinate (2-truepositive-articleL) at ($(2-truepositive.north west)!0.9!(2-truepositive.south west)$);
        \coordinate (2-truepositive-articleR) at ($(2-truepositive.north east)!0.9!(2-truepositive.south east)$);

        \foreach \pos in {0.125, 0.375, ..., 0.875} {
            \node[text=eboOrange]
            at ($(2-truepositive-articleL)!\pos!(2-truepositive-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };
        %methodology
        \node[
            below = .5\baselineskip of 2-truepositive.south,
            anchor=north,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-methodology)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-methodology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-methodology-label)
        {Dignissim};

        \node[
            below = .1\baselineskip of 2-methodology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-methodology-label)
        {Nulla ut augue vehicula,\\
             tincidunt};

        \coordinate (2-methodology-articleL) at ($(2-methodology.north west)!0.9!(2-methodology.south west)$);
        \coordinate (2-methodology-articleR) at ($(2-methodology.north east)!0.9!(2-methodology.south east)$);

        \foreach \pos in {0.375, 0.625, 0.875} {
            \node[text=eboGrey21]
            at ($(2-methodology-articleL)!\pos!(2-methodology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };

        % dots
        \node[
            below = .33\baselineskip of 2-methodology.south,
            anchor=north,
            text = eboGrey21,
            font = {\sffamily},
        ] (2-dots)
        {\dots};

        % topology
        \node[
            below = .33\baselineskip of 2-dots.south,
            anchor=north,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-topology)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-topology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-topology-label)
        {Luctus rhoncus};

        \node[
            below = .1\baselineskip of 2-topology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-topology-label)
        {Donec molestie mollis arcu\\
             eget consectetur};

        \coordinate (2-topology-articleL) at ($(2-topology.north west)!0.9!(2-topology.south west)$);
        \coordinate (2-topology-articleR) at ($(2-topology.north east)!0.9!(2-topology.south east)$);

        \foreach \pos in {0.625, 0.875} {
            \node[text=eboGrey21]
            at ($(2-topology-articleL)!\pos!(2-topology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };
        \end{tikzpicture}
    };

% Define center coordinate for illustration of step 1
    \path
    (2-picture.west)
    -|
    (1-caption.south)
    coordinate [midway] (1-center);

% Illustration step 1   
    \node (1-picture) at (1-center)
    {%
        \newlength{\queryHeight}%
            \setlength{\queryHeight}{10.166\baselineskip}%
            \addtolength{\queryHeight}{\heightof{\tikz\node[font={\sffamily}]{\dots};}}%
        \begin{tikzpicture}[inner sep=0pt]
        \node[
        fill = eboGrey21,
        draw = eboGrey22,
        rectangle,
        minimum height = \queryHeight,
        minimum width = \coefBoxWidth\baselineskip,
        line width = .5\eboLineWidth,
        rounded corners=\eboLineWidth,
        ] (1-query)
        {};
        \node[
        below right= .5\baselineskip and .25\baselineskip of 1-query.north west,
        anchor = north west,
        align = left,
        font = {\sffamily\scriptsize},
        text = eboGrey20,
        ](1-query-google)
        {\includegraphics[height=\baselineskip]{example-image-b}};
        \node[
        right= .25\baselineskip of 1-query-google.north east,
        anchor = north west,
        align = left,
        font = {\tiny\sffamily},
        text = eboGrey20,
        ](1-query-google)
        {$\cdot$~Duis vitae faucibus orci,\\
            venenatis nulla ac\\
            $\cdot$~Vivamus sit amet\\
            hendrerit dui};

        \coordinate (1-UL) at ($(1-query.north west)!0.2!(1-query.south west)$);
        \coordinate (1-UR) at ($(1-query.north east)!0.2!(1-query.south east)$);
        \coordinate (1-LL) at ($(1-query.north west)!1!(1-query.south west)$);
        \coordinate (1-LR) at ($(1-query.north east)!1!(1-query.south east)$);

        \foreach \x in {0.125,0.375,0.625,0.875}{
            \foreach \y/\yname in {0.166/a, 0.333/b, 0.5/c, 0.666/d , 0.833/e}{
                \coordinate (myL\yname) at ($(1-UL)!\y!(1-LL)$);
                \coordinate (myR\yname) at ($(1-UR)!\y!(1-LR)$);
                \node [text=eboGrey22] at ($(myL\yname)!\x!(myR\yname)$) {\includegraphics[height=\baselineskip]{example-image-a}};
            };
        };
        \end{tikzpicture}
    };

    % Illustration 3        
    \node (3-picture) at (3-center)
    {%
        \begin{tikzpicture}[
        remember picture,
        inner sep=0pt,
        categorizationLabel/.style={
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,
        },
        categorizationSublabel/.style={
            font={\sffamily\tiny},
            text=eboGrey21,
            align=left,
        },
        ]
        \node (3-paper) [text=eboOrange]
        at (0,0)
        {\includegraphics[height=2\baselineskip]{example-image-a}};
        \node [
            below left = .333\baselineskip and .15\baselineskip of 3-paper.north east, 
            anchor=north west,
            text=eboGrey22,
        ]
        {\includegraphics[width=\baselineskip]{example-image-c}};

        %Type of paper  
        \node (3-label-1) [
            categorizationLabel, 
            below = \baselineskip of 3-paper.south west,
            anchor = base west
        ]
        {Proin sollicitudin};

        \node (3-label-icon-1)[
            left = .5em of 3-label-1.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-1-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-1.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} ipsum ac};

        \node (3-sublabel-1-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} vestibulum};

        \node (3-sublabel-1-12) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} suscipit};

        \node (3-sublabel-1-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} venenatis};

        %Type of product    
        \node (3-label-2) [
            categorizationLabel, 
            below = 2.85\baselineskip of 3-label-1.west, 
            anchor=west,
        ]
        {Vulputate fringilla};

        \node (3-label-icon-2)[
            left = .5em of 3-label-2.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-2-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-2.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} condimentum};

        \node (3-sublabel-2-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} scelerisque};

        \node (3-sublabel-2-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-2-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} lacus};

        \node (3-sublabel-2-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} pharetra};

        %Type of open-design    
        \node (3-label-3) [
            categorizationLabel, 
            below = 2.9\baselineskip of 3-label-2.west,
            anchor=west,
        ]
        {Fusce justo est};
        \node (3-label-icon-3) [
            left = .5em of 3-label-3.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-3-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-3.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} consequat};

        \node (3-sublabel-3-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-3-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} nec facilisis};

        \node (3-sublabel-3-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-3-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} sodales};
        \end{tikzpicture}
    };


    % Illustration 4        
    \node (4-picture) at (4-center) [
    anchor=base,
    ]
    {%
        \begin{tikzpicture}[remember picture,baseline = (4-anchor)]
        \node (4-bars) 
        at (0,0) [iconGrey] 
        {\includegraphics[width=2\eboIconsUnit]{example-image-b}};

        \node (4-r-logo) 
        at (4-bars.north east) [iconGrey] 
        {\includegraphics[width=\eboIconsUnit]{example-image-c}};

        \node (4-Typologie)
        at (0, -3\eboIconsUnit) [%
            font={\sffamily\scriptsize},
            text=eboBlack,
            align=left%
        ]
        {Aenean:\strut};

        \node (4-DIY)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-Typologie.south west,
            anchor = north west
        ]
        {$\cdot$ Finibus elit\strut};

        \node (4-meta) [%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-DIY.south west,
            anchor = north west
        ]
        {$\cdot$  In orci varius\strut};

        \node (4-indus)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-meta.south west,
            anchor = north west
        ]
        {$\cdot$ Lobortis nunc\strut};

        \coordinate (4-anchor)
        at ($(4-bars.south)!0.5!(4-Typologie.north)$);
        \end{tikzpicture}%
    };

%%% ARROWS %%%
% Arrow 0 -> 1
    \path
        (0-picture.east)
    --
        (1-picture.west)
    node [midway] (01-arrow) {\tikz \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,0);};

% Arrows 1 -> 2         
    \path
        (1-picture.east)
    --
        (2-picture.west)
    node [midway] (12-arrow) {
        \begin{tikzpicture}
            \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,0);
            \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,6ex);
            \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,-6ex);
        \end{tikzpicture}
    };
% Arrow 2-3 
    \coordinate (23-middle) at ($(2-caption.east)!.5!(3-caption.west)$);
    \node [
        below = 2.2\eboIconsUnit of 23-middle
    ] {\tikz \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,0);};

% Arrows 3 -> 4 
    \path
        (3-picture.east)
    --
        (4-picture.base west)
    node [midway] (34-arrow) {%
        \begin{tikzpicture}
        \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,.75);
        \draw [eboMiddleArrow] (0,0) -- (\eboInterArrowLength,-.75);
        \end{tikzpicture}
    };

\end{tikzpicture}
\end{document}
9
  • 7
    A lot of work is in the question. Good. Commented Apr 5, 2017 at 19:04
  • Can you lay out the smallest elements first, and from left to right and top to bottom? If so, after laying out the elements for a block you could use a fit node to surround it and use that for positioning the next block. How would that sound? BTW, bonus points for trying to avoid nesting tikzpictures. Commented Apr 5, 2017 at 19:12
  • @LoopSpace It's a good approach. However I sometimes need to explicitly set some shapes' dimensions to preserve picture's homogeneity. For example the big gray rectangle at step 1 is exactly aligned with the top of "Duis tempus" and the bottom of "Luctus rhoncus". // PS: I usually draw each sub-element in a separate file, and the "merge" them together with some adjustments. / Note that the MWE is not a perfect example: it would benefit from a global redefinition using matix (more logical markup), since it is now somehow bulky.
    – ebosi
    Commented Apr 5, 2017 at 19:33
  • You can use \begin{scope}[shift=(2-center),local bounding box=2-picture] (for example), but there is no equivalent to baseline (for tikzpicture) or anchor (for a node). Commented Apr 5, 2017 at 19:58
  • 1
    Incidentally, while you can't refer to a \pic as a whole, you can refer to any nodes that you define within it. Commented Apr 5, 2017 at 22:04

3 Answers 3

16

As it's quite a complicated diagram, I'm going to record my changes as I work through it, so this might not be how I would do it if I were to draw it from scratch. The strategy throughout is to identify the positioning hierarchy and to place contents according to that.


The first inner tikzpicture is "Illustration step 2". This tikzpicture is inside a \node which is anchored with its base anchor at 2-center. The inner tikzpicture has the option baseline=(2-methodology.base). So in this group, we must have 2-methodology.base at 2-center. This means that all of the nodes in this group should be positioned relative to 2-methodology so that is the node that should be positioned first. In actual fact, everything in this group is positioned relative to 2-truepositive so what we need to do is place 2-methodology first (at 2-center), then position 2-truepositive relative to 2-methodology (which is possible by reversing the positioning instructions of the two nodes). After that, we can leave the rest of that group alone. To simulate the original containing node (2-picture), at the end of this group (where the original \end{tikzpicture} was) we use a fit node to contain this group. It would appear enough to fit 2-truepositive and 2-topology.

Now, here's one consequence of the original nesting of the tikzpictures. The anchor=base on 2-picture propagated to its subnodes. As we've removed this inheritance, we need to put it in explicitly on those which aren't otherwise anchored. That's all the example-image-a nodes.


The second inner tikzpicture is Illustration step 1. We'll take a similar approach, but as this one defines some lengths we'll enclose the sub-structure in a scope. What's a bit tricky is that the length is defined using its own sub-tikzpicture (\tikz\node[font={\sffamily}]{\dots};). However, defining it without the \tikz seems to work.

There doesn't seem to be anything else needed on this group, so we just define 1-picture to fit 1-query. It would be equivalent to replace 1-picture by 1-query in the rest of the diagram, but I'm going for minimal changes here.


Moving on to "Illustration 3", we now have a few styles defined so again we use a scope.

Positioning this group is a little trickier because there's no reference point between the inside and outside. The middle of the group is at (3-center), but without knowing how big the group will be this is difficult to ensure. One way is to measure it after placing the nodes and save that information in the aux file for reuse in the next run. Another way is to use a matrix.

Alternatively, we could say that the tops should line up and so position 3-paper so that its top is in line with the top of, say, 2-picture.

Making the containing node fit all its subnodes is trickiest here. For this diagram, we can pick out the extreme nodes (3-paper, 3-sublabel-3-12, 3-label-icon-3, 3-label-2) but if one couldn't do that one would have to list them all.


On to "Illustration 4". This one is easier than "Illustration 3" as the tikzpicture is given an explicit baseline relative to one of its subnodes. So as earlier, we position the relevant subnode first and then everything else relative to that.

Ah, actually it's a \coordinate. So we could replace 4-anchor by 4-center throughout.

This coordinate is half way between 4-bars and 4-Typologie. Again, the anchor=base of the outer node will propagate down meaning that these two nodes have been positioned using their base anchors. This means that measuring the distance between them is tricky until they've been placed. Either a matrix again, or measuring and using that measurement on the next run via the aux file, would be needed to get these absolutely accurate.

But if we take the spirit of the positioning, we can place the two such that they are equal distances from the 4-anchor coordinate (well, except that to take into account the fact that we're using the base anchor, a little adjustment seems in order). This works fine vertically, but is off horizontally. To fix the horizontal, we put 4-anchor at a position in line with 4-center horizontally but vertically in line with 4-caption.west, then when placing 4-bars and 4-Typologie we set their anchors to west and add a little horizontal spacing (1em seems to be about right).

In addition, 4-r-logo needs anchor=base.


Now to the arrows. Here, the use of inner tikzpictures seems most heinous! You're using them as a cheap way of defining coordinates, but as you've loaded the calc library, you can use that instead.

In actual fact, now that everything is in the main tikzpicture (and not hidden in sub-tikzpictures), you could use the anchors of the actual nodes for the arrow sources and targets rather than guessing the magic numbers (e.g. the +/- 6ex). I haven't made that change.


On occasion in the above then I've gone for a slightly easier option with positioning than you get by nesting tikzpictures. It wasn't completely clear if your positioning had to be absolutely as you had it, or whether there was room for manoeuvre where there was a conflict between ease of use and exact placement. Nonetheless, all of your nested tikzpictures can be removed by the method of identifying at each stage which element it is that gets positioned relative to the existing ones.

Before and after

Lastly, here's my code.

\documentclass[10pt, margin=10pt]{standalone}
%\url{http://tex.stackexchange.com/q/362307/86}
    \usepackage{graphicx}
    \usepackage{tikz}
        \usetikzlibrary{calc}
        \usetikzlibrary{positioning}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{fit}
    \usepackage{calc}

\begin{document}
%% Constants definition %%
    %Length and coefficient%
    \newlength{\eboXbigUnit}
        \setlength{\eboXbigUnit}{5em}
    \newlength{\eboYbigUnit}
        \setlength{\eboYbigUnit}{6\baselineskip}
    \newlength{\eboInterlabelDistance}
        \setlength{\eboInterlabelDistance}{2.5\baselineskip}
    \newlength{\eboIconsUnit}
        \setlength{\eboIconsUnit}{\baselineskip}
    \newlength{\eboInterArrowLength}
        \setlength{\eboInterArrowLength}{1.5\baselineskip}
    \newlength{\eboLineWidth}
        \setlength{\eboLineWidth}{.33ex}

    \newcommand{\coefBoxWidth}{6.2}
    \newcommand{\coefBoxHeight}{3}
    %Colors%
    \definecolor{eboOrange}{RGB}{250,179,52}
    \definecolor{eboOrange21}{RGB}{253,215,145}
    \definecolor{eboOrange22}{RGB}{249,163,13}

    \definecolor{eboGrey20}{RGB}{235,234,233}
    \definecolor{eboGrey21}{RGB}{173,171,172}
    \definecolor{eboGrey22}{RGB}{118,115,116}

    \definecolor{eboBlack}{RGB}{35,31,32}

\begin{tikzpicture}[
    remember picture,
    inner sep=0pt,
    outer sep=0pt,
    eboStepLabel/.style={
        font={\sffamily\scriptsize},
        text=eboOrange,
        align=center,
        anchor=base,
    },
    eboMiddleArrow/.style={
        ->,
        draw=eboGrey21,
        line width=\eboLineWidth,
        line cap=round,
        line join = round,
        >={Straight Barb[line cap=round, line join=miter, angle=45:4*\the\eboLineWidth]}
    },
    iconGrey/.style={
        text=eboBlack,
    },
]

%%% TOP LABELS %%%  
% Label 1
    \node[
    eboStepLabel,
    ] 
    (1-caption)
    at (0,0)
    {1. Lorem ipsum\\
        dolor sit amet\strut};

% Label 2
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 1-caption.east,
    anchor=west,
    ] 
    (2-caption)
    {2. consectetur adipiscing elit.\\
        Mauris eu varius eros\strut};

% Label 3
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 2-caption.east,
    anchor=west,
    ] 
    (3-caption)
    {3. Ut convallis\\
        accumsan porttitor\strut};

% Label 4
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 3-caption.east,
    anchor=west,
    ] 
    (4-caption)
    {4. Donec mollis in\\
        erat id sollicitudin\strut};

%%% ILLUSTRATIONS%%%    
% Illustration step 0
    \node (0-picture)[
        below left = \eboYbigUnit and 2.75\eboInterlabelDistance of 1-caption.south, 
        anchor=center
    ]
    {\includegraphics[width=2\baselineskip]{example-image-a}};

% Define center coordinate for illustration of steps 2 to 4
    \coordinate [below = \eboYbigUnit of 2-caption.south](2-center);
    \coordinate [below = \eboYbigUnit of 3-caption.south](3-center);
    \coordinate [below = \eboYbigUnit of 4-caption.south](4-center);

% Illustration step 2       
%        \begin{tikzpicture}[
%            inner sep=0pt, 
%            remember picture, 
%            baseline=(2-methodology.base)
%        ]
        %methodology
        \node[
            anchor=base,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-methodology) at (2-center)
        {};

        %true positive
        \node[
            above = .5\baselineskip of 2-methodology.north,
            fill = eboOrange21,
            draw = eboOrange22,
            anchor=south,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth
        ] (2-truepositive)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-truepositive.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboOrange22,
        ](2-truepositive-label)
        {Duis tempus};

        \coordinate (2-truepositive-articleL) at ($(2-truepositive.north west)!0.9!(2-truepositive.south west)$);
        \coordinate (2-truepositive-articleR) at ($(2-truepositive.north east)!0.9!(2-truepositive.south east)$);

        \foreach \pos in {0.125, 0.375, ..., 0.875} {
            \node[text=eboOrange,anchor=base]
            at ($(2-truepositive-articleL)!\pos!(2-truepositive-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };


        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-methodology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-methodology-label)
        {Dignissim};

        \node[
            below = .1\baselineskip of 2-methodology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-methodology-label)
        {Nulla ut augue vehicula,\\
             tincidunt};

        \coordinate (2-methodology-articleL) at ($(2-methodology.north west)!0.9!(2-methodology.south west)$);
        \coordinate (2-methodology-articleR) at ($(2-methodology.north east)!0.9!(2-methodology.south east)$);

        \foreach \pos in {0.375, 0.625, 0.875} {
            \node[text=eboGrey21,anchor=base]
            at ($(2-methodology-articleL)!\pos!(2-methodology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };

        % dots
        \node[
            below = .33\baselineskip of 2-methodology.south,
            anchor=north,
            text = eboGrey21,
            font = {\sffamily},
        ] (2-dots)
        {\dots};

        % topology
        \node[
            below = .33\baselineskip of 2-dots.south,
            anchor=north,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-topology)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-topology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-topology-label)
        {Luctus rhoncus};

        \node[
            below = .1\baselineskip of 2-topology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-topology-label)
        {Donec molestie mollis arcu\\
             eget consectetur};

        \coordinate (2-topology-articleL) at ($(2-topology.north west)!0.9!(2-topology.south west)$);
        \coordinate (2-topology-articleR) at ($(2-topology.north east)!0.9!(2-topology.south east)$);

        \foreach \pos in {0.625, 0.875} {
            \node[text=eboGrey21,anchor=base]
            at ($(2-topology-articleL)!\pos!(2-topology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };
%        \end{tikzpicture}
        \node[
          %draw, line width=1mm, % Uncomment this to see the boundary
          inner sep=0pt, outer sep=0pt,
          fit=(2-topology) (2-truepositive)
    ] (2-picture)
    {%
    };

% Define center coordinate for illustration of step 1
    \path
    (2-picture.west)
    -|
    (1-caption.south)
    coordinate [midway] (1-center);

% Illustration step 1   
    \begin{scope}
    \newlength{\queryHeight}%
    \setlength{\queryHeight}{10.166\baselineskip}%
    \addtolength{\queryHeight}{\heightof{{\sffamily\dots}}}

    %\begin{tikzpicture}[inner sep=0pt]
        \node[
        fill = eboGrey21,
        draw = eboGrey22,
        rectangle,
        minimum height = \queryHeight,
        minimum width = \coefBoxWidth\baselineskip,
        line width = .5\eboLineWidth,
        rounded corners=\eboLineWidth,
        ] (1-query) at (1-center)
        {};
        \node[
        below right= .5\baselineskip and .25\baselineskip of 1-query.north west,
        anchor = north west,
        align = left,
        font = {\sffamily\scriptsize},
        text = eboGrey20,
        ](1-query-google)
        {\includegraphics[height=\baselineskip]{example-image-b}};
        \node[
        right= .25\baselineskip of 1-query-google.north east,
        anchor = north west,
        align = left,
        font = {\tiny\sffamily},
        text = eboGrey20,
        ](1-query-google)
        {$\cdot$~Duis vitae faucibus orci,\\
            venenatis nulla ac\\
            $\cdot$~Vivamus sit amet\\
            hendrerit dui};

        \coordinate (1-UL) at ($(1-query.north west)!0.2!(1-query.south west)$);
        \coordinate (1-UR) at ($(1-query.north east)!0.2!(1-query.south east)$);
        \coordinate (1-LL) at ($(1-query.north west)!1!(1-query.south west)$);
        \coordinate (1-LR) at ($(1-query.north east)!1!(1-query.south east)$);

        \foreach \x in {0.125,0.375,0.625,0.875}{
            \foreach \y/\yname in {0.166/a, 0.333/b, 0.5/c, 0.666/d , 0.833/e}{
                \coordinate (myL\yname) at ($(1-UL)!\y!(1-LL)$);
                \coordinate (myR\yname) at ($(1-UR)!\y!(1-LR)$);
                \node [text=eboGrey22] at ($(myL\yname)!\x!(myR\yname)$) {\includegraphics[height=\baselineskip]{example-image-a}};
            };
        };
        %\end{tikzpicture}
        \end{scope}
    \node[
      %draw, line width=1mm, % Uncomment this to see the boundary
      inner sep=0pt, outer sep=0pt,
      fit=(1-query)
      ](1-picture)
    {%
    };

    % Illustration 3        
    %\begin{tikzpicture}[
    %remember picture,
    %inner sep=0pt,
    \begin{scope}[
        categorizationLabel/.style={
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,
        },
        categorizationSublabel/.style={
            font={\sffamily\tiny},
            text=eboGrey21,
            align=left,
        },
        ]
        \node (3-paper) [text=eboOrange,anchor=north]
        at (3-center |- 2-picture.north)
        {\includegraphics[height=2\baselineskip]{example-image-a}};
        \node [
            below left = .333\baselineskip and .15\baselineskip of 3-paper.north east, 
            anchor=north west,
            text=eboGrey22,
        ]
        {\includegraphics[width=\baselineskip]{example-image-c}};

        %Type of paper  
        \node (3-label-1) [
            categorizationLabel, 
            below = \baselineskip of 3-paper.south west,
            anchor = base west
        ]
        {Proin sollicitudin};

        \node (3-label-icon-1)[
            left = .5em of 3-label-1.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-1-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-1.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} ipsum ac};

        \node (3-sublabel-1-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} vestibulum};

        \node (3-sublabel-1-12) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} suscipit};

        \node (3-sublabel-1-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} venenatis};

        %Type of product    
        \node (3-label-2) [
            categorizationLabel, 
            below = 2.85\baselineskip of 3-label-1.west, 
            anchor=west,
        ]
        {Vulputate fringilla};

        \node (3-label-icon-2)[
            left = .5em of 3-label-2.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-2-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-2.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} condimentum};

        \node (3-sublabel-2-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} scelerisque};

        \node (3-sublabel-2-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-2-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} lacus};

        \node (3-sublabel-2-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} pharetra};

        %Type of open-design    
        \node (3-label-3) [
            categorizationLabel, 
            below = 2.9\baselineskip of 3-label-2.west,
            anchor=west,
        ]
        {Fusce justo est};
        \node (3-label-icon-3) [
            left = .5em of 3-label-3.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-3-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-3.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} consequat};

        \node (3-sublabel-3-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-3-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} nec facilisis};

        \node (3-sublabel-3-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-3-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} sodales};
        %        \end{tikzpicture}
        \end{scope}
    \node[
      %draw, line width=1mm, % Uncomment this to see the boundary
      inner sep=0pt, outer sep=0pt,
      fit=(3-paper) (3-sublabel-3-12) (3-label-icon-3) (3-label-2)
    ] (3-picture)
    {%
    };


    % Illustration 4        
%        \begin{tikzpicture}[remember picture,baseline = (4-anchor)]
        \coordinate (4-anchor) at (4-center -| 4-caption.west);

        \node (4-bars) 
        at ($(4-anchor)+(1em,1.5\eboIconsUnit)$) [iconGrey,anchor=west] 
        {\includegraphics[width=2\eboIconsUnit]{example-image-b}};

        \node (4-r-logo) 
        at (4-bars.north east) [iconGrey,anchor=base] 
        {\includegraphics[width=\eboIconsUnit]{example-image-c}};

        \node[anchor=west] (4-Typologie)
        at ($(4-anchor)+(1em,-1.5\eboIconsUnit-.5\baselineskip)$) [%
            font={\sffamily\scriptsize},
            text=eboBlack,
            align=left%
        ]
        {Aenean:\strut};

        \node (4-DIY)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-Typologie.south west,
            anchor = north west
        ]
        {$\cdot$ Finibus elit\strut};

        \node (4-meta) [%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-DIY.south west,
            anchor = north west
        ]
        {$\cdot$  In orci varius\strut};

        \node (4-indus)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-meta.south west,
            anchor = north west
        ]
        {$\cdot$ Lobortis nunc\strut};

%        \end{tikzpicture}%
    \node (4-picture) at (4-center) [
          %draw, line width=1mm, % Uncomment this to see the boundary
      inner sep=0pt, outer sep=0pt,
      fit=(4-bars) (4-r-logo) (4-Typologie) (4-DIY) (4-meta) (4-indus)
    ]
    {%
    };

%%% ARROWS %%%
% Arrow 0 -> 1
    \draw[eboMiddleArrow] ($(0-picture.east)!.5!(1-picture.west)$) ++(-.5\eboInterArrowLength,0) -- ++(\eboInterArrowLength,0);

    % Arrows 1 -> 2
    \coordinate (12-arrow) at ($(1-picture.east)!.5!(2-picture.west)$);
    \draw[eboMiddleArrow] (12-arrow) ++(-.5\eboInterArrowLength,0) -- +(\eboInterArrowLength,0);
    \draw[eboMiddleArrow] (12-arrow) ++(-.5\eboInterArrowLength,0) -- +(\eboInterArrowLength,6ex);
    \draw[eboMiddleArrow] (12-arrow) ++(-.5\eboInterArrowLength,0) -- +(\eboInterArrowLength,-6ex);

% Arrow 2-3 
    \coordinate (23-middle) at ($(2-caption.east)!.5!(3-caption.west)$);
    \draw [eboMiddleArrow] (23-middle) ++(-.5\eboInterArrowLength,-2.2\eboIconsUnit) -- ++(\eboInterArrowLength,0);

    % Arrows 3 -> 4
    \coordinate (34-arrow) at ($(3-picture.east)!.5!(4-picture.base west)$);
    \draw [eboMiddleArrow] (34-arrow) ++(-.5\eboInterArrowLength,0) -- ++(\eboInterArrowLength,.75);
    \draw [eboMiddleArrow] (34-arrow) ++(-.5\eboInterArrowLength,0) -- ++(\eboInterArrowLength,-.75);

\end{tikzpicture}
\end{document}
3
  • 1
    Wow, it's a lot of work! I do appreciate! At the same time, I feel bad, since I didn't intended one should go into its details (that's too much work!). I'm indeed especially interested in general guidelines that would be useful for anyone, i.e. how would you do it if you were to draw it from scratch (see added comment in the question). For example "I would place macro-elements using a diagram, and the use pics inside nodes, etc..."
    – ebosi
    Commented Apr 5, 2017 at 21:58
  • @ebo I understand that it's not "code review", but the problem with "general guidelines" is that they can be hard to put into practice. So I elected to show how one could remove the nested tikzpictures from the code that you gave. I don't think that doing it from scratch would be useful to you because there are so many decisions in that picture that without understanding it deeply, it would be easy to make a wrong decision that makes the whole exercise useless to you. So modifying your code hopefully illustrates the general principle of my first paragraph. Commented Apr 5, 2017 at 22:04
  • I better understand your approach now.
    – ebosi
    Commented Apr 5, 2017 at 22:06
11

The following trick will turn a scope into a node. So you can

  • name the scope by name=mother;
  • position the scope by at=(somewhere);
  • tune the position by anchor=something; (below left and anchor=45 also work).

At the same time, node names in the scope are all remembered.

\documentclass[border=9,tikz]{standalone}
\begin{document}
\makeatletter
\newbox\tikz@sand@box
\newcount\tikz@scope@depth
\tikz@scope@depth111\relax
\def\scopenode[#1]#2{%
    \begin{pgfinterruptboundingbox}%
        \advance\tikz@scope@depth111\relax%
        % process the user option
        \begin{scope}[name=tempscopenodename,at={(0,0)},anchor=center,#1]%
            % try to extract positioning information: name, at, anchor
            \global\let\tikz@fig@name\tikz@fig@name%
            \global\let\tikz@node@at\tikz@node@at%
            \global\let\tikz@anchor\tikz@anchor%
        \end{scope}%
        \let\tikz@scopenode@name\tikz@fig@name%
        \let\tikz@scopenode@at\tikz@node@at%
        \let\tikz@scopenode@anchor\tikz@anchor%
        % try to typeset this scope
        % we only need bounding box information
        % the box itself will be discard
        \setbox\tikz@sand@box=\hbox{%
            \begin{scope}[local bounding box=tikz@sand@box\the\tikz@scope@depth,#1]%
                #2%
            \end{scope}%
        }%
        % goodbye. haha
        \setbox\tikz@sand@box=\hbox{}%
        % now typeset again
        \begin{scope}[local bounding box=\tikz@scopenode@name]%
            % use the bounding box information to reposition the scope
            \pgftransformshift{\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{\tikz@scopenode@anchor}%
                               \pgf@x-\pgf@x\pgf@y-\pgf@y}%
            \pgftransformshift{\tikz@scopenode@at}%
            \begin{scope}[#1]%
                #2
            \end{scope}%
        \end{scope}%
        \pgfkeys{/pgf/freeze local bounding box=\tikz@scopenode@name}%
        \global\let\tikz@scopenode@name@smuggle\tikz@scopenode@name%
    \end{pgfinterruptboundingbox}%
    % make up the bounding box
    \path(\tikz@scopenode@[email protected] west)(\tikz@scopenode@[email protected] east);%
    % draw something, not necessary
    \draw[#1](\tikz@scopenode@[email protected] west)rectangle(\tikz@scopenode@[email protected] east);%
}

\tikz{
    \scopenode[name=A,at={(5,10)},right]{
        \scopenode[name=Aa,at={(0,3)},right]{
            \scopenode[name=Aa1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Aa2,at={(Aa1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Aa3,at={(Aa2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Ab,at={(Aa.south west)},below,red]{
            \scopenode[name=Ab1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ab2,at={(Ab1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ab3,at={(Ab2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Ac,at={(Ab.south east)},below,blue]{
            \scopenode[name=Ac1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ac2,at={(Ac1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ac3,at={(Ac2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
    }
    \scopenode[name=B,at={(A.south west)},below,line width=10.4]{
        \scopenode[name=Ba,at={(0,3)},right]{
            \scopenode[name=Ba1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ba2,at={(Ba1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ba3,at={(Ba2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Bb,at={(Ba.south west)},below,red]{
            \scopenode[name=Bb1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Bb2,at={(Bb1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Bb3,at={(Bb2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Bc,at={(Bb.south east)},below,blue]{
            \scopenode[name=Bc1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Bc2,at={(Bc1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Bc3,at={(Bc2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
    }
    \scopenode[name=C,at={(B.south west)},below,line width=20.4]{
        \scopenode[name=Ca,at={(0,3)},right]{
            \scopenode[name=Ca1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ca2,at={(Ca1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Ca3,at={(Ca2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Cb,at={(Ca.south west)},below,red]{
            \scopenode[name=Cb1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Cb2,at={(Cb1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Cb3,at={(Cb2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
        \scopenode[name=Cc,at={(Cb.south east)},below,blue]{
            \scopenode[name=Cc1,at={(2,2)},opacity=.4]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Cc2,at={(Cc1.east)},right,opacity=.7]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
            \scopenode[name=Cc3,at={(Cc2.east)},right,opacity=1]{
                \fill(0,0)rectangle(1,1)rectangle(2,2)rectangle(3,3);
            }
        }
    }
%   \foreach\A in{A,B,C}{
%       \draw[yellow,bend right,line width=10](-10,15)to(\A.west);
%       \foreach\a in{a,b,c}{
%           \draw[green,line width=5](-10,15)--(\A\a.north);
%           \foreach\n in{1,2,3}{
%               \draw(-10,15)--(\A\a\n.east);
%           }
%       }
%   }
}

\end{document}

the elephant never forgets

4
  • This is very nice, though it does not quite work with externalisation.
    – cfr
    Commented Apr 11, 2017 at 22:08
  • @cfr give me more hints. Maybe I can fix it.
    – Symbol 1
    Commented Apr 11, 2017 at 22:32
  • Never mind. I can't reproduce it now. Earlier, it seemed that figures were never recompiled automatically when I had \scopenode in the picture and I had to delete the images manually to force recompilation. But I must have been doing something stupid, because it works now. Sorry for the noise.
    – cfr
    Commented Apr 11, 2017 at 23:32
  • Your answer is truly powerful! FYI, cfr provided an updated version of them where scopenode's content is displayed above its fill color. I've then posted a follow-up question about your answer here: TikZ: Make “scopenode” compatible with matrix.
    – ebosi
    Commented Apr 19, 2017 at 22:12
9

I used saveboxes (mostly) to prevent nesting tikzpictures. One advantage is that you can measure the width, height and depth of a savebox directly using \wd\boxA, \ht\boxA and \dp\boxA (for example).

One could have done the whole thing using scopes, but it would have taken a different design approach (organizing the contents from the center out).

\documentclass[10pt, margin=10pt]{standalone}
    \usepackage{graphicx}
    \usepackage{tikz}
        \usetikzlibrary{calc}
        \usetikzlibrary{positioning}
        \usetikzlibrary{arrows.meta}
    \usepackage{calc}

%% Constants definition %%
    %Length and coefficient%
    \newlength{\eboXbigUnit}
        \setlength{\eboXbigUnit}{5em}
    \newlength{\eboYbigUnit}
        \setlength{\eboYbigUnit}{6\baselineskip}
    \newlength{\eboInterlabelDistance}
        \setlength{\eboInterlabelDistance}{2.5\baselineskip}
    \newlength{\eboIconsUnit}
        \setlength{\eboIconsUnit}{\baselineskip}
    \newlength{\eboInterArrowLength}
        \setlength{\eboInterArrowLength}{1.5\baselineskip}
    \newlength{\eboLineWidth}
        \setlength{\eboLineWidth}{.33ex}
    \newlength{\queryHeight}%
        \setlength{\queryHeight}{10.166\baselineskip}%
        \addtolength{\queryHeight}{\heightof{\tikz\node[font={\sffamily}]{\dots};}}%

    \newcommand{\coefBoxWidth}{6.2}
    \newcommand{\coefBoxHeight}{3}
    %Colors%
    \definecolor{eboOrange}{RGB}{250,179,52}
    \definecolor{eboOrange21}{RGB}{253,215,145}
    \definecolor{eboOrange22}{RGB}{249,163,13}

    \definecolor{eboGrey20}{RGB}{235,234,233}
    \definecolor{eboGrey21}{RGB}{173,171,172}
    \definecolor{eboGrey22}{RGB}{118,115,116}

    \definecolor{eboBlack}{RGB}{35,31,32}

    % 2-picture

    \newsavebox{\boxA}
    \savebox{\boxA}{\begin{tikzpicture}[
            inner sep=0pt, 
            remember picture, 
            baseline=(2-methodology.base)
        ]
        %true positive
        \node[
            fill = eboOrange21,
            draw = eboOrange22,
            anchor=north east,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth
        ] (2-truepositive)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-truepositive.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboOrange22,
        ](2-truepositive-label)
        {Duis tempus};

        \coordinate (2-truepositive-articleL) at ($(2-truepositive.north west)!0.9!(2-truepositive.south west)$);
        \coordinate (2-truepositive-articleR) at ($(2-truepositive.north east)!0.9!(2-truepositive.south east)$);

        \foreach \pos in {0.125, 0.375, ..., 0.875} {
            \node[text=eboOrange]
            at ($(2-truepositive-articleL)!\pos!(2-truepositive-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };
        %methodology
        \node[
            below = .5\baselineskip of 2-truepositive.south,
            anchor=north,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-methodology)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-methodology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-methodology-label)
        {Dignissim};

        \node[
            below = .1\baselineskip of 2-methodology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-methodology-label)
        {Nulla ut augue vehicula,\\
             tincidunt};

        \coordinate (2-methodology-articleL) at ($(2-methodology.north west)!0.9!(2-methodology.south west)$);
        \coordinate (2-methodology-articleR) at ($(2-methodology.north east)!0.9!(2-methodology.south east)$);

        \foreach \pos in {0.375, 0.625, 0.875} {
            \node[text=eboGrey21]
            at ($(2-methodology-articleL)!\pos!(2-methodology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };

        % dots
        \node[
            below = .33\baselineskip of 2-methodology.south,
            anchor=north,
            text = eboGrey21,
            font = {\sffamily},
        ] (2-dots)
        {\dots};

        % topology
        \node[
            below = .33\baselineskip of 2-dots.south,
            anchor=north,
            fill = eboGrey20,
            draw = eboGrey21,
            rectangle,
            minimum height = \coefBoxHeight\baselineskip,
            minimum width = \coefBoxWidth\baselineskip,
            line width = .5\eboLineWidth,
            rounded corners=\eboLineWidth,
        ] (2-topology)
        {};

        \node[
            below right= .25\baselineskip and .25\baselineskip of 2-topology.north west,
            anchor = north west,
            align = left,
            font = {\sffamily\scriptsize},
            text = eboGrey21,
        ](2-topology-label)
        {Luctus rhoncus};

        \node[
            below = .1\baselineskip of 2-topology-label.south west,
            anchor = north west,
            align = left,
            font = {\sffamily\tiny},
            text = eboGrey21,
        ](2-topology-label)
        {Donec molestie mollis arcu\\
             eget consectetur};

        \coordinate (2-topology-articleL) at ($(2-topology.north west)!0.9!(2-topology.south west)$);
        \coordinate (2-topology-articleR) at ($(2-topology.north east)!0.9!(2-topology.south east)$);

        \foreach \pos in {0.625, 0.875} {
            \node[text=eboGrey21]
            at ($(2-topology-articleL)!\pos!(2-topology-articleR)$)
            {\includegraphics[height=\baselineskip]{example-image-a}};
        };
        \end{tikzpicture}
 }

% 1-picture

\newsavebox{\boxB}
\savebox{\boxB}{\begin{tikzpicture}[inner sep=0pt]
        \node[
        fill = eboGrey21,
        draw = eboGrey22,
        rectangle,
        minimum height = \queryHeight,
        minimum width = \coefBoxWidth\baselineskip,
        line width = .5\eboLineWidth,
        rounded corners=\eboLineWidth,
        ] (1-query)
        {};
        \node[
        below right= .5\baselineskip and .25\baselineskip of 1-query.north west,
        anchor = north west,
        align = left,
        font = {\sffamily\scriptsize},
        text = eboGrey20,
        ](1-query-google)
        {\includegraphics[height=\baselineskip]{example-image-b}};
        \node[
        right= .25\baselineskip of 1-query-google.north east,
        anchor = north west,
        align = left,
        font = {\tiny\sffamily},
        text = eboGrey20,
        ](1-query-google)
        {$\cdot$~Duis vitae faucibus orci,\\
            venenatis nulla ac\\
            $\cdot$~Vivamus sit amet\\
            hendrerit dui};

        \coordinate (1-UL) at ($(1-query.north west)!0.2!(1-query.south west)$);
        \coordinate (1-UR) at ($(1-query.north east)!0.2!(1-query.south east)$);
        \coordinate (1-LL) at ($(1-query.north west)!1!(1-query.south west)$);
        \coordinate (1-LR) at ($(1-query.north east)!1!(1-query.south east)$);

        \foreach \x in {0.125,0.375,0.625,0.875}{
            \foreach \y/\yname in {0.166/a, 0.333/b, 0.5/c, 0.666/d , 0.833/e}{
                \coordinate (myL\yname) at ($(1-UL)!\y!(1-LL)$);
                \coordinate (myR\yname) at ($(1-UR)!\y!(1-LR)$);
                \node [text=eboGrey22] at ($(myL\yname)!\x!(myR\yname)$) {\includegraphics[height=\baselineskip]{example-image-a}};
            };
        };
        \end{tikzpicture}
}

% 3-pixcture

\newsavebox{\boxC}
\savebox{\boxC}{\begin{tikzpicture}[
        remember picture,
        inner sep=0pt,
        categorizationLabel/.style={
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,
        },
        categorizationSublabel/.style={
            font={\sffamily\tiny},
            text=eboGrey21,
            align=left,
        },
        ]
        \node (3-paper) [text=eboOrange]
        at (0,0)
        {\includegraphics[height=2\baselineskip]{example-image-a}};
        \node [
            below left = .333\baselineskip and .15\baselineskip of 3-paper.north east, 
            anchor=north west,
            text=eboGrey22,
        ]
        {\includegraphics[width=\baselineskip]{example-image-c}};

        %Type of paper  
        \node (3-label-1) [
            categorizationLabel, 
            below = \baselineskip of 3-paper.south west,
            anchor = base west
        ]
        {Proin sollicitudin};

        \node (3-label-icon-1)[
            left = .5em of 3-label-1.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-1-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-1.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} ipsum ac};

        \node (3-sublabel-1-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} vestibulum};

        \node (3-sublabel-1-12) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} suscipit};

        \node (3-sublabel-1-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-1-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} venenatis};

        %Type of product    
        \node (3-label-2) [
            categorizationLabel, 
            below = 2.85\baselineskip of 3-label-1.west, 
            anchor=west,
        ]
        {Vulputate fringilla};

        \node (3-label-icon-2)[
            left = .5em of 3-label-2.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-2-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-2.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} condimentum};

        \node (3-sublabel-2-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} scelerisque};

        \node (3-sublabel-2-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-2-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} lacus};

        \node (3-sublabel-2-22) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-2-12.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} pharetra};

        %Type of open-design    
        \node (3-label-3) [
            categorizationLabel, 
            below = 2.9\baselineskip of 3-label-2.west,
            anchor=west,
        ]
        {Fusce justo est};
        \node (3-label-icon-3) [
            left = .5em of 3-label-3.west,
            anchor=east,
            text=eboGrey22,
        ]
        {\includegraphics[height=2ex]{example-image-b}};

        \node (3-sublabel-3-11) [
            categorizationSublabel,
            below right = .05ex and .175em of 3-label-3.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} consequat};

        \node (3-sublabel-3-21) [
            categorizationSublabel,
            below = .0ex of 3-sublabel-3-11.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} nec facilisis};

        \node (3-sublabel-3-12) [
            categorizationSublabel,
            below = 0.05ex of 3-sublabel-3-21.south west,
            anchor= north west,
        ]
        {\strut\includegraphics[height=1ex]{example-image} sodales};
        \end{tikzpicture}
}

% 4-pixcture

\newsavebox{\boxD}
\savebox{\boxD}{\begin{tikzpicture}[remember picture,baseline = (4-anchor),
  iconGrey/.style={text=eboBlack},]
        \node (4-bars) 
        at (0,0) [iconGrey] 
        {\includegraphics[width=2\eboIconsUnit]{example-image-b}};

        \node (4-r-logo) 
        at (4-bars.north east) [iconGrey] 
        {\includegraphics[width=\eboIconsUnit]{example-image-c}};

        \node (4-Typologie)
        at (0, -3\eboIconsUnit) [%
            font={\sffamily\scriptsize},
            text=eboBlack,
            align=left%
        ]
        {Aenean:\strut};

        \node (4-DIY)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-Typologie.south west,
            anchor = north west
        ]
        {$\cdot$ Finibus elit\strut};

        \node (4-meta) [%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-DIY.south west,
            anchor = north west
        ]
        {$\cdot$  In orci varius\strut};

        \node (4-indus)[%
            font={\sffamily\scriptsize},
            text=eboGrey22,
            align=left,%
            below = 0pt of 4-meta.south west,
            anchor = north west
        ]
        {$\cdot$ Lobortis nunc\strut};

        \coordinate (4-anchor)
        at ($(4-bars.south)!0.5!(4-Typologie.north)$);
        \end{tikzpicture}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
\begin{tikzpicture}[
    remember picture,
    inner sep=0pt,
    outer sep=0pt,
    eboStepLabel/.style={
        font={\sffamily\scriptsize},
        text=eboOrange,
        align=center,
        anchor=base,
    },
    eboMiddleArrow/.style={
        ->,
        draw=eboGrey21,
        line width=\eboLineWidth,
        line cap=round,
        line join = round,
        >={Straight Barb[line cap=round, line join=miter, angle=45:4*\the\eboLineWidth]}
    },
]

%%% TOP LABELS %%%  
% Label 1
    \node[
    eboStepLabel,
    ] 
    (1-caption)
    at (0,0)
    {1. Lorem ipsum\\
        dolor sit amet\strut};

% Label 2
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 1-caption.east,
    anchor=west,
    ] 
    (2-caption)
    {2. consectetur adipiscing elit.\\
        Mauris eu varius eros\strut};

% Label 3
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 2-caption.east,
    anchor=west,
    ] 
    (3-caption)
    {3. Ut convallis\\
        accumsan porttitor\strut};

% Label 4
    \node[
    eboStepLabel,
    right= \eboInterlabelDistance of 3-caption.east,
    anchor=west,
    ] 
    (4-caption)
    {4. Donec mollis in\\
        erat id sollicitudin\strut};

%%% ILLUSTRATIONS%%%    
% Illustration step 0
    \node (0-picture)[
        below left = \eboYbigUnit and 2.75\eboInterlabelDistance of 1-caption.south, 
        anchor=center
    ]
    {\includegraphics[width=2\baselineskip]{example-image-a}};

% Define center coordinate for illustration of steps 2 to 4
    \coordinate [below = \eboYbigUnit of 2-caption.south](2-center);
    \coordinate [below = \eboYbigUnit of 3-caption.south](3-center);
    \coordinate [below = \eboYbigUnit of 4-caption.south](4-center);

% Illustration step 2       
    \node (2-picture) at (2-center)[
        anchor=base,
    ]
    {\usebox{\boxA}};  

% Define center coordinate for illustration of step 1
    \path
    (2-picture.west)
    -|
    (1-caption.south)
    coordinate [midway] (1-center);

% Illustration step 1   
    \node (1-picture) at (1-center)
    {\usebox{\boxB}};

    % Illustration 3        
    \node (3-picture) at (3-center)
    {\usebox{\boxC}};

    % Illustration 4        
    \node (4-picture) at (4-center) [
    anchor=base,
    ]
    {\usebox{\boxD}};

%%% ARROWS %%%
% Arrow 0 -> 1
    \begin{scope}[shift=($(0-picture.east)!.5!(1-picture.west)$),
      local bounding box=01-arrow]
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,0);
    \end{scope}

% Arrows 1 -> 2         
    \begin{scope}[shift=($(1-picture.east)!.5!(2-picture.west)$),
      local bounding box=12-arrow]
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,0);
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,6ex);
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,-6ex);
    \end{scope}
% Arrow 2-3 
    \coordinate (23-middle) at ($(2-caption.east)!.5!(3-caption.west)$);
    \begin{scope}[shift=(23-middle |- 3-paper.center)]
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,0);
    \end{scope}

% Arrows 3 -> 4 
    \begin{scope}[shift=($(3-picture.east)!.5!(4-picture.west)$),
      local bounding box=34-arrow]
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,.75);
        \draw [eboMiddleArrow] (-.5\eboInterArrowLength,0) -- (.5\eboInterArrowLength,-.75);
    \end{scope}

\end{tikzpicture}
\end{document}
4
  • 1
    This is how the tikz-qtree library gets round this very issue. Commented Apr 5, 2017 at 21:44
  • It works great! Note however that one cannot access nodes defined within the savebox outside its definition. It's also not easy to combine with externalization. (I'll expand this later in a detailed answer). Last feedback: an lrbox might be preferred over a 'simple' savebox.
    – ebosi
    Commented Apr 19, 2017 at 22:17
  • Actually, you can access the nodes inside the savebox if you use [remember picture]. IIRC, I did so somewhere in the code. Commented Apr 19, 2017 at 22:41
  • (3-paper) is defined inside \boxC Commented Apr 19, 2017 at 22:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .