4

I've recently decided to make a formal study of LaTeX so I can upgrade my talents from "copy, paste & hack" TeX user to well, someone who knows how to use the tools. One of the things I'm trying to learn is the use of TikZ to draw figures and diagrams.

So, what I'm attempting to do is to draw three table structures connected by arrows such that one points to the next. I'll include a hand-drawn sketch of what I intend at the conclusion of this question.

After hours of frustration (and some shouting at the computer, admittedly), I came up with the following MWE that produces almost exactly what I want.

\documentclass{article}

\usepackage{tikz}
\usepackage{tabularx}
\usepackage{amsmath}
\usepackage{mathtools}

\usetikzlibrary{shapes}
\usetikzlibrary{arrows}
\usetikzlibrary{shadows}
\usetikzlibrary{positioning}

\begin{document}

    \tikzstyle{box} = [
        draw,
        fill=white!7,
        minimum width=5em, 
        text centered,
        minimum height=2em,
        drop shadow
    ]

    \begin{tikzpicture}
        \node (dir0) [box, minimum width=16em, minimum height=4em] {\vdots};

        \node (dir1)  [box, anchor=north, minimum width=16em] at
            (dir0.south) {\texttt{Kernel Memory Pages}};

        \node (dir2L) [box, anchor=north west, minimum width=8em] at 
            (dir1.south west) {\texttt{Permissions}};

        \node (dir2R) [box, anchor=north east, minimum width=8em] at
            (dir1.south east) {\texttt{Table Address}};

        \node (dir3)  [box, anchor=north, minimum width=16em] at
            (dir2R.south west) {\texttt{User Memory Pages}};

        \node (dir4L) [box, anchor=north west, minimum width=8em] at 
            (dir3.south west) {\texttt{Permissions}};

        \node (dir4R) [box, anchor=north east, minimum width=8em] at
            (dir3.south east) {\texttt{Table Address}};

        \node (dir5)  [box, anchor=north, minimum width=16em, minimum 
        height=4em] at (dir4R.south west) {\vdots};
    \end{tikzpicture}
\end{document}

This produces the following output, which is my first-ever drawing with TikZ:

TikZ Table 1

Now, while I'm perfectly happy with the graphical results, I come from the school that believes that elegance in appearance of code is a virtue, and so I've started to rewrite the above example in a different style (like an example documented here under "Diagrams" - the "definition/declaration/linking" style), as once I add the other tables, the above code is bound to get messy, and I'm fearful it might be unmaintainable if I need to adjust it later on.

So, I've produced the following, which I'm much more happy with. You can tell that I've added the other two types of tables as well.

\documentclass{article}

\usepackage{tikz}
\usepackage{tabularx}
\usepackage{amsmath}
\usepackage{mathtools}

\usetikzlibrary{shapes}
\usetikzlibrary{arrows}
\usetikzlibrary{shadows}
\usetikzlibrary{positioning}

