有没有一种巧妙的方法可以画出围绕树的欧拉路径?我目前的解决方案很笨拙……
\documentclass[aspectratio=169]{beamer}
\usepackage[utf8]{inputenc}
\usetheme{moloch}
\usepackage{tikz}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{frame}
\begin{forest}
[-
[$\div$, tikz+={
\draw [-Latex, mLightBrown, thick, rounded corners]
(-.5,0) to (-1.6,-1)
to (-2.5,-2.3)
to (-3.1,-4.5)
to (-3.1,-4.9)
to (-2.5,-4.9)
to (-2.3,-4)
to (-2.1,-4.9)
to (-1.8,-4.9)
to (-1.8,-4.5)
to (-2.2,-3.3)
to (-2,-2.7)
to (-1.8,-3.7)
to (-1.4,-3.7)
to (-1.5,-2.7)
to (-1.8,-2.2)
to (-1.3,-1.3)
to (-.8,-2.2)
to (-1.5,-4.3)
to (-1.5,-4.9)
to (-1.1,-4.9)
to (-.9,-4)
to (-.7,-4.9)
to (-.3,-4.9)
to (-.3,-4.5)
to (-.7,-3.3)
to (-.5,-2.7)
to (-.3,-3.7)
to (0,-3.7)
to (0,-3)
to (-.9,-1.2)
to (0,-.2)
to (.9,-1.2)
to (0.3,-3)
to (0.3,-3.7)
to (.8,-3.7)
to (.9,-2.7)
to (1.1,-3.5)
to (.6,-4.9)
to (1.2,-4.9)
to (1.3,-4)
to (1.4,-4.9)
to (1.8,-4.9)
to (1.1,-2)
to (1.3,-1.4)
to (1.5,-2.5)
to (1.9,-2.5)
to (1.9,-2)
to (1.3,-.7)
to (.5,0);
}
[$\times$
[$+$
[3]
[1]
]
[3]
]
[$+$
[$-$
[9]
[5]
]
[2]
]
]
[$+$
[$\times$
[3]
[$-$
[7]
[4]
]
]
[6]
]
]
\end{forest}
\end{frame}
\end{document}
并得出以下结果:
答案1
这应该适用于任何每个节点都有零个或两个子节点的树。它可以适用于其他情况,但我没有在这里解释这些情况。
我本来希望定义某种step
而不是机械地去做,但我不确定如何做类似于的事情tree
,因为tree
和朋友是根据内部命令定义的。
基本策略是定义一个自定义toks
寄存器,outer walk
,我们用它来积累path
我们想要绘制的部分。我们基本上利用树结构中的规律来绘制树:我们知道forest
进程节点的顺序tree
,因此我们为每个节点向路径 (1) 添加位,为每个叶子添加位 (2)。在后一种情况下,我们确定这是第一个还是第二个子节点,以便在适当的位置将各种附加项添加到路径中。然后,我们添加最后一个节点(我们知道它是根节点),并通过 将的内容提供outer walk
给命令。\path
tikz+
无论如何,结果是,这euler
是一种机械的风格,一点也不聪明,但它确实让你写
\begin{forest}
for tree={
math content,
},
euler,
[-
[\div
[\times
[+
[3]
[1]
]
[3]
]
[+
[-
[9]
[5]
]
[2]
]
]
[+
[\times
[3]
[-
[7]
[4]
]
]
[6]
]
]
\end{forest}
生产
\documentclass[border=10pt,11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
% ateb: https://tex.stackexchange.com/a/712007/ addaswyd o gwestiwn Arne: https://tex.stackexchange.com/q/711954/
\begin{document}
\forestset{
declare toks register={outer walk},
outer walk={},
euler/.style={
before drawing tree={
for tree={
outer walk+/.process={Ow{name}{(##1.west) -- }},
if={>On={n children}{0}}{
outer walk+/.process={Ow{name}{(##1.south west) -- (##1.south east) -- (##1.east) -- }},
if n=2{
Nodewalk={}{while={> On= On> & {n}{2} {level}{1} }{u}}{outer walk+/.process={Ow{name}{(##1.east) -- }}},
if n=1{
outer walk+/.process={Ow{!u.name}{(##1.south) -- }},
}{},
}{
outer walk+/.process={Ow{!u.name}{(##1.south) -- }},
},
} {}
},
outer walk+/.process={Ow{name}{(##1.east)}},
typeout/.register=outer walk,
tikz+={
\path [draw=brown!50!orange,-Latex,rounded corners] \foresteregister{outer walk};
},
},
},
}
\begin{forest}
for tree={
math content,
},
euler,
[-
[\div
[\times
[+
[3]
[1]
]
[3]
]
[+
[-
[9]
[5]
]
[2]
]
]
[+
[\times
[3]
[-
[7]
[4]
]
]
[6]
]
]
\end{forest}
\end{document}
答案2
这不是自动化的,但您可以使用forest
节点内部 id(可通过访问)\forestoption{id}
为每个节点赋予一个name
。然后使用这些名称来绘制更适合节点的路径。
我添加了一个宏\leaf
来绘制叶子的底部并使代码更清晰一些。
\documentclass{article}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\tikzset{euler/.style={thick, orange, rounded corners, -Latex}}
\newcommand{\leaf}[1]{(N-#1.north west)--(N-#1.south west)--(N-#1.south east)--(N-#1.north east)}
\begin{document}
\begin{forest}
for tree={math content, name=N-\forestoption{id}}
[-[\div[\times[+[3][1]][3]][+[-[9][5]][2]]][+[\times[3][-[7][4]]][6]]]
\draw[euler] (N-2.west)--(N-3.west)--(N-4.west)--(N-5.west)--\leaf{6}
--(N-5.south)--\leaf{7}--(N-5.east)--(N-4.south)--\leaf{8}
--(N-4.east)--(N-3.south)--(N-9.west)--(N-10.west)--\leaf{11}
--(N-10.south)--\leaf{12}--(N-10.east)--(N-9.south)--\leaf{13}
--(N-9.east)--(N-3.east)--(N-2.south)--(N-14.west)--(N-15.west)--\leaf{16}
--(N-15.south)--(N-17.west)--\leaf{18}--(N-17.south)--\leaf{19}
--(N-17.east)--(N-15.east)--(N-14.south)--\leaf{20}--(N-14.east)--(N-2.east);
\end{forest}
\end{document}
为了让您能够看到节点的内部编号是如何工作的,这里每个节点的内容都被其内部 ID 替换。
要获取此图像,请for tree
用以下代码替换:
for tree={math content, name=N-\forestoption{id}, delay={content=\forestoption{id}}}