9

What is the best way to create diagrams like these in LaTeX? Is Tikz the way to go?

(Code for these specific instances would be useful but is not absolutely required, since I'll be needing to make diagrams similar in spirit but not identical. Also, this has almost certainly been asked before, so I would equally appreciate a link to a previous asking -- I'm just unsure what terms to search to find such a post.)

edit: looked at some old code and came up with

\begin{tikzpicture}

\draw[ultra thick,domain=0:1,samples=100, postaction={decorate}, decoration={markings, mark=at position 0.5 with {\arrow{stealth}}}] (0,1) -- (0,0);
\draw[ultra thick,domain=0:1,samples=100, postaction={decorate}, decoration={markings, mark=at position 0.5 with {\arrow{stealth}}}] (1,1) -- (0,1);
\draw[ultra thick,domain=0:1,samples=100, postaction={decorate}, decoration={markings, mark=at position 0.5 with {\arrow{stealth}}}] (1,0) -- (1,1);
\draw[ultra thick,domain=0:1,samples=100, postaction={decorate}, decoration={markings, mark=at position 0.5 with {\arrow{stealth}}}] (0,0) -- (1,0);

\node at (.5,-.2) {$a$};

\end{tikzpicture}

although this seems rather clunky.

  • I thought about doing something with tikzpicture and explicitly stating the parametrization of each length but it seems that there ought to be a more elegant way to do it. – zjs Jan 7 at 21:59
  • 1
    @zjs Just post what you have got. It will be much easier to see what you want if you post a code example. – Henri Menke Jan 7 at 22:04
11

Welcome to TeX.SE! This answer makes use of this answer.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{decorations.markings}

\begin{document}
\tikzset{lab dis/.store in=\LabDis,
lab dis=0.3,
->-/.style args={at #1 with label #2}{decoration={
  markings,
  mark=at position #1 with {\arrow{>}; \node at (0,\LabDis) {#2};}},postaction={decorate}},
  -<-/.style args={at #1 with label #2}{decoration={
  markings,
  mark=at position #1 with {\arrow{<}; \node at (0,\LabDis)
  {#2};}},postaction={decorate}},
 -*-/.style={decoration={
  markings,
  mark=at position #1 with {\fill (0,0) circle (1.5pt);}},postaction={decorate}},
  }

\begin{tikzpicture}[>=latex]
 \draw[->-=at 0.125 with label {$b$},
 ->-=at 0.375 with label {$a$},
 -<-=at 0.625 with label {$b$},
 -<-=at 0.875 with label {$a$}] (0,0) rectangle (4,4);

 \draw[lab dis=-0.3,
 -*-=0,->-=at 0.125 with label {$b$},
 -*-=0.25,->-=at 0.375 with label {$a$},
 -*-=0.5,-<-=at 0.625 with label {$b$},
 -*-=0.75,-<-=at 0.875 with label {$a$}] (2,-4) circle (2.5);
\end{tikzpicture}
\end{document}

enter image description here

  • I'm not convinced by the ->- and -*- notation. It's pretty hard to read. Now there are dashes everywhere. – Henri Menke Jan 7 at 22:33
  • 7
    @HenriMenke Well, everyone can rename these things as they wish. I do not think this is a fair criticism. And if you really feel you need to make this comment, make it here, where this notation has been proposed. This answer got 69 upvotes without anyone complaining about the notation. – user121799 Jan 7 at 23:05
5

You can place nodes on a path which should simplify the node positioning a lot. You might also want to factor out the arrow business into a style.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}

\begin{tikzpicture}[
  arrow inside/.style = {
    postaction={decorate},
    decoration={markings, mark=at position 0.5 with {\arrow{stealth}}}
  }
  ]

  \draw[arrow inside] (0,0) -- node [below] {$a$} (1,0);
  \draw[arrow inside] (0,1) -- node [above] {$a$} (1,1);
  \draw[arrow inside] (0,0) -- node [left] {$b$} (0,1);
  \draw[arrow inside] (1,0) -- node [left] {$b$} (1,1);

\end{tikzpicture}

\end{document}

enter image description here

  • 2
    Maybe move right b outside?! :-) – Sigur Jan 7 at 23:05
4

This can be an option

\documentclass[tikz, border = 10pt]{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{decorations.markings}

\def\nframes{30}
\def\frame{0}

\begin{document}

\foreach \frame in {0,0,0,0,1,...,\nframes}
{

\pgfmathsetmacro{\time}{\frame / \nframes}
\pgfmathsetmacro{\c}{20 + (3 - 20) / (1 + exp(-10 * (\time - 0.6)))}
\pgfmathsetmacro{\a}{20 + (1 - 20) / (1 + exp(-8 * (\time - 0.3)))}
\pgfmathsetmacro{\xrange}{3 + (180 - 3) / (1 + exp(-14 * (\time - 0.6)))}
\pgfmathsetmacro{\yrange}{3 + (180 - 3) / (1 + exp(-10 * (\time - 0.3)))}
\pgfmathsetmacro{\theta}{90 + (45 - 90) * \time}
\pgfmathsetmacro{\phi}{0 + (25 - 0) * \time}

\pgfplotsset{
  border one/.style={
    thick,
    red,
    samples y  = 0,
    variable   = \t,
    domain     = -\xrange:\xrange,
    postaction = {decorate},
    decoration = {markings,
                  mark = at position 0.48 with {\arrow{stealth}},
                  mark = at position 0.52 with {\arrow{stealth}}}
    },
  border two/.style={
    thick,
    green,
    samples y  = 0,
    variable   = \t,
    domain     = -\yrange:\yrange,
    postaction = {decorate},
    decoration = {markings, mark = at position 0.5 with {\arrow{stealth}}}
  }
}



\begin{tikzpicture}
\useasboundingbox (0, 0) rectangle (6, 6);
\begin{axis} [
    hide axis,
    view               = {\theta}{\phi},
    domain             = -\xrange:\xrange,
    y domain           = -\yrange:\yrange,
    samples            = 20,
    samples y          = 20,
    unit vector ratio  = 1 1 1,
    declare function   = {
      u(\x,\y) = (\c + \a * cos(\y)) * cos(\x);
      v(\x,\y) = (\c + \a * cos(\y)) * sin(\x);
      w(\x,\y) = \a * sin(\y);
    }
  ]

  \addplot3 [
    surf,
    color         = blue,
    opacity       = 0.01,
    faceted color = white,
    z buffer      = sort,
    fill opacity  = 0.5] ({u(\x, \y)}, {v(\x, \y)}, {w(\x, \y)});

  \addplot3 [border one] ({u(\t, \yrange)}, {v(\t, \yrange)}, {w(\t, \yrange)});
  \addplot3 [border one] ({u(\t, -\yrange)}, {v(\t, -\yrange)}, {w(\t, -\yrange)});
  \addplot3 [border two] ({u(\xrange, \t)}, {v(\xrange, \t)}, {w(\xrange, t)});
  \addplot3 [border two] ({u(-\xrange, \t)}, {v(-\xrange, \t)}, {w(-\xrange, t)});


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

enter image description here

DISCLAIMER Just a fun animation, I'm aware it is not exactly what the OP asked for

3

A PSTricks solution just for fun purposes.

\documentclass[pstricks,12pt]{standalone}
\usepackage{pstricks-add}

\begin{document}
\pspicture[arrowinset=0,arrowscale=2](-4,-4)(4,4)
    \curvepnodes[plotpoints=5]{0}{360}{3.5 t 45 add PtoC}{I}
    \foreach \i/\l/\a in {0/a/<,1/b/<,2/a/>,3/b/>}{%
        \pcline[ArrowInside=-\a](I\i)(I\the\numexpr\i+1)\nbput{$\l$}}
\endpspicture
\pspicture[arrowinset=0,arrowscale=2](-4,-4)(4,4)
    \pnode(0,0){O}
    \curvepnodes[plotpoints=5]{0}{360}{3.5 t 135 add PtoC}{I}
    \foreach \i/\l in {0/a,1/b,2/a,3/b}{%
        \qdisk([nodesep=3.5,angle=-45]{I\i}O){2pt}
        \psarc{->}(0,0){3.5}{(I\i)}{(I\the\numexpr\i+1)}
        \uput{8pt}[{(I\i)}](>I\i){$\l$}}
\endpspicture
\end{document}

enter image description here

enter image description here

Note: ArrowInside is not available for \psarc. I don't know why.

3

Another alternative approach using Metapost. Compile this one with lualatex.

enter image description here

\documentclass[border=5mm]{standalone}
\usepackage{luatex85}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
    path S, C;

    S = unitsquare shifted -(1/2, 1/2) scaled 100;
    C = fullcircle scaled 84 rotated 16 shifted 140 right;

    interim ahangle := 30;  % slimmer arrows...

    drawarrow subpath(0, 5/8) of S;
    drawarrow subpath(5/8, 13/8) of S;
    drawarrow subpath(4, 4-5/8) of S;
    drawarrow subpath(4-5/8, 4-13/8) of S;
    draw subpath(13/8, 4-13/8) of S;

    label.top("$a$", point 1/2 of S);
    label.top("$a$", point 5/2 of S);
    label.lft("$b$", point 3/2 of S);
    label.lft("$b$", point 7/2 of S);

    for t=0 upto 3:
        drawarrow subpath 2(t, t+1) of C;
        drawdot point 2t+3/4 of C withpen pencircle scaled 3;
        label(if odd t: "$b$" else: "$a$" fi, 9/8[center C, point 2t+7/4 of C]);
    endfor

endfig;
\end{mplibcode}
\end{document}
3

a variation of nice Henry Menke answer with use of quotes library:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings, quotes}

\begin{document}

\begin{tikzpicture}[auto=right,
  arrow inside/.style = {
    decoration={markings, mark=at position 0.5 with {\arrow{stealth}}},
    postaction={decorate},
                        }
                    ]
  \draw[arrow inside] (0,0) to ["$a$"]   (1,0);
  \draw[arrow inside] (0,1) to ["$a$" '] (1,1);
  \draw[arrow inside] (0,0) to ["$b$" '] (0,1);
  \draw[arrow inside] (1,0) to ["$b$"]   (1,1);
\end{tikzpicture}

enter image description here

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.