//////////////////////////////////////////////// // // This program takes a file containing a series of times and // positions (in decimal longitude and latitude), and outputs // the distance and average speed of each leg. This can be used to // determine the migration behavior of animals that are fitted with // satellite tracking tags. #include #include #include #include #include using namespace std; ////////////////////// // // Global Constants const float pi = 3.141592654; ////////////////////// // // Fuction Prototypes double ComputeDistance (float, float, float, float); float ComputeTime (int, int, int, int, int, int); double ComputeSpeed (double, float); float toRadians(float); float toDegrees(float); ////////////////////// // // MAIN FUNCTION int main(){ ////////////////////// // // Declare variables // File related stuff ifstream inputfile; string filename; // variables for input float StartLat, StartLong, EndLat, EndLong; int StartHour, StartMin, StartSec; int EndHour, EndMin, EndSec; char garbage; // use this to pick out the useless colons in the time format // variable for computation double distance = 0; float hours = 0; double averagespeed; // variables to keep track of totals double totaldistance = 0; float totaltime = 0; int leg = 0; ////////////////////// // // Show what program will do cout << "This program takes a filename that contains a series of" << endl; cout << "times and positions, in latitude and longitude, and specifies" << endl; cout << "the distance between the positions, and the average speed of" << endl; cout << "an animal that moved between those two points. It also computes" << endl; cout << "the total distance, and average speed over that distance." << endl; cout << endl << endl; ////////////////////// // // Get the input file name and try to open it cout << "Please enter the name of the file to process: "; getline(cin,filename); inputfile.open(filename.c_str()); if (!inputfile) { cerr << "Could not open input file: " << filename << endl; exit (1); } cout << endl << endl; ////////////////////// // // Set up column headings for output // and set decimal precision outout cout << setw(5) << "Leg" << setw(25) << "Distance(km)" << setw(25) << "Time (hours)" << setw(25) << "Average Speed (km/hr)" << endl; cout.setf(ios::fixed, ios::floatfield); cout.setf(ios::showpoint); cout << setprecision(2); ////////////////////// // // Start a loop to read lines from the file // read the first line first inputfile >> StartHour >> garbage >> StartMin >> garbage >> StartSec >> StartLat >> StartLong; // read all the other lines while (inputfile >> EndHour >> garbage >> EndMin >> garbage >> EndSec >> EndLat >> EndLong) { // add up the new leg we are working on leg++; // compute the distance between start and end distance = ComputeDistance (StartLat, StartLong, EndLat, EndLong); // add it to the totaldistance totaldistance += distance; // compute the elapsed time in hours hours = ComputeTime (StartHour, StartMin, StartSec, EndHour, EndMin, EndSec); // add it to the total time totaltime += hours; // compute the average speed averagespeed = ComputeSpeed (distance, hours); // output the results we just computed cout << setw(5) << leg << setw(25) << distance << setw(25) << hours << setw(25) << averagespeed << endl; // set the old end point to be the new start point // because the end of one leg is the start of the next StartLat = EndLat; StartLong = EndLong; StartHour = EndHour; StartMin = EndMin; StartSec = EndSec; } // end while loop // figure out the average overall speed averagespeed = ComputeSpeed (totaldistance, totaltime); // output the overall results cout << setw(5) << "-----" << setw(25) << "------------" << setw(25) << "------------" << setw(25) << "---------------------" << endl; cout << setw(5) << "Total" << setw(25) << totaldistance << setw(25) << totaltime << setw(25) << averagespeed << endl; }// end main ////////////////////// // // FUNCTION DECLARATIONS float toRadians(float degrees){ // need to convert decimal degrees to radians to // use the math trigonometric functions float radians = 0; radians = (degrees/360) * 2 * pi; return radians; } // end float toDegrees(float radians){ // need to convert radians back to degrees for // distance calculation float degrees = 0; degrees = (radians/(2 * pi)) * 360; return degrees; } double ComputeDistance (float StartLat, float StartLong, float EndLat, float EndLong){ // the formula for calculation comes from : // http://www.ncgia.ucsb.edu/education/curricula/giscc/units/ // u014/tables/table03.html double distance = 0; float intermediate; // sin, cos, and acos all use radians for arguments on gusun. Convert // from decimal degrees to radians StartLat = toRadians(StartLat); StartLong = toRadians(StartLong); EndLat = toRadians(EndLat); EndLong = toRadians(EndLong); // now apply the formula directly intermediate = acos((sin(StartLat) * sin(EndLat)) + (cos(StartLat)* cos(EndLat) * cos(fabs(StartLong - EndLong)))); // convert back to degrees before multiplying distance intermediate = toDegrees(intermediate); // compute the distance and return it distance = intermediate * 111.23; return distance; }; float ComputeTime (int Starthour, int Startmin, int Startsec, int Endhour, int Endmin, int Endsec){ int ElapsedSeconds = 0; float hours = 0; // convert each to total seconds passed since midnight int BeginSeconds = Startsec + (60 * (Startmin + (60 * Starthour))); int EndSeconds = Endsec + (60 * (Endmin + (60 * Endhour))); // now compare the two - if end is bigger it all happened the same // day and we can subtract to find the time. // otherwise, we need to subtract the start time from the total // seconds in a day, and add that to the end time if (BeginSeconds < EndSeconds) { ElapsedSeconds = EndSeconds - BeginSeconds; } else { ElapsedSeconds = ((24*60*60) - BeginSeconds) + EndSeconds; } // now convert seconds to hours // be careful of integer division hours = (static_cast(ElapsedSeconds))/(60*60); return hours; }; double ComputeSpeed (double distance, float hours){ double speed = 0; // speed is just distance over time. speed = distance/ hours; return speed; };