Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to convert all my LibreOffice diagrams to TikZ, to make my Latex document slightly prettier. I've come across a problem. There are a few symbols that I don't know how to do - and due to my general lack of knowledge about TikZ don't know how to create. I figured that this must be pretty easy work in TikZ, and since I couldn't find much proper documentation, I thought I'd ask for help here.

The symbols I want to create are the ones in this image

enter image description here

Obviously the arrows are easy, and the rounded edges rectangle is easy as well (because the line half way down is optional), but I'm not sure how I'd get the rectangle with the missing side and the rectangle with a dash in the corner?

share|improve this question
    
A general solution is surprisingly hard, actually. You would need to create a new node shape. My answer here: tex.stackexchange.com/questions/32867/… might help. –  Roelof Spijker Feb 17 '12 at 15:30

3 Answers 3

up vote 7 down vote accepted

I propose two changes to your code. The first one is using multipart nodes for DFstore and second using append after command options to draw corner lines on DFsource and some border lines in DFstore. This way your code is simpler. Be careful because DFstore and DFsource requires \draw node instead of a single \node command.

\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows}
\begin{document}
\tikzset{
DFsource/.style={
    rectangle, 
    text width=4em, 
    node distance=3cm, 
    text centered, 
    minimum height=5em,
    append after command={% We simply travel along node rectangle and small leftupper part
        ([xshift=0.3cm] \tikzlastnode.north west)-|([yshift=-0.3cm]\tikzlastnode.north west)%
        ([yshift=-0.3cm]\tikzlastnode.north west)|-(\tikzlastnode.south east)|-%
        ([xshift=0.3cm]\tikzlastnode.north west)--cycle%
        }
    },
    DFprocess/.style = {
        rectangle, 
        draw, 
        text width=6em, 
        node distance=3cm, 
        text centered, 
        rounded corners=10, 
        minimum height=8em
    },
    DFstore/.style = {
        rectangle, 
        rectangle split,
        rectangle split parts=2,
        rectangle split horizontal, 
        rectangle split draw splits,
        node distance=3cm, 
        minimum height = 2em,
        append after command={(\tikzlastnode.north east)-|(\tikzlastnode.west)|-(\tikzlastnode.south east)},
%       append after command={(\tikzlastnode.south)-|(\tikzlastnode.text split)|-(\tikzlastnode.north)}
        append after command={(\tikzlastnode.one split north)--(\tikzlastnode.one split south)}
    }
}


\tikzstyle{line} = [draw, -latex']

\begin{tikzpicture}[node distance = 2cm, auto]
% Place Nodes
\draw[red,ultra thick] node [DFsource] (user) {User};
\node [DFprocess, right of=user] (steg) {Perform Steganalysis};
\draw node [DFsource, right of=steg] (user2) {User};
\draw node [DFstore, below of=user] (store1) {1 \nodepart{two} Bitmap Image};
\draw node [DFstore, above of=user2] (store2) {2 \nodepart{two} Results};
% Connections
\path [line] (user) -- (steg);
\path [line] (steg) -- (user2);
\path [line] (store1) |- ([yshift=-0.5cm]steg.south) -- (steg);
\path [line] (steg) |- (store2);
\end{tikzpicture}
\end{document}

enter image description here

Addition by percusse

Now, the DFSource style redraws the whole node from scratch; by providing some options to the \draw commands one can further change the node line width and color. Another advantage is that the line joins are drawn properly.

share|improve this answer
    
Nice tackle :) One small detail is that the DFsource style might give incorrect results if the line width or color is changed so if needed one should draw all the node lines and then use cycle to finish off nicely for a complete set of compatible lines similar to the DFstore. –  percusse Feb 19 '12 at 13:25
    
@percusse You're right, I've tested my code with \node [DFsource, red, very thick] (user) {User}; and corner line is drawn black and thin. But I don't know how to apply same style to append after command lines. I don't understand you comment about cycle. Please, feel free to edit my answer or provide a new one. –  Ignasi Feb 19 '12 at 15:42
    
Ignasi, @Percusse many thanks, this is exactly what I wanted in the first place. These sorts of code snippets are just what I needed to help learn TikZ properly. Many thanks - it's really helpful. I'll mark this as answered - it'll be easier to use for larger DFDs than my somewhat ugly hack. –  Bakes Feb 20 '12 at 1:58
    
@Bakes Glad that I could help. Thanks to your question and Ignasi's nice answer, I realized the shape which was always on my to-do-list. In DFsource style, change the first occurence of -| to |- and you will see what I mean :P ( By the way, user2 node should start with \draw node instead of a single \node command.) –  percusse Feb 20 '12 at 2:13
    
@Bakes Glad also that I could help. Every day I'm learning new things about LaTeX and TikZ. I've made a last change to the code inserting one split north and one split south anchors. I didn't know them so I had to use a workaround to draw first split line. –  Ignasi Feb 20 '12 at 8:42

I have this code inside my library ( I think this code is from M. Wibrow). There are three variants of shapes in the next code: one side (up or down) and three sides. But it's easy to get other shapes like

 three side node/.style={box, box walls={north,south,east}, draw}

You can associate two nodes to get the exact shape or define your personal shape.

enter image description here

\documentclass{article}
\usepackage{tikz}
\begin{document}

\catcode`\@=11

\newif\ifpgf@lib@sh@box@northwall
\newif\ifpgf@lib@sh@box@southwall
\newif\ifpgf@lib@sh@box@eastwall
\newif\ifpgf@lib@sh@box@westwall

\tikzset{
 box walls/.code={\tikzset{box/.cd,#1}},
 box/.cd,
 north/.is if=pgf@lib@sh@box@northwall,
 south/.is if=pgf@lib@sh@box@southwall,
 east/.is if=pgf@lib@sh@box@eastwall,
 west/.is if=pgf@lib@sh@box@westwall,
}

\pgfdeclareshape{box}{
 \inheritsavedanchors[from=rectangle]
 \inheritanchorborder[from=rectangle]
 \inheritanchor[from=rectangle]{center}
 \inheritanchor[from=rectangle]{north}
 \inheritanchor[from=rectangle]{south}
 \inheritanchor[from=rectangle]{west}
 \inheritanchor[from=rectangle]{east}
 \inheritanchor[from=rectangle]{north west}
 \inheritanchor[from=rectangle]{south east}
 \inheritanchor[from=rectangle]{south west}
 \inheritanchor[from=rectangle]{north east}
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{base east}
    \inheritanchor[from=rectangle]{base west}
    \inheritanchor[from=rectangle]{mid}
    \inheritanchor[from=rectangle]{mid east}
    \inheritanchor[from=rectangle]{mid west}
 \backgroundpath{%
    \pgfextract@process\northwest{%
        \pgfpointadd{%
            \southwest%
            \pgf@xa=\pgf@x%
            \northeast%
            \pgf@x=\pgf@xa%
        }%
        {%
            \pgfpoint{\pgfkeysvalueof{/pgf/outer
xsep}}{-\pgfkeysvalueof{/pgf/outer ysep}}%
        }%
    }%
    \pgfextract@process\southeast{%
        \pgfpointadd{%
            \southwest%
            \pgf@ya=\pgf@y%
            \northeast%
            \pgf@y=\pgf@ya%
        }%
        {%
            \pgfpoint{-\pgfkeysvalueof{/pgf/outer
xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}%
        }%
    }%
    \pgfextract@process\southwest{%
        \pgfpointadd{\southwest}%
        {\pgfpoint{\pgfkeysvalueof{/pgf/outer
xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}%
    }%
    \pgfextract@process\northeast{%
        \pgfpointadd{\northeast}%
        {\pgfpoint{-\pgfkeysvalueof{/pgf/outer
xsep}}{-\pgfkeysvalueof{/pgf/outer ysep}}}%
    }%
    \c@pgf@counta=0\relax%  
    \ifpgf@lib@sh@box@northwall%
        \advance\c@pgf@counta by 1\relax%
    \fi%
    \ifpgf@lib@sh@box@eastwall%
        \advance\c@pgf@counta by 2\relax%
    \fi%
    \ifpgf@lib@sh@box@southwall%
        \advance\c@pgf@counta by 4\relax%
    \fi%
        \ifpgf@lib@sh@box@westwall%
        \advance\c@pgf@counta by 8\relax%
    \fi%
    \ifcase\c@pgf@counta%
    \or% 1
        \pgfpathmoveto{\northwest}\pgfpathlineto{\northeast}%
    \or% 2
        \pgfpathmoveto{\northeast}\pgfpathlineto{\southeast}%
    \or% 3
        \pgfpathmoveto{\northwest}\pgfpathlineto{\northeast}\pgfpathlineto{\southeast}%
    \or% 4
        \pgfpathmoveto{\southeast}\pgfpathlineto{\southwest}%
    \or% 5
        \pgfpathmoveto{\northwest}\pgfpathlineto{\northeast}%
        \pgfpathmoveto{\southeast}\pgfpathlineto{\southwest}%
    \or% 6
        \pgfpathmoveto{\northeast}\pgfpathlineto{\southeast}\pgfpathlineto{\southwest}%
    \or% 7
        \pgfpathmoveto{\northwest}\pgfpathlineto{\northeast}%
        \pgfpathlineto{\southeast}\pgfpathlineto{\southwest}%
    \or% 8
        \pgfpathmoveto{\southwest}\pgfpathlineto{\northwest}%
    \or% 9
        \pgfpathmoveto{\southwest}\pgfpathlineto{\northwest}\pgfpathlineto{\northeast}%
    \or% 10
        \pgfpathmoveto{\southwest}\pgfpathlineto{\northwest}%
        \pgfpathmoveto{\northeast}\pgfpathlineto{\southeast}%
    \or% 11
        \pgfpathmoveto{\southwest}\pgfpathlineto{\northwest}%
        \pgfpathlineto{\northeast}\pgfpathlineto{\southeast}%
    \or% 12
        \pgfpathmoveto{\southeast}\pgfpathlineto{\southwest}\pgfpathlineto{\northwest}%
    \or% 13
        \pgfpathmoveto{\southeast}\pgfpathlineto{\southwest}%
        \pgfpathlineto{\northwest}\pgfpathlineto{\northeast}%
    \or% 14
        \pgfpathmoveto{\northeast}\pgfpathlineto{\southeast}%
        \pgfpathlineto{\southwest}\pgfpathlineto{\northwest}%
    \else% 15
        \pgfpathmoveto{\northwest}\pgfpathlineto{\northeast}%
        \pgfpathlineto{\southeast}\pgfpathlineto{\southwest}%
        \pgfpathclose%
    \fi%
 }
}
\catcode`\@=12

