c++coordinatesdistancegreat-circle

Game- calculating of distance between two coordinates


I have a problem with my code. So our task was to create a code, which inputs info from a txt file (includes name of a city with its longitude and latitude) and make a game which asks "What city is closest to _____" and gives you 3 options, from which you have to pick. Then it tells you correct/incorrect and shows you the distances. The problem is, that my code doesn't calculate the distance between the towns in kilometres, but a really strange form. the result is e.g. 3.582e-307 and similar. Do you know what could be the problem?

    #include <iostream>
    #include <cstdlib>
    #include <stdlib.h>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <time.h>
    #include <random>
    #include <numeric>
    #include <math.h>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #define PI 3.14159265

using namespace std;

struct District {
      double lng  ;
      double lat ;
      string city  ;
};
struct Distance {
    double lng;
    double lat;
};
//void for changing degrees to rad
double dtr(double deg) {
return (deg * PI / 180);
};

//void calculation of distance
// this doesnt work correctly - the output isnt the distance in KM, i used the formula from - https://en.m.wikipedia.org/wiki/Great-circle_distance
double* distancecalc (double pos[], double distance[]) {
    Distance locat [4]  ;
    District districts [79] ;
    double posi [4];
    for (int x=0; x<4; x++) {
        posi [x] = pos [x] ;
    }
    for (int u=posi[0]; u<posi[4]; u++) {
        locat [u].lat = districts [u].lat ;
        locat [u].lng = districts [u]. lng;
        locat [u].lat = dtr(locat [u].lat );
        locat [u].lng =dtr (locat [u].lng) ;
   }

    //calculate the distance between cities (0 (base) and 1-3)
    for (int u=0; u<4; u++) {
        double ax = locat[0].lat, ay = locat[0].lng, bx = locat[u].lat, by = locat[u].lng;
        distance[u] = acos (sqrt(pow(sin((bx-ax)/2.0), 2.0)+cos(ax)*cos(bx)*pow(sin((by-ay)/2.0),2.0))) * 2 * 6371;
    return distance ;
}
}

int main () {
    int z=1;
    do { districts [79] ;
    ifstream inputFile;

    inputFile.open ("districts.txt") ;
    if (!inputFile.is_open()){
        cout << "opening txt document" << endl;
        return 0 ;
    }
    //shuffle
    int line ;
    stringstream ss;
    string sdouble ;
    for (line=0; line<79; line++) {
        getline(inputFile, districts[line].city, ';')  ;
        getline(inputFile, sdouble,  ';') ;
        ss<< sdouble;
        ss>> districts[line].lng ;
        getline(inputFile, sdouble, ';' ) ;
        ss<<sdouble;
        ss>>districts[line].lat;
        getline(inputFile, sdouble) ;

    }

    //shuffle the cities+ coordinates- array
    srand(time(NULL));
    double tempn;
    int pos1,pos2;
    string temp;
    for (int i = 0; i < 79; ++i){
        pos1 = rand()%79;
        pos2 = rand()%79;
        temp = districts [pos1].city ;
        districts [pos1].city =  districts [pos2].city;
        districts [pos2].city = temp;
        tempn = districts [pos1].lat;
        districts [pos1].lat  =  districts [pos2].lat ;
        districts [pos2].lat  = tempn;
        tempn = districts [pos1].lng  ;
        districts [pos1].lng  =  districts [pos2].lng ;
        districts [pos2].lng  = tempn;
    }

    //game
    double pos [4];
    double distance [3];
    int loop=0, answer=0, guess, total=0;
    do {
        double min=999999;
        //cout - city + options
        cout<< endl ;
        cout << "Which city is the closest  to "<< districts[loop].city<< "? Pick one of the following: " <<endl;
        pos [1] = loop;
        loop++ ;
        cout << "1) " << districts[loop].city << endl;
        pos [2]= loop;
        loop++ ;
        cout << "2) " << districts[loop].city << endl;
        pos [3] = loop;
        loop++ ;
        cout << "3) " << districts[loop].city << endl;
        pos [4] = loop;
        loop++ ;
        //calculate the difference+ find answer (which is the closest)
        cout << "Write your selection: " ;
        cin>> guess;
        for (int x=1; x<4; x++) {
            if (min>distance[x] ) {
                min= distance[x];
                answer= x;
            }
        }
        //if you guess the correct answer -
        if (guess==answer) {
            total++;
            cout<< "Correct! The distances are: " << endl;
        }
        // if you guess the incorrect answer-
        else {
            cout<< "Incorrect! The distances are:" <<endl;
        }
        //witing the distances between 1 city
        cout<< "1) " << districts[loop-3].city << "-  " << distance [1] << endl;
        cout<< "2) " << districts[loop-2].city << "-  " <<  distance [2] << endl;
        cout<< "3) " << districts[loop-1].city << "-  " << distance [3] << endl << endl;
         for (int u=0 ; u< 80; u++) {
             cout << "-" ;
         }

    } while(loop<40) ;
    //end of game
    cout << endl << "Conratulations, you finished the game! Your score is: " << total << " out of 10" << endl;
    int selection ;
    cout <<endl << "Do you want to play again?" << endl << "1= Yes" << endl << "0= No" << endl;
    cout << "Your selection: " ;
    cin>> selection;
    if (selection== 0) {
        z= 0;
    }
    else {
        z=1;
    if (system("CLS")) system("clear") ;
    }
} while  (z==1 );
}



**END OF CODE**

Solution

  • Your latitudes and longitudes are in degrees, right? The n you can avoid calling a function to transform them to radians:

    constexpr double DEG2RAD = 3.141592653589793 / 180;
    

    So that:

    for (int u=posi[0]; u<posi[4]; u++) {
        locat [u].lat = districts [u].lat * DEG2RAD;
        locat [u].lng = districts [u].lng * DEG2RAD;
    }
    

    Then, in the link you posted the formula is different, you use acos instead of asin, but most of all you didn't pass districts[] to the function, so it is local to that function and uninitialized. You have to decide if make that array global or not.

    Then you have to call distancecalc() somewhere...