Sunday 18 August 2013

Multipart nodes with multipart subparts — style issue

Multipart nodes with multipart subparts — style issue

I want to typeset multipart nodes that have multipart sub parts — similar
to the following diagram (from Miller and Ranum)

I have tried using TikZ horizontal split rectangles inside vertical split
rectangles with the following example LaTeX
\documentclass[12pt,a4paper]{article}
\usepackage[parfill]{parskip}
\usepackage{cmbright}
\renewcommand{\familydefault}{\sfdefault}
\usepackage{tikz}
\usetikzlibrary{arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{positioning}
\usetikzlibrary{trees}
\pgfkeys{/pgf/rectangle split parts=10}
\newlength{\MMtextNodeWidth}
\newcommand{\MMsetTextNodeWidth}[1]{%
\settowidth{\MMtextNodeWidth}{#1}%
}
\begin{document}
{% \normalsize
\large
\MMsetTextNodeWidth{99}
\begin{tikzpicture}
[myRectangleVSplit/.style={rectangle split
,rectangle split horizontal=false
,draw=black,thin,
% ,inner sep=0pt
,rectangle split ignore empty parts
} % requires library shapes.multipart
,myRectangleHSplit/.style={rectangle split
,rectangle split horizontal
,draw=black,thin
% ,inner sep=0.3333em
% ,outer sep=-0.3333em % did not appear to do anything
,rectangle split part align={center,base}
,rectangle split ignore empty parts
} % requires library shapes.multipart
,edge from parent/.style={draw,thick,red,-triangle 60}
% ,edge from parent fork down
,mySingleItem/.style={rectangle,draw=black,thin}
,level distance=6\MMtextNodeWidth
,level 1/.style={sibling distance=12\MMtextNodeWidth}
,level 2/.style={sibling distance=6\MMtextNodeWidth}
,level 3/.style={sibling distance=3\MMtextNodeWidth}
,level 4/.style={sibling distance=2\MMtextNodeWidth}
]
\node[myRectangleVSplit,label=above:A] (nodeA)
{rootnode\nodepart{two}\begin{tikzpicture}%
\node[myRectangleHSplit] (nodeA2)
{child1\nodepart{two}child2};
\end{tikzpicture}
}
child {node[myRectangleVSplit,label=left:B] (nodeB)
{node1\nodepart{two}
\begin{tikzpicture}
\node[myRectangleHSplit] (nodeB2)
{child1\nodepart{two}child2\nodepart{three}child3};
\end{tikzpicture}
}
child {node[mySingleItem,label=left:D] (nodeD) {node3}}
child {node[mySingleItem,label=left:E] (nodeE) {node4}}
child {node[mySingleItem,label=left:F] (nodeF) {node5}}
}
child {node[myRectangleVSplit,label=right:C] (nodeC)
{node2\nodepart{two}child1}
child {node[mySingleItem,label=right:G] (nodeG) {node6}}
};
\end{tikzpicture}
}% end size
\end{document}
The above LaTeX results in

As you can see, the spacing in nodes with multipart sub parts (nodes A and
B in my diagram) leaves a separation that is unwanted — I don't think you
can alter the inner sep for just one part (TikZ manual page 451) and even
if we got rid of that, the line thickness would be double in parts. Is
there a better strategy here ? It looks like an obvious problem but I
haven't seen something similar elsewhere.
Version 2
Instead of trying to use TikZ multi part shapes, here is a version using
tables. The table line width \arrayrulewidth is 0.4pt which is the same as
the TikZ thin line width. The nodes with the tables have inner sep set to
0pt so that the arrows meet the table boundary. Is this the right way to
do this sort of diagram and could the arrows to nodes D and F be improved
— could the start of those arrows be shifted to start nearer the
appropriate child1 and child3 in node B
Here is the code:

\documentclass[12pt,a4paper]{article}
\usepackage[parfill]{parskip}
\usepackage{bigstrut}
\usepackage{cmbright}
\renewcommand{\familydefault}{\sfdefault}
\usepackage{tikz}
\usetikzlibrary{arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{positioning}
\usetikzlibrary{trees}
\pgfkeys{/pgf/rectangle split parts=10}
\newlength{\MMtextNodeWidth}
\newcommand{\MMsetTextNodeWidth}[1]{%
\settowidth{\MMtextNodeWidth}{#1}%
}
\begin{document}
{% \normalsize
\large
\MMsetTextNodeWidth{99}
\begin{tikzpicture}
[myTabularNode/.style={rectangle,inner sep=0pt}
,mySingleItem/.style={rectangle,draw=black,thin}
,edge from parent/.style={draw,thick,red,-triangle 60}
% ,edge from parent fork down
,level distance=6\MMtextNodeWidth
,level 1/.style={sibling distance=12\MMtextNodeWidth}
,level 2/.style={sibling distance=6\MMtextNodeWidth}
,level 3/.style={sibling distance=3\MMtextNodeWidth}
,level 4/.style={sibling distance=2\MMtextNodeWidth}
]
\node[myTabularNode,label=above:A] (nodeA)
{\begin{tabular}{|c|c|}\hline
\multicolumn{2}{|c|}{rootnode\bigstrut} \\ \hline
\bigstrut child1 & child2 \\ \hline
\end{tabular}
}
child {node[myTabularNode,label=left:B] (nodeB)
{\begin{tabular}{|c|c|c|}\hline
\multicolumn{3}{|c|}{node1\bigstrut} \\ \hline
\bigstrut child1 & child2 & child3 \\ \hline
\end{tabular}
}
child {node[mySingleItem,label=left:D] (nodeD) {node3\bigstrut}}
child {node[mySingleItem,label=left:E] (nodeE) {node4\bigstrut}}
child {node[mySingleItem,label=left:F] (nodeF) {node5\bigstrut}}
}
child {node[myTabularNode,label=right:C] (nodeC)
{\begin{tabular}{|c|} \hline
node2\bigstrut \\ \hline
child1\bigstrut \\ \hline
\end{tabular}
}
child {node[mySingleItem,label=right:G] (nodeG) {node6\bigstrut}}
};
\end{tikzpicture}
}% end size
\end{document}

and here is the resulting output:

No comments:

Post a Comment