23

In the figure below, I would like both segments to have the upward arrow that's currently in the left-hand segment, but I would also like both segments to have the nice round shape that's currently in the right-hand segment.

enter image description here

MWE code:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
    \tikzstyle{smallnode}=[circle, inner sep=0mm, outer sep=0mm, minimum size=2mm, draw=black, fill=black];

    \node[smallnode, label={$i$}] (i)   at (0,0) {};
    \node[smallnode, label=below:{$j$}] (j)     at (1.5,-1) {};
    \node[smallnode, label={$k$}] (k)       at (1.5,0) {};
    \node[smallnode, label=below:{$l$}] (l)     at (0,-1) {};

    \draw (i) to[out=180, in=180, edge node={node [sloped,below] {$\leftarrow$}}] (l);
    \draw (k) .. controls ($ (k) +(2,1)$) and ($ (j) +(2,-1)$) .. (j);
\end{tikzpicture}

\end{document}

My problem is that using out/in angles, as in the left segment, doesn't allow flexibility in how "rounded" the curve appears, though it does make it very easy to add the arrow. On the other hand, using Bezier curves, as in the left segment, doesn't seem to allow edge nodes (or does it? -- I tried

\draw (k) to[out=180, in=180, edge node={node [sloped,below] {$\leftarrow$}}] 
          .. controls ($ (k) +(2,1)$) and ($ (j) +(2,-1)$) .. (j);

and a few other syntaxes but couldn't get it).

By the way, I'm a pretty new TikZ user, so if I'm doing anything else silly in this code, please let me know!

4
  • You can start reading a bit about the tension key if my memory serves me well.
    – percusse
    Oct 27, 2014 at 15:31
  • 2
    Also looseness.
    – Manuel
    Oct 27, 2014 at 15:35
  • Thanks. tension seems to apply only to plots. But looseness did the trick. @Manuel, please post as an answer; I'll accept it and post my final code. Oct 27, 2014 at 15:45
  • I didn't even read the question (and I think I don't know the answer), answer it yourself, or wait for someone else.
    – Manuel
    Oct 27, 2014 at 16:13

3 Answers 3

26

My final code, based on @Manuel's suggestion:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
    \tikzstyle{smallnode}=[circle, inner sep=0mm, outer sep=0mm, minimum size=2mm, draw=black, fill=black];

    \node[smallnode, label={$i$}] (i)   at (0,0) {};
    \node[smallnode, label=below:{$j$}] (j)     at (1.5,-1) {};
    \node[smallnode, label={$k$}] (k)       at (1.5,0) {};
    \node[smallnode, label=below:{$l$}] (l)     at (0,-1) {};

    \draw (i) to[out=150, in=210, looseness=4, edge node={node [sloped,below] {$\leftarrow$}}] (l);
    \draw (k) to[out=30, in=-30, looseness=4, edge node={node [sloped,above] {$\leftarrow$}}] (j);
\end{tikzpicture}

\end{document}

Result:

enter image description here

7

You can always place a node over the path and attach some label to it:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
    \tikzstyle{smallnode}=[circle, inner sep=0mm, outer sep=0mm, minimum size=2mm, draw=black, fill=black];

    \node[smallnode, label={$i$}] (i)   at (0,0) {};
    \node[smallnode, label=below:{$j$}] (j)     at (1.5,-1) {};
    \node[smallnode, label={$k$}] (k)       at (1.5,0) {};
    \node[smallnode, label=below:{$l$}] (l)     at (0,-1) {};

    \draw (i) to[out=180, in=180, edge node={node [sloped,below] {$\leftarrow$}}] (l);
    \draw (k) .. controls ($ (k) +(2,1)$) and ($ (j) +(2,-1)$) .. (j) node[pos=0.5, inner sep=-1pt, label=right:{$\uparrow$}] {};
\end{tikzpicture}

\end{document}

enter image description here

1
  • Thanks -- this is a good trick too, but I think looseness is a simpler way to go. Oct 27, 2014 at 16:50
5

Here's a Metapost version for comparison. I've defined the two curves as path variables, so that I can then use the point x of y notation to place a label at a suitable point along the path.

enter image description here

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

u = 1/2cm;
z1 = -z2 = (-3/2u,+u);
z3 = -z4 = (+3/2u,+u);

path h[];
h1 = z2 {dir -30} .. {dir 210} z3;
h2 = z4 {dir 210} .. {dir -30} z1;

draw h1; 
draw h2; 

label.rt (btex $\uparrow$ etex, point 0.5 of h1);
label.lft(btex $\uparrow$ etex, point 0.5 of h2);

dotlabel.top(btex $i$ etex, z1);
dotlabel.bot(btex $j$ etex, z2);
dotlabel.top(btex $k$ etex, z3);
dotlabel.bot(btex $l$ etex, z4);

endfig;
end.

However you can make rather sexier arrows by using subpath to draw an arbitrary part of the part shifted sideways a bit, like this:

enter image description here

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(2);
u = 1/2cm;

z1 = -z2 = (-3/2u,+u);
z3 = -z4 = (+3/2u,+u);

path h[];
h1 = z2 {dir -30} .. {dir 210} z3;
h2 = z4 {dir 210} .. {dir -30} z1;

draw h1; 
draw h2; 

drawarrow subpath (0.4,0.6) of h1 shifted 5 right;
drawarrow subpath (0.4,0.6) of h2 shifted 5 left;

dotlabel.top(btex $i$ etex, z1);
dotlabel.bot(btex $j$ etex, z2);
dotlabel.top(btex $k$ etex, z3);
dotlabel.bot(btex $l$ etex, z4);

endfig;
end.
1
  • Ooh, I like the sexy arrows. I don't use MetaPost but will see whether I can find a way to convert this to TikZ. Oct 27, 2014 at 20:59

You must log in to answer this question.

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