% author    : Hans Hagen
% copyright : ConTeXt Development Team
% license   : Creative Commons Attribution ShareAlike 4.0 International
% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions
% origin    : the ConTeXt distribution
%
% comment   : Because this manual is distributed with TeX distributions it comes with a rather
%             liberal license. We try to adapt these documents to upgrades in the (sub)systems
%             that they describe. Using parts of the content otherwise can therefore conflict
%             with existing functionality and we cannot be held responsible for that. Many of
%             the manuals contain characteristic graphics and personal notes or examples that
%             make no sense when used out-of-context.

\usemodule[magazine-basic,abr-02]

\usemodule[scite]

\startbuffer[abstract]
    As part of the \CONTEXT\ \LMTX\ project, we experiment with new ways to
    interface subsystems and \METAPOST\ makes a good candidate. Here I wrap up some
    experiments. It's not a manual or a recipe, just food for thought. All you see
    here might change and|/|or evolve.
\stopbuffer

\setuplayout
  [backspace=20mm,
   topspace=10mm]

\startdocument
  [title={New interfacing in \METAFUN, a preview},
   author={Hans Hagen & Alan Braslau},
  %affiliation=PRAGMA ADE,
   date=July 2019,
   number=1104 LMTX]

As we move to \CONTEXT\ \LMTX, some decisions need to be made. For instance, how
shall we introduce new functionality while not affecting the \MKIV\ code base too
much with engine related tests, messy and performance sapping. Of course we
remain downward compatible but the \LUAMETATEX\ engine sometimes permits multiple
solutions. As this is something new, for a while we can use experimental features
that may change or later disappear depending on experience. It is not a big deal
to adapt to these new possibilites and users shouldn't notice, unless of course
they currently employ (yet undocumented) low|-|level features. Part of the
solution is to have separate files for \MKIV\ and \LMTX, although that will
mostly concern low level support modules; even then differences will be subtle
and should not affect users. I must admit that some of those changes are mostly
aesthetic and often don't improve performance, although better performance
sometimes may be the case, in particular concerning \quote {extreme} usage.

But, that said, there are areas where \LMTX\ will offer entirely new
functionality. One of the areas where we are making interesting developments is
in \METAFUN, which means \METAPOST. Now, it is not to be said that some of the
core functionality needed for this will migrate from \LUAMETATEX\ (used by \LMTX)
to \LUATEX\ (used by \MKIV). But, because (due to external pressure), the later
engine is now considered stable and its functionality frozen, it is not likely to
be quickly backported or at least only will happen when this has been throughly
tested in \CONTEXT|/|\LMTX.

Over the years there have been (small) improvements in the interface but while
Alan Braslau and I experiment with new graphic abilities, we also are coming up
with (graphic) interfaces that suit \CONTEXT\ much better. Below, I will show
some examples. \footnote {These optional argument handlers themselves are
\emphasize {not} part of \METAPOST\ but implemented in \CONTEXT\ using some
experimental parsing related extensions to a version of \MPLIB\ used in
\LUAMETATEX.}

\startbuffer
\startMPcode{doublefun}
    draw lmt_grid [
        nx =  20, ny =  10,
        dx =   5, dy =   2,
        tx =  10, ty =  10,
    ] ysized 5cm withpen pencircle scaled 1mm withcolor "red" ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

What we see here is an key|/|value driven interface that has been one of the
unique core properties of \CONTEXT\ since it was created. \footnote {Note the use
of the color string \type {"red"} rather then the \METAPOST\ color variable \type
{red := (1,0,0)}. This is a small detail but here imports the color definition
from \CONTEXT, which might be a bit special.} Of course parameters can be
optional as demonstrated in:

\startbuffer
\startMPcode{doublefun}
    draw lmt_grid [
        nx =  10, ny =  10,
        dx =   1, dy =   1
    ] ysized 3cm
        withpen pencircle scaled 1mm
        withcolor "darkblue"  ;

    draw lmt_grid [
        nx = 10, ny = 10
    ] ysized 3cm shifted (4cm,0)
       withpen pencircle scaled .3mm
       withcolor "darkgreen" ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

This syntax means that we can also use the already used interface documentation
system.

We can actually go quite far in what we provide. It's not so much that these
things were not possible before, but the more concise user interface is something
new indeed. Let's start with drawing some simple axis:

