TikZ:绘制树时“跳过”级别

TikZ:绘制树时“跳过”级别

我感兴趣的是使用 TikZ 绘制有根树,这些树的叶子应该都在同一水平,就像这样:

替代文本

请不要关注花哨的样式和颜色,我只希望所有叶子都处于同一水平。有人知道怎么做吗?我查看了手册和Texample 上的相应部分,但目前为止还没有运气。

更新:在这个问题得到回答后不久,我发现了LaTeX newicktree 包,它允许您以极其简单的方式绘制此类树,只需以系统发育学中人们已经使用的格式指定它们即可。这显然比求助于 TikZ 要简单得多,但还是要感谢所有帮助我的人。

答案1

如果您准备告诉 TikZ 顶部标签的顺序,这里有一个替代方案。这有点笨拙,尤其是它会绘制多条线两次(或更多!)。另外,我相信了你的话,忽略了花哨的样式。

\documentclass{minimal}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[rotate=45]
\begin{scope}[rotate=45]
\node[coordinate] (start) at (0,0) {};
\xdef\pl{start}
\foreach \n/\l in {
  rayfinned fish/rf,
  lungfish/lf,
  salamanders/sa,
  frogs/fr,
  turtles/tt,
  lizards/lz,
  snakes/sn,
  crocodiles/cr,
  birds/bd,
  mammals/mm%
} {
  \node[transform shape,below right] (\l) at (\pl.south west) {\n};
  \xdef\pl{\l}
}
\end{scope}

\foreach \a/\b in {
  rf/mm,
  lf/mm,
  sa/mm,
  sa/fr,
  tt/mm,
  lz/mm,
  lz/sn,
  lz/bd,
  cr/bd%
} {
  \draw (\a.mid west) |- (\b.mid west);
}
\end{tikzpicture}
\end{document}

得出的结果为:

替代文本

工作原理说明

  1. 首先要理解的是旋转。此代码使用特定类型的路径绘制线条,该路径被限制为仅水平和垂直。然而,在期望的结果中,线条是对角线。解决方案:旋转图片,使对角线为内部的“水平”和“垂直”。

  2. 要理解的第二件事是双倍的旋转。外部旋转(在tikzpicture环境上)处理对角线到水平和垂直线的转换。第二次旋转(在第一个上scope)是让节点指向上方。为了正确执行此操作,我们将键添加transform shape到实际节点。这意味着节点相对于该范围之外的所有内容旋转 45 度。

  3. 现在进行节点定位。我们在 (0,0) 处定义起始坐标 ( start)。然后我们循环遍历节点,将设置\n为节点内容\l作为该节点(其标签)的简写。该宏\pl保存以前的节点,在第一次迭代时设置为起始坐标。我们希望节点排列整齐,看起来像一个排列整齐的列表。为了实现这一点,我们将西北当前节点的锚点西南前一个节点的锚点。below right节点上的键表示“使用西北锚点定位此节点”,而(\pl.south west)表示“将其放置在前一个节点的西南锚点”。最后,我们将设置为\pl当前节点的标签,该节点将成为下一次迭代中的下一个节点(请注意\xdef,如果我们使用\edef它,它将是迭代的本地节点,这不是我们想要的)。

  4. 最后,画线。我们循环遍历连接的对,从mid west一个节点的锚点到mid west另一个节点的锚点画一条线。我们首先用“上部”节点指定对,然后画一条先“垂直”然后“水平”的线(记住,在最终渲染中,这些线将旋转到对角线)。使用锚点mid west意味着线条将在基线上方半处结束ex。由于我们的线条定义非常严格,因此有时我们画在另一条线上方的事实应该不会太明显。

答案2

好问题!TikZ 不是为制作这种树而设置的。它假设每个子节点的位置是子节点数量和子节点总数的函数。用每个叶子都有一个子节点来定义树是行不通的,因为当你添加哺乳动物的叶子时,鳍鱼的叶子需要离根更远。

但您可以通过在常规点处创建不可见节点来欺骗它。我认为您的树需要有 10 层深。

或者,您可以使用自定义增长函数进行破解(参见 PGF 2.00 手册第 42 节或 2.10 手册第 53 节):

\begin{tikzpicture}[%
    grow via three points={% 
        one child at (-0.5,1) and two children at (-0.5,1) and (0.5,1)},
    genus/.style={
        rectangle,inner sep=0pt,outer sep=1pt, minimum width=5pt,minimum height=5pt,fill,
        label={[black,anchor=west,rotate around={90:(-2.5pt,0)}
               ]0:#1}},
    ]
\node[coordinate] {} [%
         grow via three points={one child at (0,0) and two children at (-4.5,9) and (0.5,1)},
         very thick,yellow
     ]
     child {node[genus=rayfinned fish] {}}
     child {
         [grow via three points={one child at (0,0) and two children at (-4,8) and (0.5,1)}]     
         child {node[genus=lungfish] {}}
         child {
             [grow via three points={one child at (0,0) and two children at (-3,6) and (1,2)}]      
             child {
                 [grow via three points={one child at (0,0) and two children at (-0.5,1) and (0.5,1)}]
                 child {node[genus=salamanders] {}}
                 child {node[genus=frogs] {}}    
             }
             child[blue] {
                 [grow via three points={one child at (0,0) and two children at (-2.5,5) and (0.5,1)}]
                 child {node[genus=turtles] {}}
                 child {
                     [grow via three points={one child at (0,0) and two children at (-0.5,1) and (2,4)}]
                     child {
                         [grow via three points={one child at (0,0) and two children at (-1,2) and (1,2)}]
                         child {
                             [grow via three points={one child at (0,0) and two children at (-0.5,1) and (0.5,1)}]
                             child {node[genus=lizards] {}}
                             child {node[genus=snakes] {}}
                         }
                         child {
                             [grow via three points={one child at (0,0) and two children at (-0.5,1) and (0.5,1)}]
                             child {node[genus=crocodiles] {}}
                             child {node[genus=birds] {}}
                         }
                     }
                     child {node[genus=mammals] {}}   
                 }
             }       
         }
     }
;
\end{tikzpicture}

使用上面的代码示例的树

这可能应该被清理——我认为你可以在每个方向和尺度上创建一个命名坐标。

答案3

我发现这个答案在官方邮件列表中。据我所知,这是一种与此处提出的方法不同的方法,但至少问题是相同的。尽管如此,我还是可以重现所需的结果。但它可能对某些人有用,所以我想在这里链接它。

还有另一个有用的提示并没有回答这个问题:如果您使用 PStricks,您可以使用命令\skiplevel

相关内容