5

I have a matrix of cell pictures, and want the first column to be right aligned and the second column to be left aligned. However I have trouble using the "nodes" key.

example

\documentclass{article}
\usepackage{tikz}
\usepackage[margin=0cm,nohead]{geometry}
\usepackage[active,tightpage]{preview}

\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usetikzlibrary{arrows}
\usetikzlibrary{matrix}

\PreviewEnvironment{tikzpicture}
\begin{document}

 \begin{tikzpicture}[very thick]
    \matrix[matrix of nodes, column sep=3ex, row sep=2ex, nodes={draw}]{
            \draw (0,0) rectangle (-2.5,1) rectangle ++ (2.5,1) rectangle ++ (-2.5,1) rectangle ++ (2.5,1);
            \draw (2,2) rectangle ++ (2.5, 1) rectangle ++ (-2.5, 1);

            \draw[thin, gray] (0,0) -- (2,2)  (0,2) -- (2,3) (0,4) -- (2,4);    
        &
            \draw (0,0) rectangle (2.5,1) rectangle ++ (-2.5,1) rectangle ++ (2.5,1) rectangle ++ (-2.5,1);
            \draw (-2,2) rectangle ++ (-2.5, 1) rectangle ++ (2.5, 1);

            \draw[thin, gray] (0,0) -- (-2,2)  (0,2) -- (-2,3) (0,4) -- (-2,4);

            \begin{scope}[-latex, shorten >=5pt, shorten <=8pt]
                \draw (-2, 2.4) -- (0, 0.5);
                \draw (-2, 2.6) -- (0, 1.5);

                \draw (-2, 3.4) -- (0, 2.5);
                \draw (-2, 3.6) -- (0, 3.5);
            \end{scope}

            \node at (-1.25,1.95) [red]{\Huge\bfseries{?}};
            \node at (-1.25,3.32) [red]{\Huge\bfseries{?}};
        \\
    };
 \end{tikzpicture}
 \end{document}

enter image description here

With this example I would expect to see bounding boxes arround the cells, however it only modifies the nodes inside the cells. I would like the frames to see the changes I make, once I actually add column 1={anchor=east}, column 2={anschor=west}. Note that for shortness this example only has one row, however the actual matrix has several rows.

As a further perk I would like to add a label in the top left and bottom center of the cell. therefor it would be great to get those positions from the cell, since the actual cellpicture might be smaller.

This can be seen in this example from the tikz manual, page 204:

\begin{tikzpicture}[every node/.style={draw}]
\matrix [draw=red]
{
\node[left] {Hallo}; \fill[blue] (0,0) circle (2pt); \\
\node {X}; \fill[blue] (0,0) circle (2pt); \\
\node[right] {g}; \fill[blue] (0,0) circle (2pt); \\
};
\end{tikzpicture}

the border of the nodes is clearly smaller then the width of the column.


Explanation With Sketch Sketch of desired result

