森林中的径向节点排列

森林中的径向节点排列

我有许多“决策树”类型的图表,我想动态地制作它们(而不是在 Illustrator 或 OmniGraffle 中)。每个图表包含几百个节点。由于节点数量众多,能够使用围绕根节点的 360 度空间(很像思维导图或圆形系统发育树)将特别有用。

我对每个节点的确切位置没有强烈的偏好。因此,LaTeX 的动态布局可能性很大(我不想手动放置数百个节点)。但如果我有时可以“微调”父节点和子节点之间的角度,布局将更有意义,也更美观。

我已经看到有一种方法可以在 TikZ 中做我想做的事情,grow cyclic但我不知道如何将其合并到用 Forest 制作的树中(我是 LaTeX 的新手,但我的理解是 Forest 是基于 TikZ 的,所以我的直觉是这应该是可能的)。

有没有办法在 Forest 中径向布局树木,或者我应该使用其他工具?

作为一个快速(且非常简单)的示例,此代码:

\documentclass[tikz,border=5pt]{standalone}
\usepackage{forest}

\usepackage[LGR,T1]{fontenc}           % these three lines added
\usepackage[utf8]{inputenc}             % so that greek symbols will show
\newcommand{\greek}[1]{\begingroup\fontencoding{LGR}\selectfont#1\endgroup}
                            % write greek like this -->  \greek{α}

\begin{document}
  \begin{forest}
    for tree={
      rectangle,
      rounded corners=0.3em,
      draw,
      minimum width=2.5em,
      l sep+=1.5em,
      s sep+=1em,
      anchor=center,
      grow=0,
     },
    delay={
       ,
    }
[kansas city
    [west
        [los angeles,
            [santa monica]
            [west hollywood]
        ]
        [san francisco,
            [the castro]
        ]
    ]
    [south
        [texas]
        [mexico]
    ]
    [east
        [north carolina]
        [south carolina]
    ]
    [north
        [wisconsin]
        [minnesota]
    ]
]
\end{forest}
\end{document}

生成此图像... 我将尺寸设置为 0,这样图片在这里会更合适

但实际上,为了让观看者更有意义,第一级节点(东、西等)应该围绕根节点呈放射状分布,有点像这样极其粗鲁小样 ... 布局很糟糕……但 360 度

...如果任何给定节点有 8 个以上的子节点,那么使用超过 180 度的弧度来定位这些子节点确实很有意义,在我看来。例如,看看这里的“l”节点有 9 个子节点:

查看有 9 个子节点的节点

我还要指出的是,我知道,calign但使用它将子节点对齐到相距超过 179 度的任何位置都会导致 Package PGF 出现“除以零”错误。任何超过 160 度的节点看起来都很糟糕,因为小角度问题会导致节点连接显著延长,但它确实可以达到 179 度。示例代码片段:

  \begin{forest}
    calign=fixed edge angles,
    calign primary angle=-89,calign secondary angle=89,
    for tree={
      rectangle,

如果需要,我可以切换到 TikZ 或其他东西,只是我在 Forest 上花费了沉没成本,而且它似乎非常适合我的用途。(我能想到的唯一解决方法是将每个图表实际上变成 4 个“分数图表”,其中每个图表覆盖一个象限,然后合并输出。但这似乎是如此糟糕的做法,我想是时候在这里问了。)

答案1

此答案基于如何在一张图片中组合自上而下和自下而上的二叉树?

它绘制了五棵树,分别代表northeastsouth和城市组。每棵树都使用 保存west。每棵树都有定制的生长方向和锚点以适应其设计。例如,树使用,等等。对于向西北生长的树,可能需要使用锚点来获得节点和边的首选排列。然后使用 绘制各个树,并使用库语法定位。每棵树都使用命令连接到根节点。northwest\saveboxnorthgrow'=north, child anchor=south, parent anchor=north\nodepositioningKansas City\draw

结果如下:

在此处输入图片描述

这是 MWE:

% http://tex.stackexchange.com/questions/213770/how-to-combine-a-top-down-and-bottom-up-binary-tree-in-one-picture
\documentclass[12pt,crop=true,border=1cm]{standalone}

\usepackage[edges]{forest}
\usepackage[none]{hyphenat}
\usetikzlibrary{shapes,positioning,arrows.meta,calc}
\tikzset{
    mynodes/.style={inner sep=0pt,draw=none}
}

\forestset{
mytree/.style={
  forked edges,
    for tree={
    draw,
    rounded corners,
    node options={align=center},
    text width=2cm
    }
  }
}

\newsavebox\North
\newsavebox\East
\newsavebox\South
\newsavebox\West
\newsavebox\NorthWest

\savebox\North{\begin{forest}
    mytree,
    for tree={
        child anchor=south,
        parent anchor=north,
        grow'=north,
        anchor=south,
}
    [North
            [Minnesota]
            [Wisconsin]
    ]
   \end{forest}
}
\savebox\East{\begin{forest}
    mytree,
    for tree={
        child anchor=west,
        parent anchor=east,
        grow'=east,
        anchor=west,
}
        [East
          [South Carolina]
          [North Carolina]
        ]
    \end{forest}
}
\savebox\South{\begin{forest}
    mytree,
    for tree={
        child anchor=north,
        parent anchor=south,
        grow'=south,
        anchor=north,
}
        [South
          [Texas]
          [Mexico]
    ]
    \end{forest}
}
\savebox\West{\begin{forest}
    mytree,
    for tree={
        child anchor=east,
        parent anchor=west,
        grow'=west,
        anchor=east,
}
        [West
            [Los Angeles
              [Santa Monica]
              [West Hollywood]
            ]
            [San Francisco
              [The Castro]
            ]
        ]
    \end{forest}
}
\savebox\NorthWest{\begin{forest}
    mytree,
    for tree={
        child anchor=south east,
        parent anchor=north west,
        grow'=north west,
        anchor=east,
}
        [North West
            [Portland]
            [Seattle
              [Redmond]
            ]
        ]
    \end{forest}
}

\begin{document}

\begin{tikzpicture}[node distance=2cm]
    \node (Kansas) at (0,0) [shape=ellipse,x radius=2cm,draw,align=center] {Kansas City};
    \node (North) [mynodes,above=of Kansas] {\usebox\North};
    \node (East)  [mynodes,right=of Kansas] {\usebox\East};
    \node (South) [mynodes,below=of Kansas] {\usebox\South};
    \node (West)  [mynodes,left=of Kansas,xshift=3mm,yshift=-3mm] {\usebox\West};
    \node (NorthWest)  [mynodes,above left=1.85cm and 2.0cm of Kansas] {\usebox\NorthWest};
%
    \draw[thick] (Kansas.north) --  (North.south);
    \draw[thick] (Kansas.east)  --  (East.west);
    \draw[thick] (Kansas.south) --  (South.north);
    \draw[thick] (Kansas.west)  -- ++(-1.85,0) ;%  (West.east);
    \draw[thick] (Kansas.north west) -- ++(-2.2,1.9) ;%  (NorthWest.south east);
\end{tikzpicture}

\end{document}

答案2

从概念上来说非常类似于罗斯的精彩回答但我不使用保存箱Ulrike Fischers 子节点技巧。这允许连接节点而不是保存箱。仍然需要进行一些手动调整。编辑grow用“北卡罗来纳”替换“s” grow',使得“北卡罗来纳”位于“南卡罗来纳”以北,并且添加了 makeboxes 以节省一些空间。

\documentclass[border=5pt]{standalone}
\usepackage{forest}
\usetikzlibrary{tikzmark} % subnode trick from https://tex.stackexchange.com/a/393656/121799
\usepackage[LGR,T1]{fontenc}           % these three lines added
\usepackage[utf8]{inputenc}             % so that greek symbols will show
\begin{document}
\forestset{universal/.style={rounded corners=0.3em,
      draw,rectangle,
      minimum width=2.5em,
      l sep+=1.5em,
      s sep+=1em,
      anchor=center,}
}
$
\begin{array}{ccc}
&\makebox[3.5cm][c]{\begin{forest}
for tree={
      universal,
      grow'=north
     },
    [\subnode{north}{north}
        [wisconsin]
        [minnesota]
    ]
\end{forest}} & \\
\vcenter{\hbox{\begin{forest}
for tree={
      universal,
      grow'=west
     },
    [\subnode{west}{west}
        [los angeles,
            [santa monica]
            [west hollywood]
        ]
        [san francisco,
            [the castro]
        ]
    ]
\end{forest}}}   
& 
\vcenter{\hbox{\begin{forest}
for tree={
      universal,
      grow'=0
     },
[\subnode{kansas}{kansas city}   
]
\end{forest}}} &
\vcenter{\hbox{\begin{forest}
for tree={
      universal,
      grow'=east
     },
    [\subnode{east}{east}
        [north carolina]
        [south carolina]
    ]
\end{forest}}} \\
&
\makebox[3em][c]{\begin{forest}
for tree={
      universal,
      grow'=south
     },
    [\subnode{south}{south}
        [texas]
        [mexico]
    ]
\end{forest}}
 &
\end{array}$
\begin{tikzpicture}[remember picture,overlay]
\draw (kansas) -- (north);
\draw (kansas) -- (west);
\draw (kansas) -- (south);
\draw (kansas) -- (east);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容