\startbuffer
\startMPcode{doublefun}
    draw lmt_axis [
        nx =  20, ny =  10,
        dx =   5, dy =   2,
    ] ysized 4cm
        withpen pencircle scaled 1mm
        withcolor "darkcyan" ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

This \quote {article} is not meant as tutorial but more as a teaser about what is
possible and hopefully it triggers users in coming up with useful demands. As the
previous axis example is not that interesting we move on to a more complex one:

\startbuffer
\startMPcode{doublefun}
    draw lmt_axis [
        sx =   5mm, sy =   5mm,
        nx =  20,   ny =  10,
        dx =   5,   dy =   2,
        tx =  10,   ty =  10,
    ] withpen pencircle scaled 1mm withcolor "darkblue" ;

    draw lmt_connected (
        for i = 1 step 2 until 20 :
            -- (i, 1 randomized 8) * 5mm
        endfor
    )
        withpen pencircle scaled 2mm withcolor "darkyellow" ;

    draw lmt_connected (
        for i = 1 step 2 until 20 :
            lmt_connection (i, 1 randomized 8) * 5mm
        endfor
    )
        withpen pencircle scaled 2mm withcolor "darkgreen" ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

These examples are made as part of exploring how to best interface with
\METAPOST, to be used by the upcoming luagraph module, a flexible and high
performance set of macros aimed at drawing graphs and to visualize data. On the
one hand, we want to free the user from dealing with details such as scales to
get the graphics right, but on the other hand it should be possible to
fine|-|tune when needed.

Again we draw an axis. Using strings as color names, mentioned in the footnote
earlier, is not new, but already present for a while. It will use the colors
defined at the \TEX\ end and is more convenient and natural than using the older
\type {\MPcolor}. The \type {lmt_connected} macro is sort of a gimmick: if you
look closely you will see that it has to start with a point (coordinate) but that
one is discarded silently. Again this is something we need to deal with.

% This is obscure, and silly. I'm sure that we can do better. Sure, but so is the
% HIDE related alternative trrickery. We probably need something getparameterpath.

The next variant uses a list of samples. Watch the use of braces, this is
something normally not part of \METAPOST\ syntax, and it signals a \LUA|-|like
list. This is a choice of interfacing. There are subtle and somewhat complicated
aspects involved here as \METAPOST\ parsing involves primaries, secondaries,
tertiaries and expressions, symbols, strings, tags and other specialities.

% Why does samples = {} require a second pair of brackets? Wouldn't a
% comma-separated list be enough in Lua? Because it's \METAPOST\ which has its own
% ideas about where expressions start and end.

\startbuffer
\startMPcode{doublefun}
    draw lmt_axis [
        sx     =  5mm, sy     =  5mm,
        nx     = 20,   ny     = 10,
        dx     =  5,   dy     =  2,
        tx     =  5,   ty     =  2,
        startx =  1,   starty =  0,

        connect = true,
        samples = {
            {
                4, 2, 4, 9, 3, 0, 8, 9, 10, 1,
                5, 3, 0, 8, 5, 6, 10, 2, 3, 5
            }
        },
        axiscolor    = "darkgreen",
        textcolor    = "darkred",
        samplecolors = {
            "darkblue"
        },
    ] withpen pencircle scaled 1mm ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

We can have multiple sample lists. But of course dealing with that is really up
to the underlying code, which itself is not that much related to \METAPOST\ but
has been delegated to \LUA.

\startbuffer
\definecolor[tdarkred]  [r=.6,a=1,t=.5]
\definecolor[tdarkgreen][g=.6,a=1,t=.5]
\definecolor[tdarkblue] [b=.6,a=1,t=.5]

\startMPcode{doublefun}
    save u ; let u = uniformdeviate ;
    draw lmt_axis [
        sx =  5mm, sy =  5mm,
        nx = 20,   ny = 10,
        dx =  5,   dy =  2,
        tx = 10,   ty =  2,
        samples = {
            {
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10
            },
            {
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10
            },
            {
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10,
                u10, u10, u10, u10, u10
            }
        },
        startx       = 1,
        starty       = 0,
        connect      = true,
        axiscolor    = "darkgray",
        textcolor    = "darkyellow",
        samplecolors = {
            "tdarkred",
            "tdarkgreen",
            "tdarkblue"
        },
    ] withpen pencircle scaled 1mm ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

