
У меня есть следующее дерево. Я хочу, чтобы крыши были такой же ширины, как текст, а не шире. Есть ли способ сделать это с помощью forest
? В частности, это должна быть ширина верхнего текста. Это важно в случаях, когда перевод намного шире исходного текста. Крыша должна соответствовать исходному тексту, поскольку именно он анализируется, перевод является дополнительным и логически не является частью структуры.
\documentclass{minimal}
\usepackage{forest}
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=bottom,where n children=0{tier=word}{}}},
background tree/.style={for tree={text opacity=0.2,draw opacity=0.2,edge={draw opacity=0.2}}}
}
\begin{document}
\begin{forest}
sn edges
[NP
[Det [das\\the] ]
[N'
[N'
[N [Bild\\picture] ]
[PP [vom Gleimtunnel\\of.the Gleimtunnel,triangle ] ] ]
[PP [im Gropiusbau\\in.the Gropiusbau,triangle ] ] ] ]
\end{forest}
\end{document}
Редактировать:Ниже приведено почти идеальное решение от Sašo. Однако осталась одна проблема. Я определил команду \trace
, которую хочу использовать в деревьях. Если я использую ее с кодом перевода, то получаю следующую ошибку:
! Argument of \@rsbox has an extra }.
<inserted text>
\par
l.45 \end{forest}
?
Вот код:
\documentclass{minimal}
\usepackage{forest}
\forestset{
with translation/.style={
l sep=0,inner xsep=0,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={append={[#1,no edge,l=0,inner xsep=0,inner ysep=0,outer ysep=0,before
computing xy={l-=2pt}]}},
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=top},
where n children=0{tier=word,delay=with translation}{} %,delay=with translation
}
}
\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}
\newcommand{\trace}{\raisebox{0.2ex}{\_}\rule{0cm}{0.7em}}
\begin{document}
\begin{forest}
sn edges
[NP
[Det [eine;a] ]
[N$'$
[A [kluge;smart] ]
[N$'$
[N [\trace ] ] ] ] ]
\end{forest}
\end{document}
\end{forest}
Есть ли способ разрешить такие команды в переведенных деревьях?
решение1
Ниже я использовал трюк, показанный в большом примере в руководстве по лесу (раздел 4.2), чтобы проанализировать содержимое узла. Затем (i) создается дополнительный узел прямо под текстом и заполняется переводом (т. е. всем, что идет после \\
в исходном содержимом) и (ii) перевод удаляется из содержимого. (Этот механизм анализа настроен на применение ко всем листьям дерева.)
Кроме того, для узлов текста и перевода установлено значение tikz
's , чтобы треугольники плотно прилегали к тексту.inner xsep
0
Редактировать: код изменен для принятия узлов без переводов. Однако, я смог сделать это только с более простым разделителем; ниже ;
используется.
Вторая правка: .expanded
обработчики в стилях append translation
и content
были заменены цепочкой .expand once
и .expand twice
для решения дополнительной проблемы, вызванной \trace
(см. отредактированный вопрос OP).
\documentclass{minimal}
\usepackage{forest}
\forestset{
with translation/.style={
l sep=0,inner xsep=0,
append translation/.expand once/.expand twice/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expand once/.expand twice/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={append={[#1,no edge,l=0,inner xsep=0,inner ysep=0,outer ysep=0,before
computing xy={l-=2pt}]}},
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=top},
if n children=0{tier=word,delay=with translation}{} %,delay=with translation
}
}
\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}
\newcommand{\trace}{\raisebox{0.2ex}{\_}\rule{0cm}{0.7em}}
\begin{document}
\begin{forest}
sn edges,
[NP
[Det [das] ]
[N'
[N'
[N [Bild;picture] ]
[PP [vom Gleimtunnel;of.the Gleimtunnel,triangle]] ] ]
[PP [im Gropiusbau;in.the Gropiusbau,triangle ] ] ] ]
\end{forest}
\begin{forest}
sn edges
[NP
[Det [eine;a] ]
[N$'$
[A [kluge;smart] ]
[N$'$
[N [\trace ] ] ] ] ]
\end{forest}
\end{document}
Третья правка: изменено where n children=0
в определении на sn edges
логически более правильное if n children=0
. Хотя это не имеет значения (кроме более медленной работы) в текущей (v1.0.10) версии пакета, версия where n children
выдает неправильный результат в (предстоящей) v1.1 пакета. Это так, потому что v1.1 исправляет ошибку с delay
. В v1.0.x, когда delay
использовался более одного раза на одном узле, первый вызов был забыт. Таким образом, неправильная версия приведенного выше кода работает в v1.0.x, несмотря на то, что delay=with translation
вызывается более одного раза. В v1.1, где вызов delay=with translation
три раза на самом деле вызывает with translation
(позже) три раза, это приводит к лишним пустым узлам.
решение2
Один из вариантов:
\documentclass{article}
\usepackage{forest}
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=bottom,where n children=0{tier=word,inner xsep=0pt,outer sep=0pt}{}}},
background tree/.style={for tree={text opacity=0.2,draw opacity=0.2,edge={draw opacity=0.2}}}
}
\newcommand\HideWd[1]{%
\makebox[0pt]{#1}%
}
\begin{document}
The default behaviour:\par
\begin{forest}
sn edges,
[NP
[Det [das\\the] ]
[N',s sep=20pt
[N',s sep=15pt
[N [Bild\\picture] ]
[PP [vom Gleimtunnel\\ of.the Gleimtunnel,triangle ] ] ]
[PP [im Gropiusbau\\ in.the Gropiusbau,triangle ] ] ] ]
\end{forest}
Hiding the wider text:\par
\begin{forest}
sn edges,
[NP
[Det [das\\the] ]
[N'
[N'
[N [Bild\\picture] ]
[PP [vom Gleimtunnel\\ \HideWd{of.the Gleimtunnel},triangle ] ] ]
[PP [im Gropiusbau\\ \HideWd{in.the Gropiusbau},triangle ] ] ] ]
\end{forest}
Hiding the wider text and correcting the separation:\par
\begin{forest}
sn edges,
[NP
[Det [das\\the] ]
[N',s sep=20pt
[N',s sep=15pt
[N [Bild\\picture] ]
[PP [vom Gleimtunnel\\ \HideWd{of.the Gleimtunnel},triangle ] ] ]
[PP [im Gropiusbau\\ \HideWd{in.the Gropiusbau},triangle ] ] ] ]
\end{forest}
\end{document}
Идея состоит в том, чтобы использовать блок шириной 0 пунктов, чтобы «скрыть» более широкий текст (именно это и \HideWd
делает команда); однако это окажет нежелательный эффект при расчете расстояния между затронутыми элементами (см. второе дерево на изображении), поэтому потребуется ручное вмешательство для предоставления некоторых соответствующих значений s sep
(см. третьи три на изображении).
решение3
Это ответ на отредактированный вопрос, касающийся проблемы объединения кода, указанного вОтвет Сашо Живановичас использованием пользовательского макроса.
Хитрость заключается в том, чтобы заменить использование \trace
в дереве новым стилем, trace
который выполняет макрос и переопределяет применение with translation
к узлам с 0 дочерними элементами.
\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=top}, for tree={where n children=0{tier=word, delay=with translation}{}}},
trace/.style={
replace by={[\trace, delay={}, tier=word]}
},
with translation/.style={
l sep=0,
inner xsep=0,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={
append={
[
#1,
no edge,
l=0,
inner xsep=0,
inner ysep=0,
outer ysep=0,
before computing xy={
l-=2pt
}
]
},
},
}
\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}
\newcommand{\trace}{\raisebox{0.2ex}{\_}\rule{0cm}{0.7em}}
\begin{document}
\begin{forest}
sn edges
[NP
[Det [eine;a] ]
[N$'$
[A [kluge;smart] ]
[N$'$
[N [, trace ] ] ] ] ]
\end{forest}
\end{document}