8

I'm trying to create a buffer symbol to my task diagram (embedded programming), but I get an arrow on top of my symbol that should be a line like the one below the text in the box. Essentially I just want a rectangle where the vertical lines are invisible. My code is below:

\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[danish]{babel}
\usepackage{tikz}
\usetikzlibrary{automata,arrows}
\usetikzlibrary{shapes,snakes}
\tikzset{
    data/.style={
        draw,
        rectangle split,
        rectangle split parts=4,
        text centered,
    },
    data+/.style={
        data,
        rectangle split every empty part={},% resets empty-part macro (explanation below)
        rectangle split empty part width=\widthof{#1},
        rectangle split empty part height=\heightof{#1},
        rectangle split empty part depth=\depthof{#1},
    },
}
\makeatletter
\pgfdeclareshape{datastore}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north west}
  \backgroundpath{
    %  store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}
\makeatother
\begin{document}
\begin{tikzpicture}[
scale=0.8,
->,>=stealth',
shorten >=1pt,
auto,
node distance=3.5cm,
transform shape,
every node/.style={font=\sffamily\scriptsize},
buffer/.style={rectangle,draw,minimum width=1.5cm,minimum height=1.1cm,align=center},
interrupt/.style={diamond,draw,minimum width=1.5cm,minimum height=1.5cm,align=center},
datastore/.style={draw,shape=datastore,inner sep=.3cm}
]
\node[state,minimum width=1.5cm] (1) {Task};
\node[interrupt] (2) [right of=1 ]{Interrupt};
\node[buffer] (3) [right of=2] {Buffer};
\node[datastore] (4) [right of=3] {Buffer};
\end{tikzpicture}
\end{document}

And this is the output: enter image description here

As you can see, that last figure is not pretty :) any help is appreciated, thanks in advance!

  • What is the purpose of `->,>=stealth' ? – Tarass May 31 '14 at 11:34
  • To draw the arrow heads on the arrows, when drawing these. I use: \path[every node/.style={font=\sffamily\scriptsize}] (1) edge [right] node[left] { } (2) Notation – Nicolai Anton Lynnerup May 31 '14 at 11:39
  • If I delete "->,>=stealth' " and use this notation: \draw[->,>=stealth'] (1) -- (2) node[above] { }; it works – Nicolai Anton Lynnerup May 31 '14 at 11:44
  • It is JLDiaz's answer that should be accepted as it solves the question not only masks it. – Tarass May 31 '14 at 12:12
6

enter image description here

\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[danish]{babel}
\usepackage{tikz}
\usetikzlibrary{automata,arrows}
\usetikzlibrary{shapes,snakes}
\tikzset{
    data/.style={
        draw,
        rectangle split,
        rectangle split parts=4,
        text centered,
    },
    data+/.style={
        data,
        rectangle split every empty part={},% resets empty-part macro (explanation below)
        rectangle split empty part width=\widthof{#1},
        rectangle split empty part height=\heightof{#1},
        rectangle split empty part depth=\depthof{#1},
    },
}
\makeatletter
\pgfdeclareshape{datastore}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north west}
  \backgroundpath{
    %  store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}
\makeatother
\begin{document}
\begin{tikzpicture}[
scale=0.8,
->,>=stealth',
shorten >=1pt,
auto,
node distance=3.5cm,
transform shape,
every node/.style={font=\sffamily\scriptsize},-,% <- protect node from arrow setttings
buffer/.style={rectangle,draw,minimum width=1.5cm,minimum height=1.1cm,align=center},
interrupt/.style={diamond,draw,minimum width=1.5cm,minimum height=1.5cm,align=center},
datastore/.style={draw,shape=datastore,inner sep=.3cm}
]
\node[state,minimum width=1.5cm] (1) {Task};
\node[interrupt] (2) [right of=1 ]{Interrupt};
\node[buffer] (3) [right of=2] {Buffer};
\node[datastore] (4) [right of=3] {Buffer};
\end{tikzpicture}
\end{document}
6

The problem is that when you define the \backgroundpath of a new node shape, you only declare the path, but not how it has to be drawn (line width, line color, arrow tips, etc..) those are inherited from the scope.

Since your picture uses the option ->, this makes all the paths with one arrow tip at the end by default (unless this is overriden with option [-] for a particular path).

If you want to create a shape whose style does not depend on the environment options (for example, the border has to be always red, or always thick, etc..) you can draw it in \behindbackgroundpath, instead of \backgroundpath. Using this, your code can include not only \pgfmoveto{} etc.. but also \pgfusepath{stroke}, for example, and code for setting graphic options before stroking it.

For example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows}
\makeatletter
\pgfdeclareshape{datastore}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north west}
  \behindbackgroundpath{
    %  store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}

    % Draw it, always blue, arrowless and .8mm width
    \pgfsetlinewidth{.8mm}\pgfsetarrows{-}\pgfsetstrokecolor{blue}\pgfusepath{stroke}
 }
}
\makeatother

\begin{document}
\begin{tikzpicture}[->, >=stealth']
  \node[datastore, red]                        (1) {Buffer};
  \node[datastore, black, right=of 1]          (2) {Buffer};
  \node[datastore, black!40!green, right=of 2] (3) {Buffer};
  \draw (1) edge (2) (2) edge (3);
\end{tikzpicture}    
\end{document}

Note how color options passed to the node do not affect the background path (but they affect the text).

Result

4

As @Tarass suggested, the third line in the code should be omitted and I should use another notation for drawing arrows. This is the working code:

\begin{tikzpicture}[
scale=0.5,
%->,>=stealth',
shorten >=1pt,
auto,
node distance=3.5cm,
transform shape,
every node/.style={font=\sffamily\scriptsize},
buffer/.style={rectangle,draw,minimum width=1.5cm,minimum height=1.1cm,align=center},
interrupt/.style={diamond,draw,minimum width=1.5cm,minimum height=1.5cm,align=center,text width = 1.5cm, text centered},
datastore/.style={draw,shape=datastore,inner sep=.2cm,text width = 1.5cm, text centered}
]

\node[state,minimum width=1.5cm] (1) {Main Task};

% LCD
\node[buffer] (2) at(4,2) {LCD Buffer};
\node[state,minimum width=1.5cm] (3) at(7.5,2) {LCD task};

% UART
\node[datastore] (4) at(4,0) {Transmit Queue};
\node[datastore] (5) at(4,-1.5) {Receive Queue};
\node[state] (6) at(7.5,-0.75) {Uart task};

% Fan
\node[datastore] (7) at(4,-3.5) {Pump Queue};
\node[datastore] (8) at(4,-5) {Expected Liter Fuel};
\node[state] (9) at(7.5,-4.25) {Pump task};

% Fan
\node[datastore] (10) at(4,-7) {Liter Fuel};
\node[state] (11) at(7.5,-7) {Encoder task};
\node[interrupt] (12) at(11,-7) {Encoder interrupt};

\draw[->,>=stealth'] (1) -- (2) node[above] { };
\draw[->,>=stealth'] (1) -- (4) node[above] { };
\draw[->,>=stealth'] (1) -- (5) node[above] { };
\draw[->,>=stealth'] (1) -- (7) node[above] { };
\draw[->,>=stealth'] (1) -- (8) node[above] { };
\draw[->,>=stealth'] (1) -- (10) node[above] { };

\end{tikzpicture}

And here is the output: enter image description here

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.