我使用 tikz 和以下代码绘制了下面的树。
我的问题是:如何绘制一个大圆圈将所有“A”节点包围起来,一个大圆圈包含所有“B”节点,依此类推(可能使用不同的颜色)?
我希望圆圈有时会相交,这没问题。
代码如下:
\documentclass[landscape]{article}
\usepackage[a4paper,left=1cm,right=1cm,top=2cm,bottom=2cm,bindingoffset=5mm]{geometry}
\usepackage{tikz}
\usepackage{tikz-qtree}
\makeatletter
\let\old@@children\@@children
\def\@@children{\futurelet\my@next\my@@children}
\def\my@@children{%
\ifx\my@next\missing\else
\expandafter\@gobble
\fi
\expandafter\old@@children}
\makeatother
\newcommand{\missing}{ \edge[draw=none]; {} }
%intended usage inside tikzpicture enviornment:
%\Tree [.3 1
% \missing ]
%To producce the same result as code below but
%it gave me an error:
%! Undefined control sequence.
%\missing -> \edge
% [draw=none]; {}
\begin{document}
\begin{tikzpicture}[level distance=30pt,sibling distance=5pt]
\Tree
[.$M$
\edge node[auto=right]{1};
[.$L$
\edge node[auto=right]{1};
[.$K$
\edge[dotted];
[.$J$
\edge node[auto=right]{1};
[.$H$
\edge node[auto=right]{2};
[.$G$
\edge node[auto=right]{1};
[.$G$
\edge node[auto=right]{1};
[.$B,G$
\edge node[auto=right]{1};
[.$B$
\edge node[auto=right]{1};
[.$A,B$
\edge node[auto=right]{1};
[.$A$
\edge node[auto=right]{1};
[.$A$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
\edge node[auto=left]{2};
[.$A$
\edge node[auto=left]{2};
[.$A$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
]
]
\edge node[auto=left]{2};
[.$B$
\edge node[auto=left]{2};
[.$B,C$
\edge node[auto=right]{1};
[.$C$
\edge node[auto=right]{1};
[.$C$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
\edge node[auto=left]{2};
[.$C$
\edge node[auto=left]{2};
[.$C$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
]
]
]
]
\edge node[auto=left]{2};
[.$G$
\edge node[auto=left]{2};
[.$D,G$
\edge node[auto=right]{1};
[.$D$
\edge node[auto=right]{1};
[.$D,E$
\edge node[auto=right]{1};
[.$E$
\edge node[auto=right]{1};
[.$E$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
\edge node[auto=left]{2};
[.$E$
\edge node[auto=left]{2};
[.$E$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
]
]
\edge node[auto=left]{2};
[.$D$
\edge node[auto=left]{2};
[.$D,F$
\edge node[auto=right]{1};
[.$F$
\edge node[auto=right]{1};
[.$F$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
\edge node[auto=left]{2};
[.$F$
\edge node[auto=left]{2};
[.$F$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
]
]
]
]
]
]
]
]
]
]
\end{tikzpicture}
\end{document}
以下是图片:
谢谢您的帮助!
答案1
已编辑问题的答案
这很简单森林。我假设使用你的原始代码,你需要命名你想要圈起来的节点,然后在它们周围画一个圆圈,但我不确定。使用森林,您可以自动将具有特定内容的节点收集到中,register
然后将其用作圆的基础。正如评论中提到的,fit
图书馆是这里的必经之路。
\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{fit}
\begin{document}
\begin{forest}
declare toks register={A nodes},
declare toks register={B nodes},
declare toks register={C nodes},
declare toks register={D nodes},
A nodes={},
B nodes={},
C nodes={},
D nodes={},
for tree={%
math content,
parent anchor=children,
child anchor=parent,
if={level()<2}{%
edge label=1,
}{%
if={(n==1)&&(n("!u")==1)}{%
edge label=1,
}{%
edge label=2,
},
}
},
before typesetting nodes={%
where edge label={1}{%
edge label/.wrap value={node [auto,swap,midway] {#1}},
}{%
edge label/.wrap value={node [auto,midway] {#1}},
},
where content={A}{% pick all nodes with the content "A"
+A nodes/.wrap pgfmath arg={(#1)}{name()},% add to register 'A nodes'
}{%
if content={D}{% pick all nodes with content "D"
+D nodes/.wrap pgfmath arg={(#1)}{name()},% add to register 'D nodes'
}{%
if content={B}{% pick all nodes with content "B"
+B nodes/.wrap pgfmath arg={(#1)}{name()},% add to register 'B nodes'
}{%
if content={C}{% pick all nodes with content "C"
+C nodes/.wrap pgfmath arg={(#1)}{name()},% add to register 'C nodes'
}{}
}
}
},
},
before packing={%
for tree={%
tier/.wrap pgfmath arg={tier #1}{level()},
},
for root={%
tikz+/.wrap pgfmath arg={% draw around all nodes in the 'A nodes' register
\node [draw=red, circle, fit=#1] {};
}{A_nodes},
tikz+/.wrap pgfmath arg={% draw around all nodes in the 'B nodes' register
\node [draw=green, circle, fit=#1] {};
}{B_nodes},
tikz+/.wrap pgfmath arg={% draw around all nodes in the 'C nodes' register
\node [draw=magenta, circle, fit=#1] {};
}{C_nodes},
tikz+/.wrap pgfmath arg={% draw around all nodes in the 'D nodes' register
\node [draw=blue, circle, fit=#1] {};
}{D_nodes},
}
}
[M
[L
[K
[J, edge={dotted}, edge label={}
[H
[G, edge label=2
[G
[{B,G}
[B
[{A,B}
[A
[A
[...]
[...]
]
]
[A
[A
[...]
[...]
]
]
]
]
[B
[{B,C}
[C
[C
[...]
[...]
]
]
[C
[C
[...]
[...]
]
]
]
]
]
]
[G
[{D,G}
[D
[{D,E}
[E
[E
[...]
[...]
]
]
[E
[E
[...]
[...]
]
]
]
]
[D
[{D,F}
[F
[F
[...]
[...]
]
]
[F
[F
[...]
[...]
]
]
]
]
]
]
]
]
]
]
]
]
\end{forest}
\end{document}
请注意,我认为结果并不美观,因为圆圈的大小使树变得混乱。但是,你明确表示你通缉重叠的圆圈,我想不出任何你能想到的不混乱的结果。所以希望这能有所帮助。
我建议shapes.geometric
与形状一起加载fit
并使用ellipse
形状,而不是circle
适合的节点:
要做到这一点,只需改变行
\usetikzlibrary{fit}
到
\usetikzlibrary{fit,shapes.geometric}
并使用以下修改后的代码before packing={}
:
before packing={%
for tree={%
tier/.wrap pgfmath arg={tier #1}{level()},
},
for root={%
tikz+/.wrap pgfmath arg={%
\node [draw=red, ellipse, fit=#1] {};
}{A_nodes},
tikz+/.wrap pgfmath arg={%
\node [draw=green, ellipse, fit=#1] {};
}{B_nodes},
tikz+/.wrap pgfmath arg={%
\node [draw=magenta, ellipse, fit=#1] {};
}{C_nodes},
tikz+/.wrap pgfmath arg={%
\node [draw=blue, ellipse, fit=#1] {};
}{D_nodes},
}
}
原始答案
最初,问题要求“圆圈年代' 而我理解这是想要在各个节点周围画出单独的圆圈。由于代码可能对真正想要这样做的人有用,所以我将其保留在下面。
您可以在树中使用node
带有标准 TikZ 选项的选项circle, draw
,就像在边缘上一样。例如:
...
\edge node[auto=left]{2};
[.\node[circle,draw]{$A$};
\edge node[auto=left]{2};
[.$A$
\edge node[auto=right]{1};
{$...$}
\edge node[auto=left]{2};
{$...$}
]
]
...
并且您可以按照通常的方式添加任何其他您喜欢的 TikZ 选项 - 例如彩色边框、文本或填充。
如果forest
是选项,您可能可以自动检测所有A
节点等,并适当格式化它们。(您可能无法只圈A
出 中的A,B
,但如果您愿意,可以A,B
与A
s 一起圈出 - 或者不。至少,A
我认为只自动圈出 会比它值得的麻烦更多。)
以下示例为所有节点绘制并填充圆圈,内容为A
(红色)、B
(绿色) 或C
(洋红色);为所有节点绘制并填充一个框,内容包含D
(蓝色/青色),并突出显示节点及其所有祖先,包括它们之间绘制的边 (蓝色)。它还在很大程度上自动化了边标签的内容和位置,同时展示了如何在必要时覆盖它。
\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
/tikz/my shape/.style={%
inner color=#1!5,
outer color=#1!20,
draw=#1,
thick,
},
/tikz/my circle/.style={%
my shape=#1,
circle,
},
for tree={%
math content,
parent anchor=children,
child anchor=parent,
if={level()<2}{%
edge label=1,
}{%
if={(n==1)&&(n("!u")==1)}{%
edge label=1,
}{%
edge label=2,
},
}
},
before typesetting nodes={%
where edge label={1}{%
edge label/.wrap value={node [auto,swap,midway] {#1}},
}{%
edge label/.wrap value={node [auto,midway] {#1}},
},
where content={A}{% pick all nodes with the content "A"
my circle=red,
}{%
if={instr("D",content())}{% pick all nodes containing "D"
my shape=blue!50!cyan,
}{%
if content={B}{% pick all nodes with content "B"
my circle=green!75!black,
}{%
if content={C}{% pick all nodes with content "C"
my circle=magenta,
}{}
}
}
},
},
before packing={%
for tree={%
tier/.wrap pgfmath arg={tier #1}{level()},
}
}
[M
[L
[K
[J, edge={dotted}, edge label={}
[H
[G, edge label=2
[G
[{B,G}
[B
[{A,B}
[A
[A
[...]
[...]
]
]
[A
[A
[...]
[...]
]
]
]
]
[B
[{B,C}
[C
[C
[...]
[...]
]
]
[C
[C
[...]
[...]
]
]
]
]
]
]
[G
[{D,G}
[D
[{D,E}
[E
[E
[...]
[...]
]
]
[E
[E
[...]
[...]
]
]
]
]
[D
[{D,F}
[F
[F
[...]
[...]
]
]
[F
[F
[..., for current and ancestors={blue, edge+=blue} % highlight this node and all of its ancestors
]
[...]
]
]
]
]
]
]
]
]
]
]
]
]
\end{forest}
\end{document}