Nikola
Nikola

Reputation: 143

transform syntax and structures containing vectors c++

I have a problem with the syntax of the function std::transform. So, I have a structure AirportInfo that contains information about the airports. Every structure is then arranged in a dictionary, so that they have unique IDs. In the structure there is a vector of pairs m_routes which contains the ID of the destination airport and also whether the flight is direct or not. (In this case only direct flight are to be considered, because all non-direct flights have already been deleted, so the second item of the pair will always be 0). The function calculateDistanceBetween returns the distance between 2 airports, by knowing their coordinates, that are being stored also in the structure in pos. Now I have to calculate the distance for every route, but I cannot get over the syntax :( Any Help will be appreciated, Thank you!

This piece of code works

// Calculates the distance between two points on earth specified by longitude/latitude.
// Function taken and adapted from http://www.codeproject.com/Articles/22488/Distance-using-Longitiude-and-latitude-using-c
float calculateDistanceBetween(float lat1, float long1, float lat2, float long2)
{
    // main code inside the class
    float dlat1 = lat1 * ((float)M_PI / 180.0f);

    float dlong1 = long1 * ((float)M_PI / 180.0f);
    float dlat2 = lat2 * ((float)M_PI / 180.0f);
    float dlong2 = long2 * ((float)M_PI / 180.0f);

    float dLong = dlong1 - dlong2;
    float dLat = dlat1 - dlat2;

    float aHarv = pow(sin(dLat / 2.0f), 2.0f) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2), 2);
    float cHarv = 2 * atan2(sqrt(aHarv), sqrt(1.0f - aHarv));
    // earth's radius from wikipedia varies between 6,356.750 km and 6,378.135 km
    // The IUGG value for the equatorial radius of the Earth is 6378.137 km
    const float earth = 6378.137f;
    return earth * cHarv;
}

struct AirportInfo
{
    std::string m_name;
    std::string m_city;
    std::string m_country;
    float pos[2]; // x: latitude, y: longitude

    std::vector<std::pair<int, int>> m_routes; // dest_id + numStops
    std::vector<float> m_routeLengths;
    float m_averageRouteLength;
};

Here is what causes the trouble:

//- For each route in AirportInfo::m_routes, calculate the distance between start and destination. Store the results in AirportInfo::m_routeLengths. Use std::transform() and calculateDistanceBetween().
void calculateDistancePerRoute(std::map<int, AirportInfo>& airportInfo)
{   //loop all structures 
    for(int i = 0; i < airportInfo.size(); i++ ){
                        // START                        END                                         SAVE 
        std::transform(airportInfo[i].pos[0], airportInfo[i].pos[1], /*...*/ , airportInfo[i].m_routeLengths.begin(), 
                        calculateDistanceBetween);

    }
    std::cout << "Calculate distance for each route" << std::endl;
} 

Upvotes: 0

Views: 75

Answers (1)

Adam Hunyadi
Adam Hunyadi

Reputation: 1952

Use std::back_inserter(airportInfo[i].m_routeLengths) (and if performance is important, reserve vector sizes in advance), instead of airportInfo[i].m_routeLengths.begin(). Also, iterating by index when there is nothing "enforcing" that the indecies in the map are going from 0...map.size() is not safe, you should prefer using a vector for the shown usecase.

I think this is something like what you want:

void calculateDistancePerRoute(std::map<int, AirportInfo>& airportInfo)
{
    for(int i = 0; i < airportInfo.size(); i++ )
    {
        float currentPosX = airportInfo.at(i).pos[0];
        float currentPosY = airportInfo.at(i).pos[1];
        std::transform(airportInfo.begin(), airportInfo.end(), std::back_inserter(airportInfo.at(i).m_routeLengths), [&] (const auto& otherAirport)
        {
           return calculateDistanceBetween(currentPosX, currentPosY, otherAirport.second.pos[0], otherAirport.second.pos[1]);
        });
    }
}

Example in Godbolt

Upvotes: 1

Related Questions