/** * 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 ) ); } }
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()))); } }