tags:

views:

140

answers:

1

I have just finished my first diagram in Tikz. It looks as I wanted it to, but am unhappy with how I have 'coded' it:

\begin{tikzpicture}
[node distance=14mm,
 item/.style={rounded corners,rectangle,
   thick,
   minimum width=20mm, minimum height=10mm}]

\node[item,draw=blue!50,fill=blue!20] (stack) {1394 Stack};
\node[item,left=of stack,draw=green!50,fill=green!20,yshift=-9mm] (app1) {Application};
\node[item,left=of stack,draw=green!50,fill=green!20,yshift=9mm] (app2) {Application};
\node[item,right=of stack,draw=orange!50,fill=orange!20] (ohci) {OHCI};
\node[item,right=of ohci,yshift=-15mm,draw=yellow!70,fill=yellow!35] (dev1) {Device};
\node[item,right=of ohci,yshift=0mm,draw=yellow!70,fill=yellow!35] (dev2) {Device};
\node[item,right=of ohci,yshift=15mm,draw=yellow!70,fill=yellow!35] (dev3) {Device};

\draw[thick] (app1) -- (stack)
             (app2) -- (stack)
             (stack) -- (ohci)
             (ohci) -- (dev1)
             (ohci) -- (dev2)
             (ohci) -- (dev3);

\node[xshift=7mm,yshift=1mm] (topUser) at (app1.east |- dev3.north) {};
\node[xshift=7mm,yshift=-1mm,label=above left:User space] (botUser) at (app1.east |- dev1.south) {};
\draw[dashed] (topUser) -- (botUser);

\node[xshift=7mm,yshift=1mm] (topKern) at (stack.east |- dev3.north) {};
\node[xshift=7mm,yshift=-1mm,label=above left:Kernel space,
label=above right:Hardware\phantom{p}] (botKern) at (stack.east |- dev1.south) {};
\draw[dashed] (topKern) -- (botKern);
\end{tikzpicture}

The things which I am uncomfortable with are:

How I have manually moved the "Application" and "Device" nodes using yshift to space them apart from one another; I am sure that there must be a more elegant way of producing a simple tree-like structure

The lines (topKern -- botKern and topUser -- botUser) going from the top of the picture to the bottom; these are manually aligned on the x-axis to be between two nodes using xshift=7mm.

My use of \phantom{p} to ensure the label "Hardware" has the same baseline as the other two labels.

+1  A: 

To build a tree structure, consult pgfmanual.pdf, Making Trees Grow.

For the lines, I would create nodes representing in the middle of two nodes, and then use the perpendicular coordinate system as you did. Also you can use current bounding box to identify the "border".

To align baselines correctly, specify text height and text depth. In your case, for instance in the style every label. But as you see, I did the labels as nodes below...

\begin{tikzpicture}[level distance=35mm,node distance=15mm,text height=1.5ex,text depth=0.25ex]

\begin{scope}[every node/.style={rounded corners,rectangle,thick,minimum width=20mm, minimum height=10mm}]
\begin{scope}[level 1/.style={sibling distance=19mm,nodes={fill=green!20,draw=green!50}}]
\node[draw=blue!50,fill=blue!20] (stack) {1394 Stack} [grow=left]
  child {node (app2) {Application}}
  child {node (app1) {Application}};
\end{scope}

\begin{scope}[level 1/.style={sibling distance=15mm,nodes={fill=yellow!70,draw=yellow!35}}]
\node[right= of stack,draw=orange!50,fill=orange!20] (ohci) {OHCI} [grow=right]
  child {node {Device}}
  child {node {Device}}
  child {node {Device}};
\end{scope}
\end{scope}

\node[below=0mm of app1] (userspace) {User space};
\node at (userspace -| stack) (kernel) {Kernel};
\node at (userspace -| ohci) (hardware) {Hardware}; 

\path (app1) -- (stack) node[coordinate,midway] (between1) {};
\draw (ohci) -- (stack) node[coordinate,midway] (between2) {};

\draw[dashed] (current bounding box.north -| between1) -- (current bounding box.south -| between1);
\draw[dashed] (current bounding box.north -| between2) -- (current bounding box.south -| between2);

\end{tikzpicture}
grddev
What is the difference between the \path and \draw commands (app1 -- stack) and (ohci) -- (stack); I can see that changing the \path to a \draw results in a 'double line'. Is it just to get the coordinates for use later?
Freddie Witherden
@Freddie: The `\path` command just constructs a path. The `\draw` command also constructs a path, but in addition draws the path. The `\path` command is just to get the coordinate, and the `\draw` command does two things at once. This is a hack. I really wanted to put everything in one tree, but it wasn't possible. It should be, but if I try to grow two nodes to the left and one to the right, the left nodes will be laid out as if there would be three nodes to the left.
grddev