
Я пытаюсь создать дерево с помощью пакета forest, в котором все листовые узлы находятся на одном уровне.
Однако линии, соединяющие более высокие узлы, проходят через другие узлы. Есть ли способ предотвратить это с помощью этого пакета?
Вот соответствующий фрагмент кода:
\begin{forest}
where n children=0{tier=word}{}
[equation, %for tree={parent anchor=south, child anchor=north}
[VARIABLE[y]]
[{=}]
[expression
[additionOrSubtraction
[multiplicationOrDivision
[atom[VARIABLE[x]]]
]
[{*}]
[atom
[{(}]
[expression
[additionOrSubtraction
[multiplicationOrDivision
[atom[INTEGER[2]]]
]
[{+}]
[multiplicationOrDivision
[atom[INTEGER[3]]]
[{*}]
[atom[VARIABLE[x]]]
]
]
]
[{)}]
]
]
]
]
\end{forest}
А вот и его изображение:
решение1
Сначала я задал пути с использованием ортогональных ребер (описано в edge path
разделе на странице 33 руководства по лесам). Теоретически также можно было бы использовать криволинейные пути, но я думаю, что это заняло бы экспоненциально больше времени.
Далее я увеличил расстояние между детьми, увеличивая s sep
значение (описано на стр. 32 руководства) в каждом конкретном случае. На некоторых уровнях было достаточно 10 мм, но на других было необходимо 20 мм.
Я не был уверен, замените ли вы "multiplicationOrDivision" и подобные строки, возможно, символами или значками (что я бы рекомендовал - или разрешите переносы строк внутри этих строк), поэтому я сделал просто быструю аппроксимацию расстояний. Конечно, для публикации это означает, что их все равно нужно будет точно настроить.
К сожалению, изображение немного увеличилось в размере. Может быть, a sidewaysfigure
или a \resizebox
могли бы подогнать его под нужный вам контекст?
Код:
\documentclass{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}for tree={%
edge path={\noexpand\path[\forestoption{edge}] (!u.parent anchor) -- +(0,-\baselineskip) -| (.child anchor)\forestoption{edge label};}},
where n children=0{tier=word}{}
[equation, s sep=15mm %for tree={parent anchor=south, child anchor=north}
[VARIABLE[y]]
[{=}]
[expression
[additionOrSubtraction, s sep=20mm
[multiplicationOrDivision
[atom[VARIABLE[x]]]
]
[{*}]
[atom, s sep=20mm
[{(}]
[expression
[additionOrSubtraction, s sep=20mm
[multiplicationOrDivision
[atom[INTEGER[2]]]
]
[{+}]
[multiplicationOrDivision, s sep=10mm
[atom[INTEGER[3]]]
[{*}]
[atom[VARIABLE[x]]]
]
]
]
[{)}]
]
]
]
]
\end{forest}
\end{document}
решение2
Если квадратные края приемлемы, то, скорее всего, получится самое аккуратное дерево, как и предполагается.
Однако нет необходимости настраивать это вручную, поскольку текущая версия Forest предоставляет такую возможность forked edges
в своей edges
библиотеке.
\usepackage[edges,linguistics]{forest}
и в преамбуле дерева
forked edges,
Я бы также порекомендовал вариант fit=band
, который избавит от необходимости вручную переставлять вещи или подбирать нужные размеры методом проб и ошибок.
for tree={%
fit=band,
},
Также может помочь настройка inner xsep=0pt
для всех узлов, кроме последнего уровня.
where n children=0{%
tier=word,
}{%
inner xsep=0pt,
},
Я также разделил ...Or...
на многострочные узлы. Не знаю, приемлемо ли это для вас или нет, но это делает диаграмму более управляемой.
Я рекомендую настроить пару макросов: один для сложения/вычитания и один для умножения/деления. Это позволит вам экспериментировать с различными вариантами, просто изменяя общие определения макросов в преамбуле.
Например:
\newcommand*\multordiv{Multiplication\\or\\Division}
\newcommand*\addorsub{Addition\\or\\Subtraction}
и что-нибудь для звездочек - они должны быть в центре, а не наверху? Вы можете рассмотреть возможность использования математического режима для последнего уровня узлов.
\newcommand*\asthere{\textasteriskcentered}
Затем спецификация дерева
[equation
[VARIABLE[y]]
[{=}]
[expression
[\addorsub
[\multordiv
[atom
[VARIABLE
[x]
]
]
]
[\asthere]
[atom
[{(}]
[expression
[\addorsub
[\multordiv
[atom
[INTEGER
[2]
]
]
]
[{+}]
[\multordiv
[atom
[INTEGER
[3]
]
]
[\asthere]
[atom
[VARIABLE
[x]
]
]
]
]
]
[{)}]
]
]
]
]
получается что-то достаточно аккуратное и, если не совсем компактное, то, по крайней мере, гораздо более содержательное.
Полный код:
\documentclass[border=5pt,tikz,multi]{standalone}
\usepackage[edges,linguistics]{forest}
\newcommand*\multordiv{Multiplication\\or\\Division}
\newcommand*\addorsub{Addition\\or\\Subtraction}
\newcommand*\asthere{\textasteriskcentered}
\begin{document}
\begin{forest}
where n children=0{%
tier=word,
}{%
inner xsep=0pt,
},
for tree={%
fit=band,
},
forked edges,
[equation
[VARIABLE[y]]
[{=}]
[expression
[\addorsub
[\multordiv
[atom
[VARIABLE
[x]
]
]
]
[\asthere]
[atom
[{(}]
[expression
[\addorsub
[\multordiv
[atom
[INTEGER
[2]
]
]
]
[{+}]
[\multordiv
[atom
[INTEGER
[3]
]
]
[\asthere]
[atom
[VARIABLE
[x]
]
]
]
]
]
[{)}]
]
]
]
]
\end{forest}
\end{document}