/* File: projectiles.c 
   Create animation for motion of projectiles 
   with the initial velocity
   35m/s and different projection angles */
#include <stdio.h>
#include <math.h>
#include <array.h>
#define g   9.8
#define t_incr 0.1
#define r 4.0

int main() {

    FILE *stream;
    stream = popen("qanimate", "w");
    if (stream == NULL) {
        fprintf(stderr, "Error: popen() failed\n");
    }

    /* Declare and initialize variables  */
    double x_ground[2] = {0.0, 150.0};  // define x coordinates for ground
    double V0 = 35, t = 0;  // initial velocity V0 = 35 m/s
    array double theta[6] = {15, 30, 45, 60, 75, 90};   // initialize an angle array theta with six launching angles in degree
    theta = theta * M_PI / 180;     // converting lauching angle from degree to radian
    array double tf[6], x[6], y[6], xf[6], yf[6];  //x[6] and y[6] are the x and y coordinate for the position at time t.
    // The array has six elements because there are six positions
    //xf[6] and yf[6] are the final x and y position of the ball.
    int i, j, k;   // counting index
    double tmax;  //tmax is the maximum time that the ball stays in the air when the ball is launched at 90 degree
    char *color[6] = {"red", "green", "blue", "pink", "turquoise", "yellow"};

    /* finding the time, x coordinates and y coordinate when the ball returns to the ground */
    for (i = 0; i < 6; i++) {
        tf[i] = 2 * V0 * sin(theta[i]) / g;
        xf[i] = tf[i] * V0 * cos(theta[i]);
        yf[i] = -0.5 * g * tf[i] * tf[i] + tf[i] * V0 * sin(theta[i]) + r;
    }

    tmax = tf[5];   // define the maximum time to be the final time of the ball that is launched at 90 degree.
    int N = (tmax + 1) / t_incr + 1;    //define the number element for the tracing position arrays
    
    double x_trace[6][N], y_trace[6][N], t_trace[6][N];     // declare arrays for tracing time and positions

    /* A comment line starting with # */
    fprintf(stream, "# qanimate data for projectile motion\n");
    /* The title displayed on the animation */
    fprintf(stream, "title \"Motion of Projectiles\"\n");
    fprintf(stream, "fixture\n");
    /* The primitive following fixture */
    fprintf(stream, "ground %f 0 %f 0.0\\\n", x_ground[0], x_ground[1]);
    fprintf(stream, "text %f %f \"Projection angle 15 degrees\"\\\n", 110.0, 90.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 83.0, 4.0, color[0]);
    fprintf(stream, "text %f %f \"Projection angle 30 degrees\" \\\n", 110.0, 80.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 73.0, 4.0, color[1]);
    fprintf(stream, "text %f %f \"Projection angle 45 degrees\"\\\n", 110.0, 70.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 63.0, 4.0, color[2]);
    fprintf(stream, "text %f %f \"Projection angle 60 degrees\"\\\n", 110.0, 60.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 53.0, 4.0, color[3]);
    fprintf(stream, "text %f %f \"Projection angle 75 degrees\"\\\n", 110.0, 50.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 43.0, 4.0, color[4]);
    fprintf(stream, "text %f %f \"Projection angle 90 degrees\"\\\n", 110.0, 40.0);
    fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", 250.0, 33.0, 4.0, color[5]);
    fprintf(stream, "animate\n");

    /* starting the animation */
    for(j = 0; j < N; j++) {
        t = j * t_incr;
        
        if (t <= tf[0]) {
            for (i = 0; i < 6; i++) {
                x[i] = t * V0 * cos(theta[i]);
                y[i] = -0.5 * g * t * t + t * V0 * sin(theta[i]) + r;
                x_trace[i][j] = x[i];
                y_trace[i][j] = y[i];
            }
        }
        else if (t > tf[0]) {   // for time t that is greater than the time that the ball launched at 15 degree,
            // redefine the position of the ball for that angle to be constant.

            if (t <= tf[1]) {
                x[0] = xf[0];
                y[0] = yf[0];
                x_trace[0][j] = x[0];
                y_trace[0][j] = y[0];
                for (i = 1; i < 6; i++) {
                    x[i] = t * V0 * cos(theta[i]);
                    y[i] = -0.5 * g * t * t + t * V0 * sin(theta[i]) + r;
                    x_trace[i][j] = x[i];
                    y_trace[i][j] = y[i];
                }
            }
            else if (t > tf[1]) {       // for time t that is greater than the time that the ball launched at 30 degree,
                // redefine the position of the ball for that angle to be constant.


                if (t <= tf[2]) {
                    x[0] = xf[0];
                    y[0] = yf[0];
                    x_trace[0][j] = x[0];
                    y_trace[0][j] = y[0];
                    x[1] = xf[1];
                    y[1] = yf[1];
                    x_trace[1][j] = x[1];
                    y_trace[1][j] = y[1];
                    for ( i = 2; i < 6 ; i++) {
                        x[i] = t * V0 * cos(theta[i]);
                        y[i] = -0.5 * g * t * t + t * V0 * sin(theta[i]) + r;
                        x_trace[i][j] = x[i];
                        y_trace[i][j] = y[i];
                    }
                }
                else if (t > tf[2]) {        // for time t that is greater than the time that the ball launched at 45 degree,
                    // redefine the position of the ball for that angle to be constant.
                    if (t <= tf[3]) {
                        x[0] = xf[0];
                        y[0] = yf[0];
                        x_trace[0][j] = x[0];
                        y_trace[0][j] = y[0];
                        x[1] = xf[1];
                        y[1] = yf[1];
                        x_trace[1][j] = x[1];
                        y_trace[1][j] = y[1];
                        x[2] = xf[2];
                        y[2] = yf[2];
                        x_trace[2][j] = x[2];
                        y_trace[2][j] = y[2];
                        for (i = 3; i < 6; i++) {
                            x[i] = t * V0 * cos(theta[i]);
                            y[i] = -0.5 * g * t * t + t * V0 * sin(theta[i]) + r;
                            x_trace[i][j] = x[i];
                            y_trace[i][j] = y[i];
                        }
                    }
                    else if (t > tf[3]) {      // for time t that is greater than the time that the ball launched at 60 degree,
                        // redefine the position of the ball for that angle to be constant.

                        if (t <= tf[4]) {
                            x[0] = xf[0];
                            y[0] = yf[0];
                            x_trace[0][j] = x[0];
                            y_trace[0][j] = y[0];
                            x[1] = xf[1];
                            y[1] = yf[1];
                            x_trace[1][j] = x[1];
                            y_trace[1][j] = y[1];
                            x[2] = xf[2];
                            y[2] = yf[2];
                            x_trace[2][j] = x[2];
                            y_trace[2][j] = y[2];
                            x[3] = xf[3];
                            y[3] = yf[3];
                            x_trace[3][j] = x[3];
                            y_trace[3][j] = y[3];
                            for (i = 4; i < 6; i++) {
                                x[i] = t * V0 * cos(theta[i]);
                                y[i] = -0.5 * g * t * t + t * V0 * sin(theta[i]) + r;
                                x_trace[i][j] = x[i];
                                y_trace[i][j] = y[i];
                            }
                        }
                        else if (t > tf[4]) {    // for time t that is greater than the time that the ball launched at 75 degree,
                            // redefine the position of the ball for that angle to be constant.

                            if (t <= tf[5]) {
                                x[0] = xf[0];
                                y[0] = yf[0];
                                x_trace[0][j] = x[0];
                                y_trace[0][j] = y[0];
                                x[1] = xf[1];
                                y[1] = yf[1];
                                x_trace[1][j] = x[1];
                                y_trace[1][j] = y[1];
                                x[2] = xf[2];
                                y[2] = yf[2];
                                x_trace[2][j] = x[2];
                                y_trace[2][j] = y[2];
                                x[3] = xf[3];
                                y[3] = yf[3];
                                x_trace[3][j] = x[3];
                                y_trace[3][j] = y[3];
                                x[4] = xf[4];
                                y[4] = yf[4];
                                x_trace[4][j] = x[4];
                                y_trace[4][j] = y[4];
                                x[5] = t * V0 * cos(theta[5]);
                                y[5] = -0.5 * g * t * t + t * V0 * sin(theta[5]) + r;
                                x_trace[5][j] = x[5];
                                y_trace[5][j] = y[5];
                            }
                            else if (t > tf[5]) {   // for time t that is greater than the time that the ball launched at 90 degree,
                                // redefine the position of the ball for that angle to be constant.
                                x[0] = xf[0];
                                y[0] = yf[0];
                                x_trace[0][j] = x[0];
                                y_trace[0][j] = y[0];
                                x[1] = xf[1];
                                y[1] = yf[1];
                                x_trace[1][j] = x[1];
                                y_trace[1][j] = y[1];
                                x[2] = xf[2];
                                y[2] = yf[2];
                                x_trace[2][j] = x[2];
                                y_trace[2][j] = y[2];
                                x[3] = xf[3];
                                y[3] = yf[3];
                                x_trace[3][j] = x[3];
                                y_trace[3][j] = y[3];
                                x[4] = xf[4];
                                y[4] = yf[4];
                                x_trace[4][j] = x[4];
                                y_trace[4][j] = y[4];
                                x[5] = xf[5];
                                y[5] = yf[5];
                                x_trace[5][j] = x[5];
                                y_trace[5][j] = y[5];
                            }
                        }
                    }
                }
            }
        }

        for (i = 0; i < 6; i++){
            if( i == 5){
                fprintf(stream, "circle %f %f %f linewidth 1 fill %s \n", x[5], y[5], r, color[5]);
                if ((t >= 0) && t < (tf[i]/4)) {
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[5]);
                    }
                }
                else if(t >= (tf[i]/4) && t < (tf[i]/2)){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[5]);
                    }
                }
                else if(t >= (tf[i]/2) && t < (tf[i]*3/4)){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[5]);
                    }
                }
                else if(t >= (tf[i]*3/4) && t < tf[i]){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[5]);
                    }
                }
                else if(t >= tf[i]){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[5]);
                    }
                }
            }
            else {
                fprintf(stream, "circle %f %f %f linewidth 1 fill %s \\\n", x[i], y[i], r, color[i]);
                if ((t >= 0) && t < (tf[i]/4)) {
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[i]);
                    }
                }
                else if(t >= (tf[i]/4) && t < (tf[i]/2)){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[i]);
                    }
                }
                else if(t >= (tf[i]/2) && t < (tf[i]*3/4)){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[i]);
                    }
                }
                else if(t >= (tf[i]*3/4) && t < tf[i]){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[i]);
                    }
                }
                else if(t >= tf[i]){
                    for(k = 0; k < j; k++){
                        fprintf(stream,"line %f %f %f %f pen %s \\\n", x_trace[i][k], y_trace[i][k], x_trace[i][k+1], y_trace[i][k+1], color[i]);
                    }
                }
            }
        }
        
        /* projectile path for 15 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill blue \\\n", x[0], y[0], r);
        /* projectile path for 30 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill red \\\n", x[1], y[1], r);
        /* projectile path for 45 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill white \\\n", x[2], y[2], r);
        /* projectile path for 60 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill green \\\n", x[3], y[3], r);
        /* projectile path for 75 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill black \\\n", x[4], y[4], r);
        /* projectile path for 90 degree */
        //fprintf(stream, "circle %f %f %f linewidth 1 fill yellow \n", x[5], y[5], r);
        
        
        
        /* define the next time t */
        
    }

    pclose(stream);
    return 0;
}
