# Asymptote fill area between two contours

I use Asymptote to make the graphics. I have two curves defined as contours C_1 and C_2. I want to fill the area between the two curves. The problem is that contour returns a guide structure in Asymptote, and this is not accepted to to buildcycle command. Can anyone tell me how to solve this problem ? Thanks. This is the code I use and which produces the two curves, but fails to fill area between these.

import graph;
import patterns;
import contour;

usepackage("mathrsfs");

size(8cm);

real eps=0.001;
real xmax=5.5,ymax=5.5;
pair af,ag;

real f(real x, real y) {return sqrt(1+x)-sqrt(x)+sqrt(1+y)-sqrt(y);}
real g(real x, real y) {return 1/sqrt(1+x)+1/sqrt(1+y);}

guide[][] Cf=contour(f,(eps,eps),(xmax,ymax),new real[] {1});
guide[][] Cg=contour(g,(eps,eps),(xmax,ymax),new real[] {1});

//these two lines are used to find intersection points
path D1=(0,ymax)--(xmax+eps,ymax);
path D2=(xmax,0)--(xmax,ymax+eps);

draw(Cf);
draw(Cg);

//path pp=buildcycle(Cf,D1,Cg,D2);
// the preceding line produces and error if commented

xaxis(Label(scale(0.75)*"$x$"),xmax=6,Arrow);
yaxis(Label(rotate(90)*scale(0.75)*"$y$"),ymax=6,Arrow);

label("$\mathscr{C}_{1}$",(xmax,0.2));
label("$\mathscr{C}_{2}$",(xmax,1.9));
label("I"  ,(.2,.2));
label("II" ,(1.,1.));
label("III",(3.5,3.5));

end;

• Is there some reason why you are using contour to produce the lines? It seems a rather complicated way to produce a single curve. May 1 '15 at 9:26
• Using f to write y = function (x) lead to a long expression. Around zero it requires large precision for fine tuned draw. Contour allows easier control over the drawing box. May 1 '15 at 22:10

It works when replacing Cf and Cg by Cf[0][0] and Cg[0][0], which allows to obtain the desired (single) guides.

path pp=buildcycle(Cf[0][0],D1,Cg[0][0],D2);


Note that I've also slightly modified D1 and D2: in your definitions, D1, D2 and pp did not intersect anyway.

path D1=(0,ymax-eps)--(xmax+eps,ymax-eps);
path D2=(xmax-eps,0)--(xmax-eps,ymax+eps);


For proper explanations about how to use contour, see the very well-made (alas not complete) tutorial on Asymptote by Charles Staats, p. 32.

import graph;
import patterns;
import contour;

usepackage("mathrsfs");

size(8cm);

real eps=0.001;
real xmax=5.5,ymax=5.5;
pair af,ag;

real f(real x, real y) {return sqrt(1+x)-sqrt(x)+sqrt(1+y)-sqrt(y);}
real g(real x, real y) {return 1/sqrt(1+x)+1/sqrt(1+y);}

guide[][] Cf=contour(f,(eps,eps),(xmax,ymax),new real[] {1});
guide[][] Cg=contour(g,(eps,eps),(xmax,ymax),new real[] {1});

//these two lines are used to find intersection points
path D1=(0,ymax-eps)--(xmax+eps,ymax-eps);
path D2=(xmax-eps,0)--(xmax-eps,ymax+eps);

path pp=buildcycle(Cf[0][0],D1,Cg[0][0],D2);
fill(pp,.8white); draw(pp);

xaxis(Label(scale(0.75)*"$x$"),xmax=6,Arrow);
yaxis(Label(rotate(90)*scale(0.75)*"$y$"),ymax=6,Arrow);

label("$\mathscr{C}_{1}$",(xmax,0.2));
label("$\mathscr{C}_{2}$",(xmax,1.9));
label("I"  ,(.2,.2));
label("II" ,(1.,1.));
label("III",(3.5,3.5));


• Great, it works fine ! thank a lot fpast, for the answer and for the suggestions. Apr 30 '15 at 18:41

Just for comparison, here is a Metapost version. There's no support for implicit equations or anything so clever (or complex) as Asymptote's contour facility, so I could not avoid some algebra to get the "long expression" that the OP was happy to avoid. And to avoid overflows when x is near zero, I'm exploiting the facts that these two curves have a symmetry about the line through (0,0)--(1,1) and that C1 goes through (9/16,9/16) while C2 goes through (3,3) -- I therefore only use a loop to construct the curves to the right of these points; I then use MP's reflectedabout macro to create the required upper halves.

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);
u := 1cm;
path xx, yy, ff, gg;
xx = (1/2 left -- 6 right) scaled u;
yy = xx rotated 90;
drawarrow xx; drawarrow yy;

vardef f(expr x) =
save s; numeric s;
s = (1+sqrt(x)-sqrt(1+x))**2;
(1-2s+s**2)/(4s)
enddef;

vardef g(expr x) =
(1+x)/(2+x-2*sqrt(1+x))-1
enddef;

s = 0.05;
ff = ((9/16,9/16) for x = 9/16+s step s until 5.5: -- (x,f(x)) endfor) scaled u;
gg = ((3,3)       for x =    3+s step s until 5.5: -- (x,g(x)) endfor) scaled u;

ff := reverse ff reflectedabout(origin,(1,1)) & ff;
gg := reverse gg reflectedabout(origin,(1,1)) & gg;

path A;
A = ff -- reverse gg -- cycle;
fill A withcolor .9[blue,white];
draw ff;
draw gg;

string s; s = "";
for $=0,9/16u,3u: s := s & "I"; label.urt(s,($,$)); endfor label.urt(btex${\cal C}_1$etex, point infinity of ff); label.urt(btex${\cal C}_2$etex, point infinity of gg); label.bot(btex$x$etex, point 1 of xx); label.lft(btex$y\$ etex, point 1 of yy);

endfig;
end.


If you wanted to draw the ends of the area as well you could just replace my draw ff; draw gg; with draw A.