\begin{document}
    \begin{tikzpicture} [
            % ----- Node definitions ----- %
            dirtablenode/.style = {
                rectangle, 
                rectangle split,
                rectangle split parts = 6,
                fill = white!5,
                minimum width  = 5em,
                minimum height = 2em,
                text centered,
                drop shadow
            },
            pagetablenode/.style = {
                rectangle,
                rectangle split,
                rectangle split parts = 3,
                fill = white!5,
                minimum width  = 5em,
                minimum height = 2em,
                text centered,
                drop shadow
            },
            memmapnode/.style = {
                rectangle,
                rectangle split,
                rectangle split parts = 4,
                fill = white!5,
                minimum width  = 5em,
                minimum height = 2em,
                text centered,
                drop shadow
            }
    ]

        % ----- Node constructions ----- %
        \node [dirtablenode] (directory) {
            \nodepart [minimum width = 16em, minimum height = 4em] {one}
                \vdots
            \nodepart [minimum width = 16em, minimum height = 2em] {two}   
                \texttt{Kernel Memory Pages}
            \nodepart [minimum width = 8em, minimum height = 2em]  {three} 
                \texttt{Permissions}
            \nodepart [minimum width = 8em, minimum height = 2em]  {four}
                \texttt{Table Address}
            \nodepart [minimum width = 16em, minimum height = 2em] {five}   
                \texttt{User Memory Pages}
            \nodepart [minimum width = 8em, minimum height = 2em]  {six} 
                \texttt{Permissions}
            \nodepart [minimum width = 8em, minimum height = 2em]  {seven}
                \texttt{Table Address}
            \nodepart [minimum width = 16em, minimum height = 4em] {eight}
                \vdots
        };

        \node [pagetablenode] (kpagetable) [right=of directory] {
            \nodepart [minimum width = 16em] {kbase}  \texttt{Base Address}
            \nodepart [minimum width = 16em] {klimit} \texttt{Address Limit}
            \nodepart [minimum width = 16em] {kperms} \texttt{Permissions}
        };

        \node [pagetablenode] (upagetable) [below=of kpagetable] {
            \nodepart [minimum width = 16em] {ubase}  \texttt{Base Address}
            \nodepart [minimum width = 16em] {ulimit} \texttt{Address Limit}
            \nodepart [minimum width = 16em] {uperms} \texttt{Permissions}
        };

        \node [memmapnode] (sysmemory) [below=of directory] {
            \nodepart [minimum width = 16em, minimum height = 4em] {one} \vdots
            \nodepart [minimum width = 16em, minimum height = 4em] {kernel} 
                \texttt{Kernel \\ Memory \\ (Protected)}
            \nodepart [minimum width = 16em, minimum height = 4em] {user} 
                \texttt{User \\ Memory \\ (Unprivileged)}
            \nodepart [minimum width = 16em, minimum height = 4em] {one} \vdots
        };

        % ----- Connection lines ----- %
        % ??
    \end{tikzpicture}
\end{document}

To put it all together and to better indicate what I'm trying to do (rather than sit here and assume people on TeX.SE read minds), here's a doodle of what I've envisioned the entire tikzpicture looking like:

Intended table layout

So, here come the parts of the question, which I've broken down. I've tried searching here for answers, but I can't find anything that addresses the issue, and looking through the TikZ manual is intimidating (to say the least) for a beginner.

  1. Does \nodepart support alignment in the same way that hand-created nodes are aligned? You'll notice that I declared the first (directory node to have 6 parts, although it actually has 8 nodeparts. Can I use the same anchor and at <reference> within \nodepart options to align these?

  2. Does the \node alignment (i.e. [right=of directory]) accept multiple alignment constraints, and if so, how would I align it such that the tops and bottoms of the respective pagetablenode instances are properly aligned with the directory?

  3. How would I align the bottom table (sysmemory) such that it lies centered between the two upper tables, with (ideally) hemispherical-ish lines connecting the right upper tables to it (as in the drawing)?

In short, what changes would I need to make to the second, more orderly MWE in order to fulfill the diagram as I have it envisioned? Keep in mind you may need to break this down for me a little bit - I'm green as grass to TikZ. I'm as interested in how the answer is right as I am in the actual answer.

  • The most answers on your question you can find in TikZ & PGF Manual for version 3.0.1a, page 726 -- 729. – Zarko Jul 22 '16 at 23:18
3

As Zarko suggested you should read rectangle split information (pages 726--728) and positioning library information.

From first you will learn that minimum width is valid for vertically splitted rectangles but minimum height is ignored. Then all these options in each nodepart can be suppressed. Rectangle split width will be fixed by maximum of inner part widths or minimum width. If you want to fix a certain minimum width you can do it in node options like is shown in kpagetable below.

When some minimum height is needed in some nodeparts we need other tools. A possible tool could be parbox (see [Yiannis' answer](https://tex.stackexchange.com/a/10273/1952 You also need to read about) to understand all parameters) but a 0 width rule \rule{0pt}{...} or phantom texts could also be used.

Reading information about positioning library you'll understand that

right= 3cm of directory.north east, anchor=north west

will force corresponding node to be placed 3cm right from upper right corner of directory node and aligned with its top line.

Similar constructions can be used to align other nodes with bottom corners.

Finally an aux node has been defined to place sysmemory node. Of course, there exist other constructions to obtain similar results.

Some more cleaning has been done on your code. First, as all blocks only differ in their parts, only one style with split parts being a parameter has been defined. If needed, minimum width option could be added to each particular node declaration.

Second, instead of \texttt{...} for each text part, option font has been used. It saves some typing.

Last comment, as it's not possible to horizontally divide a part, two part boxes and a manually drawn division have been used for lines containing permissions and table address.

\documentclass{article}

\usepackage{tikz}

\usetikzlibrary{shapes}
\usetikzlibrary{arrows}
\usetikzlibrary{shadows}
\usetikzlibrary{positioning}

\begin{document}
    \begin{tikzpicture} [
            % ----- Node definitions ----- %
            dirtablenode/.style = {
                    draw,
                rectangle, 
                rectangle split,
                rectangle split parts = #1,
                fill = white!5,
                align=center,
                drop shadow,
                font=\ttfamily
            },
    ]

        % ----- Node constructions ----- %
        \node [dirtablenode=6] (directory) {
            \nodepart{one}
                \parbox[t][15mm][c]{1cm}{\vdots}
            \nodepart[]{two}   
                Kernel Memory Pages
            \nodepart{three} 
                \parbox[t][][c]{3cm}{\centering Permissions}\parbox[t][][c]{3cm}{\centering Table Address}
            \nodepart{four}
                User Memory Pages
            \nodepart{five}   
                \parbox[t][][c]{3cm}{\centering Permissions}\parbox[t][][c]{3cm}{\centering Table Address}
            \nodepart{six} 
                \parbox[t][15mm][c]{1cm}{\vdots}
        };
          \draw (directory.two split)--(directory.three split);
          \draw (directory.four split)--(directory.five split);

        \node [dirtablenode=3, minimum width=5cm, right= 3cm of directory.north east, anchor=north west] (kpagetable) {
            \nodepart{one} Base Address
            \nodepart{two}  Address Limit
            \nodepart{three} Permissions
        };

        \node [dirtablenode=3, right=3cm of directory.south east, anchor=south west] (upagetable) {
            \nodepart{one}  Base Address
            \nodepart{two} Address Limit
            \nodepart{three} Permissions
        };

          \path (directory.south east) -- (upagetable.south west) coordinate[midway] (aux);

        \node [dirtablenode=4, below=of aux, anchor=north](sysmemory) {
            \nodepart{one} \vdots
            \nodepart{two} 
                Kernel \\ Memory \\ (Protected)
            \nodepart{three} 
                User \\ Memory \\ (Unprivileged)
            \nodepart{four} \vdots
        };

        % ----- Connection lines ----- %
       \draw[rounded corners,->] (directory.three east)--++(0:1cm)--([xshift=-1cm]kpagetable.north west)--(kpagetable.north west);
       \draw[rounded corners,->] (directory.five east)--++(0:1cm)--([xshift=-1cm]upagetable.north west)--(upagetable.north west);
       \draw[->] (kpagetable.two east) to[out=-10,in=5] (sysmemory.two east);
       \draw[->] (upagetable.two east) to[out=-10,in=5] (sysmemory.three east);
    \end{tikzpicture}
\end{document}

enter image description here

  • do you sure that all definition of minimal width and minimal height in \nodeparthave any influence on multipart node? I'm suprised that code works without to load library shadows.multipart ... – Zarko Jul 23 '16 at 10:48
  • @Zarko You're right, I've suppressed all of them. About library I supose that usetikzlibrary{shapes} already loads all inner shapes... libraries. – Ignasi Jul 23 '16 at 12:54
  • well, meanwhile I finished my answer, which is now almost the same as your after edit :-( (I will not publish it) ... anyway, in dirtablenode/.style = are two surplus options: rectangle and instead white !5 should be sufficed white. – Zarko Jul 23 '16 at 13:16
2

... I change the mind ... after while I compared my solution (hich is based on of Ignasi first solution) again to Ignasi solution, I estimated that differences are small but not negligible. So, here is my solution:

\documentclass{article}
\usepackage{tabularx}
\newcolumntype{C}{>{\centering\arraybackslash}X}

\usepackage{tikz}
\usetikzlibrary{arrows.meta,
                positioning,
                shadows,shapes}
\newcommand{\myvdots}{\vdots\rule[-2ex]{0ex}{5ex}}

\begin{document}
    \begin{tikzpicture} [% TikZ presets
                > = {Straight Barb[length=5pt]},
    node distance = 0mm and 24mm,
dirtablenode/.style args = {#1/#2}{%
        rectangle split,
        rectangle split parts = #1,
        draw,
        fill=white,
        inner sep=2mm,
        font=\ttfamily,
        text width=#2,
        align=center,
        drop shadow,
                },
                    ]
% ----- Node constructions ----- %
\node (directory)   [dirtablenode=6/16em]   
{
    \nodepart{one}      \myvdots
    \nodepart{two}      Kernel Memory Pages
    \nodepart{three}    \begin{tabularx}{\hsize}{C C} 
                Permissions &   Table Address
                        \end{tabularx}
    \nodepart{four}     User Memory Pages
    \nodepart{five}      \begin{tabularx}{\hsize}{C C} 
                Permissions &   Table Address
                        \end{tabularx}
    \nodepart{six}      \myvdots
};
\draw   (directory.two split)  -- (directory.three split)
        (directory.four split) -- (directory.five  split);
%
\node (kpagetable) [dirtablenode=3/12em, 
                    below right= of directory.north east]   
{
    \nodepart{one}      Base Address
    \nodepart{two}      Address Limit
    \nodepart{three}    Permissions
};
%
\node (upagetable) [dirtablenode=3/12em, 
                    above right=of directory.south east] 
{
    \nodepart{one}  Base Address
    \nodepart{two} Address Limit
    \nodepart{three} Permissions
};
\path (directory.south east)-- coordinate (mid) (upagetable.south west);
\node (sysmemory) [dirtablenode=4/12em, 
                   below=12mm of mid]
{
    \nodepart{one}      \myvdots
    \nodepart{two}      Kernel Memory  (Protected)
    \nodepart{three}    User   Memory  (Unprivileged)
    \nodepart{four}     \myvdots
};
% ----- Connection lines ----- %
\draw[rounded corners,->] 
(directory.three east) --++ (0:1cm) -- ([xshift=-1cm]kpagetable.north west) -- (kpagetable.north west);
\draw[rounded corners,->] 
(directory.five east) --++ (0:1cm) -- ([xshift=-1cm]upagetable.north west) -- (upagetable.north west);
\draw[->] (kpagetable.two east) to[out=-30,in=0,looseness=1.2] (sysmemory.two east);
\draw[->] (upagetable.two east) to[out=-30,in=0,looseness=1.5] (sysmemory.three east);
    \end{tikzpicture}
\end{document}

Main differences: for vertical dots I define new command, which to dots add more vertical space, multipart node has two arguments, one for number of parts, second for width of node (it is determined by \text width, so a longer text can be automatic broken into more lines), for arrows I use arrows.meta and made them bigger and with this better visible, loops are bigger and more close to be symmetric. I also remove all unnecessary option (mentioned in my comments) and package. Result is slightly different:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.