Yet another interesting variant might be this:

\startbuffer
\startluacode
    documentdata["lmx-sample-1"] = {
        {
            4, 2, 4, 9, 3, 0, 8, 9, 10, 1,
            5, 3, 0, 8, 5, 6, 10, 2, 3, 5
        }
    }
\stopluacode
\stopbuffer

\typebuffer[option=TEX] \getbuffer

\startbuffer
\startMPcode{doublefun}
    draw lmt_axis [
        sx     = 5mm, sy     = 5mm,
        nx     = 20,  ny     = 10,
        dx     = 5,   dy     = 2,
        tx     = 5,   ty     = 2,
        startx = 1,   starty = 0,

        samples      = "lmx-sample-1",
        axiscolor    = "darkgreen",
        textcolor    = "darkred",
        samplecolors = { "darkblue" },
    ] withpen pencircle scaled 1mm ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

% OOPS, doesn't work!

Adding more tricks is not that complex, take, for example:

\startbuffer
\startMPcode{doublefun}
draw lmt_axis [
    sx =  5mm, sy =  5mm,
    nx = 20,   ny = 10,
    dx =  5,   dy =  2,
    tx = 10,   ty = 10,

    list = {
        [
            connect = true,
            color   = "darkred",
            close   = true,
            points  = { (1, 1), (15, 8), (2, 10) },
            texts   = { "segment 1", "segment 2", "segment 3" }
        ],
        [
            connect = true,
            color   = "darkgreen",
            points  = { (2, 2), (4, 1), (10, 3), (16, 8), (19, 2) },
            labels  = { "a", "b", "c", "d", "e" }
        ],
        [
            connect = true,
            color   = "darkblue",
            close   = true,
            points  = { (5, 3), (8, 8), (16, 1) },
            labels  = { "1", "2", "3" }
        ]
    },

] withpen pencircle scaled 1mm  ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

yielding

\startlinecorrection
\getbuffer
\stoplinecorrection

but this is experimentation, work in progress, not to be taken as settled.

\blank

A variant on this one is the following:

\startbuffer
\startMPcode{doublefun}
draw lmt_function [

    xmin =  0, xmax = 10, xstep = .05,
    ymin = -2, ymax =  2,

    xticks = "bottom", xsmall = 80, xlarge = 20,
    yticks = "left",   ysmall = 40, ylarge =  4,

    code = "1.5 * math.cosd(240 * math.sqrt(x))",

    xlabels = "yes",
    ylabels = "yes",

    ycaption = "\strut\tfd \rotate[rotation=90]{vertical}",
    xcaption = "\strut\tfd horizontal",

    pointsymbol = "dot", pointsize = 4, pointcolor = "orange",

    sx = 2mm, sy = 4mm, linewidth = .025mm, offset = .1mm,
]
    xsized 8cm
;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

A valid question is if this should be combined with the previous but having
distinctive variants is less likely to complicate the settings, as these can
depend on the application:

\startlinecorrection
\getbuffer
\stoplinecorrection

A more complex usage (still under exploration) is demonstrated next:

\startbuffer
\definecolor[MyColorR][r=.5,t=.5,a=1]
\definecolor[MyColorG][g=.5,t=.5,a=1]
\definecolor[MyColorB][b=.5,t=.5,a=1]
\definecolor[MyColorY][r=.5,g=.5,t=.5,a=1]

\startMPcode{doublefun}
draw lmt_function [
    sx = 1mm, sy = 4mm, linewidth = .025mm, offset = .1mm,

    xmin =  0, xmax = 20, xstep     = .1,
    ymin = -2, ymax =  2,

    xticks = "bottom", xsmall = 80, xlarge = 20, xlabels = "nolimits",
    yticks = "left",   ysmall = 40, ylarge =  4, ylabels = "yes",

    code  = "1.5 * math.sind (50 * x - 150)",

    frame = "sticks", % "ticks"

    functions = {
        [
            xmin      =  1.0,
            xmax      =  7.0,
            close     = true,
            fillcolor = "MyColorR"
        ],
        [
            xmin      =  7.0,
            xmax      = 12.0,
            close     = true,
            fillcolor = "MyColorG"
        ],
        [
            xmin      = 12.0,
            xmax      = 19.0,
            close     = true,
            fillcolor = "MyColorB"
        ],
        [
            drawcolor = "darkyellow",
            drawsize  = 2,
        ],
        [
            xmin      =   4,
            xmax      =  17,
            xstep     = .25,
            drawcolor = "darkmagenta",
            shape     = "steps",
            code      = "0.5 * math.random(-2,2)",
        ],
        [
            xmin      =  5.0,
            xmax      = 15.0,
            close     = true,
            fillcolor = "MyColorY"
            code      = "1.75 * math.cosd (50 * x - 150)",
        ]
    },
    ycaption  = "\rotate[rotation=90]{\tfd\strut a mix of drawings}",
    xcaption  = "\framed[foregroundstyle=\tfd]{a mixture of $\sin(x), \cos(x), \sqrt{x}$ etc.}",
]
    xsized 8cm
