我想标记 tikz 树的屋顶。我试图像经典边缘一样标记它,但不幸的是它卡在三角形的右边缘。我使用的临时解决方案是设置pos=1
,然后使用below=Xcm
,但我需要手动设置X
参数,这很丑陋。
有没有更好的方法,比如把标签放在三角形高度的 1/3 处?
当我为所有屋顶提供相同的参数时,我得到的结果如下:
以及我的 MWE:
\documentclass{report}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{matrix,chains,positioning,decorations.pathreplacing,arrows}
\usepackage{tikz-qtree}
\usepackage{tikz-qtree-compat}
\begin{document}
\begin{figure}[H]
\centering
\begin{tikzpicture}[labelRoof/.style={pos=1,below=0.3cm}]
\Tree [.$A$ \edge[roof,fill=green] node[labelRoof]{$X$};{
\Tree [.$B$ \edge[roof,fill=red] node[labelRoof]{$X$};{
\Tree [.$C$ \edge[roof,fill=green] node[labelRoof]{$X$}; {~\quad~} ]
\quad
\Tree [.$D$ \edge[roof,fill=green] node[labelRoof]{$X$}; {~\quad~} ]}
]
\quad
\Tree [.$E$ \edge[roof,fill=red] node[labelRoof]{$X$};{
\Tree [.$F$ \edge[roof,fill=green] node[labelRoof]{$X$}; {~\quad~} ]
\quad
\Tree [.$G$ \edge[roof,fill=green] node[labelRoof]{$X$}; {~\quad~} ]}
]} ]
\end{tikzpicture}
\end{figure}
\end{document}
先感谢您。
答案1
另一种方法包括node X
在定义中 插入\roof@edge@down
,并且每次上诉屋顶边缘时都会出现节点
\documentclass{report}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{matrix,chains,positioning,decorations.pathreplacing,arrows}
\usepackage{tikz-qtree}
\usepackage{tikz-qtree-compat}
\makeatletter
\def\roof@edge@down#1#2{(#1.south) -- (#2.north west) --node[anchor=base]{$X$} (#2.north east) -- cycle}
\makeatother
\begin{document}
\begin{figure}[H]
\centering
\begin{tikzpicture}[]
\Tree [.$A$ \edge[roof,fill=green];{
\Tree [.$B$ \edge[roof,fill=red];{
\Tree [.$C$ \edge[roof,fill=green]; {~\quad~} ]
\quad
\Tree [.$D$ \edge[roof,fill=green]; {~\quad~} ]}
]
\quad
\Tree [.$E$ \edge[roof,fill=red];{
\Tree [.$F$ \edge[roof,fill=green]; {~\quad~} ]
\quad
\Tree [.$G$ \edge[roof,fill=green]; {~\quad~} ]}
]} ]
\end{tikzpicture}
\end{figure}
\end{document}
答案2
尝试改进萨利姆·布的答案...由于我不明白的原因,我无法使用calc
tikz 库和 partway 修饰符\roof@edge@down
,但它仍然可以正常工作。下面的代码定义了可用于自定义标签显示方式的新键:
roof label
设置实际标签,默认为空。roof label pos
将标签中心的位置设置在顶部顶点和底部边缘之间的某个位置,默认为距顶部顶点的 2/3 处。roof label fixed distance
将文本底部置于底部边缘上方固定距离处。2pt
除非指定距离,否则使用默认距离,见下文。默认为false
。roof label distance
自定义标签放置的距离。指定某个值将自动设置roof label fixed distance
为true
。
出于多种原因,我个人更喜欢“固定距离”模式,但由于您的问题是将其放置在相对距离,因此默认模式是“文本中心位于三角形高度的 1/3 处”。无论您选择使用哪种模式,都不要忘记roof label
在某个点提供一个值,否则 pgf/tikz 只会写入一个空字符串。
\documentclass{report}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{matrix,chains,positioning,decorations.pathreplacing,arrows}
\usepackage{tikz-qtree}
\usepackage{tikz-qtree-compat}
\makeatletter
\newif\ifRoofLabelFixedDist
\newif\ifTmpFixedDist
\tikzset{%% defining necessary keys with default values
roof label fixed distance/.is if=RoofLabelFixedDist,
@roof label distance/.store in=\myRoofLabelFixedDist,
@roof label distance=2pt,
roof label distance/.style={roof label fixed distance=true, @roof label distance={#1}},
roof label/.store in=\myRoofLabel,
roof label=,
roof label pos/.store in=\myRoofLabelPos,
roof label pos=.66,
}
\def\roof@edge@down#1#2{%
\pgfextra{%% extracting key values for later use
\global\let\tmpLabel\myRoofLabel
\global\let\tmpPos\myRoofLabelPos
\global\let\tmpDist\myRoofLabelFixedDist
\ifRoofLabelFixedDist
\global\TmpFixedDisttrue
\else
\global\TmpFixedDistfalse
\fi
}
%% performing the normal operation?
(#1.south) -- (#2.north west) -- (#2.north east) -- cycle ; %% <- the ";" clears custom keys
\ifTmpFixedDist
%% places the bottom of the text at "\tmpDist" above bottom edge
\path (#2.north) +(0,\tmpDist) node [anchor=base] {\tmpLabel} -- (#1.south)
\else
%% places the center of the text at relative position \tmpPos between top vertex and bottom edge
\path (#1.south) -- (#2.north) node [pos=\tmpPos,anchor=center] {\tmpLabel} -- (#1.south)
\fi
%% Note: the "-- (#1.south)" places pgf back to where it should have been after "(#1.south) -- (#2.north west) -- (#2.north east) -- cycle"
}
\makeatother
\begin{document}
\begin{figure}[H]
\centering
\begin{tikzpicture}[roof label=$X$] %% default value for everyone
\Tree
[.{custom label} \edge[roof,fill=green,roof label={snowflake}] ;
{
\Tree
[.{fixed dist} \edge[roof,fill=red,roof label fixed distance] ;
{
\Tree [.$C$ \edge[roof,fill=green,roof label distance=10pt] ; {~\quad~} ]
\quad
\Tree [.$D$ \edge[roof,fill=green,roof label distance=0pt] ; {~\quad~} ]
}
]
\quad
\Tree
[.{rel pos} \edge[roof,fill=red] ;
{
\Tree [.$F$ \edge[roof,fill=green,roof label pos=0.4] ; {~\quad~} ]
\quad
\Tree [.$G$ \edge[roof,fill=green,roof label pos=0.7] ; {~\quad~} ]
}
]
}
]
\end{tikzpicture}
\end{figure}
\end{document}
如果您需要自定义代码,只需对代码进行注释:\pgfextra{<code>}
这是一种告诉 pgf/tikz 暂停当前路径上的操作、执行其他操作(通常是计算一些值)然后在路径上恢复执行的方法。我用它来绕过 pgf/tikz 在其处理的每个路径之间将其键重置为默认值的事实。这让整个事情变得相当混乱,但我对数据流不够了解,无法在其他地方拦截必要的信息……
答案3
这是 Forest 版本:
\begin{forest}
for tree={
math content,
},
Roofs and roofs,
where level=1{
edge+={fill=red},
}{
edge+={fill=green},
},
[A, roof label=\Gamma
[B, roof label=\Delta
[C, roof label=\Sigma
[
]
]
[D, roof label=\Theta
[
]
]
]
[E, roof label=\Psi
[F, roof label=\Xi
[
]
]
[G, roof label=\Pi
[
]
]
]
]
\end{forest}
Roofs and roofs
是一种在整个树中绘制屋顶的样式。所有边都是标准边或覆盖多个子节点的roof
特殊边。确定级别( ) 和其他地方 ( ) 的节点的颜色。在当前节点中或下方放置标签。Roof
where level=1{...}{...}
fill
1
red
green
roof label=<maths>
$<maths>$
roof
Roof
完整代码:
\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage[linguistics]{forest}
\forestset{
declare keylist={saved edge}{},
Roof/.style={
before typesetting nodes={
delay={
if level=0{
tikz+/.process={OOw2}{edge}{edge label}{
\draw [##1] (!1.parent first)--(.children)--(!l.parent last)--cycle ##2;
},
}{
not ignore edge,
edge/.option=saved edge,
edge path'={
(!1.parent first)--(.children)--(!l.parent last)--cycle
},
},
},
for children={
saved edge/.option=edge,
no edge,
},
},
},
Roofs and roofs/.style={
before typesetting nodes={
where content={}{
content={\smash{\phantom{A}}},
}{},
},
where n children<=1{
roof,
}{
Roof,
},
},
roof label/.style={
if n children=1{
!1.edge label={node [midway,above] {$#1$}},
}{
edge label={node [midway,above] {$#1$}},
}
},
}
\begin{document}
\begin{forest}
for tree={
math content,
},
Roofs and roofs,
where level=1{
edge+={fill=red},
}{
edge+={fill=green},
},
[A, roof label=\Gamma
[B, roof label=\Delta
[C, roof label=\Sigma
[
]
]
[D, roof label=\Theta
[
]
]
]
[E, roof label=\Psi
[F, roof label=\Xi
[
]
]
[G, roof label=\Pi
[
]
]
]
]
\end{forest}
\end{document}