9

I'm trying to make a plot similar to this one but I'm having a really hard time. If anyone can help me getting the details, I'll appreciate.

enter image description here

I thought I couldn't post questions like this, but as I've seen some questions like those asking for plots similar to xkcd's, I believe it might be OK.

My far-from-good example is here. My circle has a radius=sqrt(2), but it really doesn't matter.

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}

\begin{axis}[
height=20cm,
width=20cm,
xmin=-2.5, xmax=2.5,
ymin=-2.5, ymax=2.5,
only marks,
axis x line=none,
axis y line=none
]

\draw (axis cs:0,0) circle[radius=1.41421356237];

% circle
\addplot [mark=*, mark size=0.3cm,color=red]
coordinates {
(-1,-1)
(1,1)
};
\addplot [mark=*, mark size=0.3cm,color=red]
coordinates {
(-1,1)
(1,-1)
};
% black arrows
\addplot [mark=none,color=black,
quiver={u={x}, v={-x},scale arrows=0.4}, ->]
coordinates {
(-1,-1)
(1,1)
};
\addplot [mark=none,color=black,
quiver={u={-x}, v={-x},scale arrows=0.4}, ->]
coordinates {
(-1,1)
(1,-1)
};
% blue arrows
\addplot [mark=none,color=blue,
quiver={u={x}, v={-x-0.5},scale arrows=0.5}, ->]
coordinates {
(-1,-1)
(1,1)
};
\addplot [mark=none,color=blue,
quiver={u={-x}, v={-x-0.5},scale arrows=0.5}, ->]
coordinates {
(-1,1)
(1,-1)
};

\addplot [mark=*, mark size=0.3cm,color=blue] coordinates {
(1.41421356237,0)
(-1.41421356237,0)
(0,1.41421356237)
(0,-1.41421356237)
(1.41421356237,0)
};

\end{axis}  
\end{tikzpicture}
\end{document}

which gives me this:

enter image description here

7
  • Do the green and red touching arrows have the same length?
    – Sigur
    Jan 28, 2013 at 22:31
  • @Sigur, yes, all arrows have the same lenght.
    – perr0
    Jan 28, 2013 at 22:43
  • And do you have only those circles or you want some code more flexible to works with more circles?
    – Sigur
    Jan 28, 2013 at 22:45
  • 3
    Why use pgfplots? Such figures are better drawn using pgf/tikz or metapost.
    – Aditya
    Jan 28, 2013 at 23:14
  • 1
    Tikz is the higher level language for pgf. Pgfplots is for frawing data plots, not diagrams. Metapost is much older than pgf, and much better at doing calculations. Other alternatives are pstricks (which inspite of the name works with pdftex as well) and asymptote (metapost with a c-like syntax).
    – Aditya
    Jan 29, 2013 at 14:00

2 Answers 2

11

Instead of pgfplots construction, you can use an alternating style which are slightly verbose here (repetition of ->, ultra thin etc.) Luckily the structure is easy to identify. You can furnish further according to your needs.

EDIT: Thanks to JLDiaz' color-seeing eyes, I took a stab on the green arrows. Hope it hits the right one :)

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}[>=latex,
cnode/.style={circle,inner sep=3pt,outer sep=0},
myline/.style={ultra thin,->}
]
\def\myarrowlen{5mm}
\pgfmathsetmacro{\myradius}{sqrt(2)}

\node[draw,circle,minimum size=2*\myradius cm] (bigc) at (0,0) {\tiny +};

\foreach \x in {1,...,8}{
\ifodd\x\relax
    \node[cnode,fill=red] (n-\x) at (bigc.45*\x) {};
    \draw[red,myline] (n-\x)  -- ($(n-\x)!-\myarrowlen!(bigc.45*\x+45)$);
    \draw[red,myline] (n-\x)  -- ($(n-\x)! \myarrowlen!(bigc.45*\x+45)$);
\else
    \node[cnode,fill=blue] (n-\x) at (45*\x:\myradius) {};
    \draw[blue , myline] (n-\x) -- ($(n-\x)!-\myarrowlen!(bigc.45*\x+45)$);
    \draw[green, myline] (n-\x) -- ($(n-\x)! \myarrowlen!(bigc.45*\x-45)$);
    \draw[     , myline] (n-\x) -- ++({45*(\x-2)}:\myarrowlen);
\fi
}
\end{tikzpicture}
\end{document}

