12

I'm drawing an org chart and I'd like to have arrows pointing to each of the nodes I do so. I'm also lazily using a single draw command to draw a line from each of the nodes as the last part of my process. Is there some way that I can specify an [->] going to C and B but not to hub1 in the example I've shown without drawing each line individually?

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\tikzstyle{a}=[rectangle,draw]

\begin{document}
\begin{tikzpicture}
\node [a] (A) at (0,0) {A};
\node [a,below=1cm of A] (B) {B};
\node [a,left=1cm of B] (C) {C};
\node [a,right=1cm of B] (D) {D};
\node [below=0.25cm of A] (hub1) {};
\draw [->] (A.south) -- (hub1.south) -| (C.north) (hub1.south) -- (B.north) (hub1.south) -| (D.north);

\end{tikzpicture}
\end{document}

editing on from @texenthusiast comment below I've tried using a \foreach loop to edit this, but now the arrow for B points the wrong way. Any thoughts?

\documentclass[a6]{minimal}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\tikzstyle{a}=[rectangle,draw]

\begin{document}
\begin{tikzpicture}
\node [a] (A) at (0,0) {A};
\node [a,below=1cm of A] (B) {B};
\node [a,left=1cm of B] (C) {C};
\node [a,right=1cm of B] (D) {D};
\coordinate [below=0.6cm of A] (hub1) {};
\foreach \a/\b/\c in {C/east/0.1cm,B/north/0,D/west/-0.1cm}
\draw [->] (hub1) -| ($(\a.\b)+(\c,0)$) -- (\a.\b);
\end{tikzpicture}
\end{document}
  • Unrelated hint: if you use \coordinate[below=0.5cm of A] (hub1); instead of your node definition, you can refer to (hub1) instead of the (hub1.south) anchor inside your \draw command. Perhaps a bit more elegant, as you don't have to take node dimensions into account when specifying positions. – bencarabelli Mar 18 '13 at 8:18
  • @texenthusiast I've amended the question to point out the issues with the example suggestion you've made. Thanks – Tahnoon Pasha Mar 18 '13 at 9:06
12

If you want to have the arrow to appear on every single path part, you should use the edge option which default behaviour is a line to (--) and does work similar to a to only that in a construct like

\path (A) edge (B)
          edge (C);

the second line is drawn from (A) to (C) and not from (B) to (C) as in

\draw (A) to (B) to (C);

Of course the linebreak isn’t part of TikZ’ syntax but only highlights this fact.

In the code below I have declared (hub1) as a coordinate so to not have a invisible node with an border. The path operator -| is usually not available for edge but can be easily declared in a to path.

The utilisation of such an auxiliary coordinate like (hub1) is not a bad idea in general. Though, if you often need paths like those from (A) to (C) you can declare relatively easily a |-| to path.
Instead of two -- you can also use one -- and one -| path operator. This only affects node positioning. (If needed one can also “hack” a real |-| path operator that can be used like -- or -| where you can place nodes on the whole path without manually constructing it. A similar thing was done in another answer of mine.

Note that I have explicitly avoided to use \p1 and \p2 as they would possibly overwrite the coordinates declared on a user-level.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{positioning,calc}
\tikzset{
  a/.style={rectangle,draw},
  -|/.style={to path={-| (\tikztotarget) \tikztonodes}},
  |-|/.style={to path={
      let \p{qrr@to@start}=(\tikztostart), \p{qrr@to@target}=(\tikztotarget) in
      -- (\x{qrr@to@start},.5*\y{qrr@to@start}+.5*\y{qrr@to@target}) -- (\x{qrr@to@target},.5*\y{qrr@to@start}+.5*\y{qrr@to@target}) \tikztonodes -- (\tikztotarget)
    }
  }
}

\begin{document}
\begin{tikzpicture}
\node [a] at (0,0)       (A) {A};
\node [a,below=1cm of A] (B) {B};
\node [a, left=1cm of B] (C) {C};
\node [a,right=1cm of B] (D) {D};
\coordinate [below=0.5cm of A] (hub1) {};
\path [->] (A)    edge     (B)
           (hub1) edge[-|] (C)
                  edge[-|] (D);

\end{tikzpicture}

\begin{tikzpicture}
\node [a] at (0,0)       (A) {A};
\node [a,below=1cm of A] (B) {B};
\node [a, left=1cm of B] (C) {C};
\node [a,right=1cm of B] (D) {D};
\path[every edge/.append style={|-|}, ->] (A) edge (B)
                                              edge (C)
                                              edge (D);

\end{tikzpicture}
\end{document}

Output

enter image description here

  • +1 Very nice solution! I'd thought of using edges first, too, but didn't think of your clever |- style declaration. – bencarabelli Mar 18 '13 at 14:16
  • Thanks @Qrrbrbirlbel. Any thoughts on why the arrow might be reversing on the \foreach? I'll play with the edge command but I'm not confident in my macro abilities if I want to edit the -| or |- declaration. – Tahnoon Pasha Mar 18 '13 at 15:28
  • @TahnoonPasha Sorry, haven’t seen your updated question. As a matter of fact, yes I know. (B.north) -- ($(B.north) + (0,0)$) is a zero-length line which doesn’t have a defined direction and TikZ can't place an arrow correctly there. (It defaults to an angle of 90 due trigonometric functions, I guess.) You will have to use -- in this case. – Qrrbrbirlbel Mar 18 '13 at 15:58
2

I think that texenthusiast had something like this in mind:

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\tikzstyle{a}=[rectangle,draw]

\begin{document}
\begin{tikzpicture}
\node [a] (A) at (0,0) {A};
\node [a,below=1cm of A] (B) {B};
\node [a,left=1cm of B] (C) {C};
\node [a,right=1cm of B] (D) {D};
\coordinate [below=0.5cm of A] (hub1);
\draw (A.south) -- (hub1);
\foreach \n in {C,D,B}
  \draw [->] (hub1) -| (\n.north);

\end{tikzpicture}
\end{document}

(Please correct me if I'm wrong...)

  • thanks @benwilfut. That works until you get the additional leg in the graphic in my second MWE. The actual image is quite complicated and has several shifts and that's where I'm seeing the arrow reversal you see in my example. – Tahnoon Pasha Mar 18 '13 at 9:21

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.