
package skyview.geometry.projecter;

import static java.lang.Math.*;

/**
 * Calculate the distribution of areas of TOAST pixels.
 * @author tmcglynn
 */
public class ToastPixelSize {
    
    public static void main(String[] args) throws Exception {
        int level = Integer.parseInt(args[0]);
        System.out.println("TOAST Pixel size distribution for level "+level);
        Toa proj = new Toa();
        int dim = (int) Math.pow(2,level);
        double factor = dim*dim/(4*Math.PI);
            
        double[][][] corn = proj.tile(0, 0, 0, level);
        double grand = 0;
        double min = 100;
        double max = 0;
        int cnt = 0;
        
        for (int j=0; j<dim; j += 1) {
            for (int i=0; i<dim; i += 1) {
                
                double[][]  ps = new double[4][0];
                                
                ps[0] = corn[i][j];
                ps[1] = corn[i+1][j];
                ps[2] = corn[i+1][j+1];
                ps[3] = corn[i][j+1];
                
                double total = 0;
                for (int k=0; k<4; k += 1) {
                    int km = k - 1;
                    int kp = k + 1;
                    if (km < 0) {
                        km += 4;
                    }
                    if (kp > 3) {
                        kp -= 4;
                    }
                    double a0 = ang(ps[km], ps[k]);
                    double a1 = ang(ps[k], ps[kp]);
                    double a2 = ang(ps[kp], ps[km]);
                    double cos_ang =  ( cos(a2) - cos(a0)*cos(a1) ) / (sin(a0)*sin(a1));
                    double ang;
                    if (cos_ang >= 1) {
                        ang = 0;
                    } else if (cos_ang <= -1) {
                        ang = PI;
                    } else {
                        ang = acos(cos_ang);
                    }
                    total += ang;
                }
                
                
                double area = total - 2*PI;
                double fac  = area*factor;
                if (fac > max) {
                    max = fac;
                }
                if (fac < min) {
                    min = fac;
                }
                grand += area;
                cnt += 1;
                if (level < 6) {
                    System.out.printf("%10d %17.8g %12.6f", cnt, area, fac);
                    for (int k=0; k<4; k += 1) {
                        System.out.printf(" %8.5f %8.5f %8.5f", ps[k][0], ps[k][1], ps[k][2]);
                    }
                    System.out.println();
                } else {
                    System.out.printf("%10d  %16.8g %12.6f\n", cnt, area, fac);
                }
            }
        }
        System.out.println("Grand total for area:"+grand);
        System.out.println("Min/max:"+min+" "+max);
    }
    
    public static void pnt(String lab, double[] p) {
        System.out.println("   "+lab+" "+p[0]+" "+p[1]+" "+p[2]);
    }
    
    public static double[] cross(double[] x, double[] y) {
        double[] c = new double[3];
        c[0] = x[1]*y[2] - x[2]*y[1];
        c[1] = x[2]*y[0] - x[0]*y[2];
        c[2] = x[0]*y[1] - x[1]*y[0];
        return c;
    }
    
    public static double norm(double[] x) {
        return Math.sqrt(dot(x,x));
    }
    
    public static double ang(double[] x, double[] y) {
        double cos_theta = dot(x,y)/norm(x)/norm(y);
        if (cos_theta >= 1) {
            return 0;
        } else if (cos_theta <= -1) {
            return Math.PI;
        }
        return Math.acos(cos_theta);
    }
    
    public static double dot(double[] x, double[] y) {
        double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
        return d;
    }
    
}
