Меньшие крыши для леса

Меньшие крыши для леса

У меня есть следующее дерево. Я хочу, чтобы крыши были такой же ширины, как текст, а не шире. Есть ли способ сделать это с помощью 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 xsep0

Редактировать: код изменен для принятия узлов без переводов. Однако, я смог сделать это только с более простым разделителем; ниже ;используется.

Вторая правка: .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}

трассировка и перевод

Связанный контент