Closed justonlyasy closed 2 years ago
maybe you can try to make all the cycle and fill them first and then use clip
command to clip the part you want?
import graph;
import palette;
import contour;
size(350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=100;
int Divs=15;
bounds range=bounds(0,1.1);
real[] Cvals=uniform(range.min,range.max,Divs);
guide[][] g=contour(f,a,b,Cvals,N);
pen[] Palette=quantize(BWRainbow(),Divs);
pen[][] interior=interior(g,extend(Palette,grey,black));
fill(g,interior);
draw(g);
clip(box((-2.6,-2.6),(2.6,2.6)));
xaxis("$x$",BottomTop,LeftTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
yaxis("$y$",LeftRight,RightTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
this is the output
The suggested solution works in this instance but we still need a general solution for cases that cannot be extended to closed contours (for example, horizontal contour lines).
This is actually a very old issue that got postponed when we transitioned from sourceforge to github: https://sourceforge.net/p/asymptote/bugs/84/
Good news: 13 years after the original bug report was submitted, I have finally found a much simpler solution: simply quantize a color density image (see imagecontour.asy). If you draw the contour lines wide enough (or draw the image at high-enough resolution), pixelization artifacts will be hidden and what results gives the illusion of vector graphics without the complexity of trying to fill noncyclic (unclosed) curves. The quantized image is less accurate but more appealing than the unquantized one (compare the attached images), especially for pedagogical purposes.
I will commit an update tomorrow that supports this functionality and then close this issue. I may replace fillcontour.asy (which has caused confusion, due to this unresolved issue) with the quantized example, even though the name fillcontour is perhaps a bit misleading.
You can review fillcontour.asy to remove duplicate code.
I cannot get a desired output, can you give me a suggestion? The contour lines is not same with...
import graph;
import palette;
import contour;
size(350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=15;
int divs=1;
int n=Divs*divs;
defaultpen(1bp);
pen Tickpen=black;
pen tickpen=gray+0.5*linewidth(currentpen);
pen[] Palette=quantize(BWRainbow(),n);
bounds range=image(f,Range(0,5.1),a,b,600,Palette,n);
real[] Cvals=uniform(range.min,range.max,Divs);
draw(contour(f,a,b,Cvals,N),Tickpen+squarecap+beveljoin);
limits(a-(0.3,0.3),b+(0.3,0.3));
xaxis("$x$",BottomTop,LeftTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
yaxis("$y$",LeftRight,RightTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
Your color density plot was not produced on the full data Range. Start with the example https://asymptote.sourceforge.io/gallery/2Dgraphs/fillcontour.asy and adapt it to your function (keeping only the major contours):
import graph;
import palette;
import contour;
size(350,350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=15;
defaultpen(1bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
draw(contour(f,a,b,Cvals,N,operator --),Tickpen+squarecap+beveljoin);
xaxis("$x$",BottomTop,LeftTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
yaxis("$y$",LeftRight,RightTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
The contour line caps in this example could be improved by changing squarecap to extendcap and slightly cropping. You can also force the ticks to be drawn above the color density plot:
import graph;
import palette;
import contour;
size(350,350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=15;
defaultpen(1bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
draw(contour(f,a,b,Cvals,N,operator --),Tickpen+extendcap+beveljoin);
pair eps=(1,1)*0.02;
limits(a+eps,b-eps);
crop();
xaxis("$x$",BottomTop,LeftTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}),above=true);
yaxis("$y$",LeftRight,RightTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}),above=true);
Excuse me, the last curiosity.
This code runs approximately 98% in my desired picture
// settings.render=8;
import graph;
import palette;
import contour;
size(350,350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=16;
defaultpen(1bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
draw(contour(f,a,b,Cvals,N),Tickpen+squarecap+beveljoin);
crop(); // before the limits command.
limits(a-(0.3,0.3),b+(0.3,0.3));
xaxis("$x$",BottomTop,LeftTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
yaxis("$y$",LeftRight,RightTicks(Size=4,Ticks=new real[]{-6,-4,-2,0,2,4,6}));
except for
Does this work normally? Can we delete them?
I don't know what 98% refers to.
Those circled marks are contour lines. If you don't want them, you can crop them out. The crop command has to go after the limits command and the limits command should reduce, not expand the range in order for this to work. See the example I already posted. Putting crop before the limits command has no effect.
If you are simply trying to get (-6,-6) and (6,6) to show up on your axes, here's how (or if for some reason you want a gap around the colour density image, you can use the commented draw commands instead):
import graph;
import palette;
import contour;
size(350,350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=16;
defaultpen(1bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
draw(contour(f,a,b,Cvals,N),Tickpen+extendcap+beveljoin);
pair eps=(1,1)*0.03;
limits(a+eps,b-eps);
crop();
draw(a,invisible);
draw(b,invisible);
//draw(a*1.05,invisible);
//draw(b*1.05,invisible);
xaxis("$x$",BottomTop,LeftTicks(Size=4),above=true);
yaxis("$y$",LeftRight,RightTicks(Size=4),above=true);
Done, 99.99%... Thanks again.
import graph;
import palette;
import contour;
size(350,350);
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=16;
defaultpen(.9bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
Cvals.pop(); // <--- This command solves "Those circled marks are contour lines".
draw(contour(f,a,b,Cvals,N),Tickpen+extendcap+beveljoin);
crop(); // I don't know the reason "The crop command has to go after the limits command" but this works as expected.
limits(a-(0.3,0.3),b+(0.3,0.3));
draw(box(a,b),cyan+opacity(.5));
xaxis("$x$",BottomTop,LeftTicks(Size=4,size=2));
yaxis("$y$",LeftRight,RightTicks(Size=4,size=2));
The crop command, used properly, would fix the flaw shown in your image. It belongs after the call to limits. The result below looks much better; you'll need to use Asympote version 2.75.
import graph;
import palette;
import contour;
size(350,350);
settings.gsOptions="-r1200x1200";
pair a=(-6,-6);
pair b=(6,6);
real f(real x, real y) {return (x/5)^2+(y/3)^2;}
int N=200;
int Divs=16;
defaultpen(.9bp);
pen Tickpen=black;
pen[] Palette=quantize(BWRainbow(),Divs);
bounds range=image(f,a,b,3N,Palette,Divs);
real[] Cvals=uniform(range.min,range.max,Divs);
Cvals.pop(); // Optionally remove final contour line
draw(contour(f,a,b,Cvals,N),Tickpen+extendcap+beveljoin);
pair eps=(1,1)*0.03;
limits(a+eps,b-eps);
crop();
draw(box(a+eps,b-eps),cyan+opacity(0.5));
pair gap=(1,1)*0.3;
draw(a-gap,invisible);
draw(b+gap,invisible);
xaxis("$x$",BottomTop,LeftTicks(Size=4,size=2),above=true);
yaxis("$y$",LeftRight,RightTicks(Size=4,size=2),above=true);
With your new code, when I comment draw(box(a+eps,b-eps),cyan+opacity(0.5));
and see the svg output on http://asymptote.ualberta.ca/. Is it normal? (For my computer, pdf and png are normal.)
I want to reproduce this image in Asymptote but ... Here is my code,
Can Asymptote fill for uncyclic contours like my image?