# Controlling Matrix like a shape in Tikz

Would it be possible to control a matrix in Tikz as accurately as possible as with regular shapes?

For example, inside a Tikzpicture, I could simply control a shape's size by writing

\filldraw[fill=white] (6, 2) rectangle (8, 1) node[]{};

where the numbers represent respectively the left, top, right and bottom side of the rectangle. This way I can control how "tall" or long the rectangle is.

I can't do the same with the matrix, as it only works using the syntax:

\node[] at (x, y)

However this is rather not precise as I'd like to be able to set the actual coordinates. What can I do? I have looked at the Tikz manual and on this site (and on the internet) but couldn't find anything.

Here is the example of what I have and what I want:

and here is the code:

\documentclass[10pt]{article}
\usepackage[a4paper, margin=1cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage{rotating}
\usepackage{amsmath}
\usepackage{pgfplots}
\usepackage{tikz}

\usetikzlibrary{arrows,backgrounds,snakes,shapes,shapes.multipart,positioning}
\pgfplotsset{compat=1.7}
\pagestyle{empty}

\begin{document}

\tikzstyle{typnode} = [midway, align=center, inner sep=0pt]
\tikzstyle{data} = [font=\scriptsize, inner sep=0pt, rotate=90, minimum size=0pt,text width=0.5cm]

\begin{tikzpicture}[x=6.4mm,y=5mm]
\centering
\draw[|->, -latex, draw] (0,0) -- (15,0);
\draw[-, dashed] (-0.5,0) -- (0,0);

\foreach \x [evaluate=\x as \xear using int(1600+\x*10)] in {0,1,...,15}{
\draw[-] (\x,0) node[below=7pt,anchor=east,xshift=0,rotate=45,font=\footnotesize] {$\xear$};
\draw[] (\x,-0.2) -- (\x,0.2);
\draw[] (\x+.5,0) -- (\x+.5,0.1);
}

\filldraw[fill=white] (6, 1.5) rectangle (13.1, 0.5) node[typnode]{...to here (1660-1731)};
\matrix[draw, fill=white] {\node[data]{1660}; & \node[text width=3cm,typnode]{from here...}; & \node[data]{1731};\\};

\end{tikzpicture}
\end{document}


Please note that I'm not concerned about the height of the node. The thing I really want to set are the left and right side so that the matrix fits the length denoted by the dates.

-
Can you post an MWE of what you have tried so far? It can give us a clearer picture of what you are trying to do. –  hpesoj626 Mar 30 '13 at 23:52
@hpesoj626 I usually provide it, however I don't really have an error or warning, the shape comes exactly as I want it, I just don't know how to transform it... I didn't think it was particularly necessary this time, but I'll try to come up with something for the sake of the question. :) –  Alenanno Mar 30 '13 at 23:53
I don't see the problem actually: you can insert a matrix by using math mode in a node. If you want to draw arrows and stuff like that, you can define an additional node with the fit package that overlays the old (matrix node). –  CommuSoft Mar 30 '13 at 23:57
@Alenanno It's perfectly fine to provide a MWE. Solvers can use it to make suggestions directly from the given code. It doesn't have to be always something which contains an error. That is why it is called minimal working example (MWE) :) –  hpesoj626 Mar 31 '13 at 0:01
@hpesoj626 I was aware of the meaning of MWE but thanks anyway. :D Added along with an example of what I want (the code typesets that). –  Alenanno Mar 31 '13 at 0:04

Here is a matrix-less approach.

And a macro …

## Code

\documentclass[tikz,convert=true]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning}
\tikzset{
typnode/.style={midway, align=center, inner sep=0pt},
data/.style={font=\scriptsize, inner sep=1pt, rotate=90, minimum size=0pt},
datastart/.style={below right, data, xshift=5},
dataend/.style={above right, data, xshift=5},
level/.style={
yshift = #1*.8cm
},
level/.initial=0,
}

