# Can you draw a path from a list or otherwise avoid piecewise joint declarations? (In metapost)

Say i have a mathematical function f I want to plot.

The easiest way to plot this is to evaluate it at small steps along the plotting domain and generate the points.

e.g f(0); f(0.1); f(0.2) ... get converted into (0, f(0)); (0.1, f(0.1)); (0.2, f(0.2)) ...

If one wants to draw a curve rather than dots, one could do

draw (0, f(0))--(0.1, f(0.1));
draw (0.1, f(0.1))--(0.2, f(0.2));


Inside of a loop. In other words, you write a loop, store the result of the prvious computation, compute the current value of x, draw a straigth segment, update x and continue.

Is it possible to do, for example:

%psuedocode
pair list[];
draw list;


?

• Yes, this is what \draw plot coordinates {<list>}; in TikZ does.
– user194703
Dec 24, 2019 at 3:00
• That's for tikz, does that work in metapost too? Dec 24, 2019 at 3:02
• I think so but I did not use it in a long while.
– user194703
Dec 24, 2019 at 3:05

Here's one possibility with metapost. For a macro to take an array as an argument, it is declared as a suffix argument, i.e. one that has suffixes which in this case are 0,1,2,.... The input array must start with index/suffix 0.

\documentclass[border=10cm]{standalone}
\usepackage{luamplib}

\begin{document}
\begin{mplibcode}
vardef pairs(suffix P)=
save p_,i_; path p_;
i_:=0;
p_:=P[0] forever: exitif not (known P[incr i_]); --P[i_] endfor;
p_
enddef;

beginfig(0);
u:=1cm;
pair p[];
p[0]=origin;
p[1]=u*(1,1);
p[2]=u*(2,0);
p[3]=u*(4,0);

draw pairs(p) withpen pencircle scaled 1bp withcolor red;
endfig;
\end{mplibcode}

\end{document}


Edit: As per Thruston's suggestion, we can be a bit more general here. If you would like the option of straight segments or Bezier curves then you could use:

\begin{mplibcode}
vardef pairs(suffix P)(text joiner)=
save p_,i_; path p_;
i_:=0;
P[0] forever: exitif not (known P[incr i_]); joiner P[i_] endfor
enddef;

beginfig(0);
u:=1cm;
pair p[];
p[0]=origin;
p[1]=u*(1,1);
p[2]=u*(2,0);
p[3]=u*(4,-1);
drawoptions(withpen pencircle scaled 1bp);
draw pairs(p,..) withcolor red;
draw pairs(p,--) withcolor blue;
draw pairs(p,{right}..{right});
%k:=0;
%draw pairs(p,{dir (incr k*30)}..{right}) withcolor green;
drawoptions();

endfig;
\end{mplibcode}


• You could make the pairs macro more generic if you defined it as vardef pairs(suffix P)(text joiner) = ... and then passed .. or -- or what you like as the second argument. Feb 23, 2020 at 13:38
• @Thruston That's a good idea..I both didn't think of that and didn't realize (or forgot) that I can delimit a text parameter and keep the ability to pass additional stuff. Feb 24, 2020 at 5:18

Since many TikZ answers get MetaPost answers (which is of course great) here is a TikZ answer for this presumably MetaPost question. Given a list, say, \def\mylist{(0,1) (1,2) (2.5,1/2)} it is very well known that you can plot this list with \draw[blue] plot[smooth] coordinates {\mylist};. What is somewhat less known is that you can also plot lists which have the Mathematica/C++ array structure, say, \def\mylist{{0,1},{1,2},{2.5,1/2}}. This works by exploiting that TikZ can parse and access arrays,

\draw plot[samples at={0,1,2}] ({{\mylist}[\x][0]},{{\mylist}[\x][1]});


Full MWE with smooth examples:

\documentclass[tikz,margin=3]{standalone}
\begin{document}
\begin{tikzpicture}
\def\mylist{(0,1) (1,2) (2.5,1/2)}
\draw plot coordinates {\mylist};
\draw[blue] plot[smooth] coordinates {\mylist};
\begin{scope}[yshift=-4cm]
\def\mylist{{0,1},{1,2},{2.5,1/2}}
\draw plot[samples at={0,1,2}] ({{\mylist}[\x][0]},{{\mylist}[\x][1]});
\draw[blue] plot[smooth,samples at={0,1,2}] ({{\mylist}[\x][0]},{{\mylist}[\x][1]});
\end{scope}
\end{tikzpicture}
\end{document}