In my diagram I have a few components I reuse a lot, thus making "macros" in tikz for them. The current code I have is using nested tikzpicture environments and is not exactly working as expected. Do you have any suggestions how to improve this?

I found other questions, but none seem to help me?

My code

\documentclass[]{article}

% tikz
\usepackage{tikz}
\usetikzlibrary{positioning} %relative positioning
\usetikzlibrary{fit} %box around multiople nodes
\usetikzlibrary{calc} %complex positioning
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}

\begin{tikzpicture}[
block/.style={draw},
container/.style={inner sep=0,},
]

\def\EDFA{
\begin{tikzpicture}[scale=0.25]
\draw (-1,1) --  (1,0) --  (-1,-1) -- (-1,1);
\node[anchor=north,inner sep=2pt] at (0,-1) {$1$};
\end{tikzpicture}
}


\node[block] (source) {Source};

\node[container,right= of source] (edfa) {\EDFA};

\node[block, right= of edfa] (sink) {Sink};

\draw[->] (source) -- (edfa);
\draw[->] (edfa) -- (sink);

\end{tikzpicture}

\end{document}

Update I now have this code, is there a tex-ninja way to get rid of the helper coordinates?

\documentclass[]{standalone}

% tikz
\usepackage{tikz}
\usetikzlibrary{positioning} %relative positioning

\begin{document}

\tikzset{%
    EDFA/.pic={
        \begin{scope}[scale=.5, shift={(1,0)}]
        \draw (-1,0) coordinate (-in) --  (-1,1) -- (1,0) coordinate (-out) --  (-1,-1) -- cycle;
        \node[anchor=north,inner sep=2pt] at (0,-1) {EDFA};
        \end{scope}
    },
    Coupler/.pic={
        \begin{scope}[scale=.5, shift={(1,-1)}]
        \draw (-1,1) coordinate (-in1) to[out=0,in=180] (0,0) to[out=0,in=180] (1,1) coordinate (-out1);
        \draw (-1,-1) coordinate (-in2) to[out=0,in=180] (0,0) to[out=0,in=180] (1,-1) coordinate (-out2);
        \end{scope}
    }
}

\begin{tikzpicture}[
block/.style={draw},
]


\node[block] (source) {Source};

\path coordinate[right=of source] (helper a);
\draw (helper a) pic (edfa) {EDFA};

\path coordinate[right=of edfa-out] (helper b);
\draw (helper b) pic (coupler) {Coupler};


\node[block, right= of coupler-out1] (sink) {Sink};

\draw[->] (source) -- (edfa-in);
\draw (edfa-out) -- (coupler-in1);
\draw[->] (coupler-out1) -- (sink);

\end{tikzpicture}

\end{document}

  • define a /.pic – percusse Feb 10 '16 at 18:31
  • Wlecom to SE! It seems that the small pictures pic, described are in TikZ manual (v3.0.1a), chapter 18, page 251, is what you looking for. About it use as well number of different application you can find here, on SE. – Zarko Feb 10 '16 at 18:31
up vote 2 down vote accepted

As is explained in How do I draw shapes inside a tikz node? pics can be used for defining new objects. My main problem using pics is how to place where you want because they aren't nodes and positioning them is not so easy.

Following code shows how to define EDFA block.

    EDFA/.pic={
        \begin{scope}[scale=.5]
        \draw (-1,0) coordinate (in) --  (-1,1) -- (1,0) coordinate (out) --  (-1,-1) -- cycle;
        \node[anchor=north,inner sep=2pt] at (0,-1) {$1$};
        \end{scope}

In this case, coordinate (-1,0) will act as west anchor and 1,0 as east. Both point will have an special name for further reference. Every pic is placed according its own origin (0,0). You can use Claudio's answer to Anchoring TiKZ pics for better positioning.

As your example was simple, I'd prefer to star with EDFA and place Source and Sink after it.

\documentclass[]{article}

% tikz
\usepackage{tikz}
\usetikzlibrary{positioning} %relative positioning

\begin{document}

\tikzset{%
    EDFA/.pic={
        \begin{scope}[scale=.5]
        \draw (-1,0) coordinate (in) --  (-1,1) -- (1,0) coordinate (out) --  (-1,-1) -- cycle;
        \node[anchor=north,inner sep=2pt] at (0,-1) {$1$};
        \end{scope}
    }
}

\begin{tikzpicture}[
block/.style={draw},
]

\draw pic (edfa) {EDFA};

\node[block, left=of edfain] (source) {Source};

\node[block, right= of edfaout] (sink) {Sink};

\draw[->] (source) -- (edfain);
\draw[->] (edfaout) -- (sink);

\end{tikzpicture}

\end{document}

enter image description here

I understand that your components are more complex than EDFA because for this particular case an isosceles triangle node with a label will do the work and it can be used as a node and not as a pic:

\documentclass[]{article}

% tikz
\usepackage{tikz}
\usetikzlibrary{positioning} %relative positioning
\usetikzlibrary{shapes.geometric}

\begin{document}

\begin{tikzpicture}[
    block/.style={draw},
    edfa/.style={isosceles triangle, minimum width=1cm, 
         draw, anchor=west, isosceles triangle stretches, 
         minimum height=1cm, label=-80:#1}
]

\node[block] (source) {Source};

\node[edfa=1, right=of source] (edfa) {};

\node[block, right= of edfa] (sink) {Sink};

\draw[->] (source) -- (edfa);
\draw[->] (edfa) -- (sink);

\end{tikzpicture}

\end{document}

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.