
/***************************************************************************
 * 
 *                  NE PAS MODIFIER CETTE SECTION 
 *                  
 **************************************************************************/
import java.awt.*;
import Listes.*;

public class Expresso extends FenetreTortue
{ 
     
/***************************************************************************
 * 
 *                      SECTION MODIFIABLE 
 *                  
 **************************************************************************/
 
 
 
/********************** Parametres de l'interface ************************/

    public static int baseFenetre = 600; // Largeur de la fenêtre
    public static int hauteurFenetre = 500; // Hauteur de la fenêtre
    public static String titreFenetre = "Fractales IFS"; // Titre de la fenêtre
    // Le texte
    public static boolean zoneTexte = true; // Indique si on désire ou non une zone de texte
    // Les boutons
    public static String[] nomsBoutonsLigne1 = {"Nouvelle transformation",unicode("D#eaigfinir textuellement"), "Effacer la transformation"}; // Noms des boutons de la ligne 1
    public static String[] nomsBoutonsLigne2 = { "Ajouter des points", "Effacer les points", "Effacer tout",  "Quitter"}; // Noms des boutons de la ligne 2
    // Les menus
    public static String[] nomsMenus1 = {"Fractales IFS", unicode("#Agra propos"), "Sauver", "Ramener", "Quitter"}; // Exemple: private static String[] nomsMenus1 = {"nomMenu", "nomItem_1", ...};
    public static String[] nomsMenus2 = {}; // Laissez vide si vous ne désirez pas de menu
    public static String[] nomsMenus3 = {};
    public static String[] nomsMenus4 = {};
    public static String[] nomsMenus5 = {};
    public static String[] nomsMenus6 = {};
    public static String[] nomsMenus7 = {};
    public static String[] nomsMenus8 = {};
    
    public static void ajoutDeGlissieres(){
        ajouterGlissiereLigne1(unicode("Nombre d'it#eaigrations (x 100)"), 1,1000,10,0);
        ajouterGlissiereLigne1(unicode("#Eaigchelle"), 0,10,1,2);
    }

/****************** Initialisation *********************************/
   
    public void initialisation(){
    // Placer ici les actions a realiser a l'ouverture
    fixerProportionZoneTexte(0.2);
    tailleTexte(24);
    //afficherTransfos();
    }
    
/****************** Placer vos procedures ici ****************************/

 int nbMaxTransfo =8, nbTransfos=0, noTransfoEditee=-1, rayonDisque = 3, noPointChoisi;
 Color[] couleursTransfos = {bleu, rouge, vert, magenta, cyan, orange, rose, noir};
 double[][] transfos =new double[nbMaxTransfo][6];
 double seuil = 5, facteur, origine1x,origine1y,origine2x, origine2y, pointX, pointY, echelle, translatX, translatY, tempX, tempY;
 boolean actionDroite;
 
 public void miseAjour() {
     afficherTransfos();
     afficherPoints(10*valEnt(valeurGlissiere(1)), true);
     afficherFocus();
    }
    
 public void deselectionner() {
     noTransfoEditee=-1;
     videTexte();
}
 
 public void afficherTransfos() {
     double hauteur = hauteurZoneGraphique();
     double largeur = largeurZoneGraphique();
     fixeOrigineTortue(largeur/2, hauteur/2);
     origine1x = -largeur/4;
     origine1y = 0;
     origine2x = largeur/4;
     origine2y = 0;
     translatX = 0;
     translatY = 0;
     facteur = min(largeur/8, hauteur/4);
     videGraphique();
     cc(noir);
     segment(0, -hauteur/2, 0, hauteur/2);
     cc(grisClair);
     segment(origine1x, -hauteur/2, origine1x, hauteur/2);
     segment(-largeur/2, origine1y, 0, origine1y);
     cercle(origine1x, origine1y, facteur);
     //deselectionner();
     for(int i=0;i<nbTransfos;i++) {
            cc(noir);
            segmentGauche(transfos[i][2], transfos[i][5], transfos[i][2]+facteur*transfos[i][0], transfos[i][5]+facteur*transfos[i][3]);
            cc(couleursTransfos[i]);
            segmentGauche(transfos[i][2], transfos[i][5], transfos[i][2]+facteur*transfos[i][1], transfos[i][5]+facteur*transfos[i][4]);
    }
}

 public void afficherPoints(int nbPoints, boolean depart) {
    int transfoCourante;
    double temp;
    if (echelle != valeurGlissiere(2)) {afficherTransfos(); afficherFocus();}
    echelle = valeurGlissiere(2);
    if (depart) { pointX = 0; pointY = 0;}
    if (nbTransfos == 0) {return ;}
    for (int i=0; i<nbPoints; i++) {
        transfoCourante = hasard(0,nbTransfos-1);
        temp = appliquerTransfoX(transfoCourante, pointX, pointY);
        pointY = appliquerTransfoY(transfoCourante, pointX, pointY);
        pointX = temp;
        cc(couleursTransfos[transfoCourante]);
        tracerPoint(pointX, pointY);
    }
}

 public void tracerPoint(double x, double y) {
    x = origine2x+echelle*x + translatX;
    if (x<0) {return;}
    y = origine2y+echelle*y + translatY;
    segment(x, y, x+1, y);
}

 public void segmentGauche(double x1, double y1, double x2, double y2) {
     segment(origine1x+x1, origine1y+y1, origine1x+x2, origine1y+y2);
    }

 public double appliquerTransfoX(int no, double x, double y) {
     return transfos[no][0]*x + transfos[no][1]*y + transfos[no][2];
}


 public double appliquerTransfoY(int no, double x, double y) {
     return transfos[no][3]*x + transfos[no][4]*y + transfos[no][5];
}

 public void ajouterTransfo() {
    if (nbTransfos == 8) {return;}
    transfos[nbTransfos][0] = 1;
    transfos[nbTransfos][1] = 0;
    transfos[nbTransfos][2] = 0;
    transfos[nbTransfos][3] = 0;
    transfos[nbTransfos][4] = 1;
    transfos[nbTransfos][5] = 0;
    noTransfoEditee = nbTransfos;
    nbTransfos = nbTransfos+1;
    afficherTransfos();
    afficherPoints(10*valEnt(valeurGlissiere(1)), true);
    afficherFocus();
}

 public void afficherFocus() {
    if (noTransfoEditee == -1) {return ;}
    couleurRemplissage(couleursTransfos[noTransfoEditee]);
    double p1x = transfos[noTransfoEditee][2];
    double p1y = transfos[noTransfoEditee][5];
    double p2x = p1x + facteur*transfos[noTransfoEditee][0];
    double p2y = p1y + facteur*transfos[noTransfoEditee][3];
    double p3x = p1x + facteur*transfos[noTransfoEditee][1];
    double p3y = p1y + facteur*transfos[noTransfoEditee][4];
    disque(origine1x+p1x, origine1y+p1y, rayonDisque);
    disque(origine1x+p2x, origine1y+p2y, rayonDisque);
    disque(origine1x+p3x, origine1y+p3y, rayonDisque);
    ecrireTransfo(noTransfoEditee);
    }

 public void ecrireTransfo(int n) {
     videTexte();
     ecrisRC("x' = ("+transfos[n][0]+")x + ("+transfos[n][1]+")y + "+transfos[n][2]);
     ecrisRC("y' = ("+transfos[n][3]+")x + ("+transfos[n][4]+")y + "+transfos[n][5]);
    }
    
 public void definirTransfoTextuelle(int n) {
      transfos[n][0] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de a:", transfos[n][0]);
      transfos[n][1] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de b:", transfos[n][1]);
      transfos[n][2] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de c:", transfos[n][2]);
      transfos[n][3] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de d:", transfos[n][3]);
      transfos[n][4] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de e:", transfos[n][4]);
      transfos[n][5] = demanderNombre("Transformation "+n, "x' = ax + by + c" + chariot + "y' = dx + ey + f" + chariot + "Valeur de f:", transfos[n][5]);
    }
    
 public double distPS(double x, double y, double x1, double y1, double x2, double y2) {
    x = x -x1;
    y = y - y1;
    x2 = x2 - x1;
    y2 = y2 - y1;
    double norme = sqrt(x2*x2+y2*y2);
    double proj = (x*x2+y*y2)/norme; //produit scalaire --> cos: test si projection sur segment
    if (proj < 0) {return 1000;}
    if (proj > norme) {return 1000;}
    return abs (x*y2-y*x2)/norme; // produit vectoriel --> sin: nous donne la distance ˆ la droite
}

 public double distPT(double x, double y, int n) {
    double p1x = transfos[n][2];
    double p1y = transfos[n][5];
    double p2x = p1x + facteur*transfos[n][0];
    double p2y = p1y + facteur*transfos[n][3];
    double p3x = p1x + facteur*transfos[n][1];
    double p3y = p1y + facteur*transfos[n][4];
    return min(distPS(x, y, p1x, p1y, p2x, p2y), distPS(x, y, p1x, p1y, p3x, p3y));
}

 public void transfoSelectionnee(double x, double y) {
     double  d;
     int t = -1;
     double dMin = 1000;
     x = x - origine1x; y = y - origine1y;
     for(int i=0; i<nbTransfos; i++) {
         d = distPT(x,y,i);
         if(d<dMin && d< seuil) {dMin = d; t = i;}
     }
     if (t != -1) {noTransfoEditee = t;} else {deselectionner();}
     miseAjour();
}

public void identifierPointTransfo(double x,double y) {
    if (noTransfoEditee == -1) {return;}
    double p1x = transfos[noTransfoEditee][2];
    double p1y = transfos[noTransfoEditee][5];
    double p2x = p1x + facteur*transfos[noTransfoEditee][0];
    double p2y = p1y + facteur*transfos[noTransfoEditee][3];
    double p3x = p1x + facteur*transfos[noTransfoEditee][1];
    double p3y = p1y + facteur*transfos[noTransfoEditee][4];
    noPointChoisi = 0;
    if (distPP(x, y, p1x, p1y) < seuil) {noPointChoisi = 1;}
    if (distPP(x, y, p2x, p2y) < seuil) {noPointChoisi = 2;}
    if (distPP(x, y, p3x, p3y) < seuil) {noPointChoisi = 3;}
    modifierPointTransfo(x,y);
}

public void modifierPointTransfo(double x,double y) {
    if (noTransfoEditee == -1 || noPointChoisi == 0) {return;} 
    double p1x = transfos[noTransfoEditee][2];
    double p1y = transfos[noTransfoEditee][5];
    switch (noPointChoisi) {
        case 1: 
            transfos[noTransfoEditee][2] = x; 
            transfos[noTransfoEditee][5] = y; 
            break;
        case 2: 
            transfos[noTransfoEditee][0] = (x-p1x)/facteur; 
            transfos[noTransfoEditee][3] = (y-p1y)/facteur; 
            break;
        case 3: 
            transfos[noTransfoEditee][1] = (x-p1x)/facteur; 
            transfos[noTransfoEditee][4] = (y-p1y)/facteur; 
            break;
    }
    miseAjour();
}

public double distPP(double x1, double y1, double x2, double y2) {
    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}

public void effacerPoints() {
    couleurRemplissage(blanc);
    rectanglePlein(1,hauteurZoneGraphique(),largeurZoneGraphique(),-hauteurZoneGraphique());
}
    
/**************  Les actions des boutons  ************************************/

public void actionBouton1(){ // Nouvelle transformation
    ajouterTransfo();
}    

public void actionBouton2(){ //Definition textuelle de transfo
    if (noTransfoEditee == -1) {return ;}
    definirTransfoTextuelle(noTransfoEditee);
    miseAjour();  
}

public void actionBouton3(){  // Effacer la transformation
    if (noTransfoEditee == -1) {return;}
    for (int i = noTransfoEditee; i< nbTransfos-1; i++) {
        transfos[i] = transfos[i+1];}
    nbTransfos = nbTransfos - 1;
    deselectionner();
    miseAjour();
}

public void actionBouton4(){ // Ajouterpoints
    afficherPoints(valEnt(100*valeurGlissiere(1)), false);
}

public void actionBouton5(){ // Effacer points
    effacerPoints();
}

public void actionBouton6(){  // Effacer tout
    nbTransfos = 0;
    deselectionner();
    afficherTransfos();
    afficherPoints(0, true);
} 

public void actionBouton7(){  // Quitter
    quitter();
}   
/**************  Les actions des menus  ****************************/

 public void actionMenu1Item1() {
    message("Fractales IFS"+chariot+unicode("par Andr#eaig Boileau")+chariot+unicode("et Maurice Garan#?cedon"));
}

 public void actionMenu1Item2() {
     if (appletP()){message("On ne peut enregistrer dans un applet"); return;}
    viderDonneesASauver();
    ajouterDonnee(nbTransfos);
    for(int i=0; i<nbTransfos; i++) {
        for (int j=0; j<6; j++) {
            ajouterDonnee(transfos[i][j]);
        }}
    sauverDonnees();
}

 public void actionMenu1Item3() {
    lireFichier();
    if (tailleFichier() == 0) {return ;}
    nbTransfos = valEnt(lireDonnee(0)); 
    int k = 1;
    for(int i=0; i<nbTransfos; i++) {
        for (int j=0; j<6; j++) {
            transfos[i][j] = valDec(lireDonnee(k)); k = k+1;;
        }}
        
     deselectionner();
     miseAjour();
}

 public void actionMenu1Item4() {
    quitter();
}
   
/*************** Les actions des glissieres *********************************/  

    
  
/**************** Les actions de la souris *******************************/
    
    public void clicSouris(double x, double y){
        if (x>0) {pointX = (x - origine2x)/echelle; pointY = (y - origine2y)/echelle;} else {transfoSelectionnee(x,y);}
    }
    
    public void debutGlisser(double x, double y){
        if (x<0) {actionDroite = false; identifierPointTransfo(x - origine1x,y - origine1y);} 
        else {actionDroite = true; tempX = x; tempY =y;}
    }
    
    public void finGlisser(double x, double y){
        if (actionDroite) 
            {translatX = translatX + x - tempX; 
             translatY = translatY + y - tempY;
             effacerPoints();
             afficherPoints(10*valEnt(valeurGlissiere(1)), true);} 
        else {glisserEnCours(x,y);}
    }
    
    public void glisserEnCours(double x, double y){
       if (!actionDroite) {modifierPointTransfo(x - origine1x,y - origine1y);}
    }
    
/***************************************************************************
 * 
 *                  NE PAS MODIFIER CETTE SECTION 
 *                  
 **************************************************************************/    
    
    public static String[][] Menus = {nomsMenus1, nomsMenus2, nomsMenus3, nomsMenus4, nomsMenus5, nomsMenus6, nomsMenus7, nomsMenus8};    
    
    public Expresso(int l, int h, String titre, String[] nomsBoutons1, String[] nomsBoutons2, String[][] Menus, boolean avecTexte){
        super(l, h, titre, nomsBoutons1, nomsBoutons2, Menus, avecTexte);
    }
    
    public Expresso() {
        this(baseFenetre, hauteurFenetre, titreFenetre, nomsBoutonsLigne1, nomsBoutonsLigne2, Menus, zoneTexte);
    }
    
    public static void executer(boolean applet){
        initGlissieres();
        ajoutDeGlissieres();
        Expresso maFenetre = new Expresso();
        faireApplet(applet);
        maFenetre.toFront();
        maFenetre.initialisation();
    }
    
    public static void main(String[] args){
        executer(false);
    }
     
}  
