13

Suppose, I have this structure:

enter image description here

Code:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc,shapes, positioning}
\begin{document}
\def\len{1cm}
\begin{tikzpicture}[node distance = \len, auto]
\tikzset{
    line/.style = {draw},
    block/.style = {rectangle, draw, text centered, minimum height=2em},
}
\node [block] (1-1) {1-1};
\node [block, below = of 1-1] (1-2) {1-2};
\path [line] (1-1) -- (1-2);
\node [block, below right = of 1-2] (2-1) {2-1};
\path [line] (1-2) -| (2-1);
\node [block, right = of 2-1] (3-1) {3-1};
\node [block, dotted] at(3-1|-1-2) (3-2) {3-1};
\path [line] (1-1) -| (3-1);
\end{tikzpicture}
\end{document}

How can I position node 3-1 to the right of node 2-1 and on the same level with 1-2, using calc library? I drew the desired position, using dotted borders.

Please, don't suggest to use matrix.

Update

1 approach is to use above right = of 2-1. It would work for this test case, but if node 1-2 is tall, it wouldn't position 1-3 vertically to the centre of it:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc,shapes, positioning}
\begin{document}
\def\len{1cm}
\begin{tikzpicture}[node distance = \len, auto]
\tikzset{
    line/.style = {draw},
    block/.style = {rectangle, draw, text centered, minimum height=2em},
}
\node [block] (1-1) {1-1};
\node [block, below = of 1-1, text width = 1cm] (1-2) {text, text, text (!): $\frac{1}{2}$};
\path [line] (1-1) -- (1-2);
\node [block, below right = of 1-2] (2-1) {2-1};
\path [line] (1-2) -| (2-1);
\node [block, above right = of 2-1] (3-1) {3-1};
\path [line] (1-1) -| (3-1);
\end{tikzpicture}
\end{document}

Gives this:

enter image description here

Update 2

@Bordaigorl suggested to use right = 2 of 1-2. But if 2-1 is wide, it will visually overlap with 3-1:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc,shapes, positioning}
\begin{document}
\def\len{1cm}
\begin{tikzpicture}[node distance = \len, auto]
\tikzset{
    line/.style = {draw},
    block/.style = {rectangle, draw, text centered, minimum height=2em},
}
\node [block] (1-1) {1-1};
\node [block, below = of 1-1, text width = 1cm] (1-2) {text, text, text (!): $\frac{1}{2}$};
\path [line] (1-1) -- (1-2);
\node [block, below right = of 1-2] (2-1) {2-2-2-2-2};
\path [line] (1-2) -| (2-1);
\node [block, right = 2 of 1-2] (3-1) {3-1};
\path [line] (1-1) -| (3-1);
\end{tikzpicture}
\end{document}

enter image description here

Possible solution

I used an extra \coordinate node to the right of 2-1. Is it possible to solve the problem without it?

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc,shapes, positioning}
\begin{document}
\def\len{1cm}
\begin{tikzpicture}[node distance = \len, auto]
\tikzset{
    line/.style = {draw},
    block/.style = {rectangle, draw, text centered, minimum height=2em},
}
\node [block] (1-1) {1-1};
\node [block, below = of 1-1, text width = 1cm] (1-2) {text, text, text (!): $\frac{1}{2}$};
\path [line] (1-1) -- (1-2);
\node [block, below right = of 1-2] (2-1) {2-2-2-2-2};
\path [line] (1-2) -| (2-1);
\node [coordinate, right = of 2-1.east] (3-1) {};
\node [block] at(3-1|-1-2) (3-2) {3-1};
\path [line] (1-1) -| (3-2);
\end{tikzpicture}
\end{document}

enter image description here

10
  • Seriously, you should use a matrix of nodes... :p
    – jub0bs
    Nov 11, 2013 at 20:22
  • @Jubobs I looked at Gonzalo Medinas answer here: tex.stackexchange.com/questions/70336/…, but couldn't make it work for my case. Is it possible to use calc?
    – user4035
    Nov 11, 2013 at 20:25
  • is there a specific reason you want a solution with calc? Or you meant positioning?
    – Bordaigorl
    Nov 11, 2013 at 20:57
  • You can use above right=of 2-1? You can use \coordinate (@) at (1-2-|2-1.east); and then right=of @. Many possibilities. Also compare node distance=1cm with node distance=1cm and 1cm for diagonal placements. Nov 11, 2013 at 21:02
  • @Bordaigorl I think, it would require using both positioning and calc.
    – user4035
    Nov 11, 2013 at 21:02

