Я попытался использовать решение, приведенное вэта почтадля воздействия на узлы дерева forest
, но решение не работает с автоматическими именами, присвоенными forest
узлам: см. MN(ot)WE ниже.
Есть ли способ это исправить? Если нет, то что делает что-то не так? Проблема с catcode?
\documentclass{article}
\usepackage{tikz}
\usepackage{forest}
\makeatletter
\protected\def\tikz@fig@main#1{%
\expandafter\gdef\csname labeltextof@\tikz@fig@name\endcsname{#1}%
\iftikz@node@is@pic%
\tikz@node@is@picfalse%
\tikz@subpicture@handle{#1}%
\else%
\tikz@@fig@main#1\egroup%
\fi}
\makeatother
\newcommand\labeltextof[1]{\csname labeltextof@#1\endcsname}
\newcommand{\aftercolorof}[2]{% #1 is the color, #2 us the node
\path (#2.center) node[#1] {\labeltextof{#2}};
}
\newcommand{\changetxt}[2]{% #1 the node, #2 the text
\path (#1.center) node[white, fill=white] {\labeltextof{#1}};
\path (#1.center) node[black] {#2};
}
\begin{document}
\section{OK}
\begin{forest}
[
[$A$, name = nA
[$B$, name = nB]
[$C$, name = nC]
]
[$D$, name = nD]
]
\aftercolorof{red}{nA}
\aftercolorof{blue}{nD}
\changetxt{nB}{...}
\changetxt{nC}{?}
\end{forest}
\section{KO}
\begin{forest}
[
[$A$
[$B$]
[$C$]
]
[$D$]
]
\aftercolorof{red}{!1}
\aftercolorof{blue}{!2}
\changetxt{!11}{...}
\changetxt{!12}{?}
\end{forest}
\end{document}
решение1
Такие команды \aftercolorof{red}{!1}
не работают, потому !1
чтонетавтоматическое имя, присвоенное узлу лесом. Эти имена имеют форму node@N
, с N
возрастанием в порядке, в котором лес анализирует скобочное представление узла. Во втором дереве \aftercolorof{red}{node@3}
цвета A
красные.
!1
этоотносительное имя узла: инструкция о том, как достичь некоторого узла, начиная с другого узла. Например, в OP \aftercolorof{red}{!1}
мы начинаем с корневого узла (весь код TikZ, следующий за спецификацией дерева, прикреплен к корневому узлу; и перед ) нет имени узла, !
а затем переходим к его первому потомку, A
.
Итак, чтобы код OP работал так, как задумано, нам нужно создать \aftercolorof
и \changetxt
принять относительные имена узлов. Это проще всего сделать, переопределив \labeltextof
, как показано ниже, но будьте осторожны: код содержит внутреннюю команду леса \forest@nameandgo
. Эта команда изменяет текущий узел леса, поэтому имя (или любой другой параметр) затем можно получить через \forest(e)option
.
\makeatletter
\newcommand\labeltextof[1]{%
\begingroup
\forest@nameandgo{#1}%
\edef\tempnodename{\foresteoption{name}}%
\expandafter\endgroup
\csname labeltextof@\tempnodename\endcsname
}
\makeatother
PS Forest вычисляет положение узлов второго уровня, используя исходный текст ( B
и C
), поэтому «изменение» текста узла на \changetxt
может привести к получению неоптимального дерева.