]> git.mxchange.org Git - flightgear.git/blob - src/Navaids/navdb.cxx
Miscellaneous tweaks and Bugfixes. Mostly memory leaks ported from the plib
[flightgear.git] / src / Navaids / navdb.cxx
1 // navdb.cxx -- top level navaids management routines
2 //
3 // Written by Curtis Olson, started May 2004.
4 //
5 // Copyright (C) 2004  Curtis L. Olson - http://www.flightgear.org/~curt
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 #include <simgear/compiler.h>
28
29 #include STL_STRING
30
31 #include <simgear/debug/logstream.hxx>
32
33 #include <Airports/runways.hxx>
34 #include <Airports/simple.hxx>
35 #include <Main/globals.hxx>
36
37 #include "navrecord.hxx"
38 #include "navdb.hxx"
39
40 SG_USING_STD( string );
41
42
43 // load and initialize the navigational databases
44 bool fgNavDBInit( FGAirportList *airports,
45                   FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
46                   FGNavList *dmelist, FGNavList *mkrlist, 
47                   FGNavList *tacanlist, FGNavList *carrierlist,
48                   FGTACANList *channellist)
49 {
50     SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaid Databases");
51     // SG_LOG(SG_GENERAL, SG_INFO, "  VOR/NDB");
52     // SGPath p_nav( globals->get_fg_root() );
53     // p_nav.append( "Navaids/default.nav" );
54     // navlist->init( p_nav );
55
56     // SG_LOG(SG_GENERAL, SG_INFO, "  ILS and Marker Beacons");
57     // beacons->init();
58     // SGPath p_ils( globals->get_fg_root() );
59     // p_ils.append( "Navaids/default.ils" );
60     // ilslist->init( p_ils );
61
62
63     SGPath path( globals->get_fg_root() );
64     path.append( "Navaids/nav.dat" );
65
66     sg_gzifstream in( path.str() );
67     if ( !in.is_open() ) {
68         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
69         exit(-1);
70     }
71
72     // skip first two lines
73     in >> skipeol;
74     in >> skipeol;
75
76
77 #ifdef __MWERKS__
78
79  FIXME -- Please report to the FlightGear mailing list, if you still use a
80           compiler identifying itself as __MWERKS__ that needs this hack.
81           There are 41 instances of it in the SimGear & FilghtGear code,
82           and they are scheduled for removal.
83
84     char c = 0;
85     while ( in.get(c) && c != '\0' ) {
86         in.putback(c);
87 #else
88     while ( ! in.eof() ) {
89 #endif
90
91         FGNavRecord *r = new FGNavRecord;
92         in >> (*r);
93         if ( r->get_type() > 95 ) {
94             delete r;
95             break;
96         }
97
98         /*cout << "id = " << r->get_ident() << endl;
99         cout << " type = " << r->get_type() << endl;
100         cout << " lon = " << r->get_lon() << endl;
101         cout << " lat = " << r->get_lat() << endl;
102         cout << " elev = " <<r->get_elev_ft() << endl;
103         cout << " freq = " << r->get_freq() << endl;
104         cout << " range = " << r->get_range() << endl;
105         cout << " name = " << r->get_name() << endl << endl; */
106
107         // fudge elevation to the field elevation if it's not specified
108         if ( fabs(r->get_elev_ft()) < 0.01 && r->get_apt_id().length() ) {
109             // cout << r->get_type() << " " << r->get_apt_id() << " zero elev"
110             //      << endl;
111             const FGAirport* a = airports->search( r->get_apt_id() );
112             if ( a ) {
113                 r->set_elev_ft( a->getElevation() );
114                 // cout << "  setting to " << a.elevation << endl;
115             }
116         }
117
118         if ( r->get_type() == 2 || r->get_type() == 3 ) {
119             // NDB=2, VOR=3
120             navlist->add( r );
121         } else if ( r->get_type() == 4 || r->get_type() == 5 ) {
122             // ILS=4, LOC(only)=5
123             loclist->add( r );
124         } else if ( r->get_type() == 6 ) {
125             // GS=6
126             gslist->add( r );
127         } else if ( r->get_type() == 7 || r->get_type() == 8
128                     || r->get_type() == 9 )
129         {
130             // Marker Beacon = 7,8,9
131             mkrlist->add( r );
132         } else if ( r->get_type() == 12 || r->get_type() == 13) {
133             // DME with ILS=12; standalone DME=13
134             string str1( r->get_name() );
135             string::size_type loc1= str1.find( "TACAN", 0 );
136             string::size_type loc2 = str1.find( "VORTAC", 0 );
137                        
138             if( loc1 != string::npos || loc2 != string::npos ){
139                  //cout << " name = " << r->get_name() ;
140                  //cout << " freq = " << r->get_freq() ;
141                  tacanlist->add( r );
142                  }
143                 
144             dmelist->add( r );
145             
146         }
147                 
148         in >> skipcomment;
149     }
150
151 // load the carrier navaids file
152     
153     string file, name;
154     path = "";
155     path = globals->get_fg_root() ;
156     path.append( "Navaids/carrier_nav.dat" );
157     
158     file = path.str();
159     SG_LOG( SG_GENERAL, SG_INFO, "opening file: " << path.str() );
160     
161     sg_gzifstream incarrier( path.str() );
162     
163     if ( !incarrier.is_open() ) {
164         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
165         exit(-1);
166     }
167     
168     // skip first two lines
169     //incarrier >> skipeol;
170     //incarrier >> skipeol;
171     
172 #ifdef __MWERKS__
173     char c = 0;
174     while ( incarrier.get(c) && c != '\0'  ) {
175         incarrier.putback(c);
176 #else
177     while ( ! incarrier.eof() ) {
178 #endif
179         
180         FGNavRecord *r = new FGNavRecord;
181         incarrier >> (*r);
182         carrierlist->add ( r );
183         /*cout << " carrier lon: "<<  r->get_lon() ;
184         cout << " carrier lat: "<<  r->get_lat() ;
185         cout << " freq: " << r->get_freq() ;
186         cout << " carrier name: "<<  r->get_name() << endl;*/
187                 
188         //if ( r->get_type() > 95 ) {
189         //   break;}
190     } // end while
191
192 // end loading the carrier navaids file
193
194 // load the channel/freqency file
195     string channel, freq;
196     path="";
197     path = globals->get_fg_root();
198     path.append( "Navaids/TACAN_freq.dat" );
199     
200     SG_LOG( SG_GENERAL, SG_INFO, "opening file: " << path.str() );
201         
202     sg_gzifstream inchannel( path.str() );
203     
204     if ( !inchannel.is_open() ) {
205         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
206         exit(-1);
207     }
208     
209     // skip first line
210     inchannel >> skipeol;
211     
212 #ifdef __MWERKS__
213     char c = 0;
214     while ( inchannel.get(c) && c != '\0'  ) {
215         in.putback(c);
216 #else
217     while ( ! inchannel.eof() ) {
218 #endif
219
220         FGTACANRecord *r = new FGTACANRecord;
221         inchannel >> (*r);
222         channellist->add ( r );
223         //cout << "channel = " << r->get_channel() ;
224         //cout << " freq = " << r->get_freq() << endl;
225         
226     } // end while
227
228  
229  // end ReadChanFile
230
231
232     return true;
233 }
234
235
236 // Given a localizer record and it's corresponding runway record,
237 // adjust the localizer position so it is in perfect alignment with
238 // the runway.
239 static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
240                                  double threshold )
241 {
242     double hdg = rwy->_heading;
243     hdg += 180.0;
244     if ( hdg > 360.0 ) {
245         hdg -= 360.0;
246     }
247
248     // calculate runway threshold point
249     double thresh_lat, thresh_lon, return_az;
250     geo_direct_wgs_84 ( 0.0, rwy->_lat, rwy->_lon, hdg,
251                         rwy->_length/2.0 * SG_FEET_TO_METER,
252                         &thresh_lat, &thresh_lon, &return_az );
253     // cout << "Threshold = " << thresh_lat << "," << thresh_lon << endl;
254
255     // calculate distance from threshold to localizer
256     double az1, az2, dist_m;
257     geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
258                         thresh_lat, thresh_lon,
259                         &az1, &az2, &dist_m );
260     // cout << "Distance = " << dist_m << endl;
261
262     // back project that distance along the runway center line
263     double nloc_lat, nloc_lon;
264     geo_direct_wgs_84 ( 0.0, thresh_lat, thresh_lon, hdg + 180.0, 
265                         dist_m, &nloc_lat, &nloc_lon, &return_az );
266     // printf("New localizer = %.6f %.6f\n", nloc_lat, nloc_lon );
267
268     // sanity check, how far have we moved the localizer?
269     geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
270                         nloc_lat, nloc_lon,
271                         &az1, &az2, &dist_m );
272     // cout << "Distance moved = " << dist_m << endl;
273
274     // cout << "orig heading = " << loc->get_multiuse() << endl;
275     // cout << "new heading = " << rwy->_heading << endl;
276
277     double hdg_diff = loc->get_multiuse() - rwy->_heading;
278
279     // clamp to [-180.0 ... 180.0]
280     if ( hdg_diff < -180.0 ) {
281         hdg_diff += 360.0;
282     } else if ( hdg_diff > 180.0 ) {
283         hdg_diff -= 360.0;
284     }
285
286     if ( fabs(hdg_diff) <= threshold ) {
287         loc->set_lat( nloc_lat );
288         loc->set_lon( nloc_lon );
289         loc->set_multiuse( rwy->_heading );
290     }
291 }
292
293
294 // This routines traverses the localizer list and attempts to match
295 // each entry with it's corresponding runway.  When it is successful,
296 // it then "moves" the localizer and updates it's heading so it
297 // *perfectly* aligns with the runway, but is still the same distance
298 // from the runway threshold.
299 void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist,
300                                 double threshold ) {
301     nav_map_type navmap = loclist->get_navaids();
302
303     nav_map_const_iterator freq = navmap.begin();
304     while ( freq != navmap.end() ) {
305         nav_list_type locs = freq->second;
306         nav_list_const_iterator loc = locs.begin();
307         while ( loc != locs.end() ) {
308             string name = (*loc)->get_name();
309             string::size_type pos1 = name.find(" ");
310             string id = name.substr(0, pos1);
311             name = name.substr(pos1+1);
312             string::size_type pos2 = name.find(" ");
313             string rwy = name.substr(0, pos2);
314
315             FGRunway r;
316             if ( runways->search(id, rwy, &r) ) {
317                 update_loc_position( (*loc), &r, threshold );
318             }
319             ++loc;
320         }
321         ++freq;
322     }
323 }
324