\tikzset{
 underline node/.style={box, box walls=south, draw},
 overline node/.style={box, box walls=north, draw},
 three side node/.style={box, box walls={north,south,west}, draw}
}

\begin{tikzpicture}
\node at (0,0) [underline node, draw] {$F=1$};
\node at (2,0) [overline node] {$F=2$};
\node at (4,0) [three side node] {$F=3$};
\end{tikzpicture}

\end{document}
share|improve this answer
1  
That does look like the work of Wibrow. –  Matthew Leingang Feb 17 '12 at 19:05
    
Google with a correct search says Yes! It's from Mark !! –  Alain Matthes Feb 17 '12 at 19:17

Hm. So after looking at those potential solutions, and internally crying at the necessary mess, I wondered whether I could to it in a stylistically messy, but much more concise way. My solution was very simple. To make a 3 sided rectangle, draw a four sided rectangle then paint over one of the sides. To make a rectangle with a strike in the corner, draw a line between the two appropriate points. It still needs a bit of work, but I think that on the whole, it's good enough for me.

So, I ended up with this:

dfd

Using this code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows}
\begin{document}
\tikzstyle{DFsource} = [rectangle, draw, text width=4em, node distance=3cm, text centered, minimum height=5em]
\tikzstyle{DFprocess} = [rectangle, draw, text width=6em, node distance=3cm, text centered, rounded corners=10, minimum height=8em]
\tikzstyle{DFstore} = [rectangle, draw, text width = 10em, node distance=3cm, minimum height = 2em]
\tikzstyle{line} = [draw, -latex']

\begin{tikzpicture}[node distance = 2cm, auto]
% Place Nodes
\node [DFsource] (user) {User};
\draw ([xshift=0.3cm]user.north west) -- ([yshift=-0.3cm]user.north west);

\node [DFprocess, right of=user] (steg) {Perform Steganalysis};

\node [DFsource, right of=steg] (user2) {User};
\draw ([xshift=0.3cm]user2.north west) -- ([yshift=-0.3cm]user2.north west);

\node [DFstore, below of=user] (store1) {\hspace{0.1cm} 1 \hspace{0.4cm} Bitmap Image};
\draw ([xshift=0.75cm]store1.south west) -- ([xshift=0.75cm]store1.north west);
\draw [color=white, line width=3pt] (store1.south east) -- (store1.north east);

\node [DFstore, above of=user2] (store2) {\hspace{0.1cm} 2 \hspace{0.4cm} Results};
\draw ([xshift=0.75cm]store2.south west) -- ([xshift=0.75cm]store2.north west);
\draw [color=white, line width=3pt] (store2.south east) -- (store2.north east);

\path [line] (user) -- (steg);
\path [line] (steg) -- (user2);
\path [line] (store1) |- ([yshift=-0.5cm]steg.south) -- (steg);
\path [line] (steg) |- (store2);


\end{tikzpicture}
share|improve this answer
2  
Overstriking with white works with a white background. Not so much if you have a presentation with some colourful (perhaps shaded) background. In that sense, clipping might be more appropriate. –  Werner Feb 17 '12 at 23:38
    
@Werner Correct. However, I don't know what clipping is, or how you do it (unless you're talking about what the above posters are doing, in which case it seems like it's too much effort!). Thankfully, this document is to be printed on bog-standard photocopier paper, so I'm in the clear! –  Bakes Feb 18 '12 at 0:29
    
@Bakes: For some quick clipping examples, take a look a these on TeXample. In essence, you make can make a box, put it on top of a picture, and tell TikZ to ignore everything outside it. i.e. for this question, you could draw a standard rectangle, and use clipping to remove one side for the open ended nodes. –  qubyte Feb 18 '12 at 10:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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