Tikz 适合可变数量的节点

Tikz 适合可变数量的节点

我想在使用 tikz 绘制的一些节点上绘制一个矩形或椭圆形。

如果节点数量固定,我知道如何做到这一点:我只需枚举它们。

我想知道如果我有可变数量的节点,是否有办法做到这一点?

目前我使用这样的东西:

     \node[draw,dotted,fit=(V1) (V2)] {};

但我想放入多个节点,它们的数量由变量给出。有办法解决这个问题吗?理想情况下,我想要像这样的东西,枚举所有节点

\node[draw,dotted,fit=(V1) .. (V\numvis)] {};

由于我的节点的布局,我实际上可以使用:

\node[draw,dotted,fit=(V1) (V\numvis)] {};

但我对更通用的方式感兴趣,这样当我改变布局时就可以有一些东西。

谢谢!

以下是完整的工作代码:

\documentclass[11pt, twoside]{article}
\usepackage{tikz}
\usetikzlibrary{fit,matrix,chains,positioning,decorations.pathreplacing,arrows}


\begin{document}
\begin{figure}[h]
\centering
\def\layersep{2cm} % Gap between visible & hidden units
\def\numvis{8} % Number if visible units
\def\numhid{5} % Number of hidden units
\def\numhidsnd{5}
\def\numhidthrd{4}
\begin{tikzpicture}[
    node distance=\layersep,
    line/.style={shorten >=2pt,shorten <=2pt,>=stealth},
    downarrow/.style={<-,shorten >=2pt,shorten <=2pt,>=stealth, thick,},
    uparrow/.style={->,shorten >=2pt,shorten <=2pt,>=stealth, thick, color=red},
    doublearrow/.style={<->,shorten >=2pt,shorten <=2pt,>=stealth, thick},
    surround/.style={draw=blue, thick, dotted, rounded corners},
    ]
    \tikzstyle{neuron}=[circle,fill=black!25,minimum size=21pt,inner sep=0pt];
    \tikzstyle{visible neuron}=[neuron];
    \tikzstyle{hidden neuron}=[neuron];
    \tikzstyle{annot}=[text width=10em];

    % Iterate over visible units
    \foreach \name / \y in {1,...,\numvis}
        \node[visible neuron] (V\name) at (\y,0) {};

    % Iterate over hidden units
    \foreach \name / \y in {1,...,\numhid}
        % Calculate the appropriate offset for the hidden unit based on the
        % number of visible units.
        \pgfmathparse{\y + (\numvis - \numhid) * 0.5}
        \node[hidden neuron] (H\name) at (\pgfmathresult, \layersep) {};

     \foreach \name / \y in {1,...,\numhidsnd}
        % Calculate the appropriate offset for the hidden unit based on the
        % number of visible units.
        \pgfmathparse{\y + (\numhid - \numhidsnd) * 0.5}
        \node[hidden neuron] (H2\name) at (\pgfmathresult + 1.5, 2 * \layersep) {};

    \foreach \name / \y in {1,...,\numhidthrd}
        % Calculate the appropriate offset for the hidden unit based on the
        % number of visible units.
        \pgfmathparse{\y + (\numhidsnd - \numhidthrd) * 0.5}
        \node[hidden neuron] (H3\name) at (\pgfmathresult + 1.5, 3 * \layersep) {};

      \node[surround, dotted,fit=(V1)  (V\numvis)] (allvis) {};
      \node[surround, fit=(H1)  (H\numhid)] (allhid) {};
      \node[surround, fit=(H21)  (H2\numhidsnd)] (allhid2) {};
      \node[surround, fit=(H31)  (H3\numhidthrd)] (allhid3) {};

      \draw[uparrow] (allvis) -- (allhid);
      \draw[uparrow] (allhid) -- (allhid2);
      \draw[downarrow] (allvis) -- (allhid);
      \draw[downarrow] (allhid) -- (allhid2);

      \draw[doublearrow] (allhid2) -- (allhid3);

      \node[annot,left of=V1, node distance=1.5cm] (hl) {Visible layer};
      \node[annot,  above of=hl] (a) {Hidden layer};
      \node[annot, above of=a] (b){Hidden layer};
      \node[annot, above of=b] (c) {Hidden layer};

\end{tikzpicture}
\caption{Generative versus recognition weights in a DBN.}
\label{fig:rbm}
\end{figure}

\end{document}

答案1

使用foreach语法,您可以轻松描述想要适应的节点:

