The TikZ documentation gives the following example for adding a label on an edge in a tree:

  \node {r}
    child {node {t}
      edge from parent node {label}};

Now, I want to tweak the way the edges are drawn. Namely, I want to be able to specify an arbirtary number of wires to link the two nodes. I'm pretty close to it, but I get stuck when I want to label midway, as in the example. My problem is with the following, stripped example:

[edge from parent path={%
  \foreach \n in {0} { (\tikzparentnode) -- (\tikzchildnode) }}]

When this tweak is put, the label of the first example is stuck to the bottom of the picture. My first idea was to add a portion of path so that the node {label} can be attached to something. The closest I can get to is:

[edge from parent path={%
  \foreach \n in {0} { (\tikzparentnode) -- (\tikzchildnode) };
  \path ($(\tikzparentnode)!.5!(\tikzchildnode)$)}]

This terminates the path and starts a new one. Now, label gets positioned at the right place. But here is the odd thing. Let's define a counter to see how many of those paths are actually drawn (the expected value being 1) :

    [edge from parent path={%
      \foreach \n in {0} { (\tikzparentnode) -- (\tikzchildnode) };
      \path ($(\tikzparentnode)!.5!(\tikzchildnode)$)}]
  \node (root) {r}
    child {node {t}
      edge from parent node {label}};

With my previous fix, the path is drawn... 2 times! (I noticed that because with multiple wires, it is pretty obvious). Also, if I put a semicolon immediately after {label}, it seems that everything runs smoothly; trouble is, the usual syntax has to work too...

Summing up, my question is:

How can I redefine edge from parent path so that I can use a foreach in it, and still be able to place a label midway between the nodes?

  • 1
    I ended up ending my path with let \p1 = ($ (\tikzparentnode)!.5!(\tikzchildnode) $) in (\p1) -- (\p1), but this is not entirely satisfactory: the following node will be positioned at the right position, but, of course, I can't change it using [pos=].
    – Michaël
    Sep 22, 2010 at 18:54

1 Answer 1


The solution is to suppress drawing edge from parent itself and define the code (inside user-defined pgfkey) of drawing your specific edges, which should be executed as an option to edge from parent. Alas, there's, probably undesired, consequence of making you to explicitly say edge from parent every time you want to draw the label node.

    edge from parent/.style=my incredible edge,
    my incredible edge/.code={
        \foreach \n in {0.5,1} {
            \draw (\tikzparentnode.south) .. controls +(0,-\n) and +(0,\n) .. (\tikzchildnode.north);
    \node {root}
        child {node {left}}
        child {node {right}
            child {node {child}}
            child {node {child}} edge from parent node[near end] (A) {label}

    \filldraw[red] (A) circle[radius=1pt];

enter image description here

  • Thank you Dmitry. Alas, the solution you give explicitly draws a second time the path, which is the behavior I want to get rid of. Moreover, you draw an edge at a place there might be none (recall the goal is to put multiple wires, and with an even number, there is no "middle wire"). That's why I used "\path" instead of drawing. Thanks though!
    – Michaël
    Apr 21, 2011 at 13:00
  • @Michael: Note that I've propsed another solution. Apr 22, 2011 at 3:04
  • @Dmitry: thanks! That's great! Two things; 1. why not "edge from parent/.style={my incredible edge}"? 2. Would you mind adding some explanation as to why this works? (I was expecting the last "line in memory" to be the last one \drawn in "my incredible edge", but when I translate those lines, "label" does not move, thus the "line in memory" is (tikzparentnode.anchor)--(tikzchildnode.anchor), even though this line is never mentioned.) Thank you very much!
    – Michaël
    Apr 22, 2011 at 9:57
  • @Michael: You are welcome! 1. Hey, that's cool point! I change may solution accordingly. Now with joint effort it becomes more consice! 2. The previous solution worked as follows: a) the straight line is mentioned by default, we make it invisible by draw=none b) my incredible edge is drawn in a usual manner, independently of anything else. Regarding present solution: instead of suppressing rendering of straight line we merely replace it by execution of code for my incredible edge. But now I miss why label is still placed along straight line (it still mentions somewhere...) Apr 22, 2011 at 12:19
  • @Michael: Well, I guess I understood: replacing initial style, we discard draw option. The path, that directly joins nodes, still mentioned, but not drawn. Apr 22, 2011 at 12:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .