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:
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;
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.
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;