settings.outformat="pdf";
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);

