4

I am looking for a better way to create images like the following:

enter image description here

I want to make diagram with blocks and ports (the things with Greek letters) so that I can do the following:

  • Not have to space blocks manually (automatically take account of the ports and their width in spacing the blocks).
  • Automatically change the width and height of blocks so that they're wide enough to hold all their ports.
  • Change the shape/color of ports in a way that's aware of their location. (i.e. make the color of the side of a port that opposite the block red with a style, or a NOT circle that an arrow goes into.)
  • Not have nested tikzpicture environments constantly (it's annoying and there's got to be a better way. This will become particularly salient when I get to stuff where ports will have ports of their own. (ports can have modifiers and the like which change their meaning)).

Right now my code for creating diagrams like the above is very hacky and manual and as the diagrams I need grow larger, it's become progressively harder. I'm mainly looking for examples or advice on making more modular and composable structures out of TikZ, as well as advice on code style.

\documentclass[tikz,crop]{standalone}
\usepackage{amssymb,amsmath}

\usepackage{tikz}
\usetikzlibrary{
  calc,
  positioning,
  shapes.arrows%
}

\begin{document}
    \begin{tikzpicture}[remember picture]
      \tikzstyle{component}=[rectangle
                            ,draw
                            ,node distance =1.5cm
                            ,minimum height = 0.8cm]
      \tikzstyle{port side}=[node distance=0 cm
                            ,outer sep=-0.2 pt
                            ,inner sep=0pt]
      \tikzstyle{port}=[rectangle
                       ,draw
                       ,node distance=0.1 cm,
                       ,outer sep=0 pt
                       ,minimum height = 0.6cm
                       ,minimum width = 0.6cm
                       ,inner sep = 3pt]

      \node[component] (blk1) {Block 1};
      \node[port side,right=of blk1] (blk1.right) {
          \begin{tikzpicture}
            \node[port] (alp) {$\alpha$};
          \end{tikzpicture}
        };
      \node[port side,above=of blk1] (blk1.above) {
          \begin{tikzpicture}
            \node[port] (bet1) {$\beta$};
          \end{tikzpicture}
        };


      \node[component,right=of blk1] (blk2) {Block 2};
      \node[port side,left=of blk2] (blk2.left) {
        \begin{tikzpicture}
          \node[port] (del) {$\delta$};
        \end{tikzpicture}
      };
      \node[port side,above=of blk2] (blk2.above) {
        \begin{tikzpicture}
          \node[port] (bet2) {$\beta$};
        \end{tikzpicture}
      };
      \node[port side,right=of blk2] (blk2.right) {
        \begin{tikzpicture}
          \node[port] (gam) {$\gamma$};
        \end{tikzpicture}
      };

      \node[component,right=of blk2] (blk3) {Block 3};
      \node[port side,left=of blk3] (blk3.left) {
        \begin{tikzpicture}
          \node[port] (eps) {$\epsilon$};
        \end{tikzpicture}
      };
      \node[port side,above=of blk3] (blk3.above) {
        \begin{tikzpicture}
          \node[port] (bet3) {$\beta$};
          \node[port,right=of bet3] (eta) {$\eta$};
        \end{tikzpicture}
      };
      \node[port side,right=of blk3] (blk3.right) {
        \begin{tikzpicture}
          \node[port] (thet) {$\theta$};
        \end{tikzpicture}
      };

      \node[component,right=of blk3] (blk4) {Block 4};
      \node[port side,left=of blk4] (blk4.left) {
        \begin{tikzpicture}
          \node[port] (iota) {$\iota$};
        \end{tikzpicture}
      };
      \node[port side,above=of blk4] (blk4.above) {
        \begin{tikzpicture}
          \node[port] (kap) {$\kappa$};
        \end{tikzpicture}
    };

    \draw[<-] (alp.east) -- (del.west);
    \draw[<-] (gam.east) -- (eps.west);
    \draw[<-] (thet.east) -- (iota.west);

    \draw[rounded corners,solid,<-] (bet1.north) |- +(-1cm,0.2cm);
    \draw[rounded corners,solid,<-] (bet2.north) |- +(-4cm,0.2cm);
    \draw[rounded corners,solid,<-] (bet3.north) |- +(-4.5cm,0.2cm);
    \draw[dashed] ($(bet1.north)+(-1,0.2cm)$) -- +(-.5cm,0cm);

    \draw[rounded corners,solid,<-] (eta.north) |- +(-8.55cm,0.4cm);
    \draw[dashed] ($(eta.north)+(-8.55cm,0.4cm)$) -- +(-.5cm,0cm);

    \draw[rounded corners,solid,<-] (kap.north) |- +(1cm,0.2cm);
    \draw[dashed] ($(kap.north)+(1cm,0.2cm)$) -- +(.5cm,0cm);

  \end{tikzpicture}
