Horizontal fixing of Tikz nodes

(Please feel free to offer a better and more precise subject title.)

I have two vertical chains with different count of nodes in it. But I want to visualize that some nodes of the right belong to one of the left. They need to appear in the same row/line. In the example code below you see Y and two nodes should appear on the right side of it.

The problem here is that I can not handle the right chain like it has 4 nodes and join them. Using \matrix make it impossible to use chain.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,positioning,chains,scopes}

\begin{document}
\begin{tikzpicture}
[
myright/.style={
draw},
myleft/.style={
myright,
on chain,
fill=cyan!30}
]
% LEFT
{[start chain=L going below,
every node/.append style=myleft]
\node {X};
\node {Y};
\node {Z};
}

% RIGHT
{[start chain=R going below]
\node [myright,right=of L-1] {belong to X};

\matrix [right=of L-2]
{
\node [myright] {belong to Y};\\
\node [myright] {also belong to Y};\\
};

\node [myright,right=of L-3] {belong to Z};
}
\end{tikzpicture}
\end{document}


btw: This question is related to this one about drawing PRISMA flow chart.

• If you place two nodes in branch R and both belong to Y, they cannot both be aligned horizontally with Y because R is going below. And what about the final node? Where is C which it should align with? – cfr Jan 28 '16 at 22:23
• The TikZ manual has an example which combines a matrix of nodes with chains, by the way. – cfr Jan 28 '16 at 22:26
• The example mentioned by cfr is in page 70. – Ignasi Jan 29 '16 at 9:51
• The thing is, it isn't clear what you are trying to do. You cannot align 2 nodes horizontally with Y and align those 2 nodes vertically with the node with content belong to X. The way you describe the nodes as children of nodes on the left suggests that your branches should really be going right, with the main chain going below rather than the main chain going right with branches going below. (Or if this is really a tree, maybe a tree structure would work better.) Right now, you appear to want a spatio-temporal impossibility. The TikZ gurus are good. But not that good ;). – cfr Jan 29 '16 at 20:43
• @Ignasi Page 545 in the version I have. – cfr Jan 29 '16 at 22:31

As I understand the current version of this question, the picture you've drawn places the nodes correctly but does not allow them to be joined with the ease of chained nodes, because the right column of nodes are not chained. Also, perhaps you want some separation between the two nodes belonging to Y, though I'm not sure.

Note that the best way to do this kind of thing is very heavily dependent on the details of the diagram in question, your own familiarity with different aspects of TikZ and different libraries, and whether the diagram is a one-off or one of a sequence of similar diagrams. There's a balance to be struck here between efficiency/elegance in coding the diagram (which might involve a great deal of effort to set up) and ease of set up (if any).

Just given the current example, if I've understood the issue correctly, I would try something like this.

1. Create the left hand chain of nodes, including a branch from X going right.

2. Place the topmost right node on the branch from X.

3. Position a matrix to the right of Y, aligning with the top right node.

4. Position the bottom right node to the right of Z, aligning with the top right node.

5. Create the second, right hand chain, adding the nodes on the right to the chain and joining them as they are added.

This is a little messy in terms of naming and mix of methods but you end up with two chains of nodes which can be easily joined and referred to. Note that there is no problem with a node being in more than one chain or a matrix and a chain or....

If you do not want to separate the nodes belonging to Y, delete the row sep. If you do not want them joined, delete the relevant [join].

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{matrix,positioning,chains,scopes}
\begin{document}
\begin{tikzpicture}
[
myleft/.style={
draw,
fill=cyan!30}
]
% LEFT
{[start chain=L going below,
every on chain/.append style={myleft},
every node/.append style={on chain},
]
\node {X};
{[start branch=X going right,
every on chain/.append style={fill=none}
]
\node {belong to X};
}
\node {Y};
\node {Z};
}
\matrix (m) [row sep=2.5pt, matrix of nodes, every node/.append style={draw}] at (L-2 -| L/X-2)
{
belong to Y\\
also belong to Y\\
};
\node (z2) [draw] at (L-3 -| L/X-2) {belong to Z};
% RIGHT
{[start chain=R going below]
\chainin (L/X-2);
\chainin (m-1-1) [join];
\chainin (m-2-1) [join];
\chainin (z2) [join];
}
\end{tikzpicture}
\end{document}

