5

I am creating a block diagram which has two layers : the main one and the background one. What I am trying to do, is draw a rectangle as a background using relative coordinates.

My code is

\documentclass{standalone}
 \usepackage{tikz}
 \usetikzlibrary{backgrounds}
\begin{document}
\tikzstyle{block}=[fill=white,draw=red,minimum size=1.5cm, rounded corners,align=center]
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}
\begin{tikzpicture}
 \node[block] (2D) {$2$D\\Histogramm};
 \node[draw=none,left of=2D,node distance=3cm] (dummy) {};
 \node[block,above of=dummy,node distance=1cm] (E) {E\\signal};
 \node[block,below of=dummy,node distance=1cm] (DE) {$\Delta$E\\signal};
 \node[block,right of=2D,node distance=3cm] (region) {$p$ signal\\selection};
 \node[block,right of=region,node distance=3cm] (projection) {E detector\\projection};
 \node[block,right of=projection,node distance=3cm] (smoothing) {smoothing};
 \node[block,right of=smoothing,node distance=3cm] (rebinning) {rebinning};
 \begin{pgfonlayer}{background}
  \draw[fill=gray!30,rounded corners] (E.north west)+(-0.5,0.5)rectangle(rebinning.south east)+(1,2);
 \end{pgfonlayer}
\end{tikzpicture}
\end{document}

and my output is

enter image description here

Although (E.north west)+(-0.5,0.5) works I don't seem to understand why (rebinning.south east)+(0.5,-2) doesn't. Any idea on how to solve this?

  • I would use the fit library for this. – Claudio Fiandrino Sep 5 '14 at 7:30
  • @ClaudioFiandrino : I didn't know about this library! Thank's for that! Do you have any idea nonetheless why aren't the relative coordinates not working there? – Thanos Sep 5 '14 at 7:38
  • Instead of (E.north west)+(-0.5,0.5) you can use ([shift={(-0.5,0.5)}]E.north west). Note { and } when using shift. They are not necessary when using xshift or yshift. – Ignasi Sep 5 '14 at 7:42
  • @Thanos: Harish's answer is explaining the reason. Just a minor addition: the point is that rectangle operation takes into account the first coordinate it encounters after the key, so the trick to make your code working would be \draw[fill=gray!30,rounded corners] (E.north west)+(-0.5,0.5)rectangle($(rebinning.south east)+(1,-2)$);(with a -2, not plus). – Claudio Fiandrino Sep 5 '14 at 7:42
8

You can make use of the fit-library. You can pass the nodes you want to include to the fit-option and put the fitting-node on the background layer.

In your example it is sufficient to fit the three outermost nodes to get the fitting-node into the right position:

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{backgrounds, fit}

\begin{document}
 \tikzstyle{block}=[fill=white,draw=red,minimum size=1.5cm, rounded  corners,align=center]
 \begin{tikzpicture}
  \node[block] (2D) {$2$D\\Histogramm};
  \node[draw=none,left of=2D,node distance=3cm] (dummy) {};
  \node[block,above of=dummy,node distance=1cm] (E) {E\\signal};
  \node[block,below of=dummy,node distance=1cm] (DE) {$\Delta$E\\signal};
  \node[block,right of=2D,node distance=3cm] (region) {$p$ signal\\selection};
  \node[block,right of=region,node distance=3cm] (projection) {E detector\\projection};
  \node[block,right of=projection,node distance=3cm] (smoothing) {smoothing};
  \node[block,right of=smoothing,node distance=3cm] (rebinning) {rebinning};
  \begin{scope}[on background layer]
   \node [fit=(E) (DE) (rebinning), fill= gray!30, rounded corners, inner sep=.5cm] {};
  \end{scope}
 \end{tikzpicture}
\end{document}

rendered image

This way you also can easily add a label-text to your background node using:

\node [fit=..., label={<position>:Your label text here}] {};

Where <position> is the angle/position where your label gets positioned (e.g. above, below, -45, ...). For more information about this have a look at the pgfmanual.

EDIT: Approach using relative coordinates (see comments)

To get your above code working the way you wrote it, you can make use of the calc-library and calculate the points of the rectangle.

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{backgrounds, calc}

\begin{document}

\tikzstyle{block}=[fill=white,draw=red,minimum size=1.5cm, rounded corners,align=center]
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}
\begin{tikzpicture}
 \node[block] (2D) {$2$D\\Histogramm};
 \node[draw=none,left of=2D,node distance=3cm] (dummy) {};
 \node[block,above of=dummy,node distance=1cm] (E) {E\\signal};
 \node[block,below of=dummy,node distance=1cm] (DE) {$\Delta$E\\signal};
 \node[block,right of=2D,node distance=3cm] (region) {$p$ signal\\selection};
 \node[block,right of=region,node distance=3cm] (projection) {E detector\\projection};
 \node[block,right of=projection,node distance=3cm] (smoothing) {smoothing};
 \node[block,right of=smoothing,node distance=3cm] (rebinning) {rebinning};
 \begin{pgfonlayer}{background}
  \draw[fill=gray!30,rounded corners] ($(DE.south west) +(-0.5,-0.5)$) rectangle ($(rebinning.north east) +(1,1.5)$);
 \end{pgfonlayer}
\end{tikzpicture}
\end{document}

