6

I'm struggling with a matrix where I want to put drawings into the cells, but would still like to reference the cells as it is possible with (text) nodes, e.g. for annotation.

I know that I can achieve this by putting text nodes and inside the text put another \tikz and draw (2nd row in the example). However, putting a text node into the tikz picture with the sole purpose of having another TikZ picture inside feels a terrible waste. Is there a more elegant way?

I tried to use nodes in empty cells = true, but the cells with drawings inside are not empty, they just don't have a node. So that doesn't help.

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{decorations.pathreplacing}
\begin{document}
\begin{tikzpicture}
\newcommand{\punkt}{\fill (0, 0) circle (1mm);}
\newcommand{\tpunkt}{{\tikz\fill (0, 0) circle (1mm);}}
\matrix (m) [matrix of nodes,
    nodes={rectangle,draw, fill=yellow}
]{
    \punkt  & \punkt \\
    \tpunkt & \tpunkt\\
};

\draw[decorate, decoration = brace] (m-2-2.south east) -- node [below] {foo} (m-2-1.south west);
% doesn't work, because nodes m-1-1 and m-1-2 do not exist:
% \draw[decorate, decoration = brace] (m-1-1.north west) -- node [above] {bar} (m-1-2.north east);
\end{tikzpicture}
\end{document}

