围绕森林树的欧拉行走

围绕森林树的欧拉行走

有没有一种巧妙的方法可以画出围绕树的欧拉路径?我目前的解决方案很笨拙……

\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给命令。\pathtikz+

无论如何,结果是,这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}}}

相关内容