Пример #1
0
/**
 * See http://en.wikipedia.org/wiki/Latitude#Degree_length
 *
 * TODO: check if these calculatiosn (based on the oa2gm source code) are
 *       correct.  I guess not, because they both use 6371e3 for computing
 *       new latitudinal and longitudinal points.  This is not 100% correct.
 *       We should probably follow WGS84 or IERS 2003 ellipsoids.
 */
void Circle::discretize( std::vector<Coordinate>& coords, double resolution ) const
{

    // Each circle must have *at least* 360 points (or more if the specified resolution is
    // not satisfied when taking 360 points).
    const int min_nb_points = 360;
    int nbPoints = max((int)(2*pi*radius/resolution), min_nb_points);

    coords.clear();
    coords.reserve(nbPoints);

    double deg_lat, deg_lon;
    double angle;

    Coordinate centerCoord = center.getCoordinate();
    Latitude lat = centerCoord.getLatitude();
    Longitude lon = centerCoord.getLongitude();

    // Compute arcdegree of latitude respectively longitude difference of the center.
    double arcdegree_lat = lat.getArcDegree();
    double arcdegree_lon = lon.getArcDegree(lat);

    for (int i = 0; i < nbPoints; ++i)
    {
        angle = 2*pi*i/nbPoints;

        deg_lon = lon.getAngle() + getRadiusM()*cos(angle)/arcdegree_lon;
        deg_lat = lat.getAngle() + getRadiusM()*sin(angle)/arcdegree_lat;
        coords.push_back( Coordinate( deg_lat, deg_lon ) );
    }
}
Пример #2
0
void Parser::handleLine(const std::string& line)
{
    smatch matches;

    if ( regex_match(line, matches, regexMap.find(REGEX_COMMENT)->second) )
    {
        // do nothing.
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AC)->second) )
    {
        airspaces.push_back(new Airspace);

        setCurrentDirection('+');
        currentArcCenter.reset();

        // Assign the parsed class to the current airspace.
        string matched_text( matches[1].first, matches[1].second );
        getCurrentAirspace()->setClass( parseAirspaceClass(matched_text) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AN)->second) )
    {
        string airspace_name( matches[1].first, matches[1].second );
        getCurrentAirspace()->setName(airspace_name);
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AH)->second) )
    {
        string airspace_ceiling(matches[1].first, matches[1].second);
        getCurrentAirspace()->setCeilingString(airspace_ceiling);
        getCurrentAirspace()->setCeiling( parseAltitude(airspace_ceiling) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AL)->second) )
    {
        string airspace_floor(matches[1].first, matches[1].second);
        getCurrentAirspace()->setFloorString(airspace_floor);
        getCurrentAirspace()->setFloor( parseAltitude(airspace_floor) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AT)->second) )
    {
        string airspace_coordinate(matches[1].first, matches[1].second);
        getCurrentAirspace()->add( Label(getCurrentAirspace()->getName(), parseCoordinate(airspace_coordinate)) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_VX)->second) )
    {
        string matched_text(matches[1].first, matches[1].second);
        setCurrentArcCenter(parseCoordinate(matched_text));
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_VD)->second) )
    {
        string direction_string;
        for (unsigned int i = 1; i < matches.size(); ++i)
        {
            direction_string.assign(matches[i].first, matches[i].second);
        }
        setCurrentDirection(direction_string[0]);
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DP)->second) )
    {
        string point_coordinate( matches[1].first, matches[1].second );
        getCurrentAirspace()->add( new Point(parseCoordinate(point_coordinate)) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DA)->second) )
    {
        // Read the matched values and create our Arc.
        string radiusNM(   matches[1].first, matches[1].second );
        string angleStart( matches[2].first, matches[2].second );
        string angleEnd(   matches[3].first, matches[3].second );

        Arc arc( *(getCurrentArcCenter()), atof(radiusNM.c_str()),
                 atof(angleStart.c_str()), atof(angleEnd.c_str()), getCurrentDirection());

        getCurrentAirspace()->add( &arc );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DB)->second) )
    {
        // We have a DB-record, now check if the coords are specified correctly...
        string dbcoords( matches[1].first, matches[1].second );
        if ( regex_match(dbcoords, matches, regexMap.find(REGEX_DB_COORDS)->second) )
        {
            // Fetch the start and end coordinate for this arc.
            string coord1( matches[1].first, matches[1].second );
            string coord2( matches[2].first, matches[2].second );
            Coordinate c1 = parseCoordinate(coord1);
            Coordinate c2 = parseCoordinate(coord2);

            std::shared_ptr<Coordinate> currentArcCenter = getCurrentArcCenter();

            // Retrieve latitude and longitude of the arc-center.
            Latitude lat = currentArcCenter->getLatitude();
            Longitude lon = currentArcCenter->getLongitude();

            // Compute arcdegree of latitude respectively longitude, based on the center's coordinates.
            double arcdegree_lat = lat.getArcDegree();
            double arcdegree_lon = lon.getArcDegree(lat);

            // Compute start and end angle (in standard coordinate frame!)
            // Note that we have to take into account the arcdegrees here!!!
            double dLat1 = ( c1.getLatitude().getAngle()  - currentArcCenter->getLatitude().getAngle()  )*arcdegree_lat;
            double dLon1 = ( c1.getLongitude().getAngle() - currentArcCenter->getLongitude().getAngle() )*arcdegree_lon;
            double dLat2 = ( c2.getLatitude().getAngle()  - currentArcCenter->getLatitude().getAngle()  )*arcdegree_lat;
            double dLon2 = ( c2.getLongitude().getAngle() - currentArcCenter->getLongitude().getAngle() )*arcdegree_lon;
            double startAngle = 180.0*atan2(dLat1, dLon1)/pi;
            double endAngle   = 180.0*atan2(dLat2, dLon2)/pi;

            // Convert start and end angle to airspace coordinate frame.
            startAngle = 90 - startAngle;
            endAngle   = 90 - endAngle;

            // Use maximum of the two radii (for safety reasons).
            //double radius = max( c1.getDistance(getCurrentCoordinate()), c2.getDistance(getCurrentCoordinate()) );
            // Use minimum of the two radii.
            //double radius = min( c1.getDistance(getCurrentCoordinate()), c2.getDistance(getCurrentCoordinate()) );
            // Use average of the two radii.
            double radius = ( c1.getDistance(*currentArcCenter) + c2.getDistance(*currentArcCenter) )*0.5;

            // Add the arc points to this space's Polygon.
            getCurrentAirspace()->add( new Arc(*currentArcCenter,
                                               radius/1852.0, startAngle, endAngle, getCurrentDirection()) );
        }
        else
        {
            cout << "\nERROR: invalid coordinate string specification in DB-record: " << line << endl;
            exit(1);
        }

    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DC)->second) )
    {
        // Get circle radius (in Nautical Miles) from what we've just read.
        string radiusNM;
        radiusNM.assign(matches[1].first, matches[1].second);

        // Add circle to this Airspace.
        Point center(*(getCurrentArcCenter()));
        getCurrentAirspace()->add(new Circle(center, atof(radiusNM.c_str())));

    }
}