9

I would like to draw a diagram that contains both an image, two blocks of text and a tikzpicture. More precisely, it should look as follows

Image -> Rectangle with text -> Tikzpicture -> Rectangle with text

Possibly, over each arrow, I want to add some text and below each image, rectangle or tikz image I may also want to add some text. I want that image, the rectangles and the tikzpicture have more or less the same height and width, without destroying the aspect ratio of the image and tizkpicture.

Here's a sketch.

enter image description here

I've started to use this code

\documentclass{article}

\usepackage{graphicx}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\node[inner sep=0pt] (russell) at (0,0)
    {\includegraphics[width=.25\textwidth]{my_image.pdf}};

\node[inner sep=0pt] (whitehead) at (5,0)
    {\includegraphics[width=.25\textwidth]{my_image.pdf}};

\draw[->,thick] (russell.mid east) -- (whitehead.mid west)
    node[midway,fill=white] {Principia Mathematica};

\end{tikzpicture}
\end{document}

However, I am not sure how to modify it for my purposes. Moreover, note that I want the arrows to go from the middle of the image (and not from the bottom, as happens if you run the code above, although I am using mid there). So, how can I draw the diagram that I describe above? It should look professional, in the sense that I need to use it in a research paper.

PS: If you can assume that each block could be replaced by another type of block (e.g. the rectangle with the text could eventually be replaced with an image), that would be great, given that I am still not sure if this is the best diagram for my purposes.

3
  • Can you maybe show a hand drawn sketch?
    – TobiBS
    Aug 26, 2020 at 11:19
  • 1
    As said in the documentation "The standard shapes also define a mid anchor (and mid west and mid east). This anchor is half the height of the character “x” above the base line.". If you want the real center, use the east and west anchor. Aug 26, 2020 at 11:52
  • 1
    I don't answer questions which basically consist in drawing a tikz pictures. I prefer to spent my time on other things than looking up keys in the tikz documentation. Aug 26, 2020 at 12:10

3 Answers 3

4

Define some commands to use later:

  • \getpicdimen: get the width and height and save them to \picwidth and \picheight by default. Star version means using node name as the argument.
  • \drawbox[<options>](name){width}{height}: draw a rectangle node of given width and height
  • \fittobox[macro][macro]{width}{height}(shift){tikz code}: to fit the pic in a box of given width and height

The code below is for simple example. With the commands above, you can eventually define an environment equalfig to make it more conveniant to achieve the same effect.

enter image description here

