5

I want to label a scale based on a variable value and I wrote a metapost code like this.

$ := 1;
for i = -.3cm step .6cm until 3.6cm:
    label.bot(str$,(i,-3.7cm));
    $ := incr($);
endfor;

It just labels "$" instead of its value. How to output the variables value?

3 Answers 3

8

To get the value of the variable, use the decimal macro. The following works:

$:=1;
for i = -.3cm step .6cm until 3.6cm:
    label.bot(decimal $,(i,-3.7cm));
    $ := incr($);
endfor

To quote the MetaPost manual:

The str operator is generally for emergency use only.

further

The decimal operator takes a number and returns the string representation.

8

The problem with using solutions like

$ := 1;
for i = -.3cm step .6cm until 3.6cm:
  label.bot(decimal $,(i,-3.7cm));
  $ := incr($);
endfor;

is that the infont operator is called to typeset the labels. infont has very few typesetting abilities, particularly with mathematical expressions, to the contrary of the btex … etex flags which allows the use of TeX and co. for this task.

Currently there are at least three ways to achieve the inclusion of variables in a label with MetaPost, while leaving the typesetting to (La)TeX:

  • Using the TEX.mp package and the TEX function it defines.

    input TEX;
    beginfig(1);
    $ := 1;
    for i = -.3cm step .6cm until 3.6cm:
      label.bot(TEX("$n_" & decimal $ & "$"),(i,-3.7cm));
      $ := incr($);
    endfor;
    endfig;
    end.
    

    TEX.mp calls Plain TeX by default to typeset the labels but it can be configured to use LaTeX as well. It works quite well, but processing a big loop takes an awful lot of time since each call of the TEX function triggers the creation and the processing of a new separate file. See the MetaPost manual, p. 63 and 64 (as for the version contained in TeX Live 2014).

  • Using the much more flexible latexmp package and its textext function, inspired from the function with the same name defined in the MetaFun format included in ConTeXt. This is by far the best way to include labels if you use standalone MetaPost and the LaTeX format for your papers. As its name implies, it uses LaTeX (exclusively) to typeset the labels. Contrary to TEX, it needs two runs to produce the labels (they can be automatized), but since these labels are passed to a single file for processing it goes much quicker anyway. Also latexmp is more easily configurable to suit the author's typesetting needs (e.g. for reproducing the LaTeX preamble of the file which is supposed to contain the drawings). The latexmp documentation is very well done and gives all the details.

     input latexmp;
     beginfig(1);
     $ := 1;
     for i = -.3cm step .6cm until 3.6cm:
       label.bot(textext("$n_" & decimal $ & "$"),(i,-3.7cm));
       $ := incr($);
     endfor;
     endfig;
     end.
    
  • Including the MetaPost program in a LuaLaTeX file (for example with the standalone class) and using the luamplib package. It also has a textext function with the same properties as before, but the author needs to run the file only once to produce the labels. See the luamplib documentation. The main advantage of this tactic is that the labels are automatically typeset in the same fonts as in the general LuaLaTeX document, and so it becomes possible to use OpenType fonts in MetaPost drawings (which is quite impossible to do with standalone MetaPost).

    \documentclass{standalone}
    \usepackage{luamplib}
    \begin{document}
    \begin{mplibcode}
    beginfig(1);
    $ := 1;
    for i = -.3cm step .6cm until 3.6cm:
     label.bot(textext("$n_" & decimal $ & "$"),(i,-3.7cm));
     $ := incr($);
    endfor;
    endfig;          
    \end{mplibcode}
    \end{document}
    

There is also the possibility to use ConTeXt and its own textext function, but I'm not fluent at all in this format.

Each of this method produces the same result, much more difficult to achieve with the mere use of strings combined with the infont operator (if it is possible at all to achieve it this way):

enter image description here

3
  • 2
    In ConTeXt MkIV, you don't need to use the textext function because all strings that are typeset using infont operator in metapost are typeset using TeX. So you can just use label("$ n_{" & decimal(i) & "}$", origin) and it just works
    – Aditya
    Commented Feb 16, 2015 at 21:57
  • @Aditya Is it not because textext is still called, but behind the scene? And if I recall the Metafun manual correctly, textext must still be written explicitly in a standalone MetaPost file which uses ConTeXt as label typesetter and upon which you call the Metafun format. BTW, you can write only label("the text", the_point) with latexmp if you write setupLaTeXmp(textextlabel=enable); at the beginning of your .mp file. Same with LuaLaTeX and luamplib if you write \mplibtextextlabel{enable} in the preamble. In both cases, textext will work but in the background. Commented Feb 16, 2015 at 22:30
  • 1
    @Aditya I've just searched the Metafun manual and as I recalled it is stated there (p. 42) that textext still does the work, but indeed in the background: "When you run inside ConTeXt (as we do here) there is no difference between infont and the TeX methods. This is because we overload the infont operator and also pass its content to TeX. Both infont and btex use the macro textext which is intercepted and redirects the task to TeX. This happens in the current run so there is no need to pass extra information about fonts." Commented Feb 16, 2015 at 22:39
4

If you need a label, which is in TeX (between btex and etex), and you want to use value of a variable there, you can do something like this:

a[0]:=1/2;
for t=0 upto 7:
  a[t+1]:=sqrt(a[t]);
  draw (a[t]*ux,a[t]*uy)--(a[t]*ux,a[t+1]*uy);
  draw (a[t]*ux,a[t+1]*uy)--(a[t+1]*ux,a[t+1]*uy);
  draw (a[t]*ux,-dx)--(a[t]*ux,dx);
  write "label.bot (btex $x_{"&decimal(t)&"}$ etex,(a["&decimal(t)&"]*ux,-dx));"
  to "mptextmp.mp";
endfor;

write EOF to "mptextmp.mp";
scantokens "input mptextmp"  

See also this post on SO: METAPOST: using loop variables in labels

1
  • The code I posted above was part of the metapost source used to obtain this.
    – Martin
    Commented Apr 26, 2014 at 12:30

You must log in to answer this question.

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