2

My problem is that I want to draw several horizontal "layers" of nodes (implemented as chains), with connections between them. When I try to position a node absolutely, it is additionally offset in the chain's direction:

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{chains}
\begin{document}
\begin{tikzpicture}[
  node distance=1,
  block/.style={
    on chain,
    inner sep=0pt,outer sep=0pt,
    draw,minimum height=10,minimum width=2}
]

\path[start chain=layer1]
  node[block] {}
  node[block,join] {}
  node[block,join] {}
;

\path[start chain=layer2]
  node[block,join=with layer1-3,below=of layer1-end] {}
  node[block,join] {}
  node[block,join] {}
;

%\path[start chain=layer1right] % WORKS
\path[continue chain=layer1]    % DOES NOT WORK, BUT WHY?
  node[block,join=with layer2-end,anchor=center] at (layer2-end |- layer1-end) {}
  node[block,join] {}
  node[block,join] {}
;

\end{tikzpicture}
\end{document}

I also tried variants like

node[block,join=with layer2-end placed {at=(layer2-end |- layer1-end)},anchor=center] {}

and I don't understand why I get the additional offset (I did find a workaround, see below). According to the pgfmanual, I think this should've worked:

Independently of which form is used, the ⟨text⟩ inside ⟨direction⟩ that follows going or placed (separated by a compulsory space) can have two different effects:

(a) If it contains an equal sign, then this ⟨text⟩ is used as the placement rule, that is, it is simply executed.

(b) If it does not contain an equal sign, then ⟨text⟩=of \tikzchainprevious is used as the placement rule.

Note that in the first case, inside the ⟨text⟩ you have access to \tikzchainprevious and \tikzchaincount for doing your positioning calculations.

My workaround (see commented out code) is to start a new chain (which has the additional advantage that I could remove the anchor=center). I cannot use above=of ..., because in my real code, the blocks have different heights, and the nodes on layer1 will not be aligned anymore.

  • 1
    While code snippets are useful in explanations, it is always best to compose a fully compilable MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. This is especially important for tikz as there are numerous libraries. – Peter Grill May 31 '16 at 7:23
  • Can you simply indicate where you like to have start of continuation of layer1 chain? Above end of layer2? Or on an arbitrary place? – Zarko May 31 '16 at 9:44
  • Yes, horizontically aligned with the end of layer2, and vertically aligned with layer1, exactly as expressed by the at (...). If you uncomment the "WORKS" line, and comment out the "DOES NOT WORK" line, you can also see the intended result. – hans_meine May 31 '16 at 9:49
  • @PeterGrill Thanks for the heads-up, I edited the code. (I am using a script that allows me to view such .tikz files, so for me it already was a MWE.) – hans_meine May 31 '16 at 9:51
  • See, if this help: \path[continue chain=layer1] [block,join=with layer2-end,above=of layer2-end] {} node[block,join] {} node[block,join] {}; – Zarko May 31 '16 at 10:06
3

I would:

  • set up layer2 as a branch;
  • add the precisely positioned node outside the chain;
  • use \chainin to add that node into the chain before continuing with the remaining nodes.

For example:

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{chains,scopes}
\begin{document}
\begin{tikzpicture}
  [
    node distance=1,
    basic block/.style={%
      inner sep=0pt,
      outer sep=0pt,
      draw,
      minimum height=10,
      minimum width=2,
    },
    block/.style={%
      basic block,
      on chain,
    },
    start chain=layer1,
  ]
  \path
  node [block] {}
  node [block,join,minimum height=20] {}
  node [block,join,minimum height=5] {}
  ;
  {[start branch=layer2 going below]
    \node [block,join,minimum height=20] {};
  }
  {[continue branch=layer2 going right]
    \path
    node [block,join] {}
    node [block,join,minimum height=30] {}
    ;
  }
  \node (a) [basic block] at (layer1/layer2-end |- layer1-3) {};
  [continue chain=layer1]
  \chainin (a) [join=with layer1/layer2-end];
  \path
  node [block,join,minimum height=20] {}
  node [block,join] {}
  ;
\end{tikzpicture}
\end{document}

mixed nodes in chains

Note that the chains implementation is a little ... eccentric ... at times. As I understand it, it is considered deprecated and, hence, very unlikely to get significant improvements.

[I think this is a shame because the idea has a pleasing simplicity and is more friendly to beginners than the functionality provided by the graphs syntax, which replaces it. The graphs syntax is, however, more flexible, powerful and concise.]

  • (+1) ... for solution and special for your comments on the end. This good to know! Chains serve me very well ... – Zarko May 31 '16 at 21:42
  • It's interesting. I never used on grid that I remember. I'm always curious to see what other people use. – cfr May 31 '16 at 21:46
  • Accepted because - although it does not directly answer the question why the offset is there - it points to the superceding graphs syntax and points out chains' excentricity. Thanks also for the branching demo; despite the unfortunate lengthening of the node names (layer1/layer2-end), this looks like a good match. – hans_meine Jun 1 '16 at 6:25
3

If I understand question correctly, than you looking for something like this:

enter image description here

Code:

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{chains,positioning}

    \begin{document}
\begin{tikzpicture}[
  node distance=1,
  block/.style={
    on chain,
    inner sep=0pt,outer sep=0pt,
    draw,minimum height=10,minimum width=2}
                    ]
\path[start chain=layer1]
  node[block] {}
  node[block,join] {}
  node[block,join] {};
\path[start chain=layer2]
  node[block,join=with layer1-end,below=of layer1-end] {}
  node[block,join] {}
  node[block,join] {};
\path[continue chain=layer1]   
  node[block,join=with layer2-end,above=of layer2-end] {}% <--
  node[block,join] {}
  node[block,join] {};
\end{tikzpicture}
    \end{document}

As you see, in continuation I use the same syntax as you for draw chain layer2. Options continue chain=... means that the chain will continue, where you indicate, in this case above of end node in chain2.

Main benefits to use of chains is relative positioning of nodes: next node in chain is always placed relatively to node before it.

Addendum: From comments can be concluded, that you looking for nodes on the grid:

enter image description here

New MWE:

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{chains,positioning}

\begin{document}
\begin{tikzpicture}[
    on grid,
  node distance=2cm and 0.5 cm,
  block/.style={
    on chain,
    inner sep=0pt,outer sep=0pt,
    draw,minimum height=#1,minimum width=2}
                    ]
\path[start chain=layer1]
  node[block=1cm] {}
  node[block=2cm,join] {}
  node[block=1cm,join] {};
\path[start chain=layer2]
  node[block=1cm,join=with layer1-end,below=of layer1-end] {}
  node[block=1cm,join] {}
  node[block=1cm,join] {};
\path[continue chain=layer1]
  node[block=2cm,join=with layer2-end,above=of layer2-end] {}% <--
  node[block=1cm,join] {}
  node[block=1cm,join] {};
\end{tikzpicture}
\end{document}
  • That's actually what I started with. I am sorry; the MWE no longer shows that I cannot use above=of ..., because in general (with varying block heights), it does not give you aligned nodes on layer1. I will add that constraint to the question. Since I managed to work around the problem by using two chains, the question really is, why do I need to do that? – hans_meine May 31 '16 at 15:06
  • Well, my crystal ball is recently fogy, so I can't see, what is your problem :-). As I now understand, you need to employ "on grid" option. See my edit of answer ... – Zarko May 31 '16 at 15:31

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.