\documentclass{article}
\usepackage{tikz}
\usepackage{geometry}
\geometry{margin=2cm, paperwidth=40cm}
\usepackage{graphicx}
\usepackage{mwe}
\usetikzlibrary{fit, calc, positioning}
\usepackage{xparse}
\NewDocumentCommand { \getpicdimen } { s O{\picwidth} O{\picheight} +m }
  {
    \begin{pgfinterruptboundingbox}
    \begin{scope}[local bounding box=pic, opacity=0]
      \IfBooleanTF {#1}
        { \node[inner sep=0pt, fit=(#4)] {}; }
        { #4 }
    \end{scope}
    \path ($(pic.north east)-(pic.south west)$);
    \end{pgfinterruptboundingbox}
    \pgfgetlastxy{#2}{#3}
  }

\NewDocumentCommand { \drawbox } { O{} D(){box} m m }
  {
    \node[inner sep=0pt, minimum width=#3, minimum height=#4, draw, #1] (#2) {};
  }

\ExplSyntaxOn
\fp_new:N \l__scale_fp
\NewDocumentCommand { \fittobox } { O{\picwidth} O{\picheight} m m D(){0, 0} +m }
  {
    \getpicdimen[#1][#2]{#6}
    \fp_compare:nTF
      {
        % pic ratio
        \dim_ratio:nn { #1 } { #2 } >
        % box ratio
        \dim_ratio:nn { #3 } { #4 }
      }
      % {}{}
      { \fp_set:Nn \l__scale_fp { 0.9*\dim_ratio:nn { #3 } { #1 } } }
      { \fp_set:Nn \l__scale_fp { 0.9*\dim_ratio:nn { #4 } { #2 } } }
    \begin{scope}[
      shift={($(#5) - \fp_use:N \l__scale_fp*(pic.center)$)},
      scale=\fp_use:N \l__scale_fp,
      ]
      #6
    \end{scope}
  }
\ExplSyntaxOff

\begin{document}
\centering
\begin{tikzpicture}
  \node[inner sep=0pt] (img) at (0,0)
    {\includegraphics[width=.2\textwidth]{example-image-a.pdf}};
  \getpicdimen*[\nodewidth][\nodeheight]{img}
  \typeout{aaa \nodewidth}
  \drawbox[right=.066\textwidth of img, rounded corners](box1){\nodewidth}{\nodeheight}
  \drawbox[right=.066\textwidth of box1, rounded corners](box2){\nodewidth}{\nodeheight}
  \drawbox[right=.066\textwidth of box2, rounded corners](box3){\nodewidth}{\nodeheight}
  % some text
  \node[text width=\dimexpr\nodewidth-8pt, align=justify] at (box1) {A very
    very very very very very very very very very very very very long text to
  show \ldots.};
  \node[text width=\dimexpr\nodewidth-8pt, align=justify] at (box3) {A very
    very very very very very very very very very very very very long text to
  show \ldots.};
  % arrow
  \tikzset{mynode/.style={midway, font=\small, above}}
  \tikzset{myarrow/.style={shorten <=2mm, shorten >=2mm}}
  \draw[->, myarrow] (img.east) -- (box1.west) node[mynode] {a1};
  \draw[->, myarrow] (box1.east) -- (box2) node[mynode] {a2};
  \draw[->, myarrow] (box2.east) -- (box3) node[mynode] {a3};
  \node[below=1em of img] {Image};
  \node[below=1em of box1] {Text 1};
  \node[below=1em of box2] {Pic code};
  \node[below=1em of box3] {Text 2};
  % pic code
  \tikzset{shorten >=1pt,->,draw=black!50, node distance=2.5cm,
    neuron/.style={circle,fill=black!25,minimum size=17pt,inner sep=0pt},
    input neuron/.style={neuron, fill=green!40},
    output neuron/.style={neuron, fill=red!40},
    hidden neuron/.style={neuron, fill=blue!40},
    pics/graph/.style={
      code={
        \draw[double=orange,white,thick,double distance=1pt,shorten >=0pt]
          plot[variable=\t,domain=-0.5:0.5,samples=51] ({\t},{#1});
      }
    },
    nodes={transform shape}
  }
  \fittobox{\nodewidth}{\nodeheight}(box2.center){
    % \node {a};
    % Input layer
    \foreach \name / \y in {1,...,2}
        \node[input neuron] (I-\name) at (0,0.5-2*\y) {$i\y$};

    % Hidden layer
    \foreach \name / \y in {1,...,5}
        \path[yshift=0.5cm]
            node[hidden neuron] (H-\name) at (2.5,-\y cm) {$h\y$};

    % Output node
    \node[output neuron, right of=H-3] (O) {$o$};

    % Connect every node in the input layer with every node in the hidden layer.
    \foreach \source in {1,...,2}
        \foreach \dest in {1,...,5}
            \path (I-\source) edge (H-\dest);

    % Connect every node in the hidden layer with the output layer
    \foreach \source in {1,...,5}
        \path (H-\source) edge (O);

    \begin{scope}[xshift=7cm]

      % Input layer
      \foreach \name / \y in {1,...,2}
          \node[input neuron] (I-\name) at (0,0.5-2*\y) {$i\y$};

      % Hidden layer
      \foreach \name / \y in {1,...,5}
          \path[yshift=0.5cm]
              node[hidden neuron] (H-\name) at (2.5,-\y cm) {$h\y$};

      % Output node
      \node[output neuron, right of=H-3] (O) {$o$};

      % Connect every node in the input layer with every node in the hidden layer.
      \foreach \source in {1,...,2}
          \foreach \dest in {1,...,5}
              \path (I-\source) edge (H-\dest);

      % Connect every node in the hidden layer with the output layer
      \foreach \source in {1,...,5}
          \path (H-\source) edge (O);
     \path (I-1) -- (H-1) pic[midway]{graph={-0.3+0.6*exp(-6*\t*\t)}};
     \path (I-2) -- (H-2) pic[midway]{graph={-0.3+0.6*exp(-25*(\t+0.15)*(\t+0.15))}};
    \end{scope}
  }
\end{tikzpicture}
\end{document}
3
  • I update my question. Use rounded corners and shorten options which can be searched in network. I think they are not too related to your question.
    – ZhiyuanLck
    Aug 26, 2020 at 14:54
  • Answer updated, fix the bug.
    – ZhiyuanLck
    Aug 26, 2020 at 16:01
  • 1
    This option is just to show example more clearly, all length can be adjusted. I feel you just don't want to know what these commands can do... If you actually do not understand or do not want to understand my answer, just ignore it.
    – ZhiyuanLck
    Aug 27, 2020 at 0:24
6

Personally I like to use scopes for this kind of issue.

I've prepared an MWE for you, which should help you get started with your own figure.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{graphicx}

\begin{document}
    \centering
    \begin{tikzpicture}
        \begin{scope}[xshift=0cm]
            \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (imageA) {\includegraphics[width=3cm]{example-image-a}};
        \end{scope}
        
        \begin{scope}[xshift=4.5cm]
        \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (textA) {\textbf{Sometext}};
        \end{scope}
        
        \begin{scope}[xshift=9cm]
        \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (imageB) {\includegraphics[width=3cm]{example-image-b}};
        \end{scope}
        
        %finally, add arrows
        \draw[very thick,->,>=stealth] ($(imageA.east)+(0.2,0)$) -- ($(textA.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {transform};
        \draw[very thick,->,>=stealth] ($(textA.east)+(0.2,0)$) -- ($(imageB.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {use};
    \end{tikzpicture}
\end{document}

If I remember correctly, there is also an easier way to not have the arrows connect to your nodes, so this is more of a quick and dirty solution.

It will look something like this: Example of tikz image using scopes

EDIT: I added a tikz picture in the third scope.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{graphicx}

\begin{document}
    \centering
    \begin{tikzpicture}
        \begin{scope}[xshift=0cm]
            \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (imageA) {\includegraphics[width=3cm]{example-image-a}};
        \end{scope}
        
        \begin{scope}[xshift=4.5cm]
        \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (textA) {\textbf{Sometext}};
        \end{scope}
        
        \begin{scope}[xshift=9cm]
            \clip node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (tikzcode) {};
            \draw[fill=blue] (0,1.5) circle (1cm);  
        \end{scope}
        
        %finally, add arrows
        \draw[very thick,->,>=stealth] ($(imageA.east)+(0.2,0)$) -- ($(textA.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {transform};
        \draw[very thick,->,>=stealth] ($(textA.east)+(0.2,0)$) -- ($(tikzcode.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {use};
    \end{tikzpicture}
\end{document}

enter image description here

EDIT 2: Using the neural network as requested in the comments.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{graphicx}
\def\layersep{2.5cm}
\begin{document}
    \centering
    \begin{tikzpicture}
        
        \begin{scope}[xshift=0cm]
            \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (imageA) {\includegraphics[width=3cm]{example-image-a}};
        \end{scope}
        
        \begin{scope}[xshift=4.5cm]
        \node[minimum width=3cm,minimum height=3cm,inner sep=0pt,draw] (textA) {\textbf{Sometext}};
        \end{scope}
        
        \begin{scope}[xshift=12cm,shorten >=1pt,->,draw=black!50, node distance=\layersep,
        neuron/.style={circle,fill=black!25,minimum size=17pt,inner sep=0pt},
        input neuron/.style={neuron, fill=green!40},
        output neuron/.style={neuron, fill=red!40},
        hidden neuron/.style={neuron, fill=blue!40},
        pics/graph/.style={code={\draw[double=orange,white,thick,double distance=1pt,shorten >=0pt]plot[variable=\t,domain=-0.5:0.5,samples=51] ({\t},{#1});}}]
        \clip node[minimum width=7cm,minimum height=6cm,inner sep=0pt] (tikzcode) {};
        \begin{scope}[xshift=-2.5cm,yshift=2.5cm]
        % Input layer
        \foreach \name / \y in {1,...,2}
        \node[input neuron] (I-\name) at (0,0.5-2*\y) {$i\y$};
        
        % Hidden layer
        \foreach \name / \y in {1,...,5}
        \path[yshift=0.5cm]
        node[hidden neuron] (H-\name) at (2.5,-\y cm) {$h\y$};
        
        % Output node
        \node[output neuron, right of=H-3] (O) {$o$};
        
        % Connect every node in the input layer with every node in the hidden layer.
        \foreach \source in {1,...,2}
        \foreach \dest in {1,...,5}
        \path (I-\source) edge (H-\dest);
        
        % Connect every node in the hidden layer with the output layer
        \foreach \source in {1,...,5}
        \path (H-\source) edge (O);
        
        
        % Input layer
        \foreach \name / \y in {1,...,2}
        \node[input neuron] (I-\name) at (0,0.5-2*\y) {$i\y$};
        
        % Hidden layer
        \foreach \name / \y in {1,...,5}
        \path[yshift=0.5cm]
        node[hidden neuron] (H-\name) at (2.5,-\y cm) {$h\y$};
        
        % Output node
        \node[output neuron, right of=H-3] (O) {$o$};
        
        % Connect every node in the input layer with every node in the hidden layer.
        \foreach \source in {1,...,2}
        \foreach \dest in {1,...,5}
        \path (I-\source) edge (H-\dest);
        
        % Connect every node in the hidden layer with the output layer
        \foreach \source in {1,...,5}
        \path (H-\source) edge (O);
        \path (I-1) -- (H-1) pic[midway]{graph={-0.3+0.6*exp(-6*\t*\t)}};
        \path (I-2) -- (H-2) pic[midway]{graph={-0.3+0.6*exp(-25*(\t+0.15)*(\t+0.15))}};
        \end{scope}
        \end{scope}
        
        %finally, add arrows
        \draw[very thick,->,>=stealth] ($(imageA.east)+(0.2,0)$) -- ($(textA.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {transform};
        \draw[very thick,->,>=stealth] ($(textA.east)+(0.2,0)$) -- ($(tikzcode.west)+(-0.2,0)$) node [text width=2.5cm,midway,above,align=center,font=\tiny] {use};
    \end{tikzpicture}
\end{document}

Looks like this: Image using the neural network example

You'll have to play around a bit with the lengths and sizes of things to get what you want exactly, but in principle this should work.

4
  • Just delete the draw from the node command, I used it here only to visualise how things work.
    – Markus G.
    Aug 26, 2020 at 12:05
  • I added a more complex example, now using an independent non-node in the third image. Hope this helps.
    – Markus G.
    Aug 26, 2020 at 12:16
  • Of course not, that would defeat the purpose of using scopes. I mean, you are already inside a tikz environment. You could always try using inline \tikz{} within a node, but I'm not sure that would be a good solution. If you want to add something very complicated or complex, such as a pgf plot or a petri net I suggest you compile this seperately and then include the pdf image.
    – Markus G.
    Aug 26, 2020 at 12:26
  • Let us continue this discussion in chat.
    – Markus G.
    Aug 26, 2020 at 12:47
1

A possible solution:

\documentclass{article}

\usepackage{graphicx}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\node[inner sep=0pt] (russell) at (0,0)
    {\includegraphics[width=.25\textwidth]{example-image-a.pdf}};

\node[inner sep=0pt, text width=.25\textwidth, align=left,
    draw, inner sep=5pt] (whitehead) at (5,0)
    {A lot of text here, but not so much so that I can use
    \texttt{lipsum} so writing nonsense.};

\draw[->,thick] (russell.east) -- (whitehead.west)
    node[midway,above, fill=white, inner sep=0pt, outer sep=5pt] {Principia};

\begin{scope}[xshift=9cm, local bounding box=mybbox]
    \draw (-1,-1) rectangle (1,1);
    \draw (0,0) -- (.3,.0) circle[radius=0.5];
\end{scope}

\draw[->,thick] (whitehead.east) -- (mybbox.west)
    node[midway,above, fill=white, inner sep=0pt, outer sep=5pt] {Really?};
\end{tikzpicture}
\end{document}

enter image description here

The main trick for the picture is to maintain it centered around y=0 because you did that for the other boxes, so I used the "bounding rectangle" trick. You can make it invisible using something like:

    \path[use as bounding box]  (-1,-1) rectangle (1,1);

instead of the explicit rectangle in the last scope.

enter image description here

0

You must log in to answer this question.