13

I have to draw a memory region map - and failed. What I found on the web does not correspond to my ideas and wishes (or was not drawn with TikZ).

I drew the concept as a hand-drawn sketch

Hand made sketch

Unfortunately, at my draw the addresses to the left and right of the drawn blocks (UpperXXX, LowerXXX and 0xABCD) are not aligned as they should be. The memory size should be at the bottom right or left of the blocks; some blocks contain continuous text.

What I have is

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains, scopes}

\begin{document}
\begin{tikzpicture}[
        node distance=0mm and 0mm,
        font=\sffamily
    ]
    \tikzset{
        N/.style={
            draw,
            fill=green!20,
            minimum width={width("Memory UVWXYZ")+6pt},
            text centered,
        }
    }
    \begin{scope}[start chain=M going below,
        nodes={on chain=M},
        text height=3ex,
        text depth=0.25ex,
    ]{
        \node[N, fill=blue!20!white] (M5) {M5};
        \node[N, fill=blue!30!white, text height=6ex] (M4) {M4};
        \node[N, fill=blue!40!white, text height=6ex] (M3) {M3};
        \node[N, fill=blue!50!white, align=center, text height=8ex] (M2) {M2, with long\\text describing\\something};
        \node[N, fill=blue!60!white] (M1) {M1};
        % adress for M1, **this moves the block unintentially**
        %\node[left=0.5em] at (M1.north west) {\footnotesize Upper4};
        %\node[left=0.5em] at (M1.south west) {\footnotesize Lower4};
        \node[N, fill=blue!70!white] (M0) {M0};
        % detailed view of M0
        \node (M01) [N, right=5em of M0] {Region 1};
        \node (M02) [N, above=of M01] {Region 2};
        \draw[densely dashed] (M0.north east) -- (M02.north west)
                            (M0.south east) -- (M01.south west);
        % adress for M0
        \node[left=0.5em] at (M0.north west) {\footnotesize Upper5};
        \node[left=0.5em] at (M0.south west) {\footnotesize Lower5};
        % adress for M01 (aka M0 Region 1)
        \node[left=-3.5em] at (M01.north east) {\footnotesize Upper1};
        \node[left=-3.5em] at (M01.south east) {\footnotesize Lower1};
    }
    \end{scope}
\end{tikzpicture}

\end{document}

which results into this:

TikZ image so far

