3

In the following picture, I would like to align the label 1470 = 1400 + 70 as if it was 1470 : see the red arrow. This feature is needed for any node, not only the root one, and an automatic procedure is needed.

enter image description here

Here is the alignment wanted.

enter image description here

Here is the MWE used.

\documentclass[12pt]{article}

\usepackage{forest}

\usepackage[utf8]{inputenc} \usepackage[T1]{fontenc}

\begin{document}

\begin{forest} for tree={math content} [{1470 = 1400 + 70} [7] [210 [7] [30 [3] [10 [2] [5] ] ] ] ] \end{forest}

\end{document}

projetmbc
  • 13,315

2 Answers2

6

Here is how to do that with the help of mathtools.

\documentclass[12pt]{article}
\usepackage[T1]{fontenc}
\usepackage{mathtools}
\usepackage{forest}

\begin{document}

\begin{forest} for tree={math content} [1470 \mathrlap{{}= 1400 + 70} % <--- [7] [210 [7] [30 [3] [10 [2] [5] ] ] ] ] \end{forest} \end{document}

enter image description here

Zarko
  • 296,517
5

While I have used mathtools' \mathrlap before with forest, I believe there is a solution with plain TikZ that also updates the bounding box accordingly.

Adding a label to the right

… of the node so that their baselines are aligned.

This uses inner xsep=0pt which might lead to unlucky padding around the text (depending on the edges):


