#include #include /* esercitazione3.c Copyright (C) 2008 by Giovanni.Organtini@roma1.infn.it This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define g 9.8 main() { /* stato iniziale */ double t=0, x = 0, y = 0; double T, dt, theta, vx, vy, v0, d, h; int i; /* osservate come spezzando la stringa in piu' tronconi il messggio si legga perfettamente e si possa 'vedere' l'effetto che fara' sullo schermo */ printf("Questo programma simula il moto di un punto materiale\n" "lanciato con velocita' iniziale v0 a un angolo theta\n" "rispetto al suolo. La simulazione e' eseguita per T\n" "secondi, a intervalli dT.\n"); do { printf("Inserisci la velocita' iniziale: "); scanf("%lf", &v0); /* in caso di errore e' necessario segnalarlo all'utente */ if (v0 < 0) { /* notate come il messaggio viene composto. Non c'e' 'a capo', ma uno spazio alla fine */ printf("Attenzione! La velocita' deve essere positiva. "); } } while (v0 < 0); do { /* per evitare un if all'interno del do si puo' dare un messaggio che si adatti a tutti i casi possibili */ printf("Inserisci l'angolo di lancio compreso tra 0 e 90 gradi: "); scanf("%lf", &theta); } while ((theta > 90) || (theta < 0)); /* trasformiamo subito in radianti */ theta = theta * M_PI / 180.; do { printf("Inserisci la durata della simulazione e l'intervallo dt\n" "separati da uno spazio. Entrambi devono essere positivi:"); /* con scanf si puo' leggere piu' di una variabile per volta usando il formato opportuno. In questo caso non e' una buona idea, perche' si fa un controllo su entrambe le variabili, ma lo facciamo per farvi vedere come si fa. */ scanf("%lf %lf", &T, &dt); } while ((T < 0) || (dt < 0)); printf("Adesso e' possibile inserire la distanza di un muro di\n" "altezza h dal punto materiale. Nel caso in cui il punto\n" "urti questo muro durante il suo moto, la simulazione sara'\n" "interrotta\n"); do { printf("Inserisci la distanza (positiva) del muro dal punto: "); scanf("%lf", &d); } while (d < 0); do { printf("Inserisci l'altezza (positiva) del muro: "); scanf("%lf", &h); } while (h < 0); /* Il programma richiede di eseguire la simulazione 4 volte, riducendo progressivamente la velocita' iniziale. E' il caso di usare un for */ for (i = 0; i < 4; i++) { vx = v0 * cos(theta) / (i + 1); vy = v0 * sin(theta) / (i + 1); /* dobbiamo imporre t=0 a ogni iterazione */ t = 0; /* non potendo prevedere quando finira' il moto, e comunque non essendo questo controllato da un contatore, usiamo un while */ while (t < T) { /* stampo prima di eseguire il calcolo per la nuova posizione cosi' stampo lo stato iniziale e non quello oltre quello finale. scrivo solo le coordinate cosi' da poterle usare in gnuplot. */ printf("%f %f\n", x, y); t += dt; x = vx * t; y = -0.5 * g * t * t + vy *t; /* eseguiamo i controlli. Se il controllo non e' superato si impone t = T, cosi' che alla prossima iterazione la condizione del while risulti falsa. */ if ((y < 0) || ((x >=d) && (y <= h))) { /* se y < 0 ho toccato il suolo. La condizione di urto con il muro e' piu' complessa: il muro potrebbe essere colpito solo se la x del punto materiale e' maggiore della coordinata x del muro. In questo caso il muro viene colpito solo se la coordinata y del punto e' maggiore dell'altezza del muro. Siccome i tempi sono discreti non e' detto che si giunga ad ottenere x=d. Scrivere questa condizione equivale ad approssimare la posizione del muro con un'indeterminazione pari a vx*dt */ t = T; } } } } /* Provate con i dati seguenti: v0=100 m/s, theta=45, T=1000, dt=.1, d=h=0. In questo caso non ci sono muri. Dopo 1000 secondi il punto finirebbe sotto terra, ma la simulazione si interrompe a y=2.17. v0=100 m/s, theta=45, T=1000, dt=.1, d=550 h=600. In questo caso il muro e' piu' o meno a meta' traiettoria ed e' molto piu' alto della massima altezza raggiunta dal punto. In questo caso il primo lancio finisce sul muro. Gli altri invece no perche' il punto non arriva fino alla distanza minima. v0=100 m/s, theta=45, T=1000, dt=.1, d=200 h=100. In questo caso il muro non s' sufficientemente alto a fermare il primo lancio, che lo scavalca. Il secondo pero' si infrange su esso, mentre gli altri due giungono a terra prima di raggiungere il muro. Mandate l'output su un file e poi usate gnuplot per fare i grafici. */