我想在使用 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}