6

Following this question's answer, what is the reason behind this spacing inequality between the center text node and left/right ones in this MWE?

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,calc}
\begin{document}
\pagestyle{empty}
\def\gap{20mm}
\begin{figure}
    \centering
    \begin{tikzpicture}[
         font = \sffamily,
line/.style = {draw, -Latex},
  rbox/.style = {draw=blue!80!black, fill=blue!20, 
               rounded corners, inner sep=2mm,
               node distance = 18mm and 10mm},
lbox/.style = {draw=black,text width=(\textwidth-2*\gap)/3, inner sep=0pt,
               node distance = 5mm}
                        ]
\node (Start)   [rbox] {Some Text};
\node (Block1)  [rbox,below  left=of Start] {Text Text};
\node (Block2)  [rbox,below=of Start]       {Text};
\node (Block3)  [rbox,below right=of Start] {Text Text Text};
\node [lbox,below=of Block1] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block2] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block3] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\path [line] (Start) -- coordinate (a) (Block2);
\path [line] (a) -| (Block1);
\path [line] (a) -| (Block3);
    \end{tikzpicture}
\caption{my figure}
    \label{fig-1}
\end{figure}
\end{document}

enter image description here

Diaa
  • 9,599
  • Add draw. The nodes are spaced equally, I suspect. The text is always aligned left, though. – cfr Aug 28 '16 at 16:33
  • @cfr I updated the question. Is that what you meant? – Diaa Aug 28 '16 at 16:41
  • discrepancy arise due to different rbox width. if you will write in the far let one the same text as it is in far right, you will get (amost) symmetrical layout. small differences is caused by left align of lbox content. See my answer. – Zarko Aug 28 '16 at 17:10
  • @Zarko I copied/pasted the same text into the three nodes. Where to see your answer? here or the other question? – Diaa Aug 28 '16 at 17:16
  • @DiaaAbidou, now it is here (below). I need some time to load-up all images, codes ... and today is Sunday in we suppose to rest not hard work .-) – Zarko Aug 28 '16 at 17:42
  • @Zarko Many thanks for help. I hope I don't ruin your Sunday remaining free time :) It is already Monday here X)). Have a nice day. – Diaa Aug 28 '16 at 17:44
  • 1
    Yes. I meant that it shows you that the nodes are skewed a bit left visually even when they are centred because the text is left-aligned rather than justified. (This isn't the only issue, I know, but draw can help diagnose at least part of what's going on.) Always draw boxes which don't align as you expect - nodes, minipages, \parboxes, coffins, other boxes ... the lot. Boxes are TeX's thing, after all. (The stuff in the boxes is really incidental. TeX only cares about arranging boxes. Just a warehouse manager, really. No interest in the contents!) – cfr Aug 28 '16 at 20:06

2 Answers2

10

Since your diagram is a tree, may I recommend Forest? Forest is a TikZ-based package for drawing trees of which I am known to be rather fond ;).

Because the nodes of a Forest tree are tabulars, we can use align[p{<dimension>}} for the terminus nodes of the tree. This makes it easy to have left-aligned textual content with the node visually aligned at the centre, relative to its parent node above. This means it does not matter if the last line of the nodes is only partially full.

\documentclass[border=10pt,multi,tikz]{standalone}

We load the packages with the edges library which supports drawing the squared edges we need.

\usepackage[edges]{forest}
\usepackage{calc}
\usetikzlibrary{arrows.meta}

Now some set-up for our tree.

