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

Alan Braslau braslau.list at comcast.net
Mon Oct 8 22:20:28 CEST 2018


On Mon, 8 Oct 2018 16:00:10 -0400 (EDT)
Aditya Mahajan <adityam at umich.edu> wrote:

> On Sun, 7 Oct 2018, Hans Hagen wrote:
> 
> > On 10/7/2018 7:14 PM, Alan Braslau wrote:  
> >> On Sun, 7 Oct 2018 17:25:35 +0200
> >> "Mikael P. Sundqvist" <mickep at gmail.com> wrote:
> >>   
> >>> ContourPlot[2 x^5 + x y + y^5 == 0, {x, 0, 2}, {y, -2, 1/2}]  
> >> 
> >> Brut force:
> >> [...]
> >>   
> > as this takes some time here's a cheat:
> >
> > \starttext
> >
> > \startbuffer[demo]
> > [...]
> > \stopbuffer
> >
> > \startTEXpage
> >     \typesetbuffer[demo]
> > \stopTEXpage
> > \stoptext
> >
> > a next run the already prepared buffer will be taken unles it has been 
> > changed.  
> 
> I thought that this will also be a good usecase of showing Lua+MP
> interaction. I wrote the code below following the metafun manual, but I cannot
> get it to compile. What am I missing?
> 
> 
> \startluacode
> local f = function(x, y) return 2*x^5  + x*y + y^5 end
> local abs = math.abs
> 
> contour = { }
> 
> function contour.generate(x_min, x_max, y_min, y_max)
>    local pts = { }
>    local length = 1000
>    local eps = 1e-3
> 
>    for xi = x_min, x_max, (x_max - x_min)/length do
>        for yi = y_min, y_max, (y_max - y_min)/length do
>            if abs(f(xi,yi)) < eps then
>               pts[#pts + 1] = {xi, yi}
>            end
>        end
>    end
> 
>    return pts
> end
> 
> contour.data = contour.generate(0, 2, -1, 0.5)
> 
> function contour.n()
>      mp.print(#contour.data)
> end
> 
> function contour.point(i)
>      mp.pair(contour.data[i])
> end
> 
> \stopluacode
> 
> \starttext
> \startMPpage[instance=doublefun]
>       pen savedpen ; savedpen := currentpen ;
>       pickup pencircle scaled .01 ;
> 
>       p := for i = 1 upto lua.contour.n() :
>            lua.contour.point(i) ..
>       endfor cycle;
> 
>       draw subpath (0,length p - 1) of p ;
>       setbounds currentpicture to (0,-2)--(2,-2)--(2,.5)--(0,.5)--cycle ;
>       currentpicture := currentpicture xsized 5cm ;
>       pickup savedpen ;
>       picture pic ; pic := currentpicture ;
>       drawarrow llcorner pic--lrcorner pic ;
>       drawarrow llcorner pic--ulcorner pic ;
>       label.rt ("$x$", lrcorner pic) ;
>       label.top("$y$", ulcorner pic) ;
>       for x=0 step .5 until 2 :
>           label.bot(decimal x,(x/2)[llcorner pic,lrcorner pic]) ;
>       endfor ;
>       for y=0 step .5 until 2.5 :
>           label.lft(decimal (y-2),(y/2.5)[llcorner pic,ulcorner pic]) ;
>       endfor ;
> \stopMPpage
> \stoptext
> 
> 
> I get an error:
> 
> 
> ! Missing argument to lua.
> <to be read again>
> contour
> <*> ...caled .01 ; p := for i = 1 upto lua.contour
> .n() : lua.contour.point(i...
> That macro has more parameters than you thought.
> I'll continue by pretending that each missing argument
> is either zero or null.
> 
> 
> Thanks,
> Aditya

You need to put it into the mp namespace:
(then eps should be made a linear function of xi)
(and, indeed this is much faster than calculating in MP)

Alan



\startluacode
local f = function(x, y) return 2*x^5  + x*y + y^5 end
local abs = math.abs

local contour = { }

function contour.generate(x_min, x_max, y_min, y_max)
   local pts = { }
   local length = 1000
   local eps = 1e-3

   local n = 0
   for xi = x_min, x_max, (x_max - x_min)/length do
       for yi = y_min, y_max, (y_max - y_min)/length do
           if abs(f(xi,yi)) < eps then
              n = n + 1
              pts[n] = {xi, yi}
           end
       end
   end

   return pts
end

contour.data = contour.generate(0, 2, -1, 0.5)

function mp.ContourN()
     mp.print(#contour.data)
end

function mp.ContourPoint(i)
     mp.pair(contour.data[i])
end

function mp.ContourPath()
    mp.path(contour.data)
end

\stopluacode

\starttext
\startMPpage[instance=doublefun]
      draw lua.mp.ContourPath() withpen pencircle scaled .01 ;
      setbounds currentpicture to (0,-2)--(2,-2)--(2,.5)--(0,.5)--cycle ;
      currentpicture := currentpicture xsized 5cm ;

      picture pic ; pic := currentpicture ;
      drawarrow llcorner pic--lrcorner pic ;
      drawarrow llcorner pic--ulcorner pic ;
      label.rt ("$x$", lrcorner pic) ;
      label.top("$y$", ulcorner pic) ;
      for x=0 step .5 until 2 :
          label.bot(decimal x,(x/2)[llcorner pic,lrcorner pic]) ;
      endfor ;
      for y=0 step .5 until 2.5 :
          label.lft(decimal (y-2),(y/2.5)[llcorner pic,ulcorner pic]) ;
      endfor ;
\stopMPpage
\stoptext



More information about the ntg-context mailing list