pair c=(0,0.8);

int iters(pair z, int max=160) {
 int n=0;
 while(abs(z) < 2 && n < max) {
   z=z*z+c;
   ++n;
 }
 return n;
}

int[] cutoffs={12,15,20,30,40,60,200};
int key(pair z) {
 int i=iters(z);
 int j=0;
 while(cutoffs[j] < i)
   ++j;
 return j;
}


int width=210;
int height=190;

real zoom=2.5/200;

int[][] values=new int[width][height];
int[] histogram;  for(int v=0; v < 10; ++v) histogram.push(0);
for(int i=0; i < width; ++i) {
 real x=zoom*(i-width/2);
 for(int j=0; j < height; ++j) {
   real y=zoom*(j-height/2);
   int v=key((x,y));
   values[i][j]=v;
   ++histogram[v];
 }
}

// Print out a histogram.
write("histogram: ");
write(histogram);


pen linepen(int i, int max) {
 real w=i == -1 || i == max+1   ? 2.0 :
   i % 10 == 0 || i == max ? 1.0 :
   i % 5 == 0              ? 0.8 :
   0.25;
 return linewidth(w);
}

pen xpen(int i) {
 return linepen(i,width)+(i == width/2 ? red :
                          i == 75 || i == width-75 ? dashed :
                          black);
}

pen ypen(int i) {
 return linepen(i,height)+(i == height/2 ? red :
                           i == 75 || i == height-75 ? dashed :
                           black);
}

// The length of the side of a cross stitch cell.
real cell=2.3mm;
transform t=scale(cell);


picture tick;
draw(tick,(0,0)--(1,1));

picture ell;
draw(ell,(0,1)--(0,0)--(0.7,0));

picture cross;
draw(cross,(0,0)--(1,1));
draw(cross,(1,0)--(0,1));

picture star;
draw(star,(0.15,0.15)--(0.85,0.85));
draw(star,(0.85,0.15)--(0.15,0.85));
draw(star,(.5,0)--(.5,1));
draw(star,(0,.5)--(1,.5));

picture triangle;
draw(triangle,(0,0)--(2,0)--(1,1.5)--cycle);

picture circle;
fill(circle,shift(1,1)*unitcircle);

picture ocircle;
draw(ocircle,shift(1,1)*unitcircle);

picture spare;
fill(spare,(0,0)--(1,1)--(0,1)--cycle);

picture[] pics={tick,ell,cross,star,triangle,circle};
pen[] colors={black,0.2purple,0.4purple,0.6purple,0.8purple,purple,
             0.8purple+0.2white};

frame[] icons;
icons.push(newframe);
for(picture pic : pics) {
 // Scaling factor, so that we don't need weird line widths.
 real X=1.0;
 frame f=pic.fit(.8X*cell,.8X*cell,Aspect);
 f=scale(1/X)*f;

 // Center the icon in the cell.
 f=shift((cell/2,cell/2)-0.5(max(f)-min(f)))*f;

 icons.push(f);
}

void drawSection(int xmin, int xmax, int ymin, int ymax) {
 static int shipoutNumber=0;

 // Draw directly to a frame for speed reasons.
 frame pic;

 for(int i=xmin; i <= xmax; ++i) {
   draw(pic,t*((i,ymin)--(i,ymax)),xpen(i));
   if(i%10 == 0) {
     label(pic,string(i),t*(i,ymin),align=S);
     label(pic,string(i),t*(i,ymax),align=N);
   }
 }
 for(int j=ymin; j <= ymax; ++j) {
   draw(pic,t*((xmin,j)--(xmax,j)),ypen(j));
   if(j%10 == 0) {
     label(pic,string(j),t*(xmin,j),align=W);
     label(pic,string(j),t*(xmax,j),align=E);
   }
 }

 if(xmin < 0)
   xmin=0;
 if(xmax >= width)
   xmax=width-1;
 if(ymin < 0)
   ymin=0;
 if(ymax >= height)
   ymax=height-1;

 int stitchCount=0;
 path box=scale(cell) *((0,0)--(1,0)--(1,1)--(0,1)--cycle);
 for(int i=xmin; i < xmax; ++i)
   for(int j=ymin; j < ymax; ++j) {
     int v=values[i][j];
     add(pic,icons[v],(i*cell,j*cell));
     //fill(pic,shift(i*cell,j*cell)*box,colors[v]);
     if(v != 0)
       ++stitchCount;
   }

 write("stitch count: ",stitchCount);

 //  shipout("xstitch"+string(shipoutNumber),pic);
 shipout(pic);
 ++shipoutNumber;
}

//drawSection(-1,width+1,-1,height+1);


//drawSection(-1,80,height-80,height+1);
//drawSection(70,150,height-80,height+1);
drawSection(quotient(width,2)-40,quotient(width,2)+40,quotient(height,2)-40,quotient(height,2)+40);
//drawSection(width-150,width-70,-1,80);
//drawSection(width-80,width+1,-1,80);