;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

Of course calling the same command multiple times with different code snippets
will also work.

\startlinecorrection
\getbuffer
\stoplinecorrection

The previous examples used new code but how about improving existing features?
Let's look at outlines.

\startbuffer
\startMPcode{doublefun}
    save h ; h = 12mm ;

    draw lmt_outline [
        text      = "hello"
        kind      = "draw",
        drawcolor = "darkblue",
    ] ysized h ;

    draw lmt_outline [
        text          = "hello",
        kind          = "fill",
        fillcolor     = "darkred",
    ] ysized h shifted (3.75h,0) ;

    draw lmt_outline [
        test          = "hello",
        kind          = "both",
        fillcolor     = "darkred",
    ] ysized h shifted (7.5h,0mm) ;

    draw lmt_outline [
        text          = "hello",
        kind          = "both",
        fillcolor     = "darkred",
        drawcolor     = "darkblue",
        rulethickness = 1/5,
    ] ysized h shifted (0,-1.25h) ;

    draw lmt_outline [
        text          = "hello",
        kind          = "reverse",
        fillcolor     = "darkred",
        drawcolor     = "darkblue",
        rulethickness = 1/2,
    ] ysized h shifted (3.75h,-1.25h) ;

    draw lmt_outline [
        text          = "hello",
        kind          = "fillup",
        fillcolor     = "darkgreen",
        rulethickness = 0,
    ] ysized h shifted (7.5h,-1.25h) ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

This interface is much nicer than the one where each variant (the parameter \type
{kind} above) had its own macro due to the need to group properties of the
outline and fill. Let's show some more:

\startbuffer
\startMPcode{doublefun}
    draw lmt_outline [
        text      = "\obeydiscretionaries\samplefile{tufte}",
        align     = "normal",
        kind      = "draw",
        drawcolor = "darkblue",
    ] xsized TextWidth ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

\startbuffer
\startMPcode{doublefun}
    draw lmt_outline [
        text      = "\obeydiscretionaries\samplefile{ward}",
        align     = "normal,tolerant",
        width     = 10cm,
        kind      = "draw",
        drawcolor = "darkblue",
    ] xsized TextWidth ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

\startbuffer
\startMPcode{doublefun}
    draw lmt_outline [
        text          = "\obeydiscretionaries\samplefile{sapolsky}",
        align         = "normal,tolerant",
        style         = "bold",
        width         = 10cm,
        kind          = "draw",
        rulethickness = 1/5,
        drawcolor     = "darkred",
    ] xsized TextWidth ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

Another \METAFUN\ text related mechanism deals with following a specific path.
That interface has evolved over time, also due to more advanced possibilities in
\MKIV. But, it's again time for a upgrade, for example:

\startbuffer
\startMPcode{doublefun}
    draw lmt_followtext [
        text    = "How well does it work {\bf 1}! ",
        path    = (fullcircle scaled 4cm),
        trace   = true,
        spread  = true,
    ] ysized 5cm ;

    draw lmt_followtext [
        text    = "How well does it work {\bf 2}! ",
        path    = fullcircle scaled 4cm,
        trace   = true,
        spread  = false,
        reverse = true,
    ] ysized 5cm shifted (0,-6cm) ;

    draw lmt_followtext [
        text        = "How well does it work {\bf 3}! ",
        trace       = true,
        autoscaleup = "yes"
    ] ysized 5cm shifted (6cm,0) ;

    draw lmt_followtext [
        text        = "How well does it work {\bf 4}! ",
        path        = fullcircle scaled 2cm,
        trace       = true,
        autoscaleup = "max"
    ] ysized 5cm shifted (6cm,-6cm) ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