• (+1) .. @cfr, in the first question (on which OP provide link), the desired picture was very different from those in this question. So I'm after four attempting to help OP completely confused, what he like to have. Use matrix for nodes with common "blue" nodes" is very good! – Zarko Jan 29 '16 at 23:34
• @Zarko Yes. I know. The question was and, really, still is very unclear. (See also my comments on the question.) I am still not certain this is what is wanted, but it seemed at least a little clearer. I notice that C is no longer an issue in this version. I'm pleased about that because I never could figure out where or what C was ;). – cfr Jan 29 '16 at 23:49

Now your example is far more simple as picture present on given link. Main differences is, that the right branch has only vertically spaced nodes. Considering this is probably on grid option what you looking for:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,chains,scopes}

\begin{document}
\begin{tikzpicture}[
node distance = 10mm and 30mm,
on grid,
start chain = A going below,
start chain = B going below,
myright/.style = {draw, minimum height=4ex, minimum width=33mm,
on chain=A},
myleft/.style = {draw, fill=cyan!30, minimum height=4ex,
on chain=B}
]
% LEFT
\begin{scope}[every node/.style={myleft}]
\node {X}; % name=B-1
\node {Y};
\node {Z};
\end{scope}
% RIGHT
\begin{scope}[every node/.style={myright}]
\node [right=of B-1]    {belong to X}; % name=A-1
\node {belong to Y};
\node {also belong to /};
\node {belong to no one};
\end{scope}
\end{tikzpicture}
\end{document}


In above MWE distances of grid is determined by node distance. Nodes are anchored to the grid with its center. This means, that if they aren't of the same width, they will not have aligned left (or right) borders.

Two chains are selected for simplest node naming (left are B-1, B-2, B-3, right are A-1, A-2, A-3 and A-4).

To this two branches it is easy add one more branch on the right (as has mentioned picture), but more effort is needed, if on the of the right branch are two nodes ...

Addendum (1): Partly considered images on question flowchart-tikz, the upgrade of the above MWE is:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,chains,positioning,scopes}

\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{3mm}