`\foreach \i in {1,...,5,9,\start,...,\end}

例如。 \start 和 \end 以及其他一些是动态计算的。

在此处输入图片描述

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\begin{document}
\begin{tikzpicture}

\foreach \i in {1,...,25} {%
    \pgfmathsetmacro{\RandX}{(rand*5 + 1) - 2.5} ;
    \pgfmathsetmacro{\RandY}{(rand*5 + 1) - 2.5} ;
    \node (V\i) at (\RandX,\RandY) {\i} ;
    }

\xdef\Loop{}
\foreach \n in {1,2,4} {\xdef\Loop{\Loop(V\n)} }

\node[draw=red,fit=\Loop] {};

\end{tikzpicture}
\end{document}

答案2

您可以将以下auto fit选项应用于每个特殊节点。其参数是要适应的特殊节点集合的名称(以及结果节点的名称)。

在此处输入图片描述

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\makeatletter
% see http://tex.stackexchange.com/a/37713
\def\@nodeundefined#1{\@ifundefined{pgf@sh@ns@#1}}
%
\tikzset{auto fit/.style={append after command={
      \pgfextra{
        \begin{pgfinterruptpath}
          \@nodeundefined{#1}{
            \node[fit=(\tikzlastnode),inner sep=0,line width=0](#1){};
          }{
            \node[fit=(#1)(\tikzlastnode),inner sep=0,line width=0](#1){};
          }
        \end{pgfinterruptpath}
      }}}}
\makeatother

\begin{document}
\begin{tikzpicture}
  \node[font=\small,auto fit=a] (V1) at ({random(0,10)},{random(0,10)}) {1} ;
  \node[font=\small,auto fit=b] (V2) at ({random(0,10)},{random(0,10)}) {2} ;
  \node[font=\small,auto fit=a] (V3) at ({random(0,10)},{random(0,10)}) {3} ;
  \node[font=\small,auto fit=b] (V4) at ({random(0,10)},{random(0,10)}) {4} ;
  \node[font=\small,auto fit=a] (V5) at ({random(0,10)},{random(0,10)}) {5} ;

  \node[draw=blue,fit=(a)]{};
  \node[draw=red,fit=(b)]{};
\end{tikzpicture}
\end{document}

答案3

如果我理解正确的话,那么你想在节点周围绘制一个矩形。你所要做的就是先绘制节点,然后使用图片边界框的角绘制一个矩形。

您还可以将节点分组到范围中,赋予范围名称并通过其名称引用它们。

\documentclass[a4paper]{article}

\usepackage{tikz}

\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
    % Create your nodes first
    \node (n1) at (0, 0) {n1};
    \node (n2) at (5, 3) {n2};
    % ...
    \node (nm) at (-2, -2) {nm};

    % After drawing the nodes, you can enclose
    % them into a rectangle using the bounding
    % box of the already drawn nodes
    \draw (current bounding box.north west) rectangle
        (current bounding box.south east);
\end{tikzpicture}

\begin{tikzpicture}
    % Create your nodes first
    \node (n1) at (0, 0) {n1};
    \node (n2) at (5, 3) {n2};
    % ...
    \node (nm) at (-2, -2) {nm};

    % After drawing the nodes, you can enclose
    % them into a rectangle using the bounding
    % box of the already drawn nodes
    % 
    % Note: this rectangle will leave 0.5cm space
    % between the nodes and the sides of the rectangle
    % (the calc tikz library was loaded for this)
    \draw[color=red] ($(current bounding box.north west) + (-0.5, 0.5)$)
        rectangle ($(current bounding box.south east) + (0.5, -0.5)$);
\end{tikzpicture}

\begin{tikzpicture}
    % Create your nodes inside scopes and give names to the scopes
    \begin{scope}[local bounding box=nodegroup1]
        \node (n1) at (0, 0) {n1};
        \node (n2) at (1, 1) {n2};
        % ...
        \node (nk) at (1, -1) {nk};
    \end{scope}

    \begin{scope}[local bounding box=nodegroup2]
        \node (m1) at (3, 0) {m1};
        \node (m2) at (4, 1) {m2};
        % ...
        \node (ml) at (4, -1) {ml};
    \end{scope}

    % Now you can reference the bounding boxes of the scopes with their names
    \draw[color=blue] ($(nodegroup1.north west) + (-0.5, 0.5)$) rectangle
        ($(nodegroup1.south east) + (0.5, -0.5)$);

    \draw[color=green] ($(nodegroup2.north west) + (-0.5, 0.5)$) rectangle
        ($(nodegroup2.south east) + (0.5, -0.5)$);

\end{tikzpicture}

\end{document}

您的 MWE 使用范围进行分组:

\documentclass[11pt, twoside]{article}
\usepackage{tikz}
\usetikzlibrary{fit, matrix, chains, positioning, decorations.pathreplacing, arrows, calc}


\begin{document}
\begin{figure}[h]
\centering
\def\layersep{2cm} % Gap between visible & hidden units
\def\numvis{8} % Number if visible units
\def\numhid{5} % Number of hidden units
\def\numhidsnd{5}
\def\numhidthrd{4}
\begin{tikzpicture}[
    node distance=\layersep,
    line/.style={shorten >=2pt,shorten <=2pt,>=stealth},
    downarrow/.style={<-,shorten >=2pt,shorten <=2pt,>=stealth, thick,},
    uparrow/.style={->,shorten >=2pt,shorten <=2pt,>=stealth, thick, color=red},
    doublearrow/.style={<->,shorten >=2pt,shorten <=2pt,>=stealth, thick},
    %surround/.style={draw=blue, thick, dotted, rounded corners},
    surround/.style={color=blue, thick, dotted, rounded corners}
    ]
    \tikzstyle{neuron}=[circle,fill=black!25,minimum size=21pt,inner sep=0pt];
    \tikzstyle{visible neuron}=[neuron];
    \tikzstyle{hidden neuron}=[neuron];
    \tikzstyle{annot}=[text width=10em];

    % Iterate over visible units
    \begin{scope}[local bounding box=group1]
        \foreach \name / \y in {1,...,\numvis}
            \node[visible neuron] (V\name) at (\y,0) {};
    \end{scope}

    % Iterate over hidden units
    \begin{scope}[local bounding box=group2]
        \foreach \name / \y in {1,...,\numhid}
            % Calculate the appropriate offset for the hidden unit based on the
            % number of visible units.
            \pgfmathparse{\y + (\numvis - \numhid) * 0.5}
            \node[hidden neuron] (H\name) at (\pgfmathresult, \layersep) {};
    \end{scope}

    \begin{scope}[local bounding box=group3]
        \foreach \name / \y in {1,...,\numhidsnd}
            % Calculate the appropriate offset for the hidden unit based on the
            % number of visible units.
            \pgfmathparse{\y + (\numhid - \numhidsnd) * 0.5}
            \node[hidden neuron] (H2\name) at (\pgfmathresult + 1.5, 2 * \layersep) {};
    \end{scope}

    \begin{scope}[local bounding box=group4]
        \foreach \name / \y in {1,...,\numhidthrd}
            % Calculate the appropriate offset for the hidden unit based on the
            % number of visible units.
            \pgfmathparse{\y + (\numhidsnd - \numhidthrd) * 0.5}
            \node[hidden neuron] (H3\name) at (\pgfmathresult + 1.5, 3 * \layersep) {};
    \end{scope}

    \draw[surround] ($(group1.north west) + (-2.5pt, 2.5pt)$) rectangle
        ($(group1.south east) + (2.5pt, -2.5pt)$);
    \draw[surround] ($(group2.north west) + (-2.5pt, 2.5pt)$) rectangle
        ($(group2.south east) + (2.5pt, -2.5pt)$);
    \draw[surround] ($(group3.north west) + (-2.5pt, 2.5pt)$) rectangle
        ($(group3.south east) + (2.5pt, -2.5pt)$);
    \draw[surround] ($(group4.north west) + (-2.5pt, 2.5pt)$) rectangle
        ($(group4.south east) + (2.5pt, -2.5pt)$);

    \draw[latex-latex] ($(group1.north) + (0, 3.5pt)$) --
        ($(group2.south) + (0, -3.5pt)$);
    \draw[latex-latex] ($(group2.north) + (0, 3.5pt)$) --
        ($(group3.south) + (0, -3.5pt)$);
    \draw[latex-latex] ($(group3.north) + (0, 3.5pt)$) --
        ($(group4.south) + (0, -3.5pt)$);

    \node[annot, left of=V1, node distance=1.5cm] (hl) {Visible layer};
    \node[annot, above of=hl] (a) {Hidden layer};
    \node[annot, above of=a] (b){Hidden layer};
    \node[annot, above of=b] (c) {Hidden layer};
\end{tikzpicture}
\caption{Generative versus recognition weights in a DBN.}
\label{fig:rbm}
\end{figure}

\end{document}

相关内容