To Clarify the desired result, I added the sketch above.

  1. I would like to seperate the images in the Matrix by lines. Preferably as is done with the green lines in the sketch below, however an outer frame is acceptable.
  2. I would like to align the pictures of the first column to the right and the pictures of the second column to the left. The (crude)x and (crude)smiley both have dimensions much smaller than the column, but are right/left aligned within the column respectivly (I thought column 1/.style={node={anchor=east} would do but I could not get it to work). Furthermore I would like to center the content vertically within the row. (I tried to indicate this with the blue linse)
  3. I would like to add labels (wine red), in the corner positions of the Matrix cells
4
  • I think there is a misunderstanding here. Can you include the end result you want to see via a matrix? Because you are using matrix of nodes but as you can see the TikZ example doesn't have it. It would be great if you can modify the question towards your final goal instead of the current problem. I feel that there is an XY problem here.
    – percusse
    Jun 14, 2013 at 7:01
  • @percusse: I am not sure, but i assume matrix of nodes to wrap every cell into a tikz node. Meaning \matrix[matrix of nodes]{1\\} is another way to write \matrix{\node{1}\\}. The main point of the example is that the nodes drawn all have different sizes, while I want my nodes to expand to the dimensions of the row/column they are in. I want my nodes to fill the cells so to speak, rather than only encompassing their contents. Did this clarify it for you?
    – ted
    Jun 14, 2013 at 9:17
  • 1
    The description of matrix of nodes in the pgfmanual includes the statement "If your cell starts with a \path command ... the \node{ start up code and the }; are suppressed." Thus no node is produced in your cells that start with a \draw command (which expands to \path). Jun 14, 2013 at 9:35
  • @AndrewSwann: Thanks for the pointer, I obviously missed that. Do you happen to know a workarround as well?
    – ted
    Jun 14, 2013 at 9:43

2 Answers 2

8
+50

I think the following captures many of the features you request. I discuss the issues after the code.

Sample output

\documentclass{article}
\usepackage{tikz}

\usetikzlibrary{calc,matrix}

\begin{document}

\begin{tikzpicture}[very thick]
  \matrix (m) [matrix of nodes, column sep=3ex, row sep=2ex,
  column 1/.style={anchor=east}, column 2/.style={anchor=west},
  nodes={draw}]{
  {\tikz{\draw (0,0) rectangle (-2.5,1) rectangle ++ (2.5,1)
  rectangle ++ (-2.5,1) rectangle ++ (2.5,1); 
  \draw (2,2) rectangle ++ (2.5, 1) rectangle ++ (-2.5, 1);
  \draw[thin, gray] (0,0) -- (2,2)  (0,2) -- (2,3) (0,4) -- (2,4);
  }}
  &
  {\tikz{\draw (0,0) rectangle (2.5,1) rectangle ++ (-2.5,1)
  rectangle ++ (2.5,1) rectangle ++ (-2.5,1); 
  \draw (-2,2) rectangle ++ (-2.5, 1) rectangle ++ (2.5, 1);
  \draw[thin, gray] (0,0) -- (-2,2)  (0,2) -- (-2,3) (0,4) -- (-2,4);
  \begin{scope}[-latex, shorten >=5pt, shorten <=8pt]
    \draw (-2, 2.4) -- (0, 0.5);
    \draw (-2, 2.6) -- (0, 1.5);
    \draw (-2, 3.4) -- (0, 2.5);
    \draw (-2, 3.6) -- (0, 3.5);
  \end{scope}
  \node at (-1.25,1.95) [red]{\Huge\bfseries{?}};
  \node at (-1.25,3.32) [red]{\Huge\bfseries{?}};}}
  \\
  x& y\\
  z& p \( \frac{\sum_{n=1}^{50} n^2}{\sin(\theta)} \)\\
  };
  % Labels
  \path (m.west) |- (m-2-1.north) node[pos=0.5,right,violet]
  {\textsf{Label 1}}; 1
  \path (m.east) |- (m-2-2.south) node[pos=0.5,left,violet]
  {\textsf{Label 2}};

  % Rules
  \path (m.north) -| ($(m-1-1.east)!0.5!(m-1-2.west)$) node[pos=0.5] (t) {};
  \path (m.south) -| ($(m-3-1.east)!0.5!(m-3-2.west)$) node[pos=0.5] (b) {};
  \draw[green] (t) -- (b);

  \foreach \i/\j in {1/2,2/3} {
  \path (m.west) |- ($(m-\i-1.south)!0.5!(m-\j-1.north)$) node[pos=0.5] (l) {};
  \path (m.east) |- ($(m-\i-1.south)!0.5!(m-\j-1.north)$) node[pos=0.5] (r) {};
  \draw[green] (l) -- (r); };
\end{tikzpicture}

\end{document}

Firstly, as noted in my comment the pgfmanual says about matrix of nodes that

If your cell starts with a \path command or any command that expands to \path, which includes \draw, \node, \fill and others, the \node{ startup code and the }; code are suppressed.

If you want a cell of this type to be a node, one work around is to put the material inside a \tikz command as follows:

{\tikz{....}}

Specifying column styles that include anchors allows for left/right alignment of columns. You can specify anchors for a specific cell via |[anchor=...]|, which would also allow you to vertically center material in a row.

Finally giving the matrix a label (m) allows one to refer to the node in the (i,j)th cell as (m-i-j), and to the matrix as one single node (m), and so you can pick out various positions in the diagram in later tikz constructs. Thus in the above code I have drawn the lines between cells via points consructed from such nodes. I also used this for placing the labels. Note that (m-i-j) is the node in the cell, not the whole cell, so you have to be careful which points you compute.

6
  • Nice! Unfortunately, I still don't understand the question especially why we are nesting tikz pictures.
    – percusse
    Jun 15, 2013 at 15:09
  • @percusse Thanks. I too have difficulty understanding what the questioner is really asking for. Putting individual pictures in an ordinary tabular, would be more natural. Jun 15, 2013 at 15:41
  • @percusse, @AndrewSwann : The question may come from my lack in understanding tex. I think I am getting along with tikz quite well, while I have issues with tex (I still have no idea about the inner workings, and I have to look up most comments in awnsers given). Since I know how to draw lines with tikz the way I want and how to add labels at point (x,y) and have no clue about how adding text labels to the upper left and the lower right corner of a tabular, this seemed unnatural for me.
    – ted
    Jun 16, 2013 at 13:31
  • (continued) Furthermore I think of this as one big picture which needs the alignment and separations and not of 2*numberOfRows pictures, thus it felt natural for me to put everything in one picture enviornment. TLDR: Maybe my unfamilarity with LaTeX is the reason for me to choose the wrong tools for the job
    – ted
    Jun 16, 2013 at 13:32
  • 1
    @ted Glad the code helped. Indeed a more detailed solution would look at all boxes in a given row and find the heighst/lowest in order to compute the rule. You may also wish to consider removing the inner sep from the first nodes containing \tikz, depending on what edge alignment you want. As for the general principals, if you dig into tikz workings you find that matrix is based on a primitive tex alignemnt construct called halign; the corresponding latex construct is essentially tabular. So replacing matrix by tabular is not so strange a thing to do. Jun 16, 2013 at 19:40
6

Your problem seems to be how to align several tikzpictures and place labels over them. One possibility would be to use remember picture and overlay options with a tabular environment to align graphics.

Please, look at next code:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}