EDIT: To sum up the comments and the information from this answer:

  • Using fit
  • Using positioning
  • Using node-label on background-node

Code:

\documentclass[tikz, border=5mm]{standalone}
\usetikzlibrary{backgrounds, positioning, fit}

\begin{document}
 \begin{tikzpicture}
  \tikzset{
   block/.style={
    draw=red,
    fill=white,
    minimum size=1.5cm,
    rounded corners,
    align=center,
   },
  }
  \node[block] (2D) {$2$D\\Histogramm};
  \node[block, above left=-.5cm and 1cm of 2D] (E) {E\\signal};
  \node[block, below left=-.5cm and 1cm of 2D] (DE) {$\Delta$E\\signal};
  \node[block, right=of 2D] (region) {$p$ signal\\selection};
  \node[block, right=of region] (projection) {E detector\\projection};
  \node[block, right=of projection] (smoothing) {smoothing};
  \node[block, right=of smoothing] (rebinning) {rebinning};
  \begin{scope}[on background layer]
   \node [fit=(E) (DE) (rebinning), fill= gray!30, rounded corners, inner sep=.5cm, label={[red]below:Your label text here}] {};
  \end{scope}
 \end{tikzpicture}
\end{document}

Rendered image: rendered image

  • Wow!!! I didn't know about this library! This is really great!!! Awesome! Thank you very much!!! Do you have any idea nonetheless why aren't the relative coordinates not working there? – Thanos Sep 5 '14 at 7:37
  • +1: You may want to not use the deprecated \tikzstyle in favor of \tikzset (see Should \tikzset or \tikzstyle be used to define TikZ styles?). Then, you may add that you can control the padding via the usual inner sep (and similar) key applied to the background node. – Claudio Fiandrino Sep 5 '14 at 7:37
  • You could also suggest using positioning library and change rigth of=..., node distance=... with right=3cm of .... – Ignasi Sep 5 '14 at 7:38
6

This isn't related to the use of layers, but rather to the way you specify the rectangle coordinates.

Consider this simpler example:

\documentclass[border=5mm]{standalone}
 \usepackage{tikz}
 \usetikzlibrary{backgrounds}
\begin{document}
\begin{tikzpicture}
\node [draw] (A) {Node A};
\node [draw] (B) at (4,0) {Node B};

\draw (A.north west) + (-0.5,0.5) rectangle (B.south east) + (0.5,-0.5);
\end{tikzpicture}
\end{document}

The line \draw (A.north west) + (-0.5,0.5) rectangle (B.south east) + (0.5,-0.5); is interpreted as meaning the following:

  • Move to the north west corner of node A.
  • Move to the point that's 0.5 units above and 0.5 units to the left of the previous point, without drawing anything.
  • Draw a rectangle to the south east corner of node B.
  • Move to the point that's 0.5 units below and 0.5 units to the right of the previous point, without drawing anything.

To make this example work in the expected way, there are different things you can do:

  • Use the calc library (\usetikzlibrary{calc}) and specify the rectangle as

     \draw [red] ($(A.north west) + (-0.5,0.5)$) rectangle ($(B.south east) + (0.5,-0.5)$);
    

or

  • Use a shift in the coordinate specifications:

        \draw [red] ([shift={(-0.5,0.5)}]A.north west) rectangle ([shift={(0.5,-0.5)}]B.south east);
    
1

You should better use fit library. But with your approach, you should choose the correct co-ordinates - x coordinate of rebinning and y coordinate of DE and to this add (0.5,-0.5).

Code:

\documentclass{standalone}
 \usepackage{tikz}
 \usetikzlibrary{backgrounds,calc}
\begin{document}
\tikzstyle{block}=[fill=white,draw=red,minimum size=1.5cm, rounded corners,align=center]
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}
\begin{tikzpicture}
 \node[block] (2D) {$2$D\\Histogramm};
 \node[draw=none,left of=2D,node distance=3cm] (dummy) {};
 \node[block,above of=dummy,node distance=1cm] (E) {E\\signal};
 \node[block,below of=dummy,node distance=1cm] (DE) {$\Delta$E\\signal};
 \node[block,right of=2D,node distance=3cm] (region) {$p$ signal\\selection};
 \node[block,right of=region,node distance=3cm] (projection) {E detector\\projection};
 \node[block,right of=projection,node distance=3cm] (smoothing) {smoothing};
 \node[block,right of=smoothing,node distance=3cm] (rebinning) {rebinning};
 \begin{pgfonlayer}{background}
  \draw[fill=gray!30,rounded corners] ($(E.north west)+(-0.5,0.5)$)rectangle($(rebinning.south east|-DE.south) +(0.5,-0.5)$) ;
 \end{pgfonlayer}
\end{tikzpicture}
\end{document}

enter image description here

1

To answer your question directly: (E.north west)+(-0.5,0.5) works only accidentally. The + operator does not add the two coordinates, instead it defines the second coordinate relative to the first one.

This means tikz moves to E.north west, then moves -0.5 in X and 0.5 in Y and from there starts drawing. But it doesn't draw to (rebinning.south east)+(0.5,-2). Instead it draws to (rebinning.south east) and then moves again 0.5 in X and -2 in Y direction.

tldr; The executed command is (E.north west)+(-0.5,0.5)rectangle(rebinning.south east) and an additional coordinate at +(1,2)

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.