# TikZ positioning: is it possible to use arithmetics?

I would like for the blue box (text3) to be below the other two boxes and to have the width of the other two boxes together. So basically I want to make the blue box (the large one in %Row2) wider without messing with the width measurements. Would that be possible?

Something like below=of node1 and node2 would do the trick but I haven't figured out a way to do it.

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning}
\begin{document}

\begin{tikzpicture}[auto,
SmallBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em, align=center, minimum height=3em},
LargeBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em,align=center, minimum height=3em}
]

\matrix[row sep=0.5em]
{
% row 1
\node {}; & \node (cell32) {}; & \node {}; & \node (cell34) {}; & \node {}; & \node {}; \\

% row 2
\node {}; &
\node {}; &
\node {\tikz{
\node [SmallBox={red}] (node1) {text1};
\node [SmallBox={green}, right=of node1] (node2) {text2};
\node [LargeBox={blue}, below=of node2] (node3) {text3};
}}; &
\node {}; &
\node {}; &
\node {}; \\
};

% horizontal line
\draw [thick] (cell32.east) -- (cell34.west);

\end{tikzpicture}
\end{document}

-
You can use fit to create a node which encloses the required nodes, and then the let..in syntax to get that node width. Also you can omit the fit node and measure instead the width of the desired nodes and add them inside the let..in construct. –  JLDiaz Mar 26 '13 at 17:06
You can also have a look to the macro \CalcDistance in Replicate this chart using LaTeX, even if in this case maybe the fit library is simpler. –  Claudio Fiandrino Mar 26 '13 at 17:25
How does the vertical line above all nodes fit in the picture here? Is it simply a horizontal line that should appear at the top of the whole picture or is it a content of the construct of nodes. For the first, the backgrounds library already provides the right tools. –  Qrrbrbirlbel Jul 19 '13 at 6:58

You can use fit library for width selection. I've added:

• fit,calc for \usetikzlibrary.
• fit={(node1) (node2)},yshift=-1em to "set" the width and move it a bit down.
• inner sep=0pt.

Code:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,fit}
\begin{document}

\begin{tikzpicture}[auto,
SmallBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em, align=center, minimum height=3em},
LargeBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em,align=center, minimum height=3em}
]

\matrix[row sep=0.5em]
{
% row 1
\node {}; & \node (cell32) {}; & \node {}; & \node (cell34) {}; & \node {}; & \node {}; \\

% row 2
\node {}; &
\node {}; &
\node {\tikz{
\node [SmallBox={red}] (node1) {text1};
\node [SmallBox={green}, right=of node1] (node2) {text2};
\node [LargeBox={blue}, below=of node2,fit={(node1) (node2)},inner sep=0pt,yshift=-1em] (node3) {text3};
}}; &
\node {}; &
\node {}; &
\node {}; \\
};

% horizontal line
\draw [thick] (cell32.east) -- (cell34.west);

\end{tikzpicture}
\end{document}


Result:

-
If you need calc library only for the shifts you can use ([yshift=-1em]...) without loading it. –  percusse Mar 26 '13 at 17:52
@percusse: Thanks, I've improved code. –  m0nhawk Mar 26 '13 at 17:56
I managed to adjust the text3 vertical height with text height=1.8em. –  Daniel Mar 26 '13 at 18:48
@Daniel (and m0nhawk) The fit library uses text width and more importantly text height and text depth to “fit” the content (this is also the reason why the inner seps still matter). The vertical space is evenly divided to the height and the depth. The baseline is thus vertically centered. I’d avoid this with either my solution or using a label=center:text3 which places a label with its anchor (default: center) at the center anchor of the node. (Obviously, the node will not stretch with the content then, but I guess that’s what you wanted anyway.) –  Qrrbrbirlbel Nov 21 '13 at 16:01

another solution that does not require use of a matrix or calculation, only fif bookstores and positionning

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,fit}
\begin{document}

\begin{tikzpicture}[auto,
SmallBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em, align=center, minimum height=3em},
LargeBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em,align=center, minimum height=3em}
]

\node [SmallBox={red}] (node1) {text1};
\node [SmallBox={green},below  right=of node1] (node2) {text2};

\node[fit=(node1) (node2),inner sep=0](node12) {};

\coordinate[below=3em of node12.south west]  (left);
\coordinate[below=3em of node12.south east]  (right);

\node [LargeBox={blue},fit=(left) (right), inner sep =0 ] (node3) {text3};

\end{tikzpicture}
\end{document}


the line

\node[fit=(node1) (node2),inner sep=0](node12) {};


determine the minimum size of the node that supports the other node with fit and inner sep=0

the last node is constructed after positioning two points in the right and left ends, again using

\coordinate[below=3em of node12.south west]  (left);
\coordinate[below=3em of node12.south east]  (right);

\node [LargeBox={blue},fit=(left) (right), inner sep =0 ] (node3) {text3};

-

The original fit key is not really suited for nodes that shall contain text and be placed differently (or should only inherit the height or the width). This can be seen in both currently existing answers where text3 is slightly shifted upwards because fit internally sets the keys text width, text height and text depth. This is also the reasons the inner sep need to set to zero. Actually the outer seps also need to be considered. More on this has been observed in TikZ: Make node height span several others.

The internals of the fit library though are great to scan any number of nodes/coordinates. The code of my answer to the linked question extend the positioning library and combines it with the fit library. It has been combined in my positioning-plus library.

It makes it possible to simply write

\node [SmallBox=red]                       (n1) {Text 1};
\node [SmallBox=green, right=of n1]        (n2) {Text 2};
\node [LargeBox=blue,  below=of -(n1)(n2)] (n3) {Text 3};


The - in the value to the below key marks the following node(s) to be used as a reference in the width of the created node (but with the inner xseps active). This is something similar to your idea of using below=of n1 and n2. The height of the third node could also be smaller than that of the other nodes.

The random horizontal line is also drawn in relation with the upper nodes. The starred version of xshift and yshift use the already established node distances as a factor. The same applies for the usual positioning keys that are prepended by one or two factors (separated by and) delimited by a colon :. The factors used here are .25 for the x direction and 1 for the y direction.

## Code

\documentclass[tikz,convert]{standalone}
\usetikzlibrary{positioning-plus}
\begin{document}
\begin{tikzpicture}[auto,
SmallBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em, align=center, minimum height=3em},
LargeBox/.style={rectangle, draw=black, fill=#1!20, minimum width=8em, align=center, minimum height=3em},
node distance=+.5em and +1cm
]

\node [SmallBox=red]                       (n1) {Text 1};
\node [SmallBox=green, right=of n1]        (n2) {Text 2};
\node [LargeBox=blue,  below=of -(n1)(n2)] (n3) {Text 3};

\coordinate[above left=1 and .25:of n1]  (pLine1);
\coordinate[above right=1 and .25:of n2] (pLine2);
\draw[red,thick] (pLine1) -- (pLine2);

\draw ([xshift*=-.25,yshift*]n1.north west) -- ([xshift*=.25,yshift*]n2.north east);
\end{tikzpicture}
\end{document}


-