4

This question already has an answer here:

I want to create a database shape in tikz that looks something like this:

enter image description here

I need the two arcs in the middle, so I cannot directly use cylinder, as suggested in this question.

Ideally, I would like to start from the cylinder shape and just add a few arcs, but I cannot figure out how to do this? Is the code of the cylinder shape available somewhere? Or is there a better way to achieve this?

I have looked at this question that asks how to create a shape for a camera, but it is quite far from what I want.

marked as duplicate by gernot, Phelype Oleinik, user36296, Stefan Pinnow, Mensch Jul 24 '18 at 17:41

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • The cylinder shape is defined in this file starting from line 4021. – Max Jul 24 '18 at 10:04
5

I don't think you need to define a new shape for this, unless you also want to use the border anchor. If you do, please let me know.

For simple usage you could use the following:

\documentclass[tikz,margin=2mm]{standalone}

\makeatletter
\tikzset{
    database/.style={
        path picture={
            \draw (0, 1.5*\database@segmentheight) circle [x radius=\database@radius,y radius=\database@aspectratio*\database@radius];
            \draw (-\database@radius, 0.5*\database@segmentheight) arc [start angle=180,end angle=360,x radius=\database@radius, y radius=\database@aspectratio*\database@radius];
            \draw (-\database@radius,-0.5*\database@segmentheight) arc [start angle=180,end angle=360,x radius=\database@radius, y radius=\database@aspectratio*\database@radius];
            \draw (-\database@radius,1.5*\database@segmentheight) -- ++(0,-3*\database@segmentheight) arc [start angle=180,end angle=360,x radius=\database@radius, y radius=\database@aspectratio*\database@radius] -- ++(0,3*\database@segmentheight);
        },
        minimum width=2*\database@radius + \pgflinewidth,
        minimum height=3*\database@segmentheight + 2*\database@aspectratio*\database@radius + \pgflinewidth,
    },
    database segment height/.store in=\database@segmentheight,
    database radius/.store in=\database@radius,
    database aspect ratio/.store in=\database@aspectratio,
    database segment height=0.1cm,
    database radius=0.25cm,
    database aspect ratio=0.35,
}
\makeatother

\begin{document}
    \begin{tikzpicture}[line width=1pt]
        \node[database,label=below:some label] {};
        \node[database,label=below:some label,database radius=1cm,database segment height=0.5cm] at (3,0) {};
    \end{tikzpicture}
\end{document}

The \makeatletter and \makeatother are necessary to use macros with @ in them. It is not really needed here, but I prefer to use it to keep macros readable and to prevent you from overwriting them somewhere without using the pgf keys.

This examples results in:

enter image description here

  • If I try to add a label \node[below of=database] {some label};, the position of the label looks incorrect. Is this because of the missing border anchor? – Peter Jul 24 '18 at 12:39
  • 1
    @Peter when you use below of=database, you place the new node at a certain distance from the center of the referenced node. With the positioning library you can use below=of database, which differs slightly in notation but makes sure that the node distance is kept between the outer dimensions of the two nodes. To add a label, it is simpler to draw the database node as follows: \node[database,label=below:some label] {};. (Both of these things don't bother with the border anchor). – Max Jul 24 '18 at 12:43
4

You are right, a cylinder exists already in shapes.geometric and is is very easy to use it to draw a database shape.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes.geometric}
\tikzset{database/.style={cylinder,aspect=0.5,draw,rotate=90,path picture={
\draw (path picture bounding box.160) to[out=180,in=180] (path picture bounding
box.20);
\draw (path picture bounding box.200) to[out=180,in=180] (path picture bounding
box.340);
}}}
\begin{document}
\begin{tikzpicture}
\node[database] {};
\end{tikzpicture}
\end{document}

enter image description here

  • This is a good solution, even keeping the border anchor intact, but it doesn't scale so nicely (+1 nonetheless for simplicity). – Max Jul 24 '18 at 14:19
  • @MaxSnippe Thanks for the upvote (and of course I upvoted your answer long time ago...;-) I'm not sure, though, I understand your concerns about scaling. At least \node[database,scale=3] {}; works fine as far as I can see. – user121799 Jul 24 '18 at 16:27
  • I should have been more specific. I actually meant when setting a different minimum width, e.g. \node[database,minimum width=2cm]{};. Firstly, this overwrites the aspect key I believe, such that the to[out=180,in=180] have a different radius then the cylinder itself, and secondly it places the border anchors (.20,.160, etc.) at completely different places. – Max Jul 24 '18 at 17:05
  • 1
    @MaxSnippe Yes, you're right, one should not stretch this ;-) – user121799 Jul 24 '18 at 17:07
  • This solution is also really nice, but I ended up accepting the other answer, because I went with that one. – Peter Jul 25 '18 at 7:38

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