I need to draw the following graphs using Metapost. How to draw the arrows on curves? Thank you very much.

enter image description here

  • What have you tried so far? Please add some example code to your question, e.g., code to draw the curves without arrows or code to draw arrows without curves. Also: is MetaPost strictly required? This can be done with packages like tikz or pstricks as well.
    – Marijn
    Oct 31, 2018 at 16:58
  • use drawarrow in combination with cutbefore and cutafter
    – sztruks
    Oct 31, 2018 at 16:59
  • Make your curves as named variables (type path), draw them, the use drawarrow + subpath to draw a shorter version of a given path on top if the original path, with an arrow at the end of the subpath. This data type path and subpath are one of the things I really miss in tikz.
    – daleif
    Oct 31, 2018 at 17:42

2 Answers 2


Metafun provides a macro arrowheadonpath to draw an arrow at any time on the path. Here is an example in ConTeXt which shows how the arrow looks like for all three arrow head variants provided in context:

  save p; path p;

  p := (1cm, 1cm) {up} .. {down} (0,0);

  ahvariant := 0;
  draw p ;
  fill arrowheadonpath(p, 0.125);

  p := p shifted (1cm,0);

  ahvariant := 1;
  draw p ;
  fill arrowheadonpath(p, 0.125);

  p := p shifted (1cm,0);

  ahvariant := 2;
  draw p ;
  fill arrowheadonpath(p, 0.125);

which gives

enter image description here


You can do this with plain Metapost as well.

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

vardef open_arrowhead expr p =
  save q,e; path q; pair e;
  e = point length p of p;
  q = gobble(p shifted -e cutafter makepath(pencircle scaled 2ahlength))
  (q rotated .5ahangle & reverse q rotated -.5ahangle)  shifted e

vardef draw_open_arrow expr p = 
    draw p;
    draw open_arrowhead p;

    path arc[];

    arc0 = 100 right .. 20 down {left} .. 100 left;

    arc1 = arc0 shifted 20 down rotated -10;
    arc2 = reverse arc0 shifted 20 down rotated 230;
    arc3 = reverse arc0 shifted 20 up reflectedabout(left, right) rotated 110;

    numeric t[], u[];
    (t1, t3) = arc1 intersectiontimes arc3;
    (u1, u2) = arc1 intersectiontimes arc2;
    (t2, u3) = arc2 intersectiontimes arc3;

    % def drawarrow = draw_open_arrow enddef;
    ahangle := 30;
    forsuffixes $=1,2,3:
        drawarrow subpath 1/2 ( 0,    t$)    of arc$;
        drawarrow subpath 1/2 (t$,    t$+u$) of arc$;
        drawarrow subpath 1/2 (t$+u$, u$+2)  of arc$;
        draw      subpath 1/2 (u$+2,  4)     of arc$;


Compile this program with mpost to get the following EPS figure:

enter image description here

Here I've used the default arrow heads with ahangle reduced from the default of 45 to 30, which makes them look a bit nicer in the middle of a line.

But if you prefer the open arrow heads in your sketch then uncomment the line

def drawarrow = draw_open_arrow enddef;

and make the arrow head angle a bit larger:

ahangle := 60;

These changes produce this figure:

enter image description here

You must log in to answer this question.

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