Tikz-tree,标记屋顶

Tikz-tree,标记屋顶

我想标记 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

尝试改进萨利姆·布的答案...由于我不明白的原因,我无法使用calctikz 库和 partway 修饰符\roof@edge@down,但它仍然可以正常工作。下面的代码定义了可用于自定义标签显示方式的新键:

  • roof label设置实际标签,默认为空。
  • roof label pos将标签中心的位置设置在顶部顶点和底部边缘之间的某个位置,默认为距顶部顶点的 2/3 处。
  • roof label fixed distance将文本底部置于底部边缘上方固定距离处。2pt除非指定距离,否则使用默认距离,见下文。默认为false
  • roof label distance自定义标签放置的距离。指定某个值将自动设置roof label fixed distancetrue

出于多种原因,我个人更喜欢“固定距离”模式,但由于您的问题是将其放置在相对距离,因此默认模式是“文本中心位于三角形高度的 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特殊边。确定级别( ) 和其他地方 ( ) 的节点的颜色。在当前节点中或下方放置标签。Roofwhere level=1{...}{...}fill1redgreenroof label=<maths>$<maths>$roofRoof

完整代码:

\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}

相关内容