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

Mon Oct 8 23:56:24 CEST 2018

On Mon, 8 Oct 2018, Aditya Mahajan wrote:

> On Mon, 8 Oct 2018, Alan Braslau wrote:
>
>> On Mon, 8 Oct 2018 16:00:10 -0400 (EDT)
>>
>>> 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}]

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.

\define\ContourPlot
{\dosingleargument\doContourPlot}

\def\doContourPlot[#1]%
{\setvariables[ContourPlot][#1]%
\ctxlua{userdata.contourplot(
function(x,y) return \getvariable{ContourPlot}{function} end,
{\getvariable{ContourPlot}{x}},
{\getvariable{ContourPlot}{y}},
\getvariable{ContourPlot}{n})}%
\useMPgraphic{doublefun::ContourPlot}}

\startluacode
userdata = userdata or { }
local abs = math.abs
local data = { }
local eps  = 1e-3

function userdata.contourplot(f, xlim, ylim, length)
local n = 0
data    = { }
for x = xlim[1], xlim[2], (xlim[2] - xlim[1])/length do
for y = ylim[1], ylim[2], (ylim[2] - ylim[1])/length do
if abs(f(x,y)) < eps*x then
n = n + 1
data[n] = {x, y}
end
end
end
end

function mp.ContourPath()
mp.path(data)
end
\stopluacode

\startuseMPgraphic{doublefun::ContourPlot}
draw lua.mp.ContourPath() withpen pencircle scaled .01 ;

% This needs to be fixed to adapt to the function.
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 ;
\stopuseMPgraphic

\starttext
\ContourPlot
[
function=2*x^5 + x*y + y^5,
x={0, 2},
y={-2, 0.5},
n=1000,
]
\stoptext

\endinput

\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