2

I've already asked a question for drawing nodes in ring form but this one here seems to be much more sophisticated.

Is there an "easy way" to draw such a network in LaTeX?

enter image description here

It does not have to look like this but it should resemble the illustration.

  • There's nothing here you could not do in any of the TeX-friendly graphics tools like TikZ, Asymptote, or Metapost. Take your pick. Or you could try something like Inkscape and export to a graphic format. The illustration you have shared looks like something done with TikZ. – Thruston Jul 10 '14 at 17:22
  • Your question leaves all the effort to our community, even typing the essentials of a TeX document such as \documentclass{}...\begin{document} etc. As it is, most of our users will be very reluctant to touch your question, and you are left to the mercy of our procrastination team who are very few in number and very picky about selecting questions. You can improve your question by adding a minimal working example (MWE) that more users can copy/paste onto their systems to work on. If no hero takes the challenge we might have to close your question. – cfr Jul 10 '14 at 21:54
  • @cfr I will provide a MWE asap. I'm at work right now. Thanks for the hint. – displayname Jul 11 '14 at 15:10
5

Here's a snippet of code which I think illustrates the major points for creating the sort of illustration that you want.

A word of caution: I've cheated a bit in the code (because I'm lazy). I'll try to explain the cheats and what you need to do to avoid them or take advantage of them.

But first, here's a particial example of the sort of illustration you want:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{hobby}
\usetikzlibrary{arrows.meta}

\makeatletter
\let\@xp\expandafter
\newcommand\xtractp{\ae@xtractp}
\def\ae@xtractp#1(#2){\def#1{#2}}