\documentclass[12pt]{article}
\usepackage{forest}
\forestset{mathrlap/.style={inner xsep=0pt,label={[anchor=text]base east:${}#1$}}}
\begin{document}
\begin{forest}
for tree={math content}
[1470, mathrlap={= 1400 + 70}
[7] [210 [7] [30 [3] [10 [2] [5] ] ] ]]
\end{forest}
\end{document}

Adding a label to the text right

… of the node so that their baselines are aligned and we don't have to change any inner xseps.

With a generic anchor text right that lies at the right border of the text (not the node) at the baseline. This keeps the parent node unchanged.

All[citation needed] (single-part) shapes that come shipped with PGF have their text box placed in the middle of the shape.

Consider the original anchors of the rectangle shape. Remember that the node's coordinate system has its origin at the text anchor. The anchors base, mid and center are at the horizontal center of text box. To get to the text right coordinates we just take double the x value of the base anchor and its y value (which should be 0pt).

enter image description here


Forest's math content puts the contents of the tree's node in \ensuremath. I don't see a good way to hook forest's content format in a label which is why I'm using explicitly $ in the label and mathrlap. (Mathtools' macros also make sure the font sizes are set up correctly depending on where \mathrlap is used which is not happening here.)

\documentclass[12pt]{article}
\usepackage{forest}
\makeatletter
\pgfdeclaregenericanchor{text right}{%
  \pgf@sh@reanchor{#1}{base}%
  \multiply\pgf@x by 2
}
\makeatother
\tikzset{
  mathrlap/.style={label={[anchor=text,       every mathrlap/.try]text right: {${}#1$}}},
  mathllap/.style={label={[anchor=text right, every mathllap/.try]text:       {$#1{}$}}},
  rlap/.style    ={label={[anchor=text,       every rlap/.try]    text right: {#1}}},
  llap/.style    ={label={[anchor=text right, every llap/.try]    text:       {#1}}}}
% forest keys so forest/label gets used
\forestset{/utils/temp/.style={#1/.style={/tikz/#1={##1}}},/utils/temp/.list={mathrlap,mathllap,rlap,llap}}

\begin{document} \begin{forest} for tree={math content} [1470, mathrlap={= 1400 + 70} [7] [210 [7] [30 [3] [10 [2] [5] ] ] ]] \end{forest} \end{document}

An “uncentered” rectangle shape

And here's the shape I was thinking of: uncentered rectangle.
It can be used by loading the ext.shapes.uncenteredrectangle library of my tikz-ext package (needs at least v0.4.1).

The simplest way to use it would be

[{1470 \nodepart{three}= 1400 + 70}, uncentered rectangle]

but since math content doesn't work with multipart shapes, you're going to need to “unmath” the \nodepart macro:

[{1470 $\nodepart{right}$ {}= 1400 + 70}, uncentered rectangle]

which is semantically ridicilous which is why I recommend not using math content on that node:

[{1470 \nodepart{right}$ {}= 1400 + 70$}, uncentered rectangle, plain content]

But as with mathlrap from before, we can just use a math align right key to set the contents of the node without having to think about much.

[,math align right={1470 = 1400 + 70}]

or with the starred version

[{1470 = 1400 + 70}, math align right*]

But forest also allows to test the content for an = and automatically apply the math align right* key then (which is what I have used in the code below).

The way I have set it up, it won't allow for another node with an = to have math align left but I'm sure there's a way to do it anyway with the right combinations of keys and styles.


The shape's definition allows it center anchors (including mid, base, north and south) to be changed on the fly. (anchor=base is used by forest.)

This means we can place the node according to one center but connect edges to it with another center by setting /pgf/uncentered rectangle center to left, text, right or real. The default is text, i.e. the center of the main middle part whose nodepart name is text.

Code (math content)

\documentclass[12pt,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{ext.shapes.uncenteredrectangle}
\forestset{
  auto align right/.style={if in content={=}{math align right*}{}},
  math align left*/.style={math align left/.expanded=\forestov{content}},
  math align right*/.style={math align right/.expanded=\forestov{content}},
  math align/.style={
    shape=uncentered rectangle, uncentered rectangle center=text, % default
    plain content}, % disable math content because of multiple node parts
  math align right/.style args={#1=#2}{math align,content={$#1$\nodepart{right}${}=#2$}},
  math align left/.style args={#1=#2}{math align, content={$#2$\nodepart{left}$#1={}$}}}
\begin{document}
\begin{forest}
    for tree={math content}, delay={for tree=auto align right}
    [{1470 = 1400 + 70}
        [7]
        [{210 = 200 + 10}
            [7]
            [{30 = 30 + 0}
                [3]
                [{10 = 2 \cdot 5}
                    [2]
                    % conflicts with auto align right ☹ 
                    % [{1 + 1 = 2}, math align left*]
                    [5]
                ]
            ]
        ]
    ]
\end{forest}
\end{document}

Code (split at :, w/o output)

\documentclass[12pt,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{ext.shapes.uncenteredrectangle}
\forestset{
  auto split colon/.style={if in content={:}{
    split colon/.expanded=\forestov{content}}{}},
  split colon/.style args={#1:#2}{
    plain content, uncentered rectangle,
    content={#1\nodepart{right}\null#2}}}
\begin{document}
\begin{forest}
  for tree={math content}, delay={for tree=auto split colon}
  [1470 : some text % space before : gets gobbled up
    [7]
    [210 : some other text
      [7]
      [30 : % (nothing in the right side, all spaces get gobbles)
        [3]
        [10 : $2 \cdot 5$
          [2]
          [5]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

Output (math content)

enter image description here

Qrrbrbirlbel
  • 119,821
  • Indeed, I only need the feature for the left nodes, and not for leaves. – projetmbc Oct 15 '22 at 07:25
  • Your code should be more powerful in an automatic context, I will test it soon. Can you explain a little the code of pgfdeclaregenericanchor? – projetmbc Oct 15 '22 at 07:27
  • Great. The code is so easy to fill. – projetmbc Oct 24 '22 at 14:41
  • Is it possible to use also text instead of just = .... by typing for example {341 : some text} to obtain with 321 some text in the output? If it is not clear, I can complete my question. – projetmbc Oct 24 '22 at 17:43
  • 1
    @projetmbc Sure, Just split at : but don't insert it back in. I've added a \null (which is just an empty \hbox{}) so that the space between : and whatever is following doesn't get gobbled. If you have both, i.e. nodes with = and :, you're going to have to nest if in content. If worse comes to worst, you have to add a splitter style to the different nodes when your nodes are very diverse. – Qrrbrbirlbel Oct 24 '22 at 19:00
  • Great! Great! Thanks for all! – projetmbc Oct 24 '22 at 19:32