2 Answers 2

11

You may use right=of 2-1 |- 1-2 (without calc library):

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\def\len{1cm}
\begin{tikzpicture}[node distance = \len, auto]
\tikzset{
    block/.style = {rectangle, draw, text centered, minimum height=2em},
}
\node [block] (1-1) {1-1};
\node [block, below = of 1-1] (1-2) {1-2};
\node [block, below right = of 1-2] (2-1) {2-1};
\node [block,right=of 2-1 |- 1-2] (3-1) {3-1};
\end{tikzpicture}
\end{document}

enter image description here

3
  • Dear Paul, how could i add a node above 2-1 and right of 1-2 i.e. pseudo-code \node [block,above=of 2-1 and right of 1-2] (4-1) {4-1} ; \node [block,above=of 2-1 |- 1-2] (4-1) {4-1}; positions the node too high / not to the right of 1-2. Thanks for any help. Jan 27, 2021 at 17:25
  • @user2957945 Try \node[block,at={(2-1 |- 1-2)}] (4-1) {4-1}; Jan 28, 2021 at 7:47
  • Great, thanks Paul; appreciate your help Jan 28, 2021 at 18:53
4

You can use positioning for that by asking it to place 3-1 "two to the right" of 1-2:

\begin{tikzpicture}[node distance = \len, auto]
    \tikzset{
        line/.style = {draw},
        block/.style = {rectangle, draw, text centered, minimum height=2em},
    }
    \node [block] (1-1) {1-1};
    \node [block, below = of 1-1] (1-2) {1-2};
    \path [line] (1-1) -- (1-2);
    \node [block, below right = of 1-2] (2-1) {2-1};
    \path [line] (1-2) -| (2-1);
    \node [block, right =2 of 1-2] (3-1) {3-1};
    % \node [block, dotted] at(3-1|-1-2) (3-2) {3-1};
    \path [line] (1-1) -| (3-1);
\end{tikzpicture}

However this does not scale well if the nodes have dissimilar sizes.

To accommodate all the constraints one can use the on grid option that, when using positioning keys, instructs TikZ to use centers of nodes as reference points for positioning:

\begin{document}
\def\len{2cm}

    \begin{tikzpicture}[x=\len, y=\len, on grid]
        \tikzset{
            line/.style = {draw},
            block/.style = {rectangle, draw, text centered, minimum height=2em},
        }
        \node [block] (1-1) {1-1};
        \node [block, below =1 of 1-1, text width = 1cm] (1-2) {text, text, text (!): $\frac{1}{2}$};
        \path [line] (1-1) -- (1-2);
        \node [block, below right =1 of 1-2] (2-1) {2-2-2-2};
        \path [line] (1-2) -| (2-1);
        \node [block, right =1.5 of 1-2] (3-1) {3-1};
        \path [line] (1-1) -| (3-1);
    \end{tikzpicture}
\end{document}

A few changes are needed:

  1. here the distances must be changes since now they stand for distances between centres, not borders (hence \def\len{2cm})
  2. we use explicit dimensionless relative coordinates in the positioning keys to be able to scale if necessary using the x and y keys

Now you can add content to the nodes as you wish but they remain in their relative positions, as now they are relative to the centres. If later on the spacing is not enough you can redefine \len (or x and y individually) to space the nodes out.

7
  • I tried it. 1 min, I'll explain, why I didn't like this approach
    – user4035
    Nov 11, 2013 at 21:07
  • question updated
    – user4035
    Nov 11, 2013 at 21:13
  • My solution does center 3-1 and 1-2 vertically...
    – Bordaigorl
    Nov 11, 2013 at 21:15
  • 1
    I'll show another potential bug in your solution. Another 5 mins
    – user4035
    Nov 11, 2013 at 21:17
  • 1
    @user4035 ok =) it seems you haven't explained all your constraints in the question...
    – Bordaigorl
    Nov 11, 2013 at 21:19

You must log in to answer this question.

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