创建更厚的 Tikz 思维导图连接器

创建更厚的 Tikz 思维导图连接器

我在 Windows 7 机器上运行 MiKTeX 2.9。我的pdflatex编译日志列出了:

pgf 2008/01/15 v2.10 (rcs-revision 1.12)

我正在使用 TikZ 的mindmap库来绘制一些图形,我非常喜欢输出。

我正在尝试调整两个节点之间连接器的圆形连接栏样式。特别是,我想更改某一层级(但不更改其他层级)节点之间连接栏的粗细。

  • 第一张图片显示了整个示例思维导图(根据下面的工作示例构建)

    第一张图片

  • 第二幅图显示了思维导图库默认样式创建的普通连接器

    第二张图片

  • 第三幅图是我想要创建的效果的模型。

    第三张图片


pgf我已阅读该库手册(版本 2.10)中的文档mindmap,并尝试使用装饰选项(例如decoration={start radius=1cm,end radius=.5cm,amplitude=2mm,angle=30})覆盖圆形连接栏的设置,但无论我为振幅设置指定什么值,输出都没有变化。角度和起始/结束半径的更改确实会影响连接器的第一部分和最后一部分,但中间的矩形永远不会改变宽度。

我已经通过以下方式取得了成功(在实现改变的意义上):

  • 将装饰选项放在节点的子节点之前(从而影响所有子节点和孙节点),例如\node [root concept] {Team\\Foo}[decoration={angle=45}]

  • 在两个命名节点之间明确指定\path (node1) to[circle connection bar] (node2);(不理想,因为明确绘制连接首先消除了使用思维导图库的巨大好处)

  • 并作为样式的一部分every circle connection bar(在 tikzpicture 或范围内指定)

我不想明确指定起始和结束半径,因为mindmap库通常会自动计算这些半径,并且我希望能够更改节点大小并调整连接栏而无需任何人工干预(只是使用比正常情况更粗的线条)。


我的问题归结为以下几点:

  • 我如何改变连接杆的幅度/厚度(也许这还需要明确设置角度)?

  • 如何将此修改仅应用于一个级别的连接?我可以在任何级别设置修改并影响以下所有级别,但我是否可以将修改限制为仅一个级别,或者将连接栏样式重置为较低级别的默认值(即在明确设置后decoration={...},如何撤消该操作)?


工作示例:

\documentclass[tikz, preview=true, border=2mm]{standalone}

\renewcommand*\familydefault{\sfdefault}

\usepackage{tikz}
\usetikzlibrary{mindmap,trees,shadows}

\begin{document}

\begin{tikzpicture}
[decoration={start radius=1cm, end radius=.5cm,amplitude=3mm,angle=30}]

% Define experience colors
\colorlet{afcolor}{blue!50}
\colorlet{mdcolor}{red!75}
\colorlet{nmndcolor}{orange!80}
\colorlet{nmescolor}{teal!70!green}
\colorlet{citscolor}{violet!75}

\begin{scope}[mindmap,
every node/.style={concept, circular drop shadow, minimum size=0pt,execute at begin node=\hskip0pt, font=\bfseries},
root concept/.append style={
    concept color=black, fill=white, line width=1.5ex, text=black, font=\huge\scshape\bfseries,},
level 1 concept/.append style={font=\bfseries},
text=white,
partner/.style={concept color=blue!80!black},
air force/.style={concept color=afcolor},
metadata/.style={concept color=mdcolor},
nmnd/.style={concept color=nmndcolor},
nmes/.style={concept color=nmescolor},
cits/.style={concept color=citscolor},
grow cyclic,
level 1/.append style={level distance=6.2cm,sibling angle=45},
level 2/.append style={level distance=3cm,sibling angle=45}]
\node [root concept] (team) {Team\\Foo}[rotate=202.5] % root
    child [partner] { node {Comp 8}
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 1}
        child [metadata] { node {\small Metadata} }
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [cits] { node {\small CITS} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 2}
        child [metadata] { node {\small Metadata} }
    }
    child [partner] { node (comp3) {Comp 3}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [cits] { node (leftmost) {\small CITS} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 4}
        child [air force] { node {\small Air Force} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 5}
        child [metadata] { node {\small Metadata} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 6}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 7}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    };