\end{document}
  • 3
    It seems that the only reason you are nesting the tikzpictures is to increase the inner sep. – John Kormylo Mar 23 '15 at 16:07
  • Please take a look at LaRiFaRi's answer for some helpful advice concerning both how to ask good questions and how to improve your code. I suggest breaking your question down, editing this one to be more specific and then asking further questions about specific points as follow-ups if that turns out to be appropriate. But be aware that you may also be rather too optimistic about what can be done automatically. You might want to look at Lua - could these be constructed as TiKZ graphs with LuaTeX? – cfr Apr 7 '15 at 2:29
1

Your question is not very clear. Please tidy your code up a bit like in my MWE below. Then ask specific questions on single problems you are having. E.g.: "How do I colour a port red, if it is above a block?"

You can start with the following. I also tried to transpose it to better coding style.

% arara: pdflatex

\documentclass[tikz]{standalone}
\usetikzlibrary{%
    ,calc
    ,positioning
    }

\begin{document}
\begin{tikzpicture}[%
    ,component/.style={%
        ,rectangle
        ,draw
        ,node distance =1.5cm
        ,minimum height = 0.8cm
        }
    ,port/.style={%
        ,rectangle
        ,draw
        ,node distance=-.4pt,
        ,minimum height = 0.6cm
        ,minimum width = 0.6cm
        }
    ,connector/.style={%
        ,rounded corners
        ,<-
        }
    ]

    \node[component] (blk1) {Block 1};
        \node[port,right=of blk1] (alp) {$\alpha$};
        \node[port,above=of blk1] (bet1) {$\beta$};

    \node[component,right=of blk1] (blk2) {Block 2};
        \node[port,left=of blk2] (del) {$\delta$};
        \node[port,above=of blk2] (bet2) {$\beta$};
        \node[port,right=of blk2] (gam) {$\gamma$};

    \node[component,right=of blk2] (blk3) {Block 3};
        \node[port,left=of blk3] (eps) {$\epsilon$};
        \node[port,above=of blk3.130] (bet3) {$\beta$};
        \node[port,above=of blk3.50] (eta) {$\eta$};
        \node[port,right=of blk3] (thet) {$\theta$};

    \node[component,right=of blk3] (blk4) {Block 4};
        \node[port,left=of blk4] (iota) {$\iota$};
        \node[port,above=of blk4] (kap) {$\kappa$};

    \path[->] (iota) edge (thet) (eps) edge (gam) (del) edge (alp);

    \draw[connector] (bet1.north) |- +(-0.1,0.2);
    \draw[connector] (bet2.north) |- +(-0.1,0.2);
    \draw[connector] (bet3.north) |- +(-6.5,0.2);
    \draw[dashed] ($(bet1.north)+(-1,0.2)$) -- +(-.5,0);

    \draw[connector] (eta.north) |- +(-8.55,0.4);
    \draw[dashed] ($(eta.north)+(-8.55,0.4)$) -- +(-.5,0);

    \draw[connector] (kap.north) |- +(1,0.2);
    \draw[dashed] ($(kap.north)+(1,0.2)$) -- +(.5,0);   
\end{tikzpicture}
\end{document}
  • 2
    (+1) for going to the trouble of cleaning up the code. I hope that OP returns here and heeds your advice! Both about the code and about asking clear, specific questions. – cfr Apr 7 '15 at 2:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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