[NTG-context] Implicit plots/level curves possible?

Alan Braslau braslau.list at comcast.net
Wed Oct 10 00:23:41 CEST 2018


On Mon, 8 Oct 2018 17:56:24 -0400 (EDT)
Aditya Mahajan <adityam at umich.edu> wrote:

> Here is a proof of concept implementation in Lua + MP so that you can use:
> 
> \ContourPlot
>    [
>      function=2*x^5 + x*y + y^5,
>      x={0, 2},
>      y={-2, 0.5},
>      n=1000, % Number of discretization points
>    ]
> 
> The code is fairly fast. But be careful. As with all ConTeXt key-value 
> assignment, `x = { ...}` is different from `x={...}`. I am being a bit 
> lazy here, and haven't adapted the metapost code to draw the axes to adapt 
> to the function.

Hans and I played with Aditya's demonstration, to complete the example.
It demonstrates some fun lua+MP+ConTeXt tricks:

Alan


\startluacode
   userdata         = userdata or { }
   userdata.contour = { }
   userdata.xlim    = { 0, 0 }
   userdata.ylim    = { 0, 0 }

   function userdata.contourplot(f, xlim, ylim, length, ef)
       local xmin, xmax = xlim[1], xlim[2]
       local ymin, ymax = ylim[1], ylim[2]
       local t = { }
       local n = 0
       for x = xmin, xmax, (xmax - xmin)/length do
           for y = ymin, ymax, (ymax - ymin)/length do
               local e = ef(x,y)
               local z =  f(x,y)
               if z < e and z > -e then
                  n = n + 1
                  t[n] = { x, y }
               end
           end
       end
       userdata.xlim    = xlim
       userdata.ylim    = ylim
       userdata.contour = t
   end

   function mp.ContourPath()
       mp.path(userdata.contour)
   end
   function mp.ContourX()
       mp.pair(userdata.xlim)
   end
   function mp.ContourY()
       mp.pair(userdata.ylim)
   end
\stopluacode

\startuseMPgraphic{doublefun::ContourPlot}{width}
    save xmin, xmax, ymin, ymax ;
    (xmin, xmax) = lua.mp.ContourX() ;
    (ymin, ymax) = lua.mp.ContourY() ;

    draw lua.mp.ContourPath() withpen pencircle scaled ((xmax-xmin)/200) ;
    setbounds currentpicture to boundingbox ((xmin,ymin)--(xmax,ymax));
    currentpicture := currentpicture xsized \MPvar{width} ;

    save pic ; picture pic ; pic := currentpicture ;
    drawarrow llcorner pic--lrcorner pic ;
    drawarrow llcorner pic--ulcorner pic ;
    label.rt ("$x$", lrcorner pic) ;
    label.top("$y$", ulcorner pic) ;
    label.bot(decimal xmin,llcorner pic) ;
    label.bot(decimal xmax,lrcorner pic) ;
    label.lft(decimal ymin,llcorner pic) ;
    label.lft(decimal ymax,ulcorner pic) ;
\stopuseMPgraphic

\unexpanded\def\ContourPlot
  {\dosingleempty\doContourPlot}

\def\doContourPlot[#1]%
  {\setvariables
     [ContourPlot]
     [x={0,0},
      y={0,0},
      w=10cm,
      n=1000,
      e=1e-2,
      #1]%
   \ctxlua{userdata.contourplot(
        function(x,y) return \getvariable{ContourPlot}{function} end,
        {\getvariable{ContourPlot}{x}},{\getvariable{ContourPlot}{y}},
        \getvariable{ContourPlot}{n},
        function(x,y) return \getvariable{ContourPlot}{e} end
   )}%
   \useMPgraphic{doublefun::ContourPlot}{width=\getvariable{ContourPlot}{w}}}

\starttext

\ContourPlot
   [function={2*x^5 + x*y + y^5},
    x={0,2},y={-2,0.5},
    n=1000,e={x/1000},w=5cm]

\stoptext


More information about the ntg-context mailing list