To clarify a bit what I'm after:

  • the circles are not just circles in the real diagram, and there are different combinations of objects in the real diagram. That makes @cacamailg's answer even less elegant (and too complicated to keep the overview) than putting \tikz{} drawings into text nodes.
  • is there a way to hand the name tikz would give to the node to the drawing macro (\punkt{*tikz-node-name*}?

  • the |style| notation doesn't help, neither, because no node is generated if I have drawing commands in the cell.

  • I start thinking whether defining custom shapes that include the drawing commands is the solution.


Edit 2: the real example.

real example

Link to the .tex file

  • There seems to be a confusion here I think: Just use nodes in empty cells for handling nodes well ...ehm ... in empty cells. You can control their properties via nodes={inner sep=0,minimum size=1mm,fill} etc. given to matrix options. As you say don't use nested tikz pictures just for this. – percusse May 1 '13 at 14:57
  • What should be referenced here with the cell node/name? There is just a path in it. It won’t have any name or even an anchor. In this simple case (circles) you can use the circle shape and reference its anchors. – Qrrbrbirlbel May 1 '13 at 15:24
  • @percusse: well, the cells with \punkt are not empty - they have the circle inside, but they don't have a node, not even an empty one. – cbeleites May 1 '13 at 16:03
  • Why don't you give the real example instead of circles to avoid doubling the effort? Maybe there is another solution that is what you are after. – percusse May 1 '13 at 16:22
  • @percusse: thanks, that's what I decided as well. The .tex file is IMHO too large to put it directly in here, so I hope a link to a gist is acceptable as well. – cbeleites May 1 '13 at 16:32
9

OK, there is a lot going on here, but hopefully the comments go someway to making it clear how I've achieved this. I use a lot of nested style definitions, which possibly may make things tricky to follow but hopefully the style names give some indication of what they do. I also use a lot of nested \foreach loops for no other reason than I found it easier than using a matrix.

Some apologies in advance for mangling the German words in the style definitions.

\documentclass[border=5pt]{standalone}
\usepackage{tikz}

% pifont for tick and cross.
\usepackage{pifont}

% Only need the matrix library for delimiters.
\usetikzlibrary{matrix,fit}
\usetikzlibrary{shapes.geometric}


% Define some colors.
\colorlet{Klasse A}{red}
\colorlet{Klasse B}{blue}
\colorlet{probe color}{Klasse A}
\colorlet{correct color}{Klasse A}
\colorlet{incorrect color}{Klasse A}
\colorlet{testproben}{gray!20}

\def\vmark{}

\tikzset{
    tight fit/.style={inner sep=0pt, outer sep=0pt},
    probe color/.code={\colorlet{probe color}{#1}},
    correct color/.code={\colorlet{correct color}{#1}},
    incorrect color/.code={\colorlet{incorrect color}{#1}},
    probe/.style args={#1-#2}{%
        outer sep=0pt,
        shape=rectangle,
        probe #1-#2/.try,
        execute at begin node={%
            % Hide the testproben spike in a style rather than
            % clutter up the main code.
            \begin{tikzpicture}[x=2.75pt,y=1.5pt, scale=0.625]
                \path [draw=probe color] plot [smooth] coordinates {(0,0) 
                (1,2) (2,10) (3,1) (4,3) (5,1) (6,4) (7,0)};
            \end{tikzpicture}}  
    },
    vorhesage/.style args={#1-#2}{
        shape=circle,
        draw=correct color,
        text=white,
        font=\bf\small,
        vorhesage #1-#2/.try,
        incorrect vorhesage #1-#2/.try,
        minimum size=0.625cm    
    },
    surrogat/.style={
        shape=regular polygon,
        regular polygon sides=3,
        minimum height=1cm,
        draw
    }
}


\tikzset{
    % The styles applied to specified testproben and (correct) vorhesage
    testproben/.style args={#1-#2}{
        probe #1-#2/.style={
            fill=testproben
        },
        vorhesage #1-#2/.style={
            fill=correct color,
            execute at begin node=\def\vmark{\ding{51}}% A tick
        }
    },
    % The styles applied to specified testproben and (incorrect) vorhesage
    testproben */.style args={#1-#2}{
        probe #1-#2/.style={
            fill=testproben
        },
        incorrect vorhesage #1-#2/.style={
            fill=incorrect color,
            draw=correct color,
            very thick,
            execute at begin node=\def\vmark{\ding{55}}% A cross
        }
    },
    Daten A/.style={
        A/.try,
        probe color=Klasse A,
    },
    Daten B/.style={
        B/.try,
        probe color=Klasse B,
        shift={(5,0)}
    },
    Vorhesage A/.style={
        A/.try,
        correct color=Klasse A,
        incorrect color=Klasse B,
    },
    Vorhesage B/.style={
        B/.try,
        correct color=Klasse B,
        incorrect color=Klasse A,
        shift={(5,0)}
    },      
    iteration 1/.style={
        % Define the testproben (and vorhesagen) for iteration 1
        A/.style={
            testproben={1-4}, % testproben row 1, column 4
            testproben={2-3}, testproben={2-5},
            testproben *={3-1}, testproben={3-2},
        },
        B/.style={
            testproben={1-2}, testproben={1-3},
            testproben *={2-1},
            testproben={3-4}
        },
    },
    iteration 2/.style={
        A/.style={
            testproben={1-1}, testproben={1-4},testproben={1-5},
            testproben={2-2},
            testproben={3-5}
        },
        B/.style={
            testproben={1-2}, testproben={2-1},
            testproben={3-1}, testproben={3-3}
        }
    },
    iteration 3/.style={
        A/.style={
            testproben={1-5}, testproben={1-4},
            testproben={2-2}, testproben={2-2},
            testproben *={3-1}
        },
        B/.style={
            testproben={1-2}, 
            testproben={2-1},
            testproben={3-3}, testproben={3-4}
        },
    }
}

\begin{document}

\begin{tikzpicture}[x=0.75cm, y=0.75cm, >=stealth]

\foreach \itr in {1,2,3}{
    % Install the A and B styles for this iteration.
    % The A and B styles define the testproben for Klasse A
    % and Kasse B.
    \tikzset{iteration \itr/.try}
    \foreach \g in {1,2,3}{
        \ifcase\g
        \or
            % Draw the probes
            \foreach \K/\I/\J in {A/3/5, B/3/4}{%
                % Install the Daten \K style.
                % For Daten Klasse A this sets the probe color to blue
                % For Daten Klasse B this sets the probe color to red
                % and shifts everything along.
                % In both cases the relevant style (A or B) is `executed'
                % defining which probes are testproben.
                \tikzset{Daten \K/.try}
                \foreach \i in {1, ..., \I}{%
                    \foreach \j in {1, ..., \J}{%
                        \node (probe \itr-\K-\i-\j) at (\j, -\itr*3.5-\i) 
                           [probe=\i-\j] {};
                    }
                }
                % Define a node that fits around all the nodes for this
                % particular Daten Klasse.
                \node [tight fit,fit=(probe \itr-\K-1-1) 
                (probe \itr-\K-\I-\J)] 
                    (iteration \itr\space daten \K){};
            }
        \or
            % Now draw the Surrogats (Surrogaten?)
            \foreach \I in {1,2,3}{
                \tikzset{shift=(probe \itr-B-1-4.east)}
                \node (surrogat \itr-\I) at (1.125,1-\I) [surrogat] {};
                \draw [ultra thick, ->] 
                    (surrogat \itr-\I.west) ++(-0.625,0) -- ++(0.5,0);
                \draw [ultra thick, ->] 
                    (surrogat \itr-\I.east) ++(0.125,0) -- ++(0.5,0);
            }
        \or
            % Finally the Forcasts
            %
            % Shift things along a but from the surrogats.
            \tikzset{shift={(surrogat \itr-1)}, shift=(0:0.5)}
            \foreach \K/\I/\J in {A/3/5, B/3/4}{
                % This is the same as for the Daten Klasse,
                % execept tis time the vorhesage proben are drawn.
                \tikzset{Vorhesage \K/.try}
                \foreach \i in {1, ..., \I}{
                    \foreach \j in {1, ..., \J}{
                        \node (vorhesage \itr-\K-\i-\j) at (\j, -\i+1) 
                        [vorhesage=\i-\j] {\vmark};
                    }
                },
                % Draw a node around each set of vorhesage nodes.
                \node [tight fit, 
                   fit=(vorhesage \itr-\K-1-1) (vorhesage \itr-\K-\I-\J)] 
                (iteration \itr\space vorhesage \K){};
            }               
        \fi%
    }
}

% Now add the labels and delimiters.

\foreach \itr in {1,2,3}{
    \node [tight fit, fit={(iteration \itr\space daten A)}, left 
    delimiter=\{, label={[xshift=-0.5cm]left:\itr. 
    Iteration}] {};
}
\foreach \K in {A, B}{

    \node [tight fit, fit={(iteration 1 daten \K)}, above 
    delimiter=\{,label={[yshift=0.5cm]90:Daten Klassen \K}] {};

    \node [tight fit, fit={(iteration 1 vorhesage \K)}, above 
        delimiter=\{,label={[yshift=0.5cm, align=center]90:{Vorhesage 
        \\Proben \K}}] {};
}

\node [fill=testproben, rounded corners=1ex, below=0.25cm, anchor=north west]  
(testprobe)
    at (probe 3-A-3-1.south east){Testprobe};

\draw [very thick, ->, rounded corners=1ex]
    (testprobe.west) -| (probe 3-A-3-1.south);

\node [below=0.25cm, anchor=north west]  
(trainingsprobe)
    at (probe 3-A-3-4.south east){Trainingsprobe};

\draw [very thick, ->, rounded corners=1ex]
    (trainingsprobe.west) -| (probe 3-A-3-4.south);

\node [below=1cm, anchor=north east]  
(surrogatsmodelle)
    at (surrogat 3-3.south west){$i=3\times k=3$ Surrogatsmodelle};

\draw [very thick, ->, rounded corners=1ex]
    (surrogatsmodelle.east) -| (surrogat 3-3.south);

\node [below=0.5cm, align=left, anchor=north west] (eingeordnet)
    at (vorhesage 3-A-3-1.south east){Testprobe aus Klasse \textcolor{Klasse 
    A}{A} wird \\als Klasse \textcolor{Klasse B}{B} eingeordnet};

\draw [very thick, ->, rounded corners=1ex]
    (eingeordnet.west) -| (vorhesage 3-A-3-1.south);

\end{tikzpicture}

\end{document}

enter image description here

  • Wow, thanks. There's a lot of new stuff for me to learn in here. BTW: plural of Surrogat is Surrogate, but Surrogatmodelle = surrogate models (approximations to a "final"/"the" model) is already plural. – cbeleites May 3 '13 at 15:43
2

To be honest I didn't understand your question. Nevertheless, I did the following, which I don't know if fits your needs.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{decorations.pathreplacing}

\tikzset{ball/.style={rectangle,fill=none}}
\tikzset{square/.style={rectangle,draw,fill=yellow}}

\newcommand{\punkt}[1]{\fill (0, 0) circle (1mm) node (#1) {};}
\newcommand{\tpunkt}[1]{{\fill (0, 0) circle (1mm) node (#1) {};}}

\begin{document}
\begin{tikzpicture}
\matrix (m) [row 1/.style={nodes=ball},row 2/.style={nodes=square}
]{%
    \punkt{n1} & \punkt{n2} \\
    \tpunkt{n3} & \tpunkt{n4} \\
};

\foreach \i in {1,2,3,4} \fill (n\i) circle (1mm);

\draw[decorate, decoration = brace] (n1.north west) -- node [above] {bar} (n2.north east);

\draw[decorate, decoration={brace,mirror}] (n3.south west) -- node [below] {foo} (n4.south east);
\end{tikzpicture}
\end{document}

enter image description here

  • Please see my updated question. I did use nested \foreach loops before trying to change to matrix, that works, but is far from elegant. – cbeleites May 1 '13 at 16:24

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.