[Tex/LaTex] TikZ reuse code for building nesting pictures

nestingtikz-pgf

This is not new here. But with the solutions in:

I couldn't put it to work.

Basically what I want is to define a command that will be a picture and can be used inside other picture as a node, similarly how the shape is defined. So that I can reuse the code because each picture has many elements. See the MWE:

\documentclass{standalone}

\usepackage{ellipsis}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{shapes.geometric}

\newcommand{\MUE}[1]{%
\begin{tikzpicture}
\node[draw, shape = rectangle, minimum width=15mm, minimum height=7.5mm] (box) {#1};

\draw ($(box.south west)+(0.25,0)$) circle (4pt);
\draw ($(box.south east)-(0.25,0)$) circle (4pt);
\draw[fill=black] ($(box.south west)+(0.25,0)$) circle (1pt);
\draw[fill=black] ($(box.south east)-(0.25,0)$) circle (1pt);

\draw ($(box.north west)+(0.25,0)$) -- +(0,0.25) node[midway] (ant1) {};
\draw ($(box.north east)-(0.25,0)$) -- +(0,0.25) node[midway] (ant2) {};

\node at ($(ant1)!0.5!(ant2)$) {\dots};

\draw (ant1.north) -- +(135:0.25);
\draw (ant1.north) -- +(45:0.25);
\draw (ant2.north) -- +(135:0.25);
\draw (ant2.north) -- +(45:0.25);
\end{tikzpicture}
}
\newcommand{\MBS}[1]{%
\begin{tikzpicture}
\node[draw, shape = dart, shape border rotate = 90, minimum width = 10mm, minimum height = 10mm] (base) {#1};

\draw[line join = round] (base.110) -- (base.70) -- (base.north west) -- (base.north east) -- cycle;

\draw ($(base.north)+(0.5,0)$) -- +(0,0.25) node[midway] (ant1) {};
\draw ($(base.north)-(0.5,0)$) -- +(0,0.25) node[midway] (ant2) {};
\draw[cap = rect, line join = round] (ant1.south) -- (ant2.south);

\node at ($(ant1)!0.5!(ant2)$) {\dots};

\draw (ant1.north) -- +(135:0.25);
\draw (ant1.north) -- +(45:0.25);
\draw (ant2.north) -- +(135:0.25);
\draw (ant2.north) -- +(45:0.25);
\end{tikzpicture}
}

\begin{document}
\begin{tikzpicture}

\node[draw, shape = circle, fill = yellow!30] at (0,0) (test1) {\MBS{BS}};

\node[draw, shape = circle, fill = blue!30] at (3,3) (test2) {\MUE{UE1}};
\node[draw, shape = circle, fill = blue!30] at (3,-3) (test3) {\MUE{UE2}};

\draw[->] (test1) -- (test2);
\draw[->] (test1) -- (test3);

\end{tikzpicture}
\end{document}

As it can be seen, the antennas in the picture are not correcly placed because I am using draw, shape = circle in the nodes of the second picture. Also, if I add inner sep = 0pt the result is even worst. How can I use such kind of nesting inside TikZ?

enter image description here

Best Answer

Don't use nodes here; neither to mark positions on the path (you can use a coordinate for that) nor to get back to the top point on that line, just use the path you already used there (you are allowed to use a path after node) or just re-calculate the coordinate or use move-tos to there (leave out the -- in your path).

I also provide an antenna insert path style that takes one argument, namely the number of the coordinate, the rest is a mix of relative (+) as well as relative and move-to (++) operators.

The same is valid for the \MBS macro. Here I have opted to draw the dart with an outer sep of zero, so that the anchors lie in the middle of line (which needs to go against with drawing the antenna part (notice the yshift=.8pt which comes from the line width used with the thick style).

I commented the original placement of the \dots and added another way to place the dots, namely with a label (\MUE) and a node on a path (\MBS).
Feel free to not use this.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathreplacing,decorations.markings,shapes.geometric}
\tikzset{antenna/.style={insert path={-- coordinate (ant#1)  ++(0,0.25) -- + (135:0.25) + (0,0) -- +(45:0.25)}}}
\newcommand{\MUE}[1]{%
\begin{tikzpicture}[every node/.append style={rectangle,minimum width=+0pt}]
\node[draw, shape = rectangle, minimum width=15mm, minimum height=7.5mm,label=\dots] (box) {#1};

\draw ([xshift=.25cm] box.south west) circle (4pt)
      ([xshift=-.25cm]box.south east) circle (4pt);
\fill ([xshift=.25cm] box.south west) circle (1pt)
      ([xshift=-.25cm]box.south east) circle (1pt);

\draw ([xshift=.25cm] box.north west) [antenna=1];
\draw ([xshift=-.25cm]box.north east) [antenna=2];

%\node at ($(ant1)!0.5!(ant2)$) {\dots};
\end{tikzpicture}}
\newcommand{\MBS}[1]{%
\begin{tikzpicture}
\node[draw, shape = dart, shape border rotate = 90, minimum width = 10mm, minimum height = 10mm,outer sep=+0pt] (base) {#1};

\draw[line join = bevel] (base.110) -- (base.70) -- (base.north west) -- (base.north east) -- cycle;

\draw[line cap=rect] ([xshift=.5cm,yshift=.8pt] base.north) [antenna=1];
\draw[line cap=rect] ([yshift=.8pt]ant1 |- base.north) -- node[above,shape=rectangle]{\dots} ([xshift=-.5cm,yshift=.8pt]base.north) [antenna=2];

%\node at ($(ant1)!0.5!(ant2)$) {\dots};
\end{tikzpicture}}

\begin{document}
\begin{tikzpicture}

\node[draw, shape = circle, fill = yellow!30] at (0,0) (test1) {\MBS{BS}};

\node[draw, shape = circle, fill = blue!30] at (3,3) (test2) {\MUE{UE1}};
\node[draw, shape = circle, fill = blue!30] at (3,-3) (test3) {\MUE{UE2}};

\draw[->] (test1) -- (test2);
\draw[->] (test1) -- (test3);
\end{tikzpicture}
\end{document}

Output

enter image description here