package algorithmrepository;

import java.util.Random;
import oneLinersForAlgoTests.algoBinaryMatrixFile;
import junit.framework.TestCase;

/** Tests for DelaunayTriangulationInterpolation */
public class DelaunayTriangulationInterpolationTest extends TestCase {
    private static final int nx = 200, ny = 200;
    private static final double x0 = 0, x1 = 10;
    private static final double y0 = 0, y1 = 10;
    private static final double z0 = 0, z1 = 10;
    private static final int nPoints = 5000;
    
    String tmpPath  = System.getProperty("java.io.tmpdir");
    
    private double xx[], yy[], grid[][];
    
    private double[][] createPoints(double[][] points, double pointZ[]){
        
        // nPoints=10: seed=333 is quite nice, seed=555 has 2 very thin triangles and sharp drops 
        Random randGen = new Random(333);

        for (int i=0; i < nPoints; i++){
            points[i][0] = x0 + (x1 - x0) * randGen.nextDouble();
            points[i][1] = y0 + (y1 - y0) * randGen.nextDouble();
            pointZ[i] = z0 + (z1 - z0) * randGen.nextDouble();
        }
        
        return points;
    }
    
    private void createGrid(){
        xx = new double[nx*ny]; 
        yy = new double[nx*ny];
        grid = new double[nx+1][ny+1];
        
        double dx = (x1 - x0) / (nx - 1);
        double dy = (y1 - y0) / (ny - 1);
        for(int i=0; i < nx; i++){
            double x = x0 + i * dx;
            grid[i+1][0] = x;
            for(int j=0; j < ny; j++){
                double y = y0 + j * dy;
                xx[i*ny+j] = x;
                yy[i*ny+j] = y;
                grid[0][j+1] = y;                
            }
        }
    }

    public void testInterpolation(){
        
        createGrid();
        
        double[][] points = new double[nPoints][2];
        double pointZ[] = new double[nPoints];
        
        System.out.print("Grid...");
        createPoints(points, pointZ);
        
        System.out.print("done.\nTriangulate...");
        DelaunayTriangulationInterpolation interp = new DelaunayTriangulationInterpolation(points, pointZ, -1);  

        System.out.print("done.\nOutput...");
        algoBinaryMatrixFile.mustWrite(tmpPath + "/pts.bin", interp.getPoints(), false);
        algoBinaryMatrixFile.mustWrite(tmpPath + "/tri.bin", interp.getTriangleVertexCoords(), false);
       
        System.out.print("done.\nEval...");
        double zz[] = interp.eval(xx, yy);

        System.out.print("done.\nOutput...");
        for(int i=0; i < nx; i++)
            for(int j=0; j < ny; j++)
                grid[i+1][j+1] = zz[i*ny+j];

        algoBinaryMatrixFile.mustWrite(tmpPath + "/grid.bin", grid, false);
        
        System.out.print("done.\nGaussian...");
        //refill with gaussian at grid centre
        double xm = (x0 + x1)/2, ym = (y0 + y1) / 2;
        double sx = (x1 - x0) / 3;
        double sy = (y1 - y0) / 5;
        double newZ[] = new double[nPoints];
        for(int i=0; i < nPoints; i++){
            newZ[i] = Math.exp( -0.5*Math.pow((points[i][0]-xm)/sx, 2)  -0.5*Math.pow((points[i][1]-ym)/sy, 2) );
        }
        
        System.out.print("done.\nSet...");
        interp.setF(newZ);
        
        System.out.print("done.\nEval...");
        zz = interp.eval(xx, yy);
        
        System.out.print("done.\nOutput...");
        for(int i=0; i < nx; i++)
            for(int j=0; j < ny; j++)
                grid[i+1][j+1] = zz[i*ny+j];

        algoBinaryMatrixFile.mustWrite(tmpPath + "/gridGauss.bin", grid, false);

        System.out.println("done.");
    }
    
}
