6

I want to represent a layered software architecture. There is already an interesting approach on this site. But I can't add small boxes to the bottom (to be exact: one more row, containing two boxes of equal size).


Layered architecture

\documentclass[border=2px]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows, chains, calc}

\tikzset{
    green/.style  = {draw, rectangle, minimum width=2cm, minimum height=1cm, text centered, text width=1.2cm, font=\footnotesize, draw=black, fill=green!30},
    blue/.style   = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=5.0cm, font=\footnotesize, draw=black, fill=blue!30},
    yellow/.style = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=5.0cm, font=\footnotesize, draw=black, fill=yellow!30},
}

\begin{document}
\begin{tikzpicture}[start chain=1 going right,
  start chain=2 going below, node distance=1mm]
  \node [name=r1c1, on chain=1, green] {VC++};
  \node [name=r1c2, on chain=1, green] {VB.NET};
  \node [name=r1c3, on chain=1, green] {C\#.NET};
  \node [name=r1c4, on chain=1, green] {Others};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in
  node [name=r2c1, on chain=2, blue, anchor=north west, yshift=-1mm,
  minimum width=\n1-\pgflinewidth]
  at (r1c1.south west) {COM-API Interface};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in
  node [name=r3c1, on chain=2, yellow, minimum width=\n1-\pgflinewidth] {Autodesk Inventor Application};

\end{tikzpicture}
\end{document}

This code is not my own. It is copied from the link above.

Bernard
  • 271,350
mike
  • 333

3 Answers3

7
\documentclass[border=2px]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows, chains, calc,positioning}

\tikzset{
    green/.style  = {draw, rectangle, minimum width=2cm, minimum height=1cm, text centered, text width=1.2cm, font=\footnotesize, draw=black, fill=green!30},
    blue/.style   = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=5.0cm, font=\footnotesize, draw=black, fill=blue!30},
    yellow/.style = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=5.0cm, font=\footnotesize, draw=black, fill=yellow!30},
    red/.style={minimum height=1cm, text centered, font=\footnotesize, draw=black, fill=red!30}
}

\begin{document}
\begin{tikzpicture}[start chain=1 going right,
  start chain=2 going below, node distance=1mm]
  \node [name=r1c1, on chain=1, green] {VC++};
  \node [name=r1c2, on chain=1, green] {VB.NET};
  \node [name=r1c3, on chain=1, green] {C\#.NET};
  \node [name=r1c4, on chain=1, green] {Others};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in
  node [name=r2c1, on chain=2, blue, anchor=north west, yshift=-1mm,
  minimum width=\n1-\pgflinewidth]
  at (r1c1.south west) {COM-API Interface};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in
  node [name=r3c1, on chain=2, yellow, minimum width=\n1-\pgflinewidth] {Autodesk Inventor Application};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$),
  \p2=($(r1c1.east)-(r1c2.west)$), \n1 ={veclen(\x1,\y1)},\n2={\x2} in
  node [name=r4c1, on chain=2, red,xshift=-0.25*(\n1+2*\pgflinewidth-0.5*\n2), 
  minimum width=0.5*(\n1-\pgflinewidth+\n2)] {Pffft};
  \draw let \p1=($(r1c4.east)-(r1c1.west)$),
  \p2=($(r1c1.east)-(r1c2.west)$), \n1 ={veclen(\x1,\y1)},\n2={\x2} in
  node[right=1mm of r4c1,
  name=r4c2, red,minimum width=0.5*(\n1-\pgflinewidth+\n2)] {Pfffft};
\end{tikzpicture}
\end{document}

enter image description here

  • 2
    +1 for the great ligatures in the last row ;) – Max Sep 10 '18 at 13:48
  • 2
    @Max This is marmot language. You need to pronounce it as "Pffft". ;-) –  Sep 10 '18 at 13:48
  • 1
    @marmot but... but... that's Billy the (lobotomized) cat! http://abcs-of-art.blogspot.com/2007/09/letter-p-i-chose-pfft-for-p-as.html ;-P – Rmano Sep 10 '18 at 13:58
  • @Rmano If you drop one f, the meaning changes completely. ;-) –  Sep 10 '18 at 14:00
  • @marmot Could you add some little explaining (or references)? – mike Sep 11 '18 at 08:12
  • And is it advisable to use absolute values in order to change the columns within the rows without affecting other rows? – mike Sep 11 '18 at 08:17
  • @mike I;ll be happy to add explanations if you give me a hint which aspect should be explained. And what do you mean by absolute values? What I did here is to se the calc library in order to in infer the dimensions from the upper rows and apply them to the lower rows. That way you only have to change one dimension in order to make a change, and do not have to adjust many things, which could be messy. –  Sep 11 '18 at 11:11
  • @marmot Okay, then I'll specify :) What are \p1, \p2, \n1, and \n2? I meant absolute coordinates -- your solution uses length relative to existing nodes. If I change some nodes (e.g. remove any from the first row), the following rows change. So I should either use absolute values oooor I should plan ahead better. – mike Sep 11 '18 at 11:32
  • 1
    @mike Not, this is the calc syntax. What it does is to set the first point, \p1, to the difference between (r1c4.east) and (r1c1.west). With this syntax, \x1 will be the x-value of that difference, and \y1 the y-value. \n1 and \n2 are then numbers derived from these coordinates. Specifically, \n1 is the length (veclen) of the difference, and \n2 is just the x-value of the second point \p2. I use the values to compute the shifts of the red boxes and their widths. So if you change the green boxes, the red boxes will automatically adjust themselves. –  Sep 11 '18 at 11:41
