import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

/*
*  Jean-Claude Marti
*       Projection de Craster
    janvier 2017
  d'apres : https://github.com/d3/d3-geo-projection/blob/master/src/craster.js

*/


public class Craster_  implements PlugInFilter {

  double pi=Math.PI;
  double eps=1.E-6;
  double sqrt3=Math.sqrt(3.);
  double sqrtPi=Math.sqrt(pi);



public int setup(String arg, ImagePlus imp) {
    if (arg.equals("about")){
      showAbout();
      return DONE;
    }
    return DOES_RGB+NO_CHANGES;
  }

  void showAbout(){
     IJ.showMessage("PELURE", "");
  }


int rgbColor(int rouge, int vert, int bleu){
// chaque couleur dans [0..255]
      return ((rouge & 0xff) << 16) + ((vert & 0xff) <<8)+ (bleu & 0xff);
  }  

//===========================
  double [] crasterInvert(double x, double y) {
    double [] res = new double[2];
    double tet,fi;
     fi= 3 * Math.asin(y / (sqrt3 * sqrtPi));
    tet=sqrtPi * x / (sqrt3 * (2 * Math.cos(2 * fi / 3) - 1));
    res[0]=tet; res[1]=fi;
    return res;
  };

//===========================
public void run(ImageProcessor ip) {

  int W0 = ip.getWidth();
  int H0 = ip.getHeight();
  int Wp=W0;
  int Hp=H0;
  int Xc=Hp/2;
  int Yc=Wp/2;


  double tet0=0;

  int i,j;
  int xp,yp;
  int yp1;
  int x0,y0;

  double xr,yr;
  double tet,fi;
  double [] res = new double[2];
  

  ImagePlus projection = NewImage.createRGBImage("Craster",Wp,Hp,1,NewImage.FILL_WHITE);
  ImageProcessor proj_ip = projection.getProcessor();
  proj_ip.copyBits(ip,0,0,Blitter.COPY);
  int[] pixels = new int[Wp*Hp];
  for (i=0; i<Wp*Hp; i++){pixels[i]=rgbColor(255,255,255);}



  for(xp=0; xp<Hp; xp++) {
    yr=(double) (3.5*(xp-Xc))/Hp; 
    for (yp=0; yp<Wp; yp++) {
      xr=(double) (6.5*(Yc-yp))/Wp; 
      res=crasterInvert(xr,yr);
      tet=-res[0]; fi=-res[1];
      if (((tet<=pi) && (tet>=-pi)) && ((fi>=-pi/2) && (fi<=pi/2))) {
        x0=(int) (H0*(pi/2-fi)/pi);
        y0=(int) (W0*(pi+tet+tet0)/(2*pi)) % W0;
        pixels[Wp*xp+yp]=ip.getPixel(y0,x0);
      } else pixels[Wp*xp+yp]=rgbColor(255,255,255);
    }
  }


  proj_ip.setPixels(pixels);
  projection.show();
  projection.updateAndDraw();
  }
}