%% command to assist in drawing parallel lines out of nodes
\newcommand\shiftdraw{\ae@shiftdraw}
\def\ae@shiftdraw[shift by=#1,#2] (#3) -- (#4);{%%
      \path let \p1=($(#4)-(#3)$),
                \n1={atan(\y1/\x1)},
                \n2={\n1+180},
                \n3={\n1+90},
                \n4={#1*cos(\n3)},
                \n5={#1*sin(\n3)}
            in
            [draw,#2] ([yshift=\n5,xshift=\n4]#3.\n1) -- ([yshift=\n5,xshift=\n4]#4.\n2);
}

%% commands to assist in drawing the blob
\newcommand\drawblob{\ae@blob}
\def\set@path#1\@nil#2\@nil{\path#2#1;}
\def\ae@blob#1{%%
  \let\ae@blob@path\relax{}%%
  \foreach \myn in {1,...,#1}
  {
    \ifx\ae@blob@path\relax
      \xdef\ae@blob@path{(b\myn)}%%
    \else
      \xdef\ae@blob@path{\ae@blob@path .. (b\myn)}%%
    \fi
   %%\node (N\myn) at (b\myn) {N\myn};
  }
  \@xp\set@path\ae@blob@path\@nil[draw,use Hobby shortcut,closed=true,fill=gray!80,opacity=0.90]\@nil}

\makeatother

\begin{document}

\begin{tikzpicture}[cn/.style={draw,circle,inner sep=2.5pt,outer sep=1.75pt},>=Stealth]

  \node (win) at (-2.5,0.75) {};
  \node (yn) at (8,2)  {yn};
  \path (yn) -- ++(1,0)   node[draw,circle] (E)    {$-$}  
             -- ++(0,3)   node              (yt)   {yt}    
             -- ++(-1,-1) node              (wout) {wout};

  \def\myc{0}
  \foreach \myq in {(0,0),
                    (0.5,2), 
                    (1,3),
                    (2,3.5),
                    (4,3),
                    (3.5,1),
                    (3.7,-1),
                    (2,-0.5)}
  {
     \expandafter\xtractp\expandafter\myp\myq    
     \xdef\myc{\number\numexpr\myc+1}
     \coordinate (c\myc) at (\myp);
     \coordinate (b\myc) at ($(\myp)!-0.6cm!(2,1)$);
     %% \draw[->] (2,1) -- (b\myc);
  }

  %% drawing
  \draw[line width=4pt,black!80,->] (win) to[out=30,in=150] (yn);

  \drawblob{8}

  \foreach \myp in {-1,0,1}
  {
    \node[inner sep=2.5pt,outer sep=1.75pt,draw,circle] (LN\myp) at (-3,\myp) {};
    \draw[gray,->] (LN\myp) -- ++(30:1.35cm);
    \draw[gray,->] (LN\myp) -- ++(-30:1.35cm);
  }

  \draw[->] (yt) -- (E);
  \draw[->] (E) -- ++(0,-2) -- ++(-3,0) -- (wout);


  \foreach \myc in {1,...,8}
  {
     \node[circle,inner sep=2.5pt,outer sep=1.75pt,draw] (n\myc) at (c\myc) {};
  }

  \draw[looseness=8,->] (n2) to[out=100,in=160] (n2);
  \draw[->] (n2) -- (n3);
  \shiftdraw[shift by=2pt,->] (n3) -- (n4);
  \shiftdraw[shift by=-2pt,<-] (n3) -- (n4);

\end{tikzpicture}

\end{document}

enter image description here

When drawing illustrations in LaTeX, you have several choices. My two favorite choices are TikZ and pstricks. Everything here can be accomplished using TikZ. Both TikZ and pstricks are suites of packages and provide a lot of power. As such, there is a concomitant learning curve. Choose one, stick with it, and learn it well. I do not recommend switching between the two unless you want your head to explode: they have similar approaches, somewhat different philosophies, and subtle, but salient, differences in their syntax. Both are well documented. But the documentation for pstricks is spread over multiple files. The documentation for TikZ is by-and-large all contained within one pdf-document.

Everything is drawn within a tikzpicture environment.

Most of what you want to be able to do in the picture can be achieved by creating nodes and/or coordinates and drawing along paths between them.

A coordinate and node are very similar. It can be useful to think of a coordinate as a dimensionless node. nodes have a somewhat ellaborate anatomy. Relevant to the above example, nodes have the following features:

  • shape
  • inner sep
  • outer sep

The default shape for a node is a rectangle.

The first thing you should notice in tikzpicture is the line:

\begin{tikzpicture}[cn/.style={draw,circle,inner sep=2.5pt,outer sep=1.75pt},>=Stealth]

I'm doing two things here.

  • cn is a custom node style that I create.

This saves time and allows for quick and easy changes (if so desired). For the custom node I set the three features mentioned above. I also add draw which is a command to make visible the shape of the node.

The thing I'm doing on this line is setting the type of arrow to use throughout the picture. I'm using Stealth and because of this I had to load the TikZ library, arrows.meta. (I use no other features of this library.)

I let you read the documentation on the syntax for nodes (it's a bit more involved than what I'm suggesting here). But this is the syntax I'm using here:

\node (<node-name>) at (<node location>) {<node content>};

What's absolutely essential here is the <node content>. You can leave the brackets empty, but you must supply them. Also notice that all TikZ commands terminate in ;. The <node location> can be a Cartesian coordinate (x,y), a polar coordinate (angle:radius), or the name of another node or coordinate.

The first two things I do is create two nodes named win and yn; only for node yn do I provide content.

The next thing you see is a \path. Paths are the backbone of most of what happens in a TikZ picture. (In fact, nodes and coordinates are just particular kinds of paths.) I use a \path command to help create the triangular path on the right hand side of the picture

enter image description here

\draw[->] (yt) -- (E);
\draw[->] (E) -- ++(0,-2) -- ++(-3,0) -- (wout);

Points along the path are connected by --. The ++ notation allows me to apply a vector to the previously plotted point to move the brush to the next point. Along the path, I define three nodes: E, yt, and wout.

The next segment of code is perhaps a bit more complicated than necessary, but I was lazy (as mentioned above). I want to create the blob in the middle of the picture. To do this, I use the TikZ library hobby. (As mentioned above almost all of the TikZ suite is explained in its manual. hobby is an exception to this rule. Its documentation is found in hobby_doc which you can access with texdoc.)

A couple of things are going on here. I use a \foreach loop to cycle over the coordinates for the points to be contained in the blob. The problem is that the macro \coordinate looks for explicitly written ( and ). So, I wrote a macro, \xtractp, to extract the x and y coordinate from within the parentheses and assign them to \myp. You don't have to use this portion of the code. All you have to do is for each point in the blob is create coordinates as

\coordinate (c1) at (0,0);  
\coordinate (c2) at (0.5,2);
\coordinate (c3) at (1,3);

We want the blob to form a border around these points so I chose an arbitrary point, (2,1), in the middle of the blob as reference to create the border points of the blob.

\coordinate (b1) at ($(c1)!-0.6cm!(2.1)$)
\coordinate (b2) at ($(c2)!-0.6cm!(2.1)$)

The syntax ($(<point a>)!<dim>!(<point b>)$) comes from the TikZ library calc. This tells TikZ to create a new point along the vector formed by <point b> - <point a> at a distance of <dim> from <point a>.

Then I draw the blob. Here I really cheat. I created a macro to handle the code for drawing the blob. By long hand what you would need to do is the following:

\path[draw,use Hobby shortcut,closed=true,fill=gray!80,opacity=0.90]
     (b1) .. (b2) .. (b3) .. (b4) .. (b5) .. (b6) .. (b7) .. (b8);

This syntax is explained in the documentation for the hobby library.

enter image description here

Actually before I draw the blob I draw a line from nodes win to yn. The order is important to get the lay-over effect. Also, this is the reason I set the opacity=0.90 when drawing the blob.

enter image description here

In the next portion of code I draw the crossing arrows on the left hand side. I use a \foreach loop for facilitate this. I also use both the ++ and polar coordinates to get the arrows pointing in the correct direction.

enter image description here

I think the rest of the code is fairly self evident except for, perhaps, the last four lines:

  \draw[looseness=8,->] (n2) to[out=100,in=160] (n2);
  \draw[->] (n2) -- (n3);
  \shiftdraw[shift by=2pt,->] (n3) -- (n4);
  \shiftdraw[shift by=-2pt,<-] (n3) -- (n4);

These lines are to draw the connections between the circles in the blob.

enter image description here

  \draw[looseness=8,->] (n2) to[out=100,in=160] (n2);

Draws the arrow originating from and pointing back to the circle. Play with the looseness to create a tighter and looser loop.

In the last two lines, I create another macro to create the parallel arrows between nodes. This is one you'll probably want to use. The syntax here is fairly powerful. I recommend that you read up on this syntax in the TikZ manual.

\newcommand\shiftdraw{\ae@shiftdraw}
\def\ae@shiftdraw[shift by=#1,#2] (#3) -- (#4);{%%
      \path let \p1=($(#4)-(#3)$),
                \n1={atan(\y1/\x1)},
                \n2={\n1+180},
                \n3={\n1+90},
                \n4={#1*cos(\n3)},
                \n5={#1*sin(\n3)}
            in
            [draw,#2] ([yshift=\n5,xshift=\n4]#3.\n1) -- ([yshift=\n5,xshift=\n4]#4.\n2);
}

I fake a key word at the beginning of this command. In other words, you must have shift by= as the text that immediately follows \shiftdraw[. Also, whether or not you want to pass optional commands on to the path, you must follow the first argument with a comma.

A final point about inner sep and outer sep.

The inner sep creates a minimum size for a node. If the node's content is too large to fit within the minimum size, TikZ will expand the size of the node.

outer sep is a bit more obscure, but very salient to this problem. It is the outer sep which allows the arrows to approach, but not go right up to, the drawn border of the node.

  • 1
    I'm not entirely happy with the \shiftdraw macro. I posted a question about whether there's a better approach. – A.Ellett Jul 12 '14 at 3:19
  • Wow, that is awesome and worked right on! Thank you very much I didn't expect to get such a huge example! – displayname Jul 13 '14 at 12:53

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.