3
\documentclass[border=5pt,tikz]{standalone}
\usetikzlibrary{fit,positioning}
    \tikzstyle{s1} = [draw,minimum width=.9cm,minimum height=.7cm,fill=green!20]
    \tikzstyle{s2} = [draw,minimum width=6.15cm,minimum height=.7cm,fill=blue!20]
    \tikzstyle{s3} = [draw,minimum width=6.15cm,minimum height=.7cm,fill=yellow!20]
    \tikzstyle{s4} = [draw,minimum width=3cm,minimum height=.7cm,fill=red!20]
\begin{document}
    \begin{tikzpicture}
        \node[s1] (a) {VC++};
        \node[s1,right=.1 of a] (b) {VB.NET};
        \node[s1,right=.1 of b] (c) {C\#.NET};
        \node[s1,right=.1 of c] (d) {Others};
            \node[s2,xshift=.87cm,below=.1 of b] (e) {COM-API Interface};
            \node[s3,below=.1 of e] (f) {Autodesk Inventor Application};
        \node[s4,below=.1 of f.south west,anchor=west,yshift=-.3cm] (foo) {Foo};
        \node[s4,right=.1 of foo,anchor=west] (bar) {Bar};
        \node[draw,fit=(a)(bar)] {};
    \end{tikzpicture}
\end{document}

Here is the output:

Screenshot

current_user
  • 5,235
  • I've got this ugly bug again. Could please someone format my code and add at the top of the text my famous "Hello!"? Thank you! – current_user Sep 10 '18 at 13:42
  • 1
    @marmot: What would I do without a marmot nearby me … – current_user Sep 10 '18 at 13:43
  • I've have to compliment you, because the code looks really clean. But I wanted to add one more row below containing two boxes of equal size. Is that possible with your solution? I guess I have to define s4? – mike Sep 10 '18 at 13:47
  • @mike: Sorry, didn't read your question exactly, yeah, you're right. I'll fix that – give me a minute … – current_user Sep 10 '18 at 13:48
  • 1
    I guess the picture I've added was a little misleading in this context. Yes, thank you! – mike Sep 10 '18 at 13:50
  • @mike: Is it so good? – current_user Sep 10 '18 at 13:52
  • 1
    Looks good, but concerning the code you might want to use \tikzset instead of \tikzstyle (see https://tex.stackexchange.com/a/52379). – TeXnician Sep 11 '18 at 06:11
1

for fun and exercised, a variation of the nice marmot's answer. by changes in definitions of the styles the code

\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{calc, chains, positioning}

\tikzset{
box/.style args = {#1/#2}{rectangle,
        minimum width=#1, fill=#2!30, draw,
        text width =\pgfkeysvalueof{/pgf/minimum width}-2*\pgfkeysvalueof{/pgf/inner xsep},
        minimum height=1cm, align=center,
        font=\footnotesize},
box/.default = 21mm/green,
        }

\begin{document}
\begin{tikzpicture}[
node distance = 2mm and 2mm,
  start chain = going right,
                    ]
\begin{scope}[every node/.style={box, on chain}]
  \node (r1c1)  {VC++};
  \node (r1c2)  {VB.NET};
  \node (r1c3)  {C\#.NET};
  \node (r1c4)  {Others};
\end{scope}
\draw   let \p1 = ($(r1c4.east)-(r1c1.west)$),
            \n1 = {veclen(\x1,\y1)} in
    node (r2c1) [box=\n1/blue,
                 below=of $(r1c1.south)!0.5!(r1c4.south)$]
                 {COM-API Interface}
    node (r3c1) [box=\n1/yellow, below=of r2c1]
                {Autodesk Inventor Application};
\draw   let \p1 = ($(r1c2.east)-(r1c1.west)$),
            \n1 ={veclen(\x1,\y1)} in
    node (r4c1) [box=\n1/red, on chain,
                 below right=2mm and 0mm of r1c1.west |- r3c1.south] {aaaa}
    node (r4c1) [box=\n1/red, on chain] {bbbb};
\end{tikzpicture}
\end{document}

enter image description here

mike
  • 333
Zarko
  • 296,517