\end{scope}

\begin{scope}[xshift=-4.5cm, yshift=-10.5cm,every node/.style={align=left,text=black}]
\matrix[row sep=0pt,column sep=1mm, align=left, nodes={align=left, anchor=west}] {
    \fill [afcolor] (0,.25ex) circle (1ex); & \node{Air Force Experience};\\
    \fill [mdcolor] (0,.25ex) circle (1ex); & \node{Metadata Environments Development Experience};\\
    \fill [nmndcolor] (0,.25ex) circle (1ex); & \node{Network Management and Network Defense Experience};\\
    \fill [nmescolor] (0,.25ex) circle (1ex); & \node{Network Management and Enterprise Services Experience};\\
    \fill [citscolor] (0,.25ex) circle (1ex); & \node{CITS Information Transport Systems Experience};\\
    };
\end{scope}
\end{tikzpicture}

\end{document}

答案1

这是一个复杂的问题,不幸的是,它的解决方案也很复杂。让我们继续。

  1. 为什么amplitude设置无效。此设置仅用于使用样式的“手动”连接simple connection bar,在这种情况下,您还必须指定初始和最终半径(请参阅手册第 385 页)。当您将样式mindmap用于整个树时,to path将安装一个特殊功能,它会自动计算初始和最终半径以及振幅。您只能指定角度。

    这个问题的解决方案是编写一个代码变体来计算半径和振幅,使它们返回更大的值。但随后我们必须以某种方式“安装”此代码,以便样式mindmap使用它。

  2. 如果我们修改安装的代码to path,则更改将影响所有思维导图,因此我们将获得“粗”连接。即使我们to path仅为第一级安装新的,其效果也是全局的,因为它也适用于安装该级别的所有子级。因此,我们需要为第一级安装代码,并为后续级别卸载它。

  3. 为了获得从父颜色逐渐变为子颜色的阴影连接,tikz 使用了一种特殊的技巧。当你设置一个时concept color,库会设置该(子)节点的颜色,并且安装代码以使用样式从其父节点绘制路径circle connection bar switch color。此样式需要一个参数,即子节点的颜色。如果我们想安装一个新的代码以将连接绘制得更粗,我们必须在此时安装它。因此,这并不取决于级别,而是取决于密钥的使用,concept color这可能发生在任何级别。

为了解决上述所有问题,我设计了一个解决方案。虽然它看起来丑陋又笨重,但它确实有效,而且这是我能做的最好的事情。它就是:

1. 新的宏来计算半径和振幅,从而产生更大的结果

我从 中获取代码tikzlibrarymindmap.code.tex,编写了以下宏,其名称以 结尾,@b以区别于原始宏。除了数字 和 之外,代码完全相同,而数字1.6.35最初是1.0.175。新值有些随意。您可以使用其他值来获得最喜欢的外观。

\def\tikz@compute@circle@radii@b{%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{center}}}%
  \pgf@xa=\pgf@x%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{west}}}%
  \advance\pgf@xa by-\pgf@x%
  \pgf@xa=1.6\pgf@xa\relax%  <<<-----  here
  \pgfkeys{/pgf/decoration/start radius/.expanded=\the\pgf@xa}%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{center}}}%
  \pgf@xa=\pgf@x%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{west}}}%
  \advance\pgf@xa by-\pgf@x%
  \pgf@xa=1.6\pgf@xa\relax%  <<<-----  and here
  \pgfkeys{/pgf/decoration/end radius/.expanded=\the\pgf@xa}%
}

