package algorithmrepository;

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

public class PolygonGridLookupTest extends TestCase {
    
    public void testPolygonGridLookupSimple() {

        //simple automatic test
        double polys[][][] = new double[][][]{
                {
                    { 1.0, 1.0 },
                    { 2.0, 2.0 },
                    { 2.0, 1.0 },
                },{
                    { 3.0, 3.0 },
                    { 4.0, 3.0 },
                    { 4.0, 4.0 },
                    { 3.0, 4.0 },
                },{
                    { 5.02, 0.00 },
                    { 5.04, 0.01 },
                    { 5.03, 0.02 },
                    { 5.01, 0.02 },
                    { 5.00, 0.01 },
                },{
                    { 0.5 + 0e-5, 3.0 + 0e-5 },
                    { 0.5 + 0e-5, 3.0 + 1e-5 },
                    { 0.5 + 1e-5, 3.0 + 0e-5 },
                }
            };
        
        PolygonGridLookup lookup = new PolygonGridLookup(polys, 20, 20);
        
        int c[][] = lookup.getPolysInGridCount();        
        for(int j=0;j<c[0].length;j++){
            for(int i=0;i<c.length;i++){
                System.out.print(c[i][j] + " ");
            }
            System.out.println();
        }
        
        assertEquals(0, lookup.getPolygonAtPoint(1.8, 1.2));
        assertEquals(3, lookup.getPolygonAtPointBruteForce(0.5+1e-8, 3.0+1e-8));
        assertEquals(3, lookup.getPolygonAtPoint(0.5+1e-8, 3.0+1e-8));
    }
    
    //heavier output and 'look at it' version
    public void testPolygonGridLookupRandom() {
        
        String tmpPath = System.getProperty("java.io.tmpdir");
        int nPolys = 500;
        double fracD = 0.4;
        
        double minX = 0, maxX = 100;
        double minY = 0, maxY = 1e6;
        
        Random randGen = new Random();
        
        double polys[][][] = new double[nPolys][3][2];
        double polysOut[][] = new double[nPolys][6];
        for(int i=0; i < nPolys; i++){
            int k=0;
            double xc = minX + randGen.nextDouble() * (maxX - minX);
            double yc = minY + randGen.nextDouble() * (maxY - minY);
            for(int j=0; j < 3; j++){
                polys[i][j][0] = xc + fracD * randGen.nextDouble() * (maxX - minX);
                polys[i][j][1] = yc + fracD * randGen.nextDouble() * (maxY - minY);
                polysOut[i][k] = polys[i][j][0]; 
                polysOut[i][3+k] = polys[i][j][1];
                k++;
            }
        }
        
        algoBinaryMatrixFile.mustWrite(tmpPath + "/polyLookup/polys.bin", polysOut, false);
        
        PolygonGridLookup lookup = new PolygonGridLookup(polys, 200, 200);
        
        int nX = 500, nY = 500;
        double dX = (maxX - minX) / (nX - 1);
        double dY = (maxY - minY) / (nY - 1);
        
        double gridOptim[][] = new double[nY+1][nX+1];
        double gridBrute[][] = new double[nY+1][nX+1];
        
        long t0 = System.currentTimeMillis();
        for(int i=0; i < nY; i++){
            double y = minY + i * dY;
            gridBrute[i+1][0] = y;
                
            for(int j=0; j < nX; j++){
                double x = minX + j * dX;
                gridBrute[0][j+1] = x;
                
                gridBrute[i+1][j+1] = lookup.getPolygonAtPointBruteForce(x, y);                
            }    
        }        
        System.out.println("Brute Force = " + (System.currentTimeMillis() - t0) + " ms");
        t0 = System.currentTimeMillis();
        
        for(int i=0; i < nY; i++){
            double y = minY + i * dY;
            gridOptim[i+1][0] = y;
                
            for(int j=0; j < nX; j++){
                double x = minX + j * dX;
                gridOptim[0][j+1] = x;
                
                gridOptim[i+1][j+1] = lookup.getPolygonAtPoint(x, y);
            }    
        }
        System.out.println("Optimised = " + (System.currentTimeMillis() - t0) + " ms");
        
        for(int i=0; i < nY; i++)
            for(int j=0; j < nX; j++)
                assertEquals(gridBrute[i+1][j+1], gridOptim[i+1][j+1]);
           
        algoBinaryMatrixFile.mustWrite(tmpPath + "/polyLookup/gridBrute.bin", gridBrute, false);
        algoBinaryMatrixFile.mustWrite(tmpPath + "/polyLookup/gridOptim.bin", gridOptim, false);
                
       /* int c[][] = lookup.getPolysInGridCount();        
        for(int j=0;j<c[0].length;j++){
            for(int i=0;i<c.length;i++){
                System.out.print(c[i][j] + " ");
            }
            System.out.println();
        }*/
    }
}
