X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAirports%2Frunways.cxx;h=ff45f4c7e7e00fe17c31a514d343e0fdb91de38b;hb=df2ce45ab71442cd24d6bb9f8da3a0c2e13a8c7c;hp=2db4a7fade8f1429f6a3f5ec5ace633478f03ac7;hpb=fe0c17625bb5aacbf02e53a43474e76b2f195ce2;p=flightgear.git diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 2db4a7fad..ff45f4c7e 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -1,4 +1,4 @@ -// runways.hxx -- a simple class to manage airport runway info +// runways.cxx -- a simple class to manage airport runway info // // Written by Curtis Olson, started August 2000. // @@ -25,8 +25,8 @@ # include #endif -// #include // for gdbm open flags -// #include // for gdbm open flags +#include // fabs() +#include // sprintf() #include @@ -41,12 +41,35 @@ SG_USING_NAMESPACE(std); +#ifndef _MSC_VER +#define NDEBUG // MSVC needs this +#endif // !_MSC_VER -FGRunway::FGRunway() { -} +#include +#include + +#ifndef _MSC_VER +#undef NDEBUG +#endif // !_MSC_VER + +#ifdef SG_HAVE_STD_INCLUDES +# include +#elif defined( __BORLANDC__ ) || defined (__APPLE__) +# include +#else +# include +#endif + +SG_USING_STD(istream); +inline istream& +operator >> ( istream& in, FGRunway& a ) +{ + int tmp; -FGRunway::~FGRunway() { + return in >> a.rwy_no >> a.lat >> a.lon >> a.heading >> a.length >> a.width + >> a.surface_flags >> a.end1_flags >> tmp >> tmp >> a.end2_flags + >> tmp >> tmp; } @@ -61,12 +84,53 @@ FGRunways::FGRunways( const string& file ) { vRunway = new c4_View; *vRunway = - storage->GetAs("runway[ID:S,Rwy:S,Longitude:F,Latitude:F,Heading:F,Length:F,Width:F,SurfaceFlags:S,End1Flags:F,End2Flags:F]"); + storage->GetAs("runway[ID:S,Rwy:S,Longitude:F,Latitude:F,Heading:F,Length:F,Width:F,SurfaceFlags:S,End1Flags:S,End2Flags:S]"); next_index = 0; } +// Return reverse rwy number +// eg 01 -> 19 +// 03L -> 21R +static string GetReverseRunwayNo(string rwyno) { + // cout << "Original rwyno = " << rwyNo << '\n'; + + // standardize input number + string tmp = rwyno.substr(1, 1); + if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) { + tmp = rwyno; + rwyno = "0" + tmp; + SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp + << " to " << rwyno ); + } + + char buf[4]; + int rn = atoi(rwyno.substr(0,2).c_str()); + rn += 18; + while(rn > 36) { + rn -= 36; + } + sprintf(buf, "%02i", rn); + if(rwyno.size() == 3) { + if(rwyno.substr(2,1) == "L") { + buf[2] = 'R'; + buf[3] = '\0'; + } else if (rwyno.substr(2,1) == "R") { + buf[2] = 'L'; + buf[3] = '\0'; + } else if (rwyno.substr(2,1) == "C") { + buf[2] = 'C'; + buf[3] = '\0'; + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " + << rwyno << " passed to GetReverseRunwayNo(...)"); + } + } + return((string)buf); +} + + // search for the specified apt id bool FGRunways::search( const string& aptid, FGRunway* r ) { c4_StringProp pID ("ID"); @@ -81,7 +145,7 @@ bool FGRunways::search( const string& aptid, FGRunway* r ) { c4_StringProp pEnd2 ("End2Flags"); int index = vRunway->Find(pID[aptid.c_str()]); - cout << "index = " << index << endl; + // cout << "index = " << index << endl; if ( index == -1 ) { return false; @@ -109,6 +173,7 @@ bool FGRunways::search( const string& aptid, FGRunway* r ) { // search for the specified apt id and runway no bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) { + string runwayno = rwyno; c4_StringProp pID ("ID"); c4_StringProp pRwy ("Rwy"); c4_FloatProp pLon ("Longitude"); @@ -121,11 +186,20 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) c4_StringProp pEnd2 ("End2Flags"); int index = vRunway->Find(pID[aptid.c_str()]); - cout << "index = " << index << endl; + // cout << "index = " << index << endl; if ( index == -1 ) { return false; } + + // standardize input number + string tmp = runwayno.substr(1, 1); + if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (runwayno.size() == 1)) { + tmp = runwayno; + runwayno = "0" + tmp; + SG_LOG(SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp + << " to " << runwayno ); + } c4_RowRef row = vRunway->GetAt(index); string rowid = (const char *) pID(row); @@ -133,7 +207,7 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) while ( rowid == aptid ) { next_index = index + 1; - if ( rowrwyno == rwyno ) { + if ( rowrwyno == runwayno ) { r->id = (const char *) pID(row); r->rwy_no = (const char *) pRwy(row); r->lon = (double) pLon(row); @@ -147,11 +221,31 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) return true; } + + // Search again with the other-end runway number + // Remember we have to munge the heading and rwy_no results if this one matches + rowrwyno = GetReverseRunwayNo(rowrwyno); + // cout << "New rowrwyno = " << rowrwyno << '\n'; + if ( rowrwyno == runwayno ) { + r->id = (const char *) pID(row); + r->rwy_no = rowrwyno; + r->lon = (double) pLon(row); + r->lat = (double) pLat(row); + r->heading = (double) pHdg(row) + 180.0; + r->length = (double) pLen(row); + r->width = (double) pWid(row); + r->surface_flags = (const char *) pSurf(row); + r->end1_flags = (const char *) pEnd2(row); + r->end2_flags = (const char *) pEnd1(row); + // I've swapped the end flags as well + + return true; + } index++; - c4_RowRef row = vRunway->GetAt(index); - string rowid = (const char *) pID(row); - string rowrwyno = (const char *) pRwy(row); + row = vRunway->GetAt(index); + rowid = (const char *) pID(row); + rowrwyno = (const char *) pRwy(row); } return false; @@ -207,6 +301,79 @@ bool FGRunways::next( FGRunway* r ) { } +// Return the runway closest to a given heading +bool FGRunways::search( const string& aptid, const int tgt_hdg, + FGRunway* runway ) +{ + string rwyNo = search(aptid, tgt_hdg); + return(rwyNo == "NN" ? false : search(aptid, rwyNo, runway)); +} + + +// Return the runway number of the runway closest to a given heading +string FGRunways::search( const string& aptid, const int tgt_hdg ) { + FGRunway r; + FGRunway tmp_r; + string rn; + double found_dir = 0.0; + + if ( !search( aptid, &tmp_r ) ) { + SG_LOG( SG_GENERAL, SG_ALERT, + "Failed to find " << aptid << " in database." ); + return "NN"; + } + + double diff; + double min_diff = 360.0; + + while ( tmp_r.id == aptid ) { + r = tmp_r; + + // forward direction + diff = tgt_hdg - r.heading; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway " << r.rwy_no << " heading = " << r.heading << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + rn = r.rwy_no; + found_dir = 0; + } + + // reverse direction + diff = tgt_hdg - r.heading - 180.0; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway -" << r.rwy_no << " heading = " << + // r.heading + 180.0 << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + rn = r.rwy_no; + found_dir = 180.0; + } + + next( &tmp_r ); + } + + // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no + // << " + " << found_dir ); + rn = r.rwy_no; + // cout << "In search, rn = " << rn << endl; + if ( found_dir == 180 ) { + rn = GetReverseRunwayNo(rn); + //cout << "New rn = " << rn << '\n'; + } + + return rn; +} + + // Destructor FGRunways::~FGRunways( void ) { delete storage; @@ -283,7 +450,6 @@ int FGRunwaysUtil::load( const string& file ) { // save the data in gdbm format bool FGRunwaysUtil::dump_mk4( const string& file ) { - // open database for writing c4_Storage storage( file.c_str(), true ); @@ -303,7 +469,7 @@ bool FGRunwaysUtil::dump_mk4( const string& file ) { // Start with an empty view of the proper structure. c4_View vRunway = - storage.GetAs("runway[ID:S,Rwy:S,Longitude:F,Latitude:F,Heading:F,Length:F,Width:F,SurfaceFlags:S,End1Flags:F,End2Flags:F]"); + storage.GetAs("runway[ID:S,Rwy:S,Longitude:F,Latitude:F,Heading:F,Length:F,Width:F,SurfaceFlags:S,End1Flags:S,End2Flags:S]"); c4_Row row;