1 // runways.cxx -- a simple class to manage airport runway info
3 // Written by Curtis Olson, started August 2000.
5 // Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <math.h> // fabs()
29 #include <stdio.h> // sprintf()
31 #include <simgear/compiler.h>
33 #include <simgear/debug/logstream.hxx>
38 #include "runways.hxx"
40 SG_USING_NAMESPACE(std);
41 SG_USING_STD(istream);
42 SG_USING_STD(multimap);
45 // add an entry to the list
46 void FGRunwayList::add( const string& id, const string& rwy_no,
47 const double longitude, const double latitude,
48 const double heading, const double length,
50 const double displ_thresh1, const double displ_thresh2,
51 const double stopway1, const double stopway2,
52 const string& lighting_flags, const int surface_code,
53 const string& shoulder_code, const int marking_code,
54 const double smoothness, const bool dist_remaining )
60 // strip trailing "x" if it exists in runway number
61 string tmp = rwy._rwy_no.substr(2, 1);
63 rwy._rwy_no = rwy._rwy_no.substr(0, 2);
68 rwy._heading = heading;
71 rwy._displ_thresh1 = displ_thresh1;
72 rwy._displ_thresh2 = displ_thresh2;
73 rwy._stopway1 = stopway1;
74 rwy._stopway2 = stopway2;
76 rwy._lighting_flags = lighting_flags;
77 rwy._surface_code = surface_code;
78 rwy._shoulder_code = shoulder_code;
79 rwy._marking_code = marking_code;
80 rwy._smoothness = smoothness;
81 rwy._dist_remaining = dist_remaining;
83 if ( rwy_no == "xxx" ) {
84 rwy._type = "taxiway";
85 // don't insert taxiways into the DB for now
88 runways.insert(pair<const string, FGRunway>(rwy._id, rwy));
93 // Return reverse rwy number
96 static string GetReverseRunwayNo(string& rwyno) {
97 // cout << "Original rwyno = " << rwyNo << '\n';
99 // standardize input number
100 string tmp = rwyno.substr(1, 1);
101 if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
104 SG_LOG( SG_GENERAL, SG_INFO,
105 "Standardising rwy number from " << tmp << " to " << rwyno );
109 int rn = atoi(rwyno.substr(0,2).c_str());
114 sprintf(buf, "%02i", rn);
115 if(rwyno.size() == 3) {
116 if(rwyno.substr(2,1) == "L") {
119 } else if (rwyno.substr(2,1) == "R") {
122 } else if (rwyno.substr(2,1) == "C") {
125 } else if (rwyno.substr(2,1) == "T") {
129 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
130 << rwyno << " passed to GetReverseRunwayNo(...)");
137 // search for the specified apt id (wierd!)
138 bool FGRunwayList::search( const string& aptid, FGRunway* r ) {
139 runway_map_iterator pos;
141 pos = runways.lower_bound(aptid);
142 if ( pos != runways.end() ) {
152 // search for the specified apt id and runway no
153 bool FGRunwayList::search( const string& aptid, const string& rwyno,
156 string revrwyno = "";
157 string runwayno = rwyno;
158 if ( runwayno.length() ) {
159 // standardize input number
160 string tmp = runwayno.substr(1, 1);
161 if (( tmp == "L" || tmp == "R" || tmp == "C" )
162 || (runwayno.size() == 1))
165 runwayno = "0" + tmp;
166 SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from "
167 << tmp << " to " << runwayno );
169 revrwyno = GetReverseRunwayNo(runwayno);
171 runway_map_iterator pos;
172 for ( pos = runways.lower_bound( aptid );
173 pos != runways.upper_bound( aptid ); ++pos)
175 if ( pos->second._rwy_no == runwayno ) {
179 } else if ( pos->second._rwy_no == revrwyno ) {
180 // Search again with the other-end runway number.
181 // Remember we have to munge the heading and rwy_no
182 // results if this one matches
185 // NOTE - matching revrwyno implies that runwayno was
187 r->_rwy_no = runwayno;
188 r->_heading += 180.0;
198 FGRunway FGRunwayList::search( const string& aptid ) {
205 // Return the runway closest to a given heading
206 bool FGRunwayList::search( const string& aptid, const int tgt_hdg,
209 string rwyNo = search(aptid, tgt_hdg);
210 return(rwyNo == "NN" ? false : search(aptid, rwyNo, runway));
214 // Return the runway number of the runway closest to a given heading
215 string FGRunwayList::search( const string& aptid, const int tgt_hdg ) {
219 double found_dir = 0.0;
221 if ( !search( aptid, &tmp_r ) ) {
222 SG_LOG( SG_GENERAL, SG_ALERT,
223 "Failed to find " << aptid << " in database." );
228 double min_diff = 360.0;
230 while ( tmp_r._id == aptid ) {
232 diff = tgt_hdg - tmp_r._heading;
233 while ( diff < -180.0 ) { diff += 360.0; }
234 while ( diff > 180.0 ) { diff -= 360.0; }
236 // SG_LOG( SG_GENERAL, SG_INFO,
237 // "Runway " << tmp_r._rwy_no << " heading = "
238 // << tmp_r._heading << " diff = " << diff );
239 if ( diff < min_diff ) {
246 diff = tgt_hdg - tmp_r._heading - 180.0;
247 while ( diff < -180.0 ) { diff += 360.0; }
248 while ( diff > 180.0 ) { diff -= 360.0; }
250 // SG_LOG( SG_GENERAL, SG_INFO,
251 // "Runway -" << tmp_r._rwy_no << " heading = " <<
252 // tmp_r._heading + 180.0 <<
253 // " diff = " << diff );
254 if ( diff < min_diff ) {
263 // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r._rwy_no
264 // << " + " << found_dir );
266 if ( found_dir == 180 ) {
267 rn = GetReverseRunwayNo(rn);
274 bool FGRunwayList::next( FGRunway* runway ) {
276 if ( current != runways.end() ) {
277 *runway = current->second;
285 FGRunway FGRunwayList::next() {
289 if ( current != runways.end() ) {
290 result = current->second;
298 FGRunwayList::~FGRunwayList( void ) {