Despite a lot of reading and trying, I can't get the addresses aligned - on the contrary, this causes everything to shift. Not to mention the specification of the memory size in the respective corners. Somehow, I haven't quite grasped the TikZ concept of positioning yet (even by use of anchor) :(

How to do it correctly, perhaps with parameterization of the upper and lower addresses, block size and text?

2 Answers 2

22

In honor of the attention to detail you put in making your examples, here is an implementation that also seeks to resemble the result you are looking for... Although at first it is difficult to understand the code because there are many ways to do the same thing with different coding, but then you will learn some good practices along the way... one of these is knowing what things each line does and for that in my case the VisualTikz manual made it much easier to undrstand for me, here you can see the code and result, something that helped me a lot.

Some important things that are useful are first to choose a unit of work for the x and y coordinates, in this case use em which is relative to the size of the text, then for the node styles you must keep in mind that you can manage their size whenever the text does not exceed the minimum dimensions that can be set, then there is the override of the inner separation dimension which is the distance from the shape box to the text, and as always it is important to use node names to be able to place other nodes using their relative points.

It is also good to work with help lines to know what is happening.

RESULT:

enter image description here

MWE:

\documentclass[border=0pt,tikz]{standalone}
\usetikzlibrary{arrows.meta,backgrounds,positioning,shapes.symbols}
\usepackage{emerald}
\usepackage[T1]{fontenc}
\definecolor{BGcolor1}{HTML}{D5D0CC}
\definecolor{BGcolor2}{HTML}{898987}
\begin{document}
    \begin{tikzpicture}[
        x=1em,
        y=1em,
        >={Stealth[inset=0pt,length=0.5em]},
        font=\ECFAugie\tiny,
        line width=0.1pt,
        fill opacity=0.2,
        text opacity=1,
        P/.style 2 args={
            draw,
            thick,
            rectangle,
            minimum height=#2em,
            minimum width=#1em,
            inner sep=0,
            outer sep=0,
            anchor=south west,
            font=\ECFAugie,
            align=center
        },
        background rectangle/.style={%By background library
            rectangle,
            shade,
            top color=BGcolor1,
            bottom color=BGcolor2,
            shading angle=85
        },show background rectangle% To show the rackground.
        ]
        
        %Start drawing the thing...
        % Help lines to plan where put all:
        \def\wcanvas{30}
        \def\hcanvas{25}
        \draw[gray!70!black,step=1em] (-0.5,-0.5) grid (\wcanvas,\hcanvas);
        \foreach \x in {0, ..., \wcanvas} {%
            \draw(\x,-0.9) node {\x};
        }
        \foreach \y in {0, ..., \hcanvas} {%
            \node at (-0.9,\y*1) {\y};
        }
        % The first arrow
        \draw[->,thick](1,7) node[anchor=0,rotate=90]{\small Address} -- +(0,8);
        %Nodes See https://tug.ctan.org/info/visualtikz/VisualTikZ.pdf#section.7
        %and https://tug.ctan.org/info/visualtikz/VisualTikZ.pdf#section.17
        \draw(5,1) node[P={8}{3},fill=green!50!orange](M0){M0}; %Absolute coodinate
        \draw(5,1+3) node[P={8}{3},fill=purple](M1){M1}; %Coordinte using arithmetic operators
        \node[P={8}{5},fill=red!50!black,above=0 of M1](M2){M2, with long \\ text describing \\ something}; % using positioning.
        \node[P={8}{3},fill=blue!50!cyan,above=0 of M2](M3){M3};
        \node[P={8}{3},fill=yellow,above=0 of M3](M4){M4};
        %Special nodes from https://tug.ctan.org/info/visualtikz/VisualTikZ.pdf#subsection.17.3
        \node[P={8}{2},tape,tape bend bottom= none,fill=black,above=-0.25 of M4](VOID-1){};
        \node[P={8}{3.5},tape,tape bend top= none,fill=orange!50!black,above=1+0.25 of VOID-1](TOP){TOP};
        % the second column...
        \node[P={8}{2},fill=green!50!yellow,right=5 of M0.south east, anchor=south west](R1){Region 1};%positioning erases first anchor defined by P style
        \node[P={8}{2},fill=green!50!black,above=0 of R1](R2){Region 2};
        \node[P={8}{3},fill=green!50!orange,above=0 of R2](R3){Also long text \\ Region 3};
        \node[P={8}{1.25},tape,tape bend bottom= none,fill=black,above=-0.25 of R3](VOID-2){};
        \node[P={8}{1.25},tape,tape bend top= none,fill=black,above=1+0.25 of VOID-2](VOID-3){};
        \node[P={8}{2},fill=red!50!white,above=0 of VOID-3](RX){Region X};
        \node[P={8}{1.25},tape,tape bend bottom= none,fill=black,above=-0.25 of RX](VOID-4){};
        %Then draw some text based in nodenames and anchors
        \def\one{\,\,\,1\,\,}%this is only to manage text separation for this font.
        \foreach \RegText/\PositoningReference/\NodeAnchor/\TextAlign in {
            0x000/M0.south west/south east/left,
            0x\one00/M0.north west/north east/left,% Change \one for 1 in normal font.
            0x\one0\one/M1.south west/south east/left,% Change \one for 1 in normal font.
            0x200/M1.north west/north east/left,
            0x20\one/M2.south west/south east/left,% Change \one for 1 in normal font.
            0x500/M2.north west/north east/left,
            0x50\one/M3.south west/south east/left,% Change \one for 1 in normal font.
            0x600/M3.north west/north east/left,
            0x60\one/M4.south west/south east/left,% Change \one for 1 in normal font.
            0x700/M4.north west/north east/left,
            0xTop/TOP.north west/north east/left,
            \one G/M0.south east/south east/left,% Change \one for 1 in normal font.
            2 G/M1.south east/south east/left,
            \one G/M2.south east/south east/left,% Change \one for 1 in normal font.
            \one G/M3.south east/south east/left,% Change \one for 1 in normal font.
            1 M/R1.south west/south west/right,
            1 M/R2.south west/south west/right,
            1 M IN/R3.south west/south west/right,
            \quad Low\one/R1.south east/south west/left,% Change \one for 1 in normal font.
            \quad Up\one/R1.north east/north west/left,% Change \one for 1 in normal font.
            \quad Low 2/R2.south east/south west/left,
            \quad Up 2/R2.north east/north west/left,
            \quad Low 3/R3.south east/south west/left,
            \quad Up 3/R3.north east/north west/left,
            \quad Low X/RX.south east/south west/left,
            \quad Up X/RX.north east/north west/left% This percent symbol is necessary to make this arrangement of code
        }{
            \draw(\PositoningReference) node[align=\TextAlign,anchor=\NodeAnchor,xscale=0.65, inner ysep=0.1em]{\scriptsize\RegText};
        }
        %Drawing the dash lines
        \foreach \RefStart/\RefEnd in {
            M0.south east/R1.south west,
            M0.south east/R3.north west,
            M2.7/RX.south west,% Nodename.angle: gives a point in the shape from the angle ray from node.center.
            M2.20/RX.north west%
        }{
            \draw[dashed, thick](\RefStart)--(\RefEnd);
        }
                
    \end{tikzpicture}
    
\end{document}
4
  • 1
    Nice +1 // Never have seen such a result before.
    – MS-SPO
    Commented Jun 10 at 10:23
  • Famuos, I went through line by line - thanks for the comments and also way to place the nodes. I'm learning a lot from this - just by doing it myself.
    – olStckEx
    Commented Jun 11 at 15:41
  • Truly excellent.
    – Sebastiano
    Commented Jun 12 at 21:04
  • I can't even comprehend how amazing this is! GREAT job!
    – Shane
    Commented Aug 29 at 21:45
8

Let's see if this can get you started with anchors etc.

Until you are confident with node anchors and positioning, I suggest you do the thing manually(*); look, for example, at this code (I commented on it; I hope it is quite easy to grasp).

\documentclass[border=10pt]{standalone}
\usepackage[T1]{fontenc}
\usepackage{tikz}
%% Styles (global) here
%% I am using the #1 "implicit argument" to add a bit of flexibility
\tikzset{memory box/.style={
        draw, fill=#1, minimum width={width("Memory UVWXYZ")+6pt},
        align=center, minimum height=4ex,
        outer sep=0pt, % this will make the borders overlap nicely
    },
    memory size/.style={
        anchor=south east, font=\tiny, inner sep=1pt
    },
    memory address/.style={
         font=\tiny\ttfamily, inner ysep=1pt, inner xsep=3pt,
         anchor=#1 east,
    },
}
\begin{document}
\begin{tikzpicture}[]
    %% I do not use chains here, doing things manually
    %% the "anchor" is the reference point of the new box
    %% "at" is where that reference point is put
    \node [memory box=blue!40] (M0) {M0};
    \node [memory box=blue!30, anchor=south] at (M0.north) (M1) {M1};
    \node [memory box=blue!20, anchor=south] at (M1.north) (M2) {M2, with long\\
        text here};
    %% Add the texts (just a couple, as example)
    %% add the size
    \node [memory size] at (M0.south east) {16};
    \node [memory size] at (M1.south east) {16};
    %% add the addresses. Probably you can use a macro to make this easier...
    \node [memory address=south] at (M0.south west) {0x000};
    \node [memory address=north] at (M0.north west) {0x100};
    \node [memory address=south] at (M1.south west) {0x101};
    \node [memory address=north] at (M1.north west) {0x200};
\end{tikzpicture}
\end{document}

enter image description here

To see how the boxes are positioned, add draw=red to the styles, and you'll see what's happening here:

enter image description here

(*) by the way, your hand-drawn sketch is really nice. Have you considered just using it?

1
  • 1
    Thank you also for the explanation and the tip with the draw! I used your style with the memory size and memory address in my project, but had to realise that one big loop for the attributes like in J Leon V.'s solution is better than 2..4 small loops for each one - or I just wasn't clever enough. The hand made sketch looks different every day, hence TikZ ;-)
    – olStckEx
    Commented Jun 11 at 15:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .