package registro;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class Normaliza {
    public static void main(String[] args) {

        double P[][] = {{31, 35}, {52, 35}, {26, 54}, {47, 51}, {62, 65}};
        //double P[][] = {{554, 129}, {383, 168}, {541, 118}, {486, 160}, {481, 174}};
        //double Q[][] = {{561, 49}, {398, 111}, {547, 41}, {499, 89}, {495, 103}};
        int i, n = P.length;

        Normal(P, 10, Centroides(P));
        //Normal(Q, 10, Centroides(Q));
    }

    public static void Normal(double P[][], double C, double Pr[])
    {
        double u20, u02, u11, l1, l2, d, u12, u21, u30, u03, t1, t2;
        double T[][] = new double[2][2], phi;
        double T2[][] = new double[2][2], Tf[][];
        int i, n = P.length;
        double Pn[][] = new double[n][2], Pc[][] = new double[n][2];
        double aux2[] = new double[2];
        double Cen[] = new double[2];
        Cen[0] = Pr[0]; Cen[1] = Pr[1];

        System.out.println("Centroides -----> " + Cen[0] + " " + Cen[1]);

        u20 = Momento(P, Cen, 2, 0);
        u02 = Momento(P, Cen, 0, 2);
        u11 = Momento(P, Cen, 1, 1);
        System.out.println(u20 +" " + u02 + " " + u11);

        d = Math.sqrt((u20 - u02)*(u20 - u02) + 4.0*u11*u11);

        l1 = (u20 + u02 + d)/2.0;
        l2 = (u20 + u02 - d)/2.0;

        if(l1 < l2)
        {
            double aux = l2;
            l2 = l1;
            l1 = aux;
        }

        System.out.println(l1 + " " + l2);
        d = Math.sqrt((l1-u20)*(l1-u20) + u11*u11);

        T[0][0] = u11/d;      T[0][1] = (l1-u20)/d;
        T[1][0] = -(l1-u20)/d; T[1][1] = u11/d;

        System.out.println("Eigenvectores");

        System.out.println(T[0][0] + " " + T[0][1]);
        System.out.println(T[1][0] + " " + T[1][1]);

        System.out.println("eigenvalores " + C/Math.sqrt(l1) + " " + C/Math.sqrt(l2));

        T[0][0] *= C/Math.sqrt(l1);
        T[0][1] *= C/Math.sqrt(l1);
        T[1][0] *= C/Math.sqrt(l2);
        T[1][1] *= C/Math.sqrt(l2);

        System.out.println(T[0][0] + " " + T[0][1]);
        System.out.println(T[1][0] + " " + T[1][1]);
        System.out.println("Puntos Compactos");

        for(i=0; i<n; i++)
        {
            aux2[0] = P[i][0] - Cen[0];
            aux2[1] = P[i][1] - Cen[1];

            multiplica(T, aux2, Pc[i]);
            System.out.println(Pc[i][0] + " " + Pc[i][1]);
        }

        //El conjunto compacto tiene centroide en Cero.

        Cen[0] = 0; Cen[1] = 0;

        u20 = Momento(Pc, Cen, 2, 0);
        u02 = Momento(Pc, Cen, 0, 2);
        u11 = Momento(Pc, Cen, 1, 1);
        u12 = Momento(Pc, Cen, 1, 2);
        u21 = Momento(Pc, Cen, 2, 1);
        u30 = Momento(Pc, Cen, 3, 0);
        u03 = Momento(Pc, Cen, 0, 3);

        t1 = C*C*(u12 + u30);
        t2 = C*C*(u03 + u21);

        phi = Math.atan(-t1/t2);
        if((-t1*Math.sin(phi) + t2*Math.cos(phi)) < 0) phi += Math.PI;

        System.out.println("Phi = " + phi);

        System.out.println(u20 +" " + u02 + " " + u11);

        System.out.println("Puntos Normalizados");

        T2[0][0] = Math.cos(phi); T2[0][1] = Math.sin(phi);
        T2[1][0] =-Math.sin(phi); T2[1][1] = Math.cos(phi);

        Tf = multiplica(T2, T);

        for(i=0; i<n; i++)
        {
            aux2[0] = P[i][0] - Pr[0];
            aux2[1] = P[i][1] - Pr[1];
            multiplica(Tf, aux2, Pn[i]);
            System.out.println(Pn[i][0] + " " + Pn[i][1]);
        }
        u20 = Momento(Pn, Cen, 2, 0);
        u02 = Momento(Pn, Cen, 0, 2);
        u11 = Momento(Pn, Cen, 1, 1);
        System.out.println(u20 +" " + u02 + " " + u11);
    }

    static public void multiplica(double A[][], double b[], double resul[])
    {
        int n=A.length, m = A[0].length, l = b.length;
        int i, j, k;
        double suma;

        for(i=0; i<n; i++)
        {
            suma = 0;
            for (j = 0; j < m; j++)
                suma += A[i][j] * b[j];
            resul[i] = suma;
        }
    }

    static public double[][] multiplica(double A[][], double b[][])
    {
        int n = A.length, m = A[0].length, r = b.length, s = b[0].length;
        int i, j, k;
        double suma=0, resul[][] = new double[n][s];
        System.out.println(n + " " + m + " " + r + " " +s);

        for (i = 0; i < n; i++) {
            for (j = 0; j < s; j++)
            {
                suma = 0;
                for (k = 0; k < m; k++)
                    suma += A[i][k] * b[k][j];

                resul[i][j] = suma;
            }
        }
        return resul;
    }

    public static double[] Centroides(double P[][])
    {

        int i, n = P.length;
        double sx =0, sy = 0;
        double C[] = new double[2];

        for(i=0; i<n; i++)
        {
            sx += P[i][0];
            sy += P[i][1];
        }

        C[0] = sx /(double) n;
        C[1] = sy /(double) n;

        return C;
    }

    public static double Momento(double P[][], double C[], int k, int l)
    {
        int i, n = P.length;
        double sx, sy, suma =0;

        for(i=0; i<n; i++)
        {
            sx = Math.pow(P[i][0] - C[0], k);
            sy = Math.pow(P[i][1] - C[1], l);
            suma += sx*sy;
        }

        return suma/(double)(n);

    }
}
