]> git.mxchange.org Git - flightgear.git/blob - src/Airports/runways.cxx
Depricated ...
[flightgear.git] / src / Airports / runways.cxx
1 // runways.cxx -- a simple class to manage airport runway info
2 //
3 // Written by Curtis Olson, started August 2000.
4 //
5 // Copyright (C) 2000  Curtis L. Olson  - curt@flightgear.org
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <math.h>               // fabs()
29 #include <stdio.h>              // sprintf()
30
31 #include <simgear/compiler.h>
32
33 #include <simgear/debug/logstream.hxx>
34 #include <simgear/misc/sgstream.hxx>
35
36 #include STL_STRING
37 #include STL_IOSTREAM
38 #include <map>
39
40 #include "runways.hxx"
41
42 SG_USING_NAMESPACE(std);
43 SG_USING_STD(istream);
44 SG_USING_STD(multimap);
45
46 inline istream&
47 operator >> ( istream& in, FGRunway& a )
48 {
49     string type;
50     int tmp;
51
52     in >> a.type;
53     if ( a.type == "R" ) {
54         in >> a.id >> a.rwy_no >> a.lat >> a.lon >> a.heading
55            >> a.length >> a.width >> a.surface_flags >> a.end1_flags
56            >> tmp >> tmp >> a.end2_flags >> tmp >> tmp;
57     } else {
58         in >> a.id >> a.rwy_no >> a.lat >> a.lon >> a.heading
59            >> a.length >> a.width >> a.surface_flags;
60     }
61
62     return in;
63 }
64
65
66 FGRunwayList::FGRunwayList( const string& file ) {
67     SG_LOG( SG_GENERAL, SG_DEBUG, "Reading runway list: " << file );
68
69     // open the specified file for reading
70     sg_gzifstream in( file );
71     if ( !in.is_open() ) {
72         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << file );
73         exit(-1);
74     }
75
76     // skip header line
77     in >> skipeol;
78
79     FGRunway rwy;
80     while ( in ) {
81         in >> rwy;
82         runways.insert(pair<const string, FGRunway>(rwy.id, rwy));
83     }
84 }
85
86
87 // Return reverse rwy number
88 // eg 01 -> 19
89 // 03L -> 21R
90 static string GetReverseRunwayNo(string rwyno) {        
91     // cout << "Original rwyno = " << rwyNo << '\n';
92     
93     // standardize input number
94     string tmp = rwyno.substr(1, 1);
95     if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
96         tmp = rwyno;
97         rwyno = "0" + tmp;
98         SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp
99                                      << " to " << rwyno );
100     }
101     
102     char buf[4];
103     int rn = atoi(rwyno.substr(0,2).c_str());
104     rn += 18;
105     while(rn > 36) {
106         rn -= 36;
107     }
108     sprintf(buf, "%02i", rn);
109     if(rwyno.size() == 3) {
110         if(rwyno.substr(2,1) == "L") {
111             buf[2] = 'R';
112             buf[3] = '\0';
113         } else if (rwyno.substr(2,1) == "R") {
114             buf[2] = 'L';
115             buf[3] = '\0';
116         } else if (rwyno.substr(2,1) == "C") {
117             buf[2] = 'C';
118             buf[3] = '\0';
119         } else {
120             SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
121             << rwyno << " passed to GetReverseRunwayNo(...)");
122         }
123     }
124     return((string)buf);
125 }
126
127
128 // search for the specified apt id (wierd!)
129 bool FGRunwayList::search( const string& aptid, FGRunway* r ) {
130     runway_map_iterator pos;
131
132     pos = runways.lower_bound(aptid);
133     if ( pos != runways.end() ) {
134         current = pos;
135         *r = pos->second;
136         return true;
137     } else {
138         return false;
139     }
140 }
141
142
143 // search for the specified apt id and runway no
144 bool FGRunwayList::search( const string& aptid, const string& rwyno,
145                            FGRunway *r )
146 {
147     // standardize input number
148     string runwayno = rwyno;
149     string tmp = runwayno.substr(1, 1);
150     if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (runwayno.size() == 1)) {
151         tmp = runwayno;
152         runwayno = "0" + tmp;
153         SG_LOG( SG_GENERAL, SG_INFO,
154                 "Standardising rwy number from " << tmp << " to " << runwayno );
155     }
156     string revrwyno = GetReverseRunwayNo(runwayno);
157
158     runway_map_iterator pos;
159     for ( pos = runways.lower_bound( aptid );
160           pos != runways.upper_bound( aptid ); ++pos)
161     {
162         if ( pos->second.rwy_no == runwayno ) {
163             current = pos;
164             *r = pos->second;
165             return true;
166         } else if ( pos->second.rwy_no == revrwyno ) {
167             // Search again with the other-end runway number.
168             // Remember we have to munge the heading and rwy_no
169             // results if this one matches
170             current = pos;
171             *r = pos->second;
172             r->rwy_no = revrwyno;
173             r->heading += 180.0;
174             string tmp = r->end1_flags;
175             r->end1_flags = r->end2_flags;
176             r->end2_flags = tmp;
177             return true;
178         }
179     }
180
181     return false;
182 }
183
184
185 // (wierd!)
186 FGRunway FGRunwayList::search( const string& aptid ) {
187     FGRunway a;
188     search( aptid, &a );
189     return a;
190 }
191
192
193 // Return the runway closest to a given heading
194 bool FGRunwayList::search( const string& aptid, const int tgt_hdg,
195                            FGRunway *runway )
196 {
197     string rwyNo = search(aptid, tgt_hdg);
198     return(rwyNo == "NN" ? false : search(aptid, rwyNo, runway));
199 }
200
201
202 // Return the runway number of the runway closest to a given heading
203 string FGRunwayList::search( const string& aptid, const int tgt_hdg ) {
204     FGRunway r;
205     FGRunway tmp_r;     
206     string rn;
207     double found_dir = 0.0;  
208  
209     if ( !search( aptid, &tmp_r ) ) {
210         SG_LOG( SG_GENERAL, SG_ALERT,
211                 "Failed to find " << aptid << " in database." );
212         return "NN";
213     }
214     
215     double diff;
216     double min_diff = 360.0;
217     
218     while ( tmp_r.id == aptid ) {
219         r = tmp_r;
220         
221         // forward direction
222         diff = tgt_hdg - r.heading;
223         while ( diff < -180.0 ) { diff += 360.0; }
224         while ( diff >  180.0 ) { diff -= 360.0; }
225         diff = fabs(diff);
226         // SG_LOG( SG_GENERAL, SG_INFO,
227         //         "Runway " << r.rwy_no << " heading = " << r.heading <<
228         //         " diff = " << diff );
229         if ( diff < min_diff ) {
230             min_diff = diff;
231             rn = r.rwy_no;
232             found_dir = 0;
233         }
234         
235         // reverse direction
236         diff = tgt_hdg - r.heading - 180.0;
237         while ( diff < -180.0 ) { diff += 360.0; }
238         while ( diff >  180.0 ) { diff -= 360.0; }
239         diff = fabs(diff);
240         // SG_LOG( SG_GENERAL, SG_INFO,
241         //         "Runway -" << r.rwy_no << " heading = " <<
242         //         r.heading + 180.0 <<
243         //         " diff = " << diff );
244         if ( diff < min_diff ) {
245             min_diff = diff;
246             rn = r.rwy_no;
247             found_dir = 180.0;
248         }
249         
250         next( &tmp_r );
251     }
252     
253     // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no
254     //         << " + " << found_dir );
255     rn = r.rwy_no;
256     // cout << "In search, rn = " << rn << endl;
257     if ( found_dir == 180 ) {
258         rn = GetReverseRunwayNo(rn);
259         //cout << "New rn = " << rn << '\n';
260     }   
261     
262     return rn;
263 }
264
265
266 bool FGRunwayList::next( FGRunway* runway ) {
267     ++current;
268     if ( current != runways.end() ) {
269         *runway = current->second;
270         return true;
271     } else {
272         return false;
273     }
274 }
275
276
277 FGRunway FGRunwayList::next() {
278     FGRunway result;
279
280     ++current;
281     if ( current != runways.end() ) {
282         result = current->second;
283     }
284
285     return result;
286 }
287
288
289 // Destructor
290 FGRunwayList::~FGRunwayList( void ) {
291 }