\def\tikz@compute@segmentamplitude@b{%
  \pgf@x=\pgfkeysvalueof{/pgf/decoration/start radius}\relax%
  \ifdim\pgf@x>\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
    \pgf@x=\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
  \fi%
  \pgf@x=.35\pgf@x\relax%   <<<----- here
  \edef\pgfdecorationsegmentamplitude{\the\pgf@x}%
}

2. 新样式将“安装”和“卸载”上述宏作为边计算的一部分。

我定义了以下两种样式,用于代替。对于必须通过粗条与父级连接的子级,以及通过标准厚度条与父级连接的子级concept color,您必须使用 。在内部,这些样式重新定义了用于计算半径和振幅并建立连接的宏。它们基于中定义的样式。thick bar concept colorstandard bar concept colortoconcept colortikzlibrarymindmap.code.tex

\tikzoption{thick bar concept color}{%
  \let\tikz@old@concept@color=\tikz@concept@color%
  \let\tikz@old@compute@circle@radii=\tikz@compute@circle@radii%
  \let\tikz@compute@circle@radii=\tikz@compute@circle@radii@b%
  \let\tikz@old@compute@segmentamplitude=\tikz@compute@segmentamplitude%
  \let\tikz@compute@segmentamplitude=\tikz@compute@segmentamplitude@b%
  \def\tikz@edge@to@parent@path{
    (\tikzparentnode)
    to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
    (\tikzchildnode)}
  \def\tikz@concept@color{#1}%
}
 \tikzoption{standard bar concept color}{%
   \let\tikz@old@concept@color=\tikz@concept@color%
   \let\tikz@compute@circle@radii=\tikz@old@compute@circle@radii%
   \let\tikz@compute@segmentamplitude=\tikz@old@compute@segmentamplitude%
   \def\tikz@edge@to@parent@path{
     (\tikzparentnode)
     to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
     (\tikzchildnode)}
   \def\tikz@concept@color{#1}%
}

3. 在思维导图中使用

使用上述设置,您必须在思维导图中thick bar concept color对第一级的所有节点使用,standard bar concept color对其余级别使用。对于您来说这很容易,因为您已经为不同类型的节点定义了特定的样式,因此您只需要:

[...]
partner/.style={thick bar concept color=blue!80!black},
air force/.style={standard bar concept color=afcolor},
metadata/.style={standard bar concept color=mdcolor},
nmnd/.style={standard bar concept color=nmndcolor},
nmes/.style={standard bar concept color=nmescolor},
cits/.style={standard bar concept color=citscolor},
[...]

4. 现在大家一起

这是完整的代码和结果:

\documentclass[tikz, preview=true, border=2mm]{standalone}

\renewcommand*\familydefault{\sfdefault}

\usepackage{tikz}
\usetikzlibrary{mindmap,trees,shadows}

\begin{document}
\makeatletter
\def\tikz@compute@circle@radii@b{%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{center}}}%
  \pgf@xa=\pgf@x%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{west}}}%
  \advance\pgf@xa by-\pgf@x%
  \pgf@xa=1.6\pgf@xa\relax%
  \pgfkeys{/pgf/decoration/start radius/.expanded=\the\pgf@xa}%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{center}}}%
  \pgf@xa=\pgf@x%
  \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{west}}}%
  \advance\pgf@xa by-\pgf@x%
  \pgf@xa=1.6\pgf@xa\relax%
  \pgfkeys{/pgf/decoration/end radius/.expanded=\the\pgf@xa}%
}

