David Luff writes:
I've fixed a bug in FGRunways::search(aptid, tgt_hdg) which wasn't working properly for airports with multiple parallel runways. I've also firmed up and pulled out into it's own function the GetReverseRunwayNo code, and done some input checking. As a result of fixing the above in runways.cxx, I've pulled out the parallel implementation in the functions that set position by airport and heading/runway number in fg_init.cxx and called the runways functions instead.
This commit is contained in:
parent
c5c3095859
commit
f2e2101264
2 changed files with 132 additions and 222 deletions
|
@ -90,6 +90,47 @@ FGRunways::FGRunways( const string& file ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
cout << "Standardising rwy number from " << tmp;
|
||||||
|
rwyno = "0" + tmp;
|
||||||
|
cout << " to " << rwyno << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// search for the specified apt id
|
||||||
bool FGRunways::search( const string& aptid, FGRunway* r ) {
|
bool FGRunways::search( const string& aptid, FGRunway* r ) {
|
||||||
c4_StringProp pID ("ID");
|
c4_StringProp pID ("ID");
|
||||||
|
@ -132,6 +173,7 @@ bool FGRunways::search( const string& aptid, FGRunway* r ) {
|
||||||
// search for the specified apt id and runway no
|
// search for the specified apt id and runway no
|
||||||
bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r )
|
bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r )
|
||||||
{
|
{
|
||||||
|
string runwayno = rwyno;
|
||||||
c4_StringProp pID ("ID");
|
c4_StringProp pID ("ID");
|
||||||
c4_StringProp pRwy ("Rwy");
|
c4_StringProp pRwy ("Rwy");
|
||||||
c4_FloatProp pLon ("Longitude");
|
c4_FloatProp pLon ("Longitude");
|
||||||
|
@ -150,13 +192,22 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standardize input number
|
||||||
|
string tmp = runwayno.substr(1, 1);
|
||||||
|
if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (runwayno.size() == 1)) {
|
||||||
|
tmp = runwayno;
|
||||||
|
cout << "Standardising rwy number from " << tmp;
|
||||||
|
runwayno = "0" + tmp;
|
||||||
|
cout << " to " << runwayno << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
c4_RowRef row = vRunway->GetAt(index);
|
c4_RowRef row = vRunway->GetAt(index);
|
||||||
string rowid = (const char *) pID(row);
|
string rowid = (const char *) pID(row);
|
||||||
string rowrwyno = (const char *) pRwy(row);
|
string rowrwyno = (const char *) pRwy(row);
|
||||||
while ( rowid == aptid ) {
|
while ( rowid == aptid ) {
|
||||||
next_index = index + 1;
|
next_index = index + 1;
|
||||||
|
|
||||||
if ( rowrwyno == rwyno ) {
|
if ( rowrwyno == runwayno ) {
|
||||||
r->id = (const char *) pID(row);
|
r->id = (const char *) pID(row);
|
||||||
r->rwy_no = (const char *) pRwy(row);
|
r->rwy_no = (const char *) pRwy(row);
|
||||||
r->lon = (double) pLon(row);
|
r->lon = (double) pLon(row);
|
||||||
|
@ -171,34 +222,11 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check reverse rwy number
|
|
||||||
// eg 01 -> 19
|
|
||||||
// 03L -> 21R
|
|
||||||
// cout << "Original rowrwyno = " << rowrwyno << '\n';
|
|
||||||
char buf[4];
|
|
||||||
int rn = atoi(rowrwyno.substr(0,2).c_str());
|
|
||||||
rn += 18;
|
|
||||||
while(rn > 36) {
|
|
||||||
rn -= 36;
|
|
||||||
}
|
|
||||||
sprintf(buf, "%02i", rn);
|
|
||||||
if(rowrwyno.size() == 3) {
|
|
||||||
if(rowrwyno.substr(2,1) == "L") {
|
|
||||||
buf[2] = 'R';
|
|
||||||
buf[3] = '\0';
|
|
||||||
} else if (rowrwyno.substr(2,1) == "R") {
|
|
||||||
buf[2] = 'L';
|
|
||||||
buf[3] = '\0';
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
|
|
||||||
<< rowrwyno << " found in FGRunways.search(...)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rowrwyno = buf;
|
|
||||||
// cout << "New rowrwyno = " << rowrwyno << '\n';
|
|
||||||
// Search again with the other-end runway number
|
// Search again with the other-end runway number
|
||||||
// Remember we have to munge the heading result if this one matches
|
// Remember we have to munge the heading and rwy_no results if this one matches
|
||||||
if ( rowrwyno == rwyno ) {
|
rowrwyno = GetReverseRunwayNo(rowrwyno);
|
||||||
|
// cout << "New rowrwyno = " << rowrwyno << '\n';
|
||||||
|
if ( rowrwyno == runwayno ) {
|
||||||
r->id = (const char *) pID(row);
|
r->id = (const char *) pID(row);
|
||||||
r->rwy_no = rowrwyno;
|
r->rwy_no = rowrwyno;
|
||||||
r->lon = (double) pLon(row);
|
r->lon = (double) pLon(row);
|
||||||
|
@ -285,10 +313,11 @@ bool FGRunways::search( const string& aptid, const int tgt_hdg,
|
||||||
// Return the runway number of the runway closest to a given heading
|
// Return the runway number of the runway closest to a given heading
|
||||||
string FGRunways::search( const string& aptid, const int tgt_hdg ) {
|
string FGRunways::search( const string& aptid, const int tgt_hdg ) {
|
||||||
FGRunway r;
|
FGRunway r;
|
||||||
|
FGRunway tmp_r;
|
||||||
string rn;
|
string rn;
|
||||||
double found_dir = 0.0;
|
double found_dir = 0.0;
|
||||||
|
|
||||||
if ( !search( aptid, &r ) ) {
|
if ( !search( aptid, &tmp_r ) ) {
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
"Failed to find " << aptid << " in database." );
|
"Failed to find " << aptid << " in database." );
|
||||||
return "NN";
|
return "NN";
|
||||||
|
@ -297,7 +326,9 @@ string FGRunways::search( const string& aptid, const int tgt_hdg ) {
|
||||||
double diff;
|
double diff;
|
||||||
double min_diff = 360.0;
|
double min_diff = 360.0;
|
||||||
|
|
||||||
while ( r.id == aptid ) {
|
while ( tmp_r.id == aptid ) {
|
||||||
|
r = tmp_r;
|
||||||
|
|
||||||
// forward direction
|
// forward direction
|
||||||
diff = tgt_hdg - r.heading;
|
diff = tgt_hdg - r.heading;
|
||||||
while ( diff < -180.0 ) { diff += 360.0; }
|
while ( diff < -180.0 ) { diff += 360.0; }
|
||||||
|
@ -327,22 +358,16 @@ string FGRunways::search( const string& aptid, const int tgt_hdg ) {
|
||||||
found_dir = 180.0;
|
found_dir = 180.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
next( &r );
|
next( &tmp_r );
|
||||||
}
|
}
|
||||||
|
|
||||||
// SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no
|
// SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no
|
||||||
// << " + " << found_dir );
|
// << " + " << found_dir );
|
||||||
// rn = r.rwy_no;
|
rn = r.rwy_no;
|
||||||
// cout << "In search, rn = " << rn << endl;
|
// cout << "In search, rn = " << rn << endl;
|
||||||
if ( found_dir == 180 ) {
|
if ( found_dir == 180 ) {
|
||||||
int irn = atoi(rn.c_str());
|
rn = GetReverseRunwayNo(rn);
|
||||||
irn += 18;
|
//cout << "New rn = " << rn << '\n';
|
||||||
if ( irn > 36 ) {
|
|
||||||
irn -= 36;
|
|
||||||
}
|
|
||||||
char buf[4]; // 2 chars + string terminator + 1 for safety
|
|
||||||
sprintf(buf, "%i", irn);
|
|
||||||
rn = buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rn;
|
return rn;
|
||||||
|
|
|
@ -655,8 +655,6 @@ static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
|
||||||
// Set current_options lon/lat given an airport id and heading (degrees)
|
// Set current_options lon/lat given an airport id and heading (degrees)
|
||||||
static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
|
static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
|
||||||
FGRunway r;
|
FGRunway r;
|
||||||
FGRunway found_r;
|
|
||||||
double found_dir = 0.0;
|
|
||||||
|
|
||||||
if ( id.length() ) {
|
if ( id.length() ) {
|
||||||
// set initial position from runway and heading
|
// set initial position from runway and heading
|
||||||
|
@ -667,72 +665,30 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
|
||||||
FGRunways runways( path.c_str() );
|
FGRunways runways( path.c_str() );
|
||||||
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
SG_LOG( SG_GENERAL, SG_INFO,
|
||||||
"Attempting to set starting position from runway code "
|
"Attempting to set starting position from airport code "
|
||||||
<< id << " heading " << tgt_hdg );
|
<< id << " heading " << tgt_hdg );
|
||||||
|
|
||||||
if ( ! runways.search( id, &r ) ) {
|
if ( ! runways.search( id, (int)tgt_hdg, &r ) ) {
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
"Failed to find " << id << " in database." );
|
"Failed to find a good runway for " << id << '\n' );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double diff;
|
|
||||||
double min_diff = 360.0;
|
|
||||||
|
|
||||||
while ( r.id == id ) {
|
|
||||||
// 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;
|
|
||||||
found_r = r;
|
|
||||||
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;
|
|
||||||
found_r = r;
|
|
||||||
found_dir = 180.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
runways.next( &r );
|
|
||||||
}
|
|
||||||
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << found_r.rwy_no
|
|
||||||
<< " + " << found_dir );
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double heading = found_r.heading + found_dir;
|
|
||||||
while ( heading >= 360.0 ) { heading -= 360.0; }
|
|
||||||
|
|
||||||
double lat2, lon2, az2;
|
double lat2, lon2, az2;
|
||||||
double azimuth = found_r.heading + found_dir + 180.0;
|
double heading = r.heading;
|
||||||
|
double azimuth = heading + 180.0;
|
||||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||||
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
SG_LOG( SG_GENERAL, SG_INFO,
|
||||||
"runway = " << found_r.lon << ", " << found_r.lat
|
"runway = " << r.lon << ", " << r.lat
|
||||||
<< " length = " << found_r.length * SG_FEET_TO_METER * 0.5
|
<< " length = " << r.length * SG_FEET_TO_METER
|
||||||
<< " heading = " << azimuth );
|
<< " heading = " << azimuth );
|
||||||
|
|
||||||
geo_direct_wgs_84 ( 0, found_r.lat, found_r.lon,
|
geo_direct_wgs_84 ( 0, r.lat, r.lon, azimuth,
|
||||||
azimuth, found_r.length * SG_FEET_TO_METER * 0.5 - 5.0,
|
r.length * SG_FEET_TO_METER * 0.5 - 5.0,
|
||||||
&lat2, &lon2, &az2 );
|
&lat2, &lon2, &az2 );
|
||||||
|
|
||||||
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) {
|
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) {
|
||||||
|
@ -769,25 +725,12 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set current_options lon/lat given an airport id and heading (degrees)
|
// Set current_options lon/lat given an airport id and runway number
|
||||||
static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
|
static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
|
||||||
FGRunway r;
|
FGRunway r;
|
||||||
FGRunway found_r;
|
|
||||||
double heading = 0.0;
|
|
||||||
string runway;
|
|
||||||
bool match = false;
|
|
||||||
|
|
||||||
// standardize input number
|
|
||||||
string tmp = rwy.substr(1, 1);
|
|
||||||
if ( tmp == "L" || tmp == "R" || tmp == "C" ) {
|
|
||||||
runway = "0";
|
|
||||||
runway += rwy;
|
|
||||||
} else {
|
|
||||||
runway = rwy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( id.length() ) {
|
if ( id.length() ) {
|
||||||
// set initial position from runway and heading
|
// set initial position from airport and runway number
|
||||||
|
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append( "Airports" );
|
path.append( "Airports" );
|
||||||
|
@ -798,84 +741,29 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
|
||||||
"Attempting to set starting position for "
|
"Attempting to set starting position for "
|
||||||
<< id << ":" << runway );
|
<< id << ":" << runway );
|
||||||
|
|
||||||
if ( ! runways.search( id, &r ) ) {
|
if ( ! runways.search( id, rwy, &r ) ) {
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
"Failed to find " << id << " in database." );
|
"Failed to find runway " << rwy <<
|
||||||
|
" at airport " << id );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( r.id == id ) {
|
|
||||||
// forward direction
|
|
||||||
if ( r.rwy_no == runway ) {
|
|
||||||
found_r = r;
|
|
||||||
heading = r.heading;
|
|
||||||
match = true;
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
|
||||||
"Runway " << r.rwy_no << " heading = " << heading );
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate reciprocal runway number
|
|
||||||
string snum = r.rwy_no;
|
|
||||||
int len = snum.length();
|
|
||||||
string letter = "";
|
|
||||||
string rev_letter = "";
|
|
||||||
int i;
|
|
||||||
for ( i = 0; i < len; ++i ) {
|
|
||||||
string tmp = snum.substr(i, 1);
|
|
||||||
if ( tmp == "L" ) {
|
|
||||||
letter = "L";
|
|
||||||
rev_letter = "R";
|
|
||||||
} else if ( tmp == "R" ) {
|
|
||||||
letter = "R";
|
|
||||||
rev_letter = "L";
|
|
||||||
} else if ( tmp == "C" ) {
|
|
||||||
letter == "C";
|
|
||||||
rev_letter = "C";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( i = 0; i < len; ++i ) {
|
|
||||||
string tmp = snum.substr(i, 1);
|
|
||||||
if ( tmp == "L" || tmp == "R" || tmp == "C" || tmp == " " ) {
|
|
||||||
snum = snum.substr(0, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Runway num = '" << snum << "'");
|
|
||||||
int num = atoi( snum.c_str() ) + 18;
|
|
||||||
while ( num > 36 ) { num -= 36; }
|
|
||||||
while ( num <= 0 ) { num += 36; }
|
|
||||||
|
|
||||||
char recip_no[10];
|
|
||||||
snprintf( recip_no, 10, "%02d%s", num, rev_letter.c_str() );
|
|
||||||
|
|
||||||
// reverse direction
|
|
||||||
if ( (string)recip_no == runway ) {
|
|
||||||
found_r = r;
|
|
||||||
heading = r.heading + 180;
|
|
||||||
while ( heading > 360.0 ) { heading -= 360; }
|
|
||||||
match = true;
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
|
||||||
"Runway " << r.rwy_no << " heading = " << heading );
|
|
||||||
}
|
|
||||||
|
|
||||||
runways.next( &r );
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( match ) {
|
|
||||||
double lat2, lon2, az2;
|
double lat2, lon2, az2;
|
||||||
|
double heading = r.heading;
|
||||||
double azimuth = heading + 180.0;
|
double azimuth = heading + 180.0;
|
||||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||||
|
|
||||||
SG_LOG( SG_GENERAL, SG_INFO,
|
SG_LOG( SG_GENERAL, SG_INFO,
|
||||||
"runway = " << found_r.lon << ", " << found_r.lat
|
"runway = " << r.lon << ", " << r.lat
|
||||||
<< " length = " << found_r.length * SG_FEET_TO_METER * 0.5
|
<< " length = " << r.length * SG_FEET_TO_METER
|
||||||
<< " heading = " << azimuth );
|
<< " heading = " << azimuth );
|
||||||
|
|
||||||
geo_direct_wgs_84 ( 0, found_r.lat, found_r.lon,
|
geo_direct_wgs_84 ( 0, r.lat, r.lon,
|
||||||
azimuth,
|
azimuth,
|
||||||
found_r.length * SG_FEET_TO_METER * 0.5 - 5.0,
|
r.length * SG_FEET_TO_METER * 0.5 - 5.0,
|
||||||
&lat2, &lon2, &az2 );
|
&lat2, &lon2, &az2 );
|
||||||
|
|
||||||
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON )
|
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON )
|
||||||
|
@ -911,9 +799,6 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
|
||||||
<< heading );
|
<< heading );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue