package registro;
import senales.funciones;
import java.util.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class Hausdorff {
    public static void main(String[] args) {

        int m = 100, p;
        double P[][] = new double[m][2];
        double Q[][] = new double[m][2];

        double ang = Math.PI/10;
        double To[] = {Math.cos(ang), -Math.sin(ang), 10, Math.sin(ang), Math.cos(ang), 5};

        double ang2 = ang;
        double T[] = {Math.cos(ang2), -Math.sin(ang2), 7.28, Math.sin(ang2), Math.cos(ang2), 3.58};
        double ti, tj;
        double ran[][] = {{0, 3.14}, {0, 20}, {0,20}};

        genera_ptos(P, Q, To);



        Q[0][0] = 1000;
        Q[0][1] = 1000;

        Q[1][0] = 3000;
        Q[1][1] = 2000;

        p= 2;
        //System.out.println(mejor(P, Q, p, ran[p], T));
        double parsal[] = prueba(P, Q, ran[1], T);
        System.out.println(parsal[0] + " " + parsal[1] + " " + parsal[2]);

    }

    static public double[] prueba(double P[][], double Q[][], double ran[], double T[])
    {
        int n = P.length;
        double dt = 1.0, t1, t2, t3, min, aux, par[] = new double[3];
        double Pn[][] = new double[n][2];

        afin(P, Pn, T);
        min = distance(Pn, Q);
        par[0] = ran[0];
        par[1] = ran[1];


        for (t1 = ran[0]; t1 <= ran[1]; t1 += dt)
            for(t2 = ran[0]; t2<=ran[1]; t2 += dt)
                for(t3 = 0; t3 <= 3.1416; t3+=0.01)
                {
                    T[0] = Math.cos(t3);
                    T[1] = -Math.sin(t3);
                    T[2] = t1;
                    T[3] = Math.sin(t3);
                    T[4] = Math.cos(t3);
                    T[5] = t2;

                    afin(P, Pn, T);
                    aux = distance(Pn, Q);
                    //System.out.println(t + " <---> " +aux);
                    if (aux < min) {
                        min = aux;
                        par[0] = t1;
                        par[1] = t2;
                        par[2] = t3;
                    }
                }
        return par;
    }

    static public double mejor(double P[][], double Q[][], int p, double ran[], double T[])
    {
        int n = P.length;
        double dt = 0.01, t, min, aux, par;
        double Pn[][] = new double[n][2];

        afin(P, Pn, T);
        min = distance(Pn, Q);
        par = ran[0];
        System.out.println(ran[0] + " -- " + ran[1]);

        for(t =ran[0]; t<=ran[1]; t +=dt)
        {
            if(p == 0)
            {
                T[0] = Math.cos(t);
                T[1] = -Math.sin(t);
                T[3] = Math.sin(t);
                T[4] = Math.cos(t);
            }
            else if(p == 1)
                T[2] = t;
            else if(p==2)
                T[5] = t;

            afin(P, Pn, T);
            aux = distance(Pn, Q);
            //System.out.println(t + " <---> " +aux);
            if(aux < min)
            {
                min = aux;
                par = t;
            }
        }
        return par;
    }

    static public void afin(double P[][], double Q[][], double T[])
    {
        int i, n;
        n= P.length;
        for(i=0; i<n; i++)
        {
            Q[i][0] = T[0]*P[i][0] + T[1]*P[i][1] + T[2];
            Q[i][1] = T[3]*P[i][0] + T[4]*P[i][1] + T[5];
        }
    }

    static public void imprime(double P[][])
    {
        int i, n = P.length;

        for(i=0; i<n; i++)
            System.out.print("[" +P[i][0] + " , " + P[i][1] + "] " );
        System.out.println("");
    }

    static public double distance(double A[][], double B[][])
    {
        int i, j, n, m;
        double min, aux;
        n = A.length;
        m = B.length;
        double dk[] = new double[n];

        for(i=0; i<n; i++)
        {
            min = d(A[i], B[0]);
            for (j = 1; j < m; j++)
            {
                aux = d(A[i], B[j]);
                if(min > aux) min = aux;
            }
            dk[i] = min;
        }
        quiksort(0, m-1, dk);
        return dk[m/2];
    }

    static public double d(double x[], double y[])
    {
        double aux = (x[0] -y[0])*(x[0] -y[0]) + (x[1] -y[1])*(x[1] -y[1]);
        return(Math.sqrt(aux));
    }

    static public void quiksort(int lo,int ho, double valor[])
    {
        int l = lo, h = ho;
        double aux, mid;

        if (ho > lo) {
            mid = valor[(lo + ho) / 2];
            while (l < h) {
                while ((l < ho) && (valor[l] < mid))++l;
                while ((h > lo) && (valor[h] > mid))--h;
                if (l <= h) {

                    aux = valor[l];
                    valor[l] = valor[h];
                    valor[h] = aux;

                    ++l;
                    --h;
                }
            }

            if (lo < h)
                quiksort(lo, h, valor);
            if (l < ho)
                quiksort(l, ho, valor);
        }
    }

    static public void genera_ptos(double P[][], double Q[][], double T[])
    {
        int i, n=P.length;
        double max =50, min = 10;
        Random alfa = new Random();


        for(i=0; i<n; i++)
        {
            P[i][0] = (max - min)*alfa.nextFloat() + min;
            P[i][1] = (max - min)*alfa.nextFloat() + min;
        }

        afin(P, Q, T);

    }
}