\forestset{%

We make gap a dimension register. However, you can stick to \newlength\gap etc. if preferred.

  declare dimen register={gap},
  gap'=20mm,

We'll need a dimension for the width of the terminus nodes. Actually, we don't strictly need it, but it seems convenient and efficient to do it this way.

  declare dimen register={lbox width},

We can use pgfmath to calculate the value of this dimension.

  lbox width=(\textwidth-2*\forestregister{gap})/3,

A simplified version of the rbox style from the MWE in the question. The other settings aren't really useful here.

  rbox/.style = {draw=blue!80!black, fill=blue!20, rounded corners},

And a redefined version of lbox.

  lbox/.style = {align/.wrap pgfmath arg={@{}p{##1 pt}@{}}{(lbox_width)}},

This basically tells Forest to get the value of the lbox width dimension register and use it in a tabular specification for nodes with this style. We kill the extra spacing at the left and right of a tabular with @{} and use lbox width as the argument for a p{} column.

}
\begin{document}

Now for the tree. The first, optional part of a Forest tree is its preamble. This is everything up to the first (unprotected) [. The preamble can specify zero or more keys to customise the appearance of the tree.

\begin{forest}

For the squared edges, we just use the style from the library edges.

  forked edges,

We want some customisation to apply to the whole tree by default.

  for tree={%
    font = \sffamily,
    edge = {draw, -{Latex}},

This sets the style for the tree's edges so that they are drawn with arrows. (draw is default anyway, but this is clearer.)

  },

Now, we want a different style for the terminus nodes, which are the ones with no children, so we'll apply one style to those nodes and another to the rest.

  where n children=0{%
    lbox,
    no edge,

For the terminus nodes, we use the lbox style and no edge so the edges won't be drawn here at all, overriding our default.

  }{%

The rest just need rbox.

    rbox,
  }

That's the customisation. Now for the tree itself using the compact bracket syntax, starting with the root node.

  [Some Text, name=Start, l sep+=5pt

I've added names for nodes corresponding to named nodes in the MWE. However, the example with Forest doesn't actually need them, so these may be omitted if they are not needed later in the diagram. l sep+=5pt adds 5pt to the separation between the root and its children, because the default looked a bit cramped to me. Obviously this can be adjusted according to taste.

    [Text Text, name=Block1

The left-most child

      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
      ]

and its child.

    ]
    [Text, name=Block2

The root's middle child

      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

and grandchild.

      ]
    ]
    [Text Text Text, name=Block3

The rightmost child

      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

and its child.

      ]
    ]
  ]

That's it for the tree. If we wanted, we could now add some regular TikZ commands here, using the node names specified, if needed. But we don't need that, so we just close the environment.

\end{forest}
\end{document}

Forest solution

Complete code:

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage[edges]{forest}
\usepackage{calc}
\usetikzlibrary{arrows.meta}
\forestset{%
  declare dimen register={gap},
  gap'=20mm,
  declare dimen register={lbox width},
  lbox width=(\textwidth-2*\forestregister{gap})/3,
  rbox/.style = {draw=blue!80!black, fill=blue!20, rounded corners},
  lbox/.style = {align/.wrap pgfmath arg={@{}p{##1 pt}@{}}{(lbox_width)}},
}
\begin{document}
\begin{forest}
  forked edges,
  for tree={%
    font = \sffamily,
    edge = {draw, -{Latex}},
  },
  where n children=0{%
    lbox,
    no edge,
  }{%
    rbox,
  }
  [Some Text, name=Start, l sep+=5pt
    [Text Text, name=Block1
      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
      ]
    ]
    [Text, name=Block2
      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
      ]
    ]
    [Text Text Text, name=Block3
      [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
      ]
    ]
  ]
\end{forest}
\end{document}
cfr
  • 198,882
  • This is exactly what I wanted. Equal space between texts below the nodes. – Mithun Aug 28 '16 at 22:42
  • @Mithun I'm happy to have answered your question without your needing to ask it! – cfr Aug 28 '16 at 22:46
  • 1
    Many thanks, actually, I asked this question (see the link in the above question) Then, Diaa made a separate question with clear details. Anyway, from now, I will use TikZ for my work. Earlier I used VISIO and Inkscape. – Mithun Aug 28 '16 at 22:53
  • 1
    I've posted the bare bones of this answer there as it possibly addresses your question better than this one. I wonder if I should delete this one and move everything there. I thought it answered this one, though. But I don't like duplicating answers. (If only because it looks like 'cheating'. But also because it is more annoying if stuff needs updating!) – cfr Aug 28 '16 at 23:06
  • @cfr Whenever you answer a TikZ question, you answer it as if you are writing a PhD thesis :)) I appreciate the minor details you put in the answer which I will address back and forth later on. – Diaa Aug 29 '16 at 03:06
  • @DiaaAbidou You mean I explain stuff? Sometimes ... ;) – cfr Aug 29 '16 at 03:59
  • @cfr I mean a lot, which puts a happy ending to any awful question :)) – Diaa Aug 29 '16 at 04:08
  • @cfr If you don't mind, I have one minor follow-up question about specifying different children styles based on their levels. Can I ask it here by updating my question? or better ask a new one linked to this question? – Diaa Aug 29 '16 at 04:08
  • @cfr One more request, how can we manage the gap between rbox and lbox? – Mithun Aug 29 '16 at 10:27
  • @Mithun If you take a look at the forest doc, you will find that the gap between the parent and its children is controlled by this l sep parameter. So, @cfr incremented this parameter in the root node by 5 pts to increase the gap between it and its children. Same applies to other parent nodes that have texts of Text, Text Text and Text Text Text. I hope @cfr can confirm my answer is correct :) However, I don't know how to globally set this parameter instead of retyping it for every parent. – Diaa Aug 29 '16 at 11:32
  • @Mithun I think I figured it out :) if you want to set the separation globally for all children, type for children={l sep=20pt}, in the forest environment preamble, for example, beside forked edges. Don't forget the comma after the curly braces if it is not the last forest preamble option you set. – Diaa Aug 29 '16 at 11:47
  • @DiaaAbidou Thanks for the effort. Anyway, I want to reduce the gap between lbox and rbox, i.e, [Text, name=Block2 and [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1. Same for all spaces betweenlbox and rbox No global change. Another point, for children={l sep=-5pt}, does not reduce the space. – Mithun Aug 29 '16 at 12:03
  • @Mithun that's beyond my knowledge. I think cfr can help you with this stuff :) – Diaa Aug 29 '16 at 12:08
  • @Mithun Please see edit in my answer to your earlier question. – cfr Aug 29 '16 at 12:54
  • @DiaaAbidou I think it would be better to ask a new question to avoid invalidating Zarko's answer to this one ;). – cfr Aug 29 '16 at 12:55
  • @cfr Can we reduce the vertical space between Text and [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ? – Mithun Aug 29 '16 at 12:58
  • @Mithun That's what my edit shows. Just check my answer to your earlier question. – cfr Aug 29 '16 at 13:04
  • @cfr I asked a new question, and I would be grateful if you could consider it. – Diaa Aug 29 '16 at 13:36
8

The asymmetry you can remove on many ways:

  • define the same text width for rboxes, for example.:

    rbox/.style = {draw=blue!80!black, fill=blue!20, rounded corners, inner sep=2mm, text width=(\textwidth-2*\gap)/3,},

  • use grid for nodes placement without defining text width of rbox, for example:

    \begin{tikzpicture}[ node distance = 18mm and \textwidth/3, on grid,

  • etc

An example, which consider the first option with smaller text width than has lbox and centered text. Also in lbox add align=justyfy (which can cause ugly looks of text) or align=center (depends on what you more prefer). Result can be:

enter image description here

or

enter image description here

if in some rbox node in second level appear two (or more) line text.

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,calc}

\usepackage{showframe}

\begin{document}
\pagestyle{empty}
\def\gap{10mm}
\begin{figure}[htb]
    \centering
    \begin{tikzpicture}[
node distance = 12mm and (\textwidth-9*\gap)/3,
%                on grid,
         font = \sffamily,
  line/.style = {draw, -Latex},
  rbox/.style = {draw=blue!80!black, fill=blue!20,
                 rounded corners, inner sep=2mm,
                 text width=(\textwidth-4*\gap)/3, align=center},
  lbox/.style = {draw=black, text width=(\textwidth-2*\gap)/3, 
                 align=justify, node distance = 3mm}
                        ]
\node (Start)   [rbox] {Some Text};
\node (Block1)  [rbox,below  left=of Start] {Text Text};
\node (Block2)  [rbox,below=of Start]       {Text};
\node (Block3)  [rbox,below right=of Start] {Text Text Text};
\node [lbox,below=of Block1] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block2] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block3] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\path [line] (Start) -- coordinate (a) (Block2);
\path [line] (a) -| (Block1);
\path [line] (a) -| (Block3);
    \end{tikzpicture}
\caption{my figure}
    \label{fig-1}
\end{figure}
\end{document}

Considering second option with combination of the first one, you can obtain (this time with centered text in lbox nodes):

enter image description here

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,calc}

\usepackage{showframe}

\begin{document}
\pagestyle{empty}
\def\gap{10mm}
\begin{figure}
    \centering
    \begin{tikzpicture}[
node distance = 18mm and \textwidth/3,
                on grid,
         font = \sffamily,
  line/.style = {draw, -Latex},
  rbox/.style = {draw=blue!80!black, fill=blue!20,
                 rounded corners, inner sep=2mm,
                 text width=(\textwidth-6*\gap)/3, align=center},
  lbox/.style = {draw=black, text width=(\textwidth-2*\gap)/3, 
                 align=center, node distance = 12mm}
                        ]
\node (Start)   [rbox] {Some Text};
\node (Block1)  [rbox,below  left=of Start] {Text Text};
\node (Block2)  [rbox,below=of Start]       {Text};
\node (Block3)  [rbox,below right=of Start] {Text Text Text};
\node [lbox,below=of Block1] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block2] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\node [lbox,below=of Block3] {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1};
\path [line] (Start) -- coordinate (a) (Block2);
\path [line] (a) -| (Block1);
\path [line] (a) -| (Block3);
    \end{tikzpicture}
\caption{my figure}
    \label{fig-1}
\end{figure}
\end{document}
Zarko
  • 296,517