\newcommand*{\fakematrix}[4][]{
\begin{scope}[#1]
\node[datastart] (d1-start) at ({(#2-1600)/10},0) {#2};
\node[dataend]   (d1-end)   at ({(#3-1600)/10},0) {#3};
\draw (d1-start.north east) rectangle (d1-end.south west) node [typnode] {#4};
\end{scope}
}
\begin{document}
\begin{tikzpicture}[x=6.4mm,y=5mm]
\draw[|->, -latex, draw] (0,0) -- (15,0);
\draw[-, dashed] (-0.5,0) -- (0,0);

\foreach \x [evaluate=\x as \xear using int(1600+\x*10)] in {0,1,...,15}{
\draw (\x,0) node[below=7pt,anchor=east,xshift=0,rotate=45,font=\footnotesize] {$\xear$};
\draw (\x,-0.2) -- (\x,0.2);
\draw (\x+.5,0) -- (\x+.5,0.1);
}

\fakematrix{1660}{1731}{Daniel Defoe}% produces the same like above
\fakematrix{1600}{1655}{Edward Doty}
\fakematrix[typnode/.append style={font=\tiny}]{1735}{1750}{Eh?}
\fakematrix[level=1]{1601}{1700}{The 17th century.}
\end{tikzpicture}
\end{document}


## Output

-
Thanks, I can't follow up at the moment but I'll give you feedback as soon as possible. :) –  Alenanno Mar 31 '13 at 1:08
Sorry for the late feedback... I was wondering, is it possible to set one more parameter which is the Y position? I mean, say if I want to set one more on top of each other (speaking 2D here)... –  Alenanno Apr 1 '13 at 16:29
Ah one more thing: I've tried customizing that datastart/.style={below right, data, xshift=5} to include a font=\scriptsize but the dates stay as big as the text. Sorry for the hassle. I think however that apart from these two things I've asked in the comments, yours is the best solution for me. :) –  Alenanno Apr 1 '13 at 16:37
@Alenanno If you find Qrrbrbirlbel's answer the best solution, you can accept it by clicking on the tick mark. –  hpesoj626 Apr 2 '13 at 9:56
@hpesoj626 Your solution and Qrrbrbirlbel's solutions are quite similar but they both work with a fixed Y position. I wanted to make that a variable as I have different lives to represent. But as I mentioned, I don't know how to add that, any attempt I make leads to errors. –  Alenanno Apr 2 '13 at 10:03

Here are two alternative solutions. The first one is through the use of matrix, as you have been attempting.

## Solution using matrix

You can try to use shift's to make it look more accurate. Here is the code.

\documentclass[10pt,border=5]{standalone}
%\usepackage[a4paper, margin=1cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage{rotating}
\usepackage{amsmath}
\usepackage{pgfplots}
%\usepackage{tikz}

\usetikzlibrary{arrows,backgrounds,snakes,shapes,shapes.multipart,positioning}
\pgfplotsset{compat=1.7}
\pagestyle{empty}

\begin{document}

\tikzset{
typnode/.style={midway, align=center, inner sep=0pt},
data/.style={font=\scriptsize, inner sep=1pt, anchor=center, rotate=90, minimum size=0pt},
}
\begin{tikzpicture}[x=6.4mm,y=5mm]
\centering
\draw[|->, -latex, draw] (0,0) -- (15,0);
\draw[-, dashed] (-0.5,0) -- (0,0);

\foreach \x [evaluate=\x as \xear using int(1600+\x*10)] in {0,1,...,15}{
\draw[-] (\x,0) node[below=7pt,anchor=east,xshift=0,rotate=45,font=\footnotesize] {$\xear$};
\draw[] (\x,-0.2) -- (\x,0.2);
\draw[] (\x+.5,0) -- (\x+.5,0.1);
}

\matrix[draw, fill=white, anchor=west] at (6,1.5) {%
\node[data]{1660};
& \node[text width=110.9, typnode]{%
Explanations...and some more explanations};
& \node[data]{1731};\\
};

\end{tikzpicture}
\end{document}


## Solution using the fit library

\documentclass[10pt,border=5]{standalone}
%\usepackage[a4paper, margin=1cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage{rotating}
\usepackage{amsmath}
\usepackage{pgfplots}
%\usepackage{tikz}

\usetikzlibrary{fit,positioning}
\pgfplotsset{compat=1.7}
\pagestyle{empty}

\begin{document}
\tikzset{
typnode/.style={midway, align=center, inner sep=0pt},
data/.style={font=\scriptsize, inner sep=0pt, rotate=90, minimum size=0pt, align=center},
}
\begin{tikzpicture}[x=6.4mm,y=5mm]
\centering
\draw[|->, -latex, draw] (0,0) -- (15,0);
\draw[-, dashed] (-0.5,0) -- (0,0);

\foreach \x [evaluate=\x as \xear using int(1600+\x*10)] in {0,1,...,15}{
\draw[-] (\x,0) node[below=7pt,anchor=east,xshift=0,rotate=45,font=\footnotesize] {$\xear$};
\draw[] (\x,-0.2) -- (\x,0.2);
\draw[] (\x+.5,0) -- (\x+.5,0.1);
}

\node [data, yshift=-2.75, anchor=center] (start) at (6,1) {1660};
\node [data, yshift=3,anchor=center] (end) at (13.1,1) {1731};

\node [fit=(start)(end), draw, align = center, inner sep=0.5pt,label=center:Explanations] {};
%    \matrix[draw, fill=white, anchor=west] at (6,1.5) {\node[data]{1660}; & \node[text width=110.9, typnode]{Explanations...and some more explanations}; & \node[data]{1731};\\};

\end{tikzpicture}
\end{document}


## Update

I have created a macro called \yourmatrix that takes four arguments. The first argument is the start year, the second the end year, the third as the y position, and the fourth as the text/explanations.

Note that the matrix, looking at it now, is not optimal. The disadvantage is that it is hard to control the actual text width as the matrix has some padding. Introducing inner sep=0pt also gives unpredictable results. You can see the problem when with

\yourmatrix{1610}{1650}{Some more!}


Here is the code that you can play with.

\documentclass[10pt,border=5]{standalone}
%\usepackage[a4paper, margin=1cm]{geometry}
\usepackage[utf8]{inputenc}
%\usepackage{rotating}
%\usepackage{amsmath}
%\usepackage{pgfplots}
\usepackage{tikz}

\usetikzlibrary{arrows,backgrounds,decorations,shapes,shapes.multipart,positioning}
%\pgfplotsset{compat=1.7}
%\pagestyle{empty}

\begin{document}
\tikzset{
typnode/.style={midway, align=center},
data/.style={font=\scriptsize, anchor=center, rotate=90, minimum size=0pt},
}

\newcommand{\yourmatrix}[4]{
\pgfmathsetmacro{\lifespan}{(#2-#1)/0.64}
\matrix[ampersand replacement=\&, inner sep=0.5pt, column sep=1mm,fill=white, draw, matrix anchor=west, anchor=west] at ({(#1-1600)/10},{#3}) {%
\node[data]{#1};
\& \node[text width=\lifespan, typnode]{%
#4};
\& \node[data,below]{#2};\\
};
}

\begin{tikzpicture}[x=6.4mm,y=5mm]
\draw[|->, -latex, draw] (0,0) -- (15,0);
\draw[-, dashed] (-0.5,0) -- (0,0);

\foreach \x [evaluate=\x as \xear using int(1600+\x*10)] in {0,1,...,15}{
\draw[-] (\x,0) node[below=7pt,anchor=east,xshift=0,rotate=45,font=\footnotesize] {$\xear$};
\draw[] (\x,-0.2) -- (\x,0.2);
\draw[] (\x+.5,0) -- (\x+.5,0.1);
}

\yourmatrix{1660}{1731}{1.5}{Here is the explanation}
\yourmatrix{1610}{1650}{2}{Some more!}
\end{tikzpicture}
\end{document}


Let me just explain the arithmetic involved with

\pgfmathsetmacro{\lifespan}{(#2-#1)/0.64}


The divisor 0.64 came from the fact that you have set x=6.4mm and each unit is labeled with increments of 10. Since 1 cm = 10 mm, each unit is then to be multiplied by a factor of 100. The part (#2-#1) gets the difference between year start and year end, and so gets the life span (\lifespan) in terms of years.

I don't know if this method has some fix but at the moment it is eluding me.

-
I've just had an insane idea... Well, let's hope it's not insane. :D I was wondering, for the Matrix solution, what if you set the text width in the matrix (not the nodes inside) to be as much points as they are for the actual lifespan? For example, from 1660 to 1731 they are 71 years. Can I set Tikz to use a new length so that 1 point equals one year in my graph, so that if I write text width=71length it spans for "71 years"? If this would be easily implemented then I'd use your matrix-related solution. :) –  Alenanno Mar 31 '13 at 13:26
Perhaps one way is to use \pgfmathsetmacro{\lifelength}{71} \pgfmathsetmacro{\lifespan}{\lifelength/6.4*10} then use text width=\lifespan in the node option. –  hpesoj626 Apr 1 '13 at 4:53
Sorry if I'm pestering you but I've been trying all morning for this but... How do you fix that macro to be applicable per case? I've meant to use "#1"... The problem is that I don't know how to calculate the length of "one year" or even one unit length so that I can tell Latex "stretch this by X points" or whatever. –  Alenanno Apr 1 '13 at 11:24
@Alenanno It's okay. But I am afraid I can't provide a better solution. See my edit. –  hpesoj626 Apr 2 '13 at 9:35
BTW, snakes library is now deprecated by decorations library for version 2.10. :) –  hpesoj626 Apr 2 '13 at 9:41