Finding cabs nearby using Great Circle Distance formula


Given GPS co-ordinates(in degrees) of a person who needs a cab and co-ordinates of all the cabs in the city stored in a text file in JSON format, find the user-id and name of all the cab drivers available in 50 km proximity.

Examples:

Input : file customers.json which contains GPS co-ordinates of a person who needs a cab in degrees and co-ordinates of all the cabs in the city stored in a text file in JSON format.

Output : file answers.json which contains user-id and Name of all the cab drivers available in 50 km proximity stored in a new file.

Approach Used:
1. Obtain latitude and longitude of each cab in string format along with their
user-id and name from the JSON encoded input file.

2. Convert latitude and longitude of the cab present in string format to double.

3. Convert latitude and longitude of both, the user and the cab present in
degrees to radians.

4. Calculate distance between the user’s location and the cab using Great Circle
Distance formula.

5. If distance is found to be less than or equal to 50 kms then output the user-
id and name of the cab driver to a new file else take no action.

Procedure to run the program :
1. Save the code and the file customers.json in a same location.
2. Now, compile the code(using cmd : g++ file_name.cpp) and run it(using cmd : ./a.out /home/gfg/customers.json) with passing file name customers.json along with proper location(e.g. /home/gfg/customers.json).
3. A file named answers.json will be created on the same location where code and customers.json file is existing.

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ code to find cabs nearby
#include <bits/stdc++.h>
using namespace std;
  
// Latitude of customer who needs a cab.
#define lat1d 12.9611159
  
// Longitude of customer who needs a cab.
#define lon1d 77.6362214
  
#define pi 3.14159265358979323846
#define earth_radius 6371.0
  
ifstream customer_list ("customers.json");
ofstream out ("answer.json");
  
// Function to convert degree to radian.
double degtorad(double deg)
{
    return ( deg * pi / 180);
}
  
// Function to calculate distance
// between 2 given locations 
// using Great Circle Distance Formula.
double distanceEarth(double lat2d, double lon2d)
{                 
    double lat1, lon1, lat2, lon2, 
           delta_lon, central_ang;
  
    lat1 = degtorad(lat1d);
    lon1 = degtorad(lon1d);
    lat2 = degtorad(lat2d);
    lon2 = degtorad(lon2d);
  
    delta_lon = lon2 - lon1;
      
    // great circle distance formula.
    central_ang = acos ( sin(lat1) *
                  sin(lat2) + cos(lat1) *
                  cos(lat2) * cos(delta_lon) ); 
                    
    return (earth_radius * central_ang);
}
  
// Structure which contains data and
// functions for accessing and processing
// data from the given customers.json file.
struct json
{
    /* i and j are used to access various
    elements of the char arrays. x is used
    to measure the size of the element of
    latitude_as_string array. y is used to
    measure the size of the element of
    longitude_as_string array. m is used
    to measure the size of the element
    of id_as_string array. n is used to
    measure the size of the element of
    name array. f keeps count of " " "
    symbol. fi keeps count of " : " symbol.
    */
    long long int length, i, j, x, y, m,
                  n, f, fi, id[100000];
      
    char latitude_as_string[1000], 
         longitude_as_string[1000], 
         id_as_string[1000], name[1000];
      
    double lat2d, lon2d;
      
    // To get each line of customers.json
    // file as string.
    string line;
  
    // Function to check whether distance between
    // 2 points is less than 50km or not.
    void distance_calculator()
    {
        if (distanceEarth(lat2d, lon2d) <= 50.0000)
        {
            // Converting id to int format.
            id[i] = atoll(id_as_string);
            i++;
            out << "{\"user_id\": " << id[i - 1] << 
                ", \"name\": " << name << "}" << endl;
        }
    }
  
    // Function to read various attributes
    // like latitude, longitude, name , id,
    // etc, from customers.json file. simplistic
    // approach is used to get JSON attributes.
    void json_parser()
    {                     
        if (customer_list.is_open())
        {
              
            while (getline(customer_list, line))
            {
                  
                f = 0; x = 0; y = 0; fi = 0; m = 0, n = 0;
                length = line.size();
  
                for (j = 0; j < length; j++)
                {
                      
                    if (line[j] == '"')
                        f++;
  
                    else if (line[j] == ':')
                        fi++;
                          
                    // To get latitude of the location.    
                    if (f == 3)
                    {
                        j++;
  
                        while (line[j] != '"')
                        {
                            latitude_as_string[x] = line[j];
                            x++; j++;
                        }
  
                        j--; latitude_as_string[x] = '\0';
                    }
                      
                    // To get longitude of the location.
                    else if (f == 13)
                    {
                        j++;
  
                        while (line[j] != '"')
                        {
                            longitude_as_string[y] = line[j];
                            y++; j++;
                        }
  
                        j--; longitude_as_string[y] = '\0';
                    }
                      
                    // To get id of the friend.
                    if (fi == 2)
                    {
                        j += 2;
  
                        while (line[j] != ',')
                        {
                            id_as_string[m] = line[j];
                            m++; j++;
                        }
  
                        j--; id_as_string[m] = '\0';
                        fi++;
                    }
                      
                    // To get name of the friend.
                    else if (fi == 4)
                    {
                        j += 2;
  
                        while (line[j] != ',')
                        {
                            name[n] = line[j];
                            n++; j++;
                        }
  
                        j--; name[n] = '\0';
                        fi++; f += 2;
                    }
                }
  
                // Converting latitude and longitude
                // in string to float.
                lat2d = atof(latitude_as_string);
                lon2d = atof(longitude_as_string);
                distance_calculator();
            }
        }
          
        // closing stream of customer's file.
        customer_list.close();
          
        // closing stream of answer's file.
        out.close();
    }
};
  
