3

I am trying to typeset a very simple diagram to illustrate DBMS interaction : two rectangles and a database shape after this definition :

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes}
\tikzstyle{database} = [cylinder,shape border rotate=90, aspect=0.25, draw ]
\begin{document}
\begin{tikzpicture}[every node/.append style={font=\scriptsize}]
\begin{scope}[every node/.append style={minimum height=1.5cm, minimum width=2cm, draw}, node distance=4cm]
\node[rectangle] (app) {Logiciel};
\node[rectangle] (sgbd) [right of=app] {SGBD};
\node[database] (data) [right of=sgbd] {Données};
\end{scope}
\draw[latex-latex] (sgbd.east) --  node[above] {Algorithmes} (data.west);
\draw[-latex] (app.15) -- node[above] {Requête} (sgbd.165);
\draw[latex-] (app.-15) -- node[below] {Réponse} (sgbd.195);
\end{tikzpicture}
\end{document}

However, the rotated cylinder does not line up with the rectangles : enter image description here

I tried adding an yshift to the definition of the style, but while this does move the shape border, it also moves the text inside and the place where the arrow points to, which I do not want.

How can I just move the drawing of the border without changing the way the node behaves in tikz's placement system ?

There is no border yshift or border shift key.

ysalmon
  • 1,160

2 Answers2

2

You could move the whole node down, and shift the text back up with \raisebox{6pt}{Données}.

In the code below I added the positioning library, and use right=of <nodename> instead of right of=<nodename>, as the latter syntax is considered deprecated. By default this would mean that the node distance is calculated between node borders instead of node centers, but I added on grid as well, which means node centers are used.

The full code for the last node I used is

\node[database, right=of sgbd.south, anchor=bottom] (data) {\raisebox{6pt}{Données}};

The use of .south and anchor=bottom ensures that the bottom of the nodes are aligned properly.

enter image description here

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning}
\tikzset{
  database/.style={cylinder,shape border rotate=90, aspect=0.25, draw}
}
\begin{document}
\begin{tikzpicture}[every node/.append style={font=\scriptsize}]
\begin{scope}[
  every node/.append style={
    minimum height=1.5cm,
    minimum width=2cm,
    draw},
    node distance=4cm,
    on grid
]

\node (app) {Logiciel};
\node[right=of app] (sgbd) {SGBD};
\node[database, right=of sgbd.south, anchor=bottom] (data) {\raisebox{6pt}{Données}};
\end{scope}
\draw[latex-latex] (sgbd.east) --  node[above] {Algorithmes} (sgbd.east -| data.west);
\draw[-latex] (app.15) -- node[above] {Requête} (sgbd.165);
\draw[latex-] (app.-15) -- node[below] {Réponse} (sgbd.195);
\end{tikzpicture}
\end{document}
Torbjørn T.
  • 206,688
  • Thanks a lot, and for explaning this right of= / right = of thing too ! I will leave the question open for some time in case somebody comes up with a more generic solution (changing the definition of styles). – ysalmon Feb 29 '20 at 14:32
1

I do think that Torbørn T.'s solution is the way to go. This is to provide an alternative in which everything is done by the database style. However, the downside is that this does not have the same anchors as the cylinder shape (which is sort of what you seem to be asking).

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{database/.style={path picture={
\draw let \p1=($(path picture bounding box.north east)-(path picture bounding
box.south west)$) in
([xshift=\pgflinewidth/2,yshift=-\pgflinewidth/2-#1*\x1]path picture bounding box.north west)
-- ([xshift=\pgflinewidth/2,yshift=\pgflinewidth/2+#1*\x1]path picture bounding box.south west)
arc[start angle=180,end angle=360,x radius=\x1/2-\pgflinewidth/2,y radius=\x1*#1] --
([xshift=-\pgflinewidth/2,yshift=-\pgflinewidth/2-#1*\x1]path picture bounding
box.north east)
arc[start angle=0,end angle=360,x radius=\x1/2-\pgflinewidth/2,y radius=\x1*#1];
},outer sep=0pt,draw=none},database/.default=0.1}
\begin{document}
\begin{tikzpicture}[every node/.append style={font=\scriptsize}]
\begin{scope}[every node/.append style={minimum height=1.5cm, minimum width=2cm, draw}, node distance=4cm]
\node[rectangle] (app) {Logiciel};
\node[rectangle] (sgbd) [right of=app] {SGBD};
\node[database] (data) [right of=sgbd] {Donn\'ees};
\end{scope}
\draw[latex-latex] (sgbd.east) --  node[above] {Algorithmes} (data.west);
\draw[-latex] (app.15) -- node[above] {Requ\^ete} (sgbd.165);
\draw[latex-] (app.-15) -- node[below] {R\'eponse} (sgbd.195);
\end{tikzpicture}
\end{document}

enter image description here

  • Wow ; you redrew the entire shape ! That's more ambitious than I was envisioning. This is also great because once defined it is easier to use if one has several instances of the shape. – ysalmon Feb 29 '20 at 19:57
  • @ysalmon Yes, as long as you limit yourself to this scenario, this can work. However, you lose the anchors of the cylinder, and if you are not careful the "contour" may run through the text. That is, this trickery can do the job as long as you use it with care. –  Feb 29 '20 at 20:14
  • 1
    Ok, so I will mark the other answer as accepted (as I have already integrated it into my code) but your is interesting to have in mind too for similar use cases. – ysalmon Feb 29 '20 at 20:17