如何使用森林在图表中拥有公共子节点

如何使用森林在图表中拥有公共子节点

我正在尝试绘制下面的图表,但我还没有找到任何解决方案来将“选项 1”和“选项 2”连接到公共子节点“C”。

在此处输入图片描述

我已尽力使用森林包,结果得到以下 MWE:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}

\begin{document}
\begin{forest}
    warn/.append style = {
        % rectangle,
        font = \sffamily\footnotesize\bfseries,
        % rounded corners = 2pt,
        % inner color = hsoorange, 
        % outer color = hsoorange
    },
    box/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = green,
        outer color   = green,
    },
    special/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = orange,
        outer color   = orange,
    },
    for tree = {
        font = \sffamily\footnotesize,
        l sep           = 0.6em,
        s sep           = 0.3em,
        minimum width   = 4.0em,
        line width    = 1pt,
        child anchor  = north,
        parent anchor = south,
        edge path={
            \noexpand\path[color=black, 
                % rounded corners=5pt,
                >={Stealth[length=10pt]}, 
                line width = 1pt, 
                -, 
                \forestoption{edge}
            ]
                (!u.parent anchor) -- +(0,-9pt) -| (.child anchor)\forestoption{edge label};
        },
    },
    forked edges,
    [Title, box
        [Option 1, box
            [A, box
                [, edge=dotted,
                    [cool, warn, edge=dotted]]
            ]
            [B, box
                [, edge=dotted
                    [not cool, warn, edge=dotted]]
            ]
            [C, special]
        ]
        [Option 2, box
            [X, box
                [, edge=dotted
                    [ok!, warn, edge=dotted]]
            ]
            [Y, box
                [1, box]
                [2, box]
                [3, box]
                [4, box]
            ]
            [Z, box]
        ]
    ]
\end{forest}
\end{document}

然而,我没能常见的子节点“C”,并且指向最后一级评论的边是中断而且不连续,看起来不太好看。

在此处输入图片描述

请问,有人可以使用森林、树木或本地 tikz 为我提供解决方案吗?

亲切的问候

答案1

这是对 Alan Munn 的答案的修改,旨在纠正假边缘的轻微错位,并采用略有不同的方法来处理底部的三个节点。

这是错位的特写。请注意,线条没有完全对齐,箭头与 C 的相邻部分接触的地方有些奇怪。

某处未对准?

我没有增加l,而是使用coordinates 将三个节点移至较低级别。我这样做是因为我认为它可以将线周围的间距改善到OK!。此节点的创建方式不同。我们不是将其创建为 X 的子节点,而是将其父节点创建为 Y 的子节点并省略边。

我们使用条件样式来格式化树,在一系列测试的基础上添加coordinate、、dotted和。我们还使用布尔值来让 C 更容易理解edge=line。此布尔选项必须在环境之外声明 - 不能在该环境内声明。也就是说,声明它是可以的,但它不能正常工作,所以没有多大意义。specialboxforest

我还稍微增加了级别之间的距离,以避免箭头看起来被压扁。显然,您可以根据需要进行调整。

% addaswyd o ateb Alun Munn: https://tex.stackexchange.com/a/693202/ i MWE George: https://tex.stackexchange.com/q/693152/ 
\documentclass[border=10pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta}
\tikzset{line/.style={draw,-Stealth}}
\forestset{declare boolean={my special}{0}}% declare a custom boolean option and set it to false by default
\begin{document}
\begin{forest}
  warn/.append style = {
    font = \sffamily\footnotesize\bfseries,
  },
  box/.append style = {
    rectangle,
    font = \sffamily\footnotesize\bfseries,
    draw          = black,
    align         = center,
    inner color   = green,
    outer color   = green,
  },
  special/.append style = {
    rectangle,
    font = \sffamily\footnotesize\bfseries,
    draw          = black,
    align         = center,
    inner color   = orange,
    outer color   = orange,
    child anchor  = 140,% set the anchor specially so we get symmetric points for the two connections from Option 1 and Option 2
    tikz+={% add in a fake edge from the node named 2's parent anchor to this node's 40 anchor
      \draw [every edge, line] (2.parent anchor) -- ++(0pt,-\forestoption{fork sep}) -| (.40);
    }
  },
  for tree = {
    font = \sffamily\footnotesize,
    l sep'           = 0.6em,
    s sep'           = 0.3em,
    minimum width   = 4.0em,
    line width    = 1pt,
    child anchor  = north,
    parent anchor = south,
    tier/.option=level,
    l sep*=2,
  },
  forked edges,
  box,
  before typesetting nodes={%
    for descendants={%
      if={> O_= O_= | {content}{}{!u.content}{}}
      {% if either the node or its parent has no content
        edge=dotted,
        if n children=0 {% if the node is a terminus
          edge=line 
        } {% if it isn't a terminus
          coordinate 
        }
      }{% if both the node and its parent have some conent
        edge=line,
        if={> {O} {my special} }%
        {% if the option 'my special' is set for the node
          special 
        }{% if that option isn't set
          box 
        }
      }
    },
  }
    [Title
      [Option 1
          [A
            [
              [cool, warn]
            ]
          ]
          [B, calign with current edge
              [
                [not cool, warn]
              ]
          ]
          [C, my special
          ]
        ]
        [Option 2, name=2
            [X]
            [Y 
                [1]
                [
                  [ok!, warn]
                ]
                [2]
                [3]
                [4]
            ]
            [Z]
        ]
    ]
\end{forest}
\end{document}

结果

答案2