int main()
{
    // Creating object of the structure json
    json obj;
      
    // To read customers.json file.
    obj.json_parser();
    return 0;
}

chevron_right


Input file (customers.json) :

{"latitude": "12.986375", "user_id": 12, "name": "Chris", "longitude": "77.043701"}
{"latitude": "11.92893", "user_id": 1, "name": "Alice", "longitude": "78.27699"}
{"latitude": "11.8856167", "user_id": 2, "name": "Ian", "longitude": "78.4240911"}
{"latitude": "12.3191841", "user_id": 3, "name": "Jack", "longitude": "78.5072391"}
{"latitude": "13.807778", "user_id": 28, "name": "Charlie", "longitude": "76.714444"}
{"latitude": "13.4692815", "user_id": 7, "name": "Frank", "longitude": "-9.436036"}
{"latitude": "14.0894797", "user_id": 8, "name": "Eoin", "longitude": "77.18671"}
{"latitude": "13.038056", "user_id": 26, "name": "Stephen", "longitude": "76.613889"}
{"latitude": "14.1225", "user_id": 27, "name": "Enid", "longitude": "78.143333"}
{"latitude": "13.1229599", "user_id": 6, "name": "Theresa", "longitude": "77.2701202"}
{"latitude": "12.2559432", "user_id": 9, "name": "Jack", "longitude": "76.1048927"}
{"latitude": "12.240382", "user_id": 10, "name": "Georgina", "longitude": "77.972413"}
{"latitude": "13.2411022", "user_id": 4, "name": "Ian", "longitude": "77.238335"}
{"latitude": "13.1302756", "user_id": 5, "name": "Nora", "longitude": "77.2397222"}
{"latitude": "13.008769", "user_id": 11, "name": "Richard", "longitude": "77.1056711"}
{"latitude": "13.1489345", "user_id": 31, "name": "Alan", "longitude": "77.8422408"}
{"latitude": "13", "user_id": 13, "name": "Olive", "longitude": "76"}
{"latitude": "11.999447", "user_id": 14, "name": "Helen", "longitude": "-9.742744"}
{"latitude": "12.966", "user_id": 15, "name": "Michael", "longitude": "77.463"}
{"latitude": "12.366037", "user_id": 16, "name": "Ian", "longitude": "78.179118"}
{"latitude": "14.180238", "user_id": 17, "name": "Patricia", "longitude": "-5.920898"}
{"latitude": "13.0033946", "user_id": 39, "name": "Lisa", "longitude": "77.3877505"}
{"latitude": "12.228056", "user_id": 18, "name": "Bob", "longitude": "76.915833"}
{"latitude": "14.133333", "user_id": 24, "name": "Rose", "longitude": "77.433333"}
{"latitude": "55.033", "user_id": 19, "name": "Enid", "longitude": "78.112"}
{"latitude": "13.121111", "user_id": 20, "name": "Enid", "longitude": "-9.831111"}
{"latitude": "11.802", "user_id": 21, "name": "David", "longitude": "-9.442"}
{"latitude": "14.374208", "user_id": 22, "name": "Charlie", "longitude": "78.371639"}
{"latitude": "13.74412", "user_id": 29, "name": "Oliver", "longitude": "76.11167"}
{"latitude": "13.761389", "user_id": 30, "name": "Nick", "longitude": "76.2875"}
{"latitude": "14.080556", "user_id": 23, "name": "Eoin", "longitude": "77.361944"}
{"latitude": "12.833502", "user_id": 25, "name": "David", "longitude": "78.122366"}

Output File (answers.json) :

{"user_id": 6, "name": "Theresa"}
{"user_id": 5, "name": "Nora"}
{"user_id": 31, "name": "Alan"}
{"user_id": 15, "name": "Michael"}
{"user_id": 39, "name": "Lisa"}

Reference: Great Circle Distance



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

4


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.