enter image description here

10
  • Hmm... Colorblind here and in the comments green and red are mentioned, sorry in advance.
    – percusse
    Jan 29, 2013 at 0:26
  • The green arrows are the third (the ones at -45) in the blue circles. By the way, great answer! (+1)
    – JLDiaz
    Jan 29, 2013 at 0:58
  • @JLDiaz Thank you very much for the pointer :)
    – percusse
    Jan 29, 2013 at 1:11
  • Thank you! This answer is really simple. Just to add to this colorblindness stuff, the arrow pointing from the red circle to the blue circle (opposite to green) is actually brown. ;)
    – perr0
    Jan 29, 2013 at 12:22
  • @percuße, your example works flawlessly in a standalone file. But when I embed it in my main document (with an \input command) it gives the error: "Package pgf Error: No shape named current axis is known \end{tikzpicture}". So I tried editing your code and included an empty \being{axis} \end{axis} and it compiles with no errors (but it draws the axis, of course). Also I noted that, despite the error, the figure is drawn in the main document. Although, as I use tikz externalize, the separate pdf file is not created. Do you know why this is hapenning?
    – perr0
    Jan 29, 2013 at 15:02
2

Here is an alternative solution using metapost (I used ConTeXt, but you can use standalone metapost, or metapost embedded in LaTeX as well).

The main difference from percusse's solution is that instead of specifying the length and angle of the arrows, I calculate it based on the location of the nodes. Unlike TikZ, metapost does not provide a nice way to shorten paths, so I define a macro that does that.

\startMPinclusions
  vardef shorten(expr p, q, d) =
    % p = start point
    % q = end point
    % d  = distance
    newpair qq;
    qq := q - d*dir(angle(q-p));
    (p -- qq)
  enddef;
\stopMPinclusions
\starttext
\startMPpage[offset=3mm]
  newnumeric u; u := 2cm; % Radius of the circle
  newnumeric w; w := 3mm; % Radius of nodes
  newnumeric d; d := 0.25mm; % Distance between arrows

  draw fullcircle scaled (2*u);

  newpath node;
  node := fullcircle scaled w;

  % Use 10 points to avoid modular arithematic
  for i = 0 upto 10 : 
      z[i] = u*dir(45*i);
  endfor

  newpair mid_point ;
  newpair scratch_point ;
  newnumeric tangent_angle;

  for i = 1 upto 8 :
    if i mod 2 = 0 : % blue node
      % Caclulate coordinates
      mid_point := 0.5[z[i], z[i-1]];
      scratch_point := 2*z[i] - 0.5(z[i] + z[i+1]);

      % Draw arrows
      drawarrow shorten(z[i], mid_point, d) withcolor green;
      drawarrow shorten(z[i], scratch_point, d) withcolor blue;

      tangent_angle := angle(0.5[mid_point, scratch_point] - z[i]);
      scratch_point := z[i] + abs(z[i] - mid_point)*dir(tangent_angle);

      drawarrow shorten(z[i], scratch_point, d) withcolor black;

      % Draw node
      fill node shifted z[i] withcolor blue;
    else : % red node
      % Caclulate coordinates
      mid_point := 0.5[z[i], z[i+1]];
      scratch_point := 2*z[i] - mid_point ;

      % Draw arrows
      drawarrow shorten(z[i], mid_point, d) withcolor red;
      drawarrow shorten(z[i], scratch_point, d) withcolor red;

      % Draw node
      fill node shifted z[i] withcolor red;
    fi
  endfor

\stopMPpage
\stoptext

enter image description here

1
  • 1
    After ConTeXt now I feel the need to learn MetaPost thanks to you. Let me finish my thesis please :P
    – percusse
    Jan 29, 2013 at 18:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .