/*
Projectile - algorithme de simulation pour SimuApplet

Copyright (C) 2002 Observatoire de Paris-Meudon

Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure.

Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU .

Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
*/

import simu.*;

/**
 * Algorithme de simulation pour SimuApplet.
 * Simule un projectile lancé sur Terre avec une vitesse initiale donnée et un angle
 * donné.
 * compilation: javac -source 1.2 -target 1.1 -encoding ISO-8859-1 -classpath SimuLab.jar Projectile.java
 */
public class Projectile extends SimuApplet {

    static final double g = 9.81;
    double dt = 0.05;
    double x,y;
    double vx,vy;
    
    // constructeur de la classe, avec la définition des paramètres de simulation
    // et des options d'affichage.
    public Projectile() {
        appletDoc("projectile_doc.xml");
        /* nouvelle version de SimuLab : les paramètres sont dans le fichier XML
        // paramètres d'entrée
        ParamIn v0 = new ParamIn();
        v0.type = "nombre";
        v0.label = "v0";
        v0.titre = "vitesse initiale";
        v0.unit = "m/s";
        v0.acquisition = "choix";
        String[] choix = {"8", "10", "12", "14"};
        v0.choix = choix;
        v0.defaut = "12";
        addParamIn(v0);
        
        ParamIn dir = new ParamIn();
        dir.type = "nombre";
        dir.label = "direction";
        dir.titre = "angle";
        dir.unit = "degres";
        dir.acquisition = "champ";
        dir.defaut = "70";
        addParamIn(dir);
        
        // paramètres de sortie
        ParamOut xv = new ParamOut();
        xv.type = "nombre";
        xv.label = "x";
        addParamOut(xv);
        ParamOut yv = new ParamOut();
        yv.type = "nombre";
        yv.label = "y";
        addParamOut(yv);
        
        // options d'affichage
        
        // affichage "plotlive"
        Affichage p = new Affichage();
        p.type = "plotlive";
        p.titre = "mouvement du projectile y/x live";
        String[][] pparams = {{"x", "y"}};
        p.params = pparams;
        p.fond = "apple.gif";
        addAffichage(p);
        
        // affichage "plot"
        p = new Affichage();
        p.type = "plot";
        p.titre = "mouvement du projectile y/x";
        p.params = pparams;
        p.fond = "apple.gif";
        addAffichage(p);

        // affichage "tableau"
        p = new Affichage();
        p.type = "tableau";
        p.titre = "mouvement du projectile";
        addAffichage(p);
        
        
        // affichage "multiplot"
        Affichage multi = new Affichage();
        multi.type = "multiplot";
        multi.titre = "mouvement du projectile y/x et x/y live";
        multi.sousAff = new Affichage[2];
        
        Affichage m1 = new Affichage();
        m1.type = "plotlive";
        m1.titre = "mouvement du projectile y/x live";
        String[][] pparamsm1 = {{"x", "y"}};
        m1.params = pparamsm1;
        m1.fond = "apple.gif";
        multi.sousAff[0] = m1;
        
        Affichage m2 = new Affichage();
        m2.type = "plotlive";
        m2.titre = "mouvement du projectile x/y live";
        String[][] pparamsm2 = {{"y", "x"}};
        m2.params = pparamsm2;
        m2.fond = "apple.gif";
        multi.sousAff[1] = m2;
        
        addAffichage(multi);
        */
    }
    
    // calcul live (utilisé avec affichage "plotlive")
    // initialisation
    public void initCalculLive(ListeValeurs in) throws SimuException {
        x = 0;
        y = 0;
        double v0 = in.lireDouble("v0");
        double angle = in.lireDouble("direction");
        vx = v0 * Math.cos(angle/180*Math.PI);
        vy = v0 * Math.sin(angle/180*Math.PI);
    }
    
    // Calcul du temps t au temps t+1.
    public ListeValeurs calculLive() throws SimuException {
        if (y < 0)
            return null; // fin du calcul
        ListeValeurs out = new ListeValeurs();
        x += vx * dt;
        y += vy * dt;
        vy -= g * dt;
        out.ajouterDouble("x", x);
        out.ajouterDouble("y", y);
        dormir(Math.round(dt*1000)); // pour bloquer le programme pendant dt secondes
        return out;
    }
    
    // calcul complet d'un coup (utilisé avec les affichages "plot" et "tableau")
    public ListeValeurs calcul(ListeValeurs in) throws SimuException {
        x = 0;
        y = 0;
        double v0 = in.lireDouble("v0");
        double angle = in.lireDouble("direction");
        vx = v0 * Math.cos(angle/180*Math.PI);
        vy = v0 * Math.sin(angle/180*Math.PI);
        ListeValeurs out = new ListeValeurs();
        while (y >= 0) {
            x += vx * dt;
            y += vy * dt;
            vy -= g * dt;
            out.ajouterDouble("x", x);
            out.ajouterDouble("y", y);
        }
        return out;
    }
}