Although \METAPOST\ can draw arrows a bit more code is involved than one would
have expected. As a consequence, influencing the way an arrowhead is drawn as
currently using variables is somewhat cumbersome. Here is an alternative:

\startbuffer
\startMPcode{doublefun}
    draw lmt_arrow [
        path = fullcircle
            scaled  3cm
            shifted (0,0cm),
    ] withcolor "darkred" ;

    draw lmt_arrow [
        location = "both"
        path     = fullcircle
            scaled  3cm
            rotated 90
            shifted (0,-3.5cm),
    ] withcolor "darkgreen" ;

    draw lmt_arrow [
        kind        = "draw",
        location    = "middle",
        alternative = "curved",
        path        = fullcircle
            scaled  3cm
            shifted (3.5cm,0cm),
    ] withcolor "darkblue" ;

    for i = 0 step 5 until 100 :
        draw lmt_arrow [
            alternative = "dimpled",
            location    = "percentage",
            percentage  = i,
            dimple      = (1/5 + i/200),
            headonly    = (i = 0),
            path        = fullcircle
                scaled  3cm
                shifted (3.5cm,-3.5cm),
        ] withcolor "darkyellow" ;
    endfor ;
\stopMPcode
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

These new interfaces for outlines, following text and arrows certainly will make
it in some form to be permanent \METAFUN\ extensions. Some will also be used in
macros at the \TEX\ end, for instance, when you load the dummy library:

\startbuffer
\useMPlibrary[dum]
\stopbuffer

\typebuffer[option=TEX] \getbuffer

You can do this:

\startbuffer
\startcombination
    {\externalfigure[crap-001]} {one}
    {\externalfigure[crap-004][alternative=triangle]} {two}
\stopcombination
\stopbuffer

\typebuffer[option=TEX]

and get:

\startlinecorrection
\getbuffer
\stoplinecorrection

This placeholder now also can be accessed directly:

\startbuffer
\useMPmacro
  [minifun]
  [placeholder]
  [width=10cm,
   height=3cm,
   reduction=.2,
   alternative=triangle,
   color=orange]
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

The \type {\useMPmacro} is an entirely new interface to \METAFUN\ code. Although
it is still experimental, we show an example. Of course, as needed, you can throw
in some \LUA\ magic.

\startbuffer
\startMPcalculation
    presetparameters "demo" [
        n = 5,
        s = 1cm,
    ] ;

    def lmt_demo = applyparameters "demo" "lmt_do_demo" enddef ;

    vardef lmt_do_demo =
        for i=1 upto getparameter "demo" "n" :
            draw fullcircle scaled (i*getparameter "demo" "s");
        endfor ;
    enddef ;
\stopMPcalculation
\stopbuffer

\typebuffer[option=TEX]

The calculation wrapper makes this code be processed immediately, which is needed
because we don't use a module.

\getbuffer

A the \TEX\ end we do this:

\startbuffer
\defineMPparameterset[demo][n=integer,s=dimension]
\stopbuffer

\typebuffer[option=TEX]

\getbuffer

We can now let the macro do its work:

\startbuffer
\startcombination[nx=4,location=middle]
    {\useMPmacro[demo][n=8,s=2mm]}        {Demo 1}
    {\useMPmacro[demo][n=4,s=4mm]}        {Demo 2}
    {\useMPmacro[demo][n=4,s=5\exheight]} {Demo 3}
    {\useMPmacro[demo]}                   {Demo 4}
\stopcombination
\stopbuffer

\typebuffer[option=TEX]

\startlinecorrection
\getbuffer
\stoplinecorrection

You can also set the parameters separately. There is one catch: there is no
grouping so in this case you need to reset the parameters afterwards.

\starttyping
\presetMPparameters[demo][n=8] \useMPmacro[demo]\blank
\presetMPparameters[demo][n=4] \useMPmacro[demo]\blank
\resetMPparameters [demo]      \useMPmacro[demo]\blank
\stoptyping

These examples demonstrate that we can make \METAPOST\ a bit friendlier for users
who are not that fluent with the language. It remains to be seen to what extent
additional modules will be written, but the possibilities are there.

\stopdocument