\begin{tabular}{rl}
\begin{tikzpicture}[very thick,remember picture,baseline=(current bounding box.center)]
\node[draw,minimum height=3cm,minimum width=2cm] (a) {A};
\end{tikzpicture}
&
\begin{tikzpicture}[very thick,remember picture,baseline=(current bounding box.center)]
\node[draw,minimum height=2cm,minimum width=3cm] (b) {B};
\end{tikzpicture}
\\
\begin{tikzpicture}[very thick,remember picture,baseline=(current bounding box.center)]
\node[draw,minimum height=1cm,minimum width=1cm] (c) {C};
\end{tikzpicture}
&
\begin{tikzpicture}[very thick,remember picture,baseline=(current bounding box.center)]
\node[draw,minimum height=2cm,minimum width=2cm] (d) {D};
\end{tikzpicture}
\end{tabular}

\begin{tikzpicture}[remember picture,overlay]
\path (a.east) -- coordinate (aux-x) (b.west);
\path (a.south) -- coordinate (aux-y) (d.north);

\draw[green,very thick] (a.north-|aux-x)--(d.south-|aux-x);
\draw[green,very thick] (a.west|-aux-y)--(b.east|-aux-y);

\node[red, below=3mm of a.south west, anchor=north west] {Label 1};

\node[red, anchor=south east] at (b.east|-d.south) {Label 2};
\end{tikzpicture}
 \end{document}

As you can see, four diferent size pictures are aligned within a tabular. With baseline=(current bounding box.center) all pictures are horizontally aligned in every row and rl tabular options provide its vertical alignement inside the column. Once the array is drawn you can use any node as reference to draw borders, place labels or add anything else you want. Remember two compile twice to get everything in its place. The result is:

enter image description here

9
  • +1 for effort, but the drawing of those boxes was not the issue. I edited my question (see the very bottom) and added a picture of what I want. AndrewSwann's comment points out what might be the root cause of the problem (why all my efforts of setting cell/.style or similar did not show the desired effects).
    – ted
    Jun 14, 2013 at 9:45
  • @ted: Now I think you just want two align several tikzpictures into a tabular. You can do it \begin{tabular}{cc}\begin{tikzpicture}...\end{tikzpicture}&\begin{tikzpicture}...\end{tikzpicture}\\ \begin{tikzpicture}... \end{tabular}. Is it what you want?
    – Ignasi
    Jun 14, 2013 at 10:00
  • Well, the tabular is not quite the ool for the job, since there is the label part (see point 3) and I would like some control over drawing the borders if possible, but that is secondary. Otherwise a tabular might be able to do the job
    – ted
    Jun 14, 2013 at 10:32
  • @ted: you can use tabular and remember picture and overlay in tikzpictures and outside the tabular draw borders and labels with tikz commands.
    – Ignasi
    Jun 14, 2013 at 10:56
  • but the Issue with that is, how do I know the dimensions of the row/column? Remember pciture presumably yields only the dimensions of the picture which may be much smaller, see row 2 in the example.
    – ted
    Jun 14, 2013 at 11:06

You must log in to answer this question.

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