3

I have created a diagram in TikZ. This is my first brush with TikZ and though I have almost completed it, I have some questions. Before asking questions, I will post my full tex file here, as a minimal version is not sufficient for explaining the question.

\documentclass{article}
\usepackage{pgfpages}
\pgfpagesuselayout{2 on 1}[a4paper,landscape, border shrink=5mm]

\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{arrows,shapes}
\usepackage[latin1]{inputenc}
\usepackage{verbatim}
\begin{document}
\tikzstyle{pre}=[<-,shorten <=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{post}=[->,shorten >=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{routed}=[to path={-- ++(0,8mm) |- (\tikztotarget)},shorten >=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{place}=[circle,thick,draw=blue!75,fill=blue!20,minimum size=6mm]
\tikzstyle{node_box}=[rectangle,thick,draw=blue!75, fill=blue!10,minimum width=25mm, minimum height=5mm]

\begin{tikzpicture}[node distance=3.7cm,>=stealth',bend angle=45,auto]

  \begin{scope}
    \node at (15,0) [node_box] (south_if) {south\_if};
    \node[node_box] (south_r) [above left of=south_if, node distance=80mm] {south\_r}
    edge [pre]  node[sloped,near start] {input} node[sloped,near end,swap] {output} (south_if);

    \node[node_box] (box_a) [above of=south_r] {box\_a}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (south_r);

    \node[node_box] (nout_join) [above of=box_a] {nout\_join}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (box_a);

    \node[node_box] (sout_join) [above right of=south_if, node distance=80mm] {sout\_join}
    edge [post]  node[sloped,near start] {output} node[sloped,below,near end,swap] {input} (south_if);

    \node[node_box] (box_b) [above of=sout_join] {box\_b}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (sout_join);

    \node[node_box] (north_r) [above of=box_b] {north\_r}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (box_b);

    \node[node_box] (north_if) [above left of=north_r, node distance=80mm] {north\_if}
    edge [post]  node[sloped,near start] {output} node[sloped,near end,swap] {input} (north_r)
    edge [pre]  node[sloped,sloped,near start] {input} node[sloped,sloped,near end,swap] {output} (nout_join);

    %% Can this be placed next to box_a automatically with out specifying node distance?                                                                                                                           
    \node[node_box] (box_c) [sloped,above of=south_if, node distance=95mm] {box\_c};
    \node[node_box] (t_rdr) [below of=box_c] {t\_rdr}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (box_c)
    edge [post]  node[sloped,very near start] {output\_n,n\_src} node[sloped,very near end, swap] {output, n\_src} (nout_join)
    edge [post]  node[sloped,very near start] {output\_s,s\_src} node[sloped,very near end, swap] {output, s\_src} (sout_join);

    \node[node_box] (t_output) [above of=box_c] {t\_output}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (box_c)
    edge [pre]  node[sloped,at start,anchor= south west] {n\_test\_in, test\_out} node[sloped,near end,swap] {test\_out, n\_test\_in} (north_r)
    edge [pre]  node[sloped,very near start,anchor= south east] {n\_test\_in, test\_out} node[sloped,very near end,anchor= north west] {test\_out, n\_test\_in} (south_r);

    \node[node_box] (south_rp) [below of=t_rdr, node distance=30mm] {south\_rp}
    edge [pre]  node[near start] {input} node[near end,swap] {out} (t_rdr);

    %% Can this node be better placed?                                                                                                                                                                             
    \node[node_box] (test_prov) [above right of=t_rdr, node distance=30mm] {test\_prov}
    edge [pre]  node[sloped,near start] {input} node[sloped,near end,swap] {prov\_out} (t_rdr)
    edge [post]  node[sloped,near start] {output} node[sloped,near end,swap] {test\_prov} (t_output);

    \node[node_box] (sink_prov) [right of=test_prov, node distance=60mm] {sink}
    edge [pre]  node[near start] {fromtest} node[near end,swap] {output1} (test_prov);

    \node[node_box] (sink_test_a) [left of=box_a, node distance=60mm] {sink}
    edge [pre]  node[near start] {test\_a} node[near end,swap] {output4} (box_a);

    \node[node_box] (sink_test_p) [right of=box_b, node distance=60mm] {sink}
    edge [pre]  node[near start] {test\_p} node[near end,swap] {output4} (box_b);
  \end{scope}

\end{tikzpicture}

\end{document}

The output image is:

enter image description here

Now to questions:

  1. node box_c is placed by specifying above of=south_if, node distance=95mm which approximates the horizontal position of box_a. Is there any way to remove the node distance and let the box_c snap to south_if and box_a automatically?

  2. Can I change the lines between south_r and t_output and t_rdr and nout_join to horizontal and vertical i.e. using -| or |-? I made some attempt at doing it, as it can be seen in \tikzstyle{routed}, but could not figure it out.

  3. I am not very happy with the positioning of test_prov node. This is not exactly a question, but suggestions are welcome :)

  4. Any improvements to the code? This is my first TikZ code, and I did it by mostly working from the example in manual. Ideally I would like to remove hard coded formatting and numbers from the main drawing into definitions at the top so that the code is more clean and maintainable.

  5. I would like to print this in an a4 sheet. Not quite figured out how to fit this graph in an a4 sheet.

Thanks for your time and help :)

Bernard
  • 271,350
Raj
  • 133

1 Answers1

3
  1. As mentioned by Ignasi, you can use

    \node (box_c) at (south_if |- box_a)  {box\_c};
    

    to place box_c at the x-coordinate of south_if and y-coordinate of box_a.

  2. You can draw a horizontal and vertical line between two nodes with \draw (a) -| (b);. (See also TikZ: What EXACTLY does the the |- notation for arrows do?)

  3. Don't have any better suggestions than what you see below.

  4. Again, Ignasi mentioned a couple of things:

    In the code below I've implemented both of these. So you'll find \tikzset{stylename/.style={<options>}} instead of \tikzstyle{stylename}=[<options>]. And I've changed from <position> of=<othernode> to <position>=of <othernode>

    There are some nodes that have manual adjustments, though mostly because of point 5.

    I've also restructured the code a bit, placing all the nodes first, and drawing the connections later. Perhaps the biggest benefit of this is that you can use a scope environment to set the same style for all the nodes. This makes the code shorter, so possibly easier to keep track of. It also allows one to collect the drawing all the lines with input/output labels in a \foreach loop.

    Whether you think such a restructuring is useful or not is up to you though, if you prefer to have the edges after the \nodes, then do that.

    Another thing to point out is that you tend to split node options over two pairs of brackets, e.g. \node[node_box] (south_r) [above left of=south_if, node distance=80mm] {south\_r}. While it obviously works, I would keep all the settings in one pair of brackets, i.e.

    \node[node_box,
         above left of=south_if,
         node distance=80mm]     (south_r) {south\_r}
    

    Some other things: the arrows library is considered as deprecated in favor of the new arrows.meta library (though it will still work for backward compatibility). See section 16.5 Reference: Arrow Tips in the manual for a list of the arrow tip names defined by arrows.meta. Also, it's not necessary to explicitly load the pgf package when you also load tikz, as tikz loads pgf.

  5. There are several places where one can save horizontal space in the diagram, so it's possible to make it fit within the margins of a standard article. For example, the sink nodes add a lot of width, so positioning those a lot closer to the main body helps.

    You can also reduce the minimum width of the node_box style a bit, at least for the node texts you have in this examples. In the code below it's reduced from 25mm to 20mm.

    You may also notice that I've added a line break in the labels on the line between north_r and t_output, the use of \\ is enabled by align=center in the labelnode style.

(The frame in the image below is generated by the showframe package, which draws a frame around the text area. Remove that for your real document.)

output of code

\documentclass[a4paper]{article}
\usepackage{showframe}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning}
\usepackage[latin1]{inputenc}
\tikzset{
  line/.style={>=Stealth,semithick, draw=blue!75},
  post/.style={line,->,shorten >=1pt},
  node_box/.style={rectangle,thick,draw=blue!75, fill=blue!10,minimum width=20mm, minimum height=5mm},
  labelnode/.style={auto,sloped,font=\footnotesize,align=center},
}

\begin{document}
\begin{center}
\begin{tikzpicture}[node distance=3cm and 1.7cm]
\begin{scope}[every node/.style={node_box}]
  \node                                       (south_if)    {south\_if};
  \node [above left=of south_if,xshift=5mm]   (south_r)     {south\_r};
  \node [above=of south_r]                    (box_a)       {box\_a};
  \node [above=of box_a]                      (nout_join)   {nout\_join};
  \node [above right=of south_if]             (sout_join)   {sout\_join};
  \node [above=of sout_join]                  (box_b)       {box\_b};
  \node [above=of box_b]                      (north_r)     {north\_r};
  \node [above left=of north_r,yshift=-1.5cm] (north_if)    {north\_if};
%
  \node [at={(south_if |- box_a)}]            (box_c)  {box\_c};
  \node [at={(box_c|-sout_join)}]             (t_rdr)       {t\_rdr};
%
  \node [above=of box_c]                       (t_output)    {t\_output};
  \node [below=2cm of t_rdr]                   (south_rp)    {south\_rp};
  \node [above right=1.5cm and 0mm of t_rdr]   (test_prov)   {test\_prov};
  \node [below right=7mm and 1cm of test_prov] (sink_prov)   {sink};
  \node [above left=1.5cm and -5mm of box_a]   (sink_test_a) {sink};
  \node [above right=1cm and -5mm of box_b]    (sink_test_p) {sink};
\end{scope}

\begin{scope}[every node/.style={labelnode}]

\foreach \i/\j in  {%
    box_b/sout_join,
    box_a/nout_join,
    north_r/box_b,
    box_c/t_rdr,
    t_rdr/south_rp,
    t_output/box_c,
    south_r/box_a}
  \draw [post] (\i) -- (\j)
     node[above,near start] {output}
     node[below,near end,swap] {input};

\foreach \i/\j in{%
    nout_join/north_if,
    sout_join/south_if}
  \draw [post] (\i) |- (\j)
    node[above,near start] {output}
    node[below,near end,swap] {input};

\foreach \i/\j in{%
    north_if/north_r,
    south_if/south_r}
  \draw [post] (\i) -| (\j)
    node[above,near start] {output}
    node[below,near end,swap] {input};

\draw [post] (t_rdr) -- (test_prov)
  node[above,pos=0.4] {prov\_out}
  node[below,pos=0.6] {input};

\draw [post] (test_prov) -- ([xshift=-3mm]t_output.south east)
  node[above,pos=0.7] {test\_prov}
  node[below,pos=0.3] {output};

\draw [post] (t_rdr) -- (sout_join)
  node[above,pos=0.45] {output\_s,src}
  node[below,pos=0.55] {output\_s,src};

\draw [post] (test_prov) -| (sink_prov)
  node[above,pos=0.4] {output1}
  node[left,sloped=false,pos=0.8] {fromtest};

\draw [post] (north_r) -- (t_output)
  node[above,pos=0.65] {n\_test\_in,\\test\_out}
  node[below,pos=0.35] {test\_out,\\n\_test\_in};

\draw [post] (box_a) -| (sink_test_a)
  node[left,sloped=false,pos=0.85] {test\_a}
  node[below,pos=0.49] {output4};

\draw [post] (box_b) -| (sink_test_p)
  node[right,sloped=false,pos=0.85] {test\_p}
  node[below,pos=0.49] {output4};

\draw [post] (t_rdr) -- (nout_join)
  node[below,near start] {output\_n,n\_src}
  node[above,near end] {output\_n,src};

\draw [post] (south_r) -- (t_output)
  node[below,near start] {test\_out,n\_test\_n}
  node[above,near end] {n\_test\_out,test\_out};

\end{scope}

\end{tikzpicture}
\end{center}
\end{document}
Torbjørn T.
  • 206,688
  • The figure looks awesome, but it will take some time for me to digest the code :) Thank you for the detailed answer! – Raj Dec 01 '17 at 06:16