Learn MetaPost

Functions and text

Functions

MetaPost lets users define their own functions through variable macros using the vardef keyword.

Lets define and draw the probability density function of the standard normal deviation.

vardef std_normal(expr x) = 
  e:=2.7182;
  pi:=3.1415;
  (1/sqrt(2*pi))*(e**-((x**2)/2))
enddef;

Notice that ** has the same precedence as * in metapost so the parentheses are needed.

Now we can use a For loop to draw the function:

Normal distribution pdf.

  draw ((-4,std_normal(-4)) for i:=-3.9 step 0.1 until 4:
      ..(i,std_normal(i)) endfor) scaled 2u yscaled u;

this gets a bit long if we are drawing several functions, so lets define a macro to draw out math functions. Since we don't have functions as such, but only macros we can't easily pass functions as input into other functions. But there is a way. In order to pass macros to other macros we can use the scantokens (string) function. This tell MetaPost to interpret a string as if it was a MetaPost command.

vardef functionpath (expr func, a, b) =
  ((a, scantokens func(a)) for i:=a step (1/(10(b-a))) until b:
      ..(i,scantokens func(i)) endfor)
enddef;

We can then replace our draw code with a call to the macro, maybe in a for loop. Of course we now have to remember to pass our macro name as a string as expected by scantokens.

  for i:=0 upto 5:
    draw functionpath("std_normal", -4, 4) scaled 2u yscaled u shifted (i*u,0);
  endfor;

Calling functions in a loop.

Text

MetaPost is often used to make figures for LaTeX documents, but in turn MetaPost also uses LaTeX to typeset text. You can do some simple text as we have seen already by just putting in strings. But if you need to include variables in your strings, or just have more control of how the text looks MetaPost uses LaTeX to compile our text into images. There are a few different ways to put input LaTeX strings in your figures, but the one I find easiest and most powerful is with the TEX.mp utility library.

TEX.mp is simply a MetaPost file thats is distributed with metapost, you should be able to load in into your session by including the line

input TEX;

Once this file is loaded you can use the TEX function to typeset labels with LaTeX commands. The TEX function expects a LaTeX formatted string, to embed MetaPost variables into the string use & for appending and decimal(x) to cast the numeric x into the decimal type which is compatible with string embedding. For example we can add a labeled x-axis to our figure:

drawarrow (-1.5,0)--(1.5,0);
for i:= -1.5 step 0.5 until 1.5:
label(TEX("$"&decimal(i)&"$"),(i,0));
endfor

Exercise

Define you own mathematical function using vardef and draw it out, add some LaTeX formatted labels to your figure using the TEX command.

Function on grid with labels.

Hint

outputformat := "png";
outputtemplate := "%j_%c.png";
hppp := 0.25;
vppp := 0.25;
u:=0.5cm;
input TEX;

vardef fun (expr x)=
  (x**2)*u/10
enddef;

beginfig(1)
  for i:=0 upto 10:
    draw (0,i*u)--(10u,i*u);
    draw (i*u,0)--(i*u,10u);
    label.bot(TEX("$x_{"& decimal(i) &"}$"),(i*u,0));
  endfor;
  draw (0,0) for i:=1 upto 10: ..(i*u,fun(i)) endfor;
endfig;
end;
Last updated on 28 Mar 2021
Published on 28 Mar 2021