size(20cm);

// The required data file is available here:
// http://www.uni-graz.at/~schwaige/asymptote/worldmap.dat
// This data was originally obtained from
// http://www.ngdc.noaa.gov/mgg_coastline/mapit.jsp

real findtheta(real phi, real epsilon=realEpsilon) {
 // Determine for given phi the unique solution -pi/2 <= theta <= pi/2 off
 // 2*theta+sin(2*theta)=pi*sin(phi)
 // in the non-trivial cases by Newton iteration;
 // theoretically the initial guess pi*sin(phi)/4  always works.
 real nwtn(real x, real y) {return x-(2x+sin(2x)-y)/(2+2*cos(2x));};
 real y=pi*sin(phi);
 if(y == 0) return 0.0;
 if(abs(y) == 1) return pi/2;
 real startv=y/4;
 real endv=nwtn(startv,y);
 if(epsilon < 500*realEpsilon) epsilon=500*realEpsilon;
 while(abs(endv-startv) > epsilon) {startv=endv; endv=nwtn(startv,y);};
 return endv;
}

pair mollweide(real lambda, real phi, real lambda0=0){
 // calculate the Mollweide projection centered at lambda0 for the point
 // with coordinates(phi,lambda)
 static real c1=2*sqrt(2)/pi;
 static real c2=sqrt(2);
 real theta=findtheta(phi);
 return(c1*(lambda-lambda0)*cos(theta), c2*sin(theta));
}

guide gfrompairs(pair[] data){
 guide gtmp;
 for(int i=0; i < data.length; ++i) {
   pair tmp=mollweide(radians(data[i].y),radians(data[i].x));
   gtmp=gtmp--tmp;
 }
 return gtmp;
}

string datafile="worldmap.dat";

file in=input(datafile,comment="/").line();
// new commentchar since "#" is contained in the file
pair[][] arrarrpair=new pair[][] ;
int cnt=-1;
bool newseg=false;
while(true) {
 if(eof(in)) break;
 string str=in;
 string[] spstr=split(str,"");

 if(spstr[0] == "#") {++cnt; arrarrpair[cnt]=new pair[] ; newseg=true;}
 if(spstr[0] != "#" && newseg) {
   string[] spstr1=split(str,'\t'); // separator is TAB not SPACE
   pair tmp=((real) spstr1[1],(real) spstr1[0]);
   arrarrpair[cnt].push(tmp);
 }
}

for(int i=0; i < arrarrpair.length; ++i)
 draw(gfrompairs(arrarrpair[i]),1bp+black);

// lines of longitude and latitude
pair[] constlong(real lambda, int np=100) {
 pair[] tmp;
 for(int i=0; i <= np; ++i) tmp.push((-90+i*180/np,lambda));
 return tmp;
}

pair[] constlat(real phi, int np=100) {
 pair[] tmp;
 for(int i=0; i <= 2*np; ++i) tmp.push((phi,-180+i*180/np));
 return tmp;
}

for(int j=1; j <= 5; ++j) draw(gfrompairs(constlong(-180+j/6*360)),white);
draw(gfrompairs(constlong(-180)),1.5bp+white);
draw(gfrompairs(constlong(180)),1.5bp+white);
for(int j=0; j <= 12; ++j) draw(gfrompairs(constlat(-90+j/6*180)),white);
//draw(gfrompairs(constlong(10)),dotted);

close(in);
shipout(bbox(1mm,darkblue,Fill(lightblue)), view=true);