\makeatletter
%---------------------------------------------------------------%
\tikzset{
suspend join/.code={\def\tikz@after@path{}},
node distance = 13mm and 44mm,
on grid = true,
start chain = A going below,
start chain = B going below,
MR/.style = {% My Right
draw, minimum height=4ex, text width=31mm,
inner sep=1mm, align=center, % left?
on chain=A},
ML/.style = {% My Left
draw=cyan!60!black, rounded corners, fill=cyan!30,
minimum width=4ex, inner sep=1mm,
node contents={\rotatebox{90}{#1}},
on chain=B},
arrow/.style = {thick,-{Triangle[]}},
}
%---------------------------------------------------------------%
\makeatother

\begin{document}
%---------------------------------------------------------------%
\begin{tikzpicture}
% LEFT BRANCH
\node [ML=X]; % name=B-1
\node [ML=Y];
\node [ML=Z];
\node [ML=WWW];
\node [ML=QQ];
% RIGHT BRANCH
\begin{scope}[every node/.style={MR,join=by arrow}]
\node [draw=none,
right=of B-1]    {}; % name=A-1, auxiliary node which serves
% as placeholder for real left and right node
% (A-L) and (A-R) defined latter in
% the TOP part of this code
\node [suspend join]    {belong to Y};
\node                   {belong to Z};
\node                   {belong to WWW, however text in this node has three lines};
\node                   {belong to QQ};
\end{scope}
% TOP ROW LEAVES (horizontally are not on grid)
\begin{scope}[node distance=2mm,
every node/.style={MR}]
\node (A-L) [ left = of A-1.center] {left top leave};
\node (A-R) [right = of A-1.center] {right top leave};
\end{scope}
% RIGHT LEAVES
\node (C-1) [MR, right = of A-3] {upper right leave};
\node (C-2) [MR, right = of A-4] {lower right leave};
% ARROWS NOT DETERMINED BY "JOIN" MACRO
\path[arrow]    (A-L) edge (A-2)    (A-R) edge (A-2)
(A-3) edge (C-1)    (A-4)edge (C-2);
\end{tikzpicture}
%---------------------------------------------------------------%
\end{document}


which gives:

The contains (i hope so) enough comments that is its structure is clear. Mai goal in code writing has been its concise and to be clear. In comparison with the first MEW, it has novelty suspend join, by which is simplified use of join macro in right branch of flowchart.

Addendum (2): Your question is like *Variable structure System, for which seems not fulfill Filipov's criteria (and consequently without sliding to some equilibrium point ...) .

Let assume:

• that second and third node (from top down) in right branch are have common blue node in the left branch
• height of these nodes in right branch is not fixed
• blue node (in the left branch) span distance from top of upper node to bottom of lower node (in right branch, to which it belong)

This can be achieved with following:

• measuring distance, which blue node should span and separeteli design this node
• introduce fake nodes for maintain left branch on grid

For this I add two libraries: calc and fit, define fake nodes and real left nodes. The code has enough comments (I hope so), that it is easy to anderstand, what it doing.

    \documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,calc,chains,fit,positioning,scopes}

\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{3mm}

\makeatletter
%---------------------------------------------------------------%
\tikzset{
suspend join/.code={\def\tikz@after@path{}},
node distance = 13mm and 44mm,
on grid = true,
start chain = A going below,
start chain = B going below,
MR/.style = {% My Right node
draw, minimum height=4ex, text width=31mm,
inner sep=1mm, align=center, % left?
on chain=A},
ML/.style = {% My Left node
draw=cyan!60!black, rounded corners, fill=cyan!30,
minimum width=4ex, inner sep=1mm,
node contents={\rotatebox{90}{#1}},
on chain=B},
FL/.style = {%Fake Left node
node contents={\rotatebox{90}{\phantom{X}}},
on chain=B},
RL/.style = {%Fake Left node
draw=cyan!60!black, rounded corners, fill=cyan!30,
minimum width=4ex, inner xsep=0pt,
label=center:\rotatebox{90}{#1},
node contents={}},
arrow/.style = {thick,-{Triangle[]}},
}
%---------------------------------------------------------------%
\makeatother

\begin{document}
%---------------------------------------------------------------%

\begin{tikzpicture}
% LEFT BRANCH
\node [ML=X];   % name=B-1
\node [FL];     % auxiliary node which maintain branch on grid
% real nodes will take a place latter
\node [FL];
\node [ML=WWWW];
\node [ML=QQ];
% RIGHT BRANCH
\begin{scope}[every node/.style={MR,join=by arrow}]
\node [suspend join,
right=of B-1]    {belong to X}; % name=A-1,
\node                   {belong to Y};
\node                   {also belong to Y};
\node                   {belong to WWWW, however text in this node has three lines};
\node                   {belong to QQ};
\end{scope}
% REAL BLUE NODE, instead of FL
\path   let \p1 = (B-2 |- A-2.north),
\p2 = (B-2 |- A-3.south),
\n1 = {veclen(\y2-\y1,\x2-\x1)} in
node[RL=Y,
minimum height=\n1,
fit=(B-2) (B-3)];
% RIGHT LEAVES
\node (C-1) [MR, right = of A-3] {upper right leave};
\node (C-2) [MR, right = of A-4] {lower right leave};
% ARROWS NOT DETERMINED BY "JOIN" MACRO
\path[arrow]    (A-3) edge (C-1)    (A-4)edge (C-2);
\end{tikzpicture}


• Sorry, I don't made my point clear. Please see my code. There are two "child nodes" for Y. Your exampel just fitted simple one node to anoathor on the horizonatl axes. – buhtz Jan 29 '16 at 20:34
• Sorry, my crystal ball is still broken ... if I understand you now correctly, than -- according to my picture -- nodes "belong to Y" and "belong to Z" has one blue node, which span distance from top of blue node "Y" to bottom of node "Z"? If this is true, than this node can not be placed on the grid anymore, consequently, the code will become quite more complicated ... – Zarko Jan 29 '16 at 20:59
• I totaly adjusted my question with new code and a screenshot. – buhtz Jan 29 '16 at 21:10
• Not adjusted ... you changed your question! If the figure, you now show in question generated by your code, what is thenwhat is wrong with your solution? – Zarko Jan 29 '16 at 21:20
• What does the on grid do, especially in the first version? Does it do anything not done by the chains already? – cfr Jan 29 '16 at 23:50