由于这不再是一棵树,因此需要一些手动干预。基本思想是创建一个没有边的节点,然后手动绘制分支。我使用该ext.paths.ortho库绘制了等效的分叉路径。您的路径代码没有达到您的要求,因此我添加了另一种添加箭头的方法,改编自这里

\documentclass[border=10pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows,ext.paths.ortho}
\tikzset{line/.style={draw,-Stealth}}
\begin{document}
\begin{forest}
    warn/.append style = {
        % rectangle,
        font = \sffamily\footnotesize\bfseries,
        % rounded corners = 2pt,
        % inner color = hsoorange, 
        % outer color = hsoorange
    },
    box/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = green,
        outer color   = green,
    },
    special/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = orange,
        outer color   = orange,
    },

    for tree = {
        font = \sffamily\footnotesize,
        l sep           = 0.6em,
        s sep           = 0.3em,
        minimum width   = 4.0em,
        line width    = 1pt,
        child anchor  = north,
        parent anchor = south,
        edge=line,
  },forked edges,
    [Title, box
        [Option 1, box
            [A, box,tier=A
                    [cool, warn, edge=dotted,l=.75in]
            ]
            [B, box,name=B
                    [not cool, warn, edge=dotted,l=.75in]
            ]
        ]
        [C,special,no edge,tier=A,name=C,
        ]
        [Option 2, box
            [X, box,name=X,
                [ok!, warn, no edge,l=.75in,name=OK]
            ]
            [Y, box
                [1, box]
                [2, box]
                [3, box]
                [4, box]
            ]
            [Z, box]
        ]
    ]
\draw[-Stealth] (B.north) r-ud[ud distance=5.6pt] (C.130);
\draw[-Stealth] (X.north) r-ud[ud distance=5.6pt] (C.50);
\draw[-Stealth,dotted] (X.south) -- (OK.north);
\end{forest}
\end{document}

代码输出

答案3

我不知道forest包,所以我建议一个简单的代码tikz

\documentclass[border=.5cm]{standalone}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
    %   \draw[gray!20] (-10,-4) grid (10,4);
        \filldraw[draw=black,fill=green] (-2,3) rectangle (2,4) node[pos=.5] (t) {\large Title};
        \filldraw[draw=black,fill=green] (-8,1) rectangle (-5,2) node[pos=.5] (o1) {\large Option1};
        \filldraw[draw=black,fill=green] (5,1) rectangle (8,2) node[pos=.5] (o2) {\large Option2};
        \draw[-latex] (0,3)--(0,2.5)--(-6.5,2.5)--(-6.5,2);
        \draw[-latex] (0,3)--(0,2.5)--(6.5,2.5)--(6.5,2);
        \draw (-6.5,1)--(-6.5,.5);
        \draw (-10,.5)--(-2.25,.5);
        \draw (10,.5)--(-1.25,.5);
        \draw[-latex] (-1.25,.5)--(-1.25,0);
        \draw[-latex] (-2.25,.5)--(-2.25,0);
        \draw[-latex] (-6.5,.5)--(-6.5,0);
        \draw[-latex] (-10,.5)--(-10,0);
        \filldraw[draw=black,fill=orange] (-2.75,-1) rectangle (-.75,0) node[pos=.5] () {\large C};
        \filldraw[draw=black,fill=green] (-11,-1) rectangle (-9.,0) node[pos=.5] () {\large A};
        \filldraw[draw=black,fill=green] (-7.5,-1) rectangle (-5.5,0) node[pos=.5] () {\large B};
        \draw (6.5,1)--(6.5,.5);
        \draw[-latex] (10,.5)--(10,0);
        \filldraw[draw=black,fill=green] (2,-1) rectangle (4,0) node[pos=.5] () {\large X};
        \filldraw[draw=black,fill=green] (5.5,-1) rectangle (7.5,0) node[pos=.5] () {\large Y};
        \filldraw[draw=black,fill=green] (9,-1) rectangle (11,0) node[pos=.5] () {\large Z};
        \draw[-latex] (6.5,.5)--(6.5,0);
        \draw[-latex] (3,.5)--(3,0);
        \draw (2,-2)--(7.4,-2);
        \draw (6.5,-1)--(6.5,-2);
        \draw[-latex] (2,-2)--(2,-2.4);
        \filldraw[draw=black,fill=green] (1.4,-3.6) rectangle (2.6,-2.4) node[pos=.5] () {\large 1};
        \draw[-latex] (3.8,-2)--(3.8,-2.4);
        \filldraw[draw=black,fill=green] (3.2,-3.6) rectangle (4.4,-2.4) node[pos=.5] () {\large 2};
        \draw[-latex] (5.6,-2)--(5.6,-2.4);
        \filldraw[draw=black,fill=green] (5,-3.6) rectangle (6.2,-2.4) node[pos=.5] () {\large 3};
        \draw[-latex] (7.4,-2)--(7.4,-2.4);
        \filldraw[draw=black,fill=green] (6.8,-3.6) rectangle (8,-2.4) node[pos=.5] () {\large 4};
        \draw[dashed] (-10,-1)--(-10,-5);
        \draw[gray,line width=3pt] (-10.5,-5)--(-9.5,-5) node[pos=.5,below] () {\bfseries cool};
        \draw[dashed] (-6.5,-1)--(-6.5,-5);
        \draw[gray,line width=3pt] (-7,-5)--(-6,-5) node[pos=.5,below] () {\bfseries not cool};
        \draw[dashed] (3,-1)--(3,-5);
        \draw[gray,line width=3pt] (2.5,-5)--(3.5,-5) node[pos=.5,below] () {\bfseries OK!};
    \end{tikzpicture}
\end{document}

输出:

在此处输入图片描述

相关内容