\def\tikz@compute@segmentamplitude@b{%
  \pgf@x=\pgfkeysvalueof{/pgf/decoration/start radius}\relax%
  \ifdim\pgf@x>\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
    \pgf@x=\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
  \fi%
  \pgf@x=.35\pgf@x\relax%
  \edef\pgfdecorationsegmentamplitude{\the\pgf@x}%
}
\tikzoption{thick bar concept color}{%
  \let\tikz@old@concept@color=\tikz@concept@color%
  \let\tikz@old@compute@circle@radii=\tikz@compute@circle@radii%
  \let\tikz@compute@circle@radii=\tikz@compute@circle@radii@b%
  \let\tikz@old@compute@segmentamplitude=\tikz@compute@segmentamplitude%
  \let\tikz@compute@segmentamplitude=\tikz@compute@segmentamplitude@b%
  \def\tikz@edge@to@parent@path{
    (\tikzparentnode)
    to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
    (\tikzchildnode)}
  \def\tikz@concept@color{#1}%
}
 \tikzoption{standard bar concept color}{%
   \let\tikz@old@concept@color=\tikz@concept@color%
   \let\tikz@compute@circle@radii=\tikz@old@compute@circle@radii%
   \let\tikz@compute@segmentamplitude=\tikz@old@compute@segmentamplitude%
   \def\tikz@edge@to@parent@path{
     (\tikzparentnode)
     to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
     (\tikzchildnode)}
   \def\tikz@concept@color{#1}%
}

\makeatother

\begin{tikzpicture}

% Define experience colors
\colorlet{afcolor}{blue!50}
\colorlet{mdcolor}{red!75}
\colorlet{nmndcolor}{orange!80}
\colorlet{nmescolor}{teal!70!green}
\colorlet{citscolor}{violet!75}

\begin{scope}[mindmap,
every node/.style={concept, circular drop shadow, minimum size=0pt,execute at begin node=\hskip0pt, font=\bfseries},
root concept/.append style={
    concept color=black, fill=white, line width=1.5ex, text=black, font=\huge\scshape\bfseries,},
level 1 concept/.append style={font=\bfseries},
text=white,
partner/.style={thick bar concept color=blue!80!black},
air force/.style={standard bar concept color=afcolor},
metadata/.style={standard bar concept color=mdcolor},
nmnd/.style={standard bar concept color=nmndcolor},
nmes/.style={standard bar concept color=nmescolor},
cits/.style={standard bar concept color=citscolor},
grow cyclic,
level 1/.append style={level distance=6.2cm,sibling angle=45},
level 2/.append style={level distance=3cm,sibling angle=45},
]
\node [root concept] (team) {Team\\Foo}[rotate=202.5] % root
    child [partner] { node {Comp 8}
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 1}
        child [metadata] { node {\small Metadata} }
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [cits] { node {\small CITS} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 2}
        child [metadata] { node {\small Metadata} }
    }
    child [partner] { node (comp3) {Comp 3}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [cits] { node (leftmost) {\small CITS} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 4}
        child [air force] { node {\small Air Force} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 5}
        child [metadata] { node {\small Metadata} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 6}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    }
    child [partner] { node {Comp 7}
        child [air force] { node {\small Air Force} }
        child [nmnd] { node {\small NM/ND} }
        child [nmes] { node {\small NM/ES} }
    };
\end{scope}

\begin{scope}[xshift=-4.5cm, yshift=-10.5cm,every node/.style={text=black}]
\matrix[row sep=0pt,column sep=1mm, nodes={anchor=west}] {
    \fill [afcolor] (0,.25ex) circle (1ex); & \node{Air Force Experience};\\
    \fill [mdcolor] (0,.25ex) circle (1ex); & \node{Metadata Environments Development Experience};\\
    \fill [nmndcolor] (0,.25ex) circle (1ex); & \node{Network Management and Network Defense Experience};\\
    \fill [nmescolor] (0,.25ex) circle (1ex); & \node{Network Management and Enterprise Services Experience};\\
    \fill [citscolor] (0,.25ex) circle (1ex); & \node{CITS Information Transport Systems Experience};\\
    };
\end{scope}
\end{tikzpicture}

\end{document}

结果

5. 提醒

以上所有内容都是丑陋的黑客行为,并修改了 tikz 内部使用的宏,因此它可能会与库的较新版本发生冲突。我的代码是使用 Texlive 2012 附带的版本(显然是v 1.9 2009/11/12文件tikzlibrarymindmap.code.tex)测试的。

相关内容