1 // navdb.cxx -- top level navaids management routines
3 // Written by Curtis Olson, started May 2004.
5 // Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
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.
24 #include <simgear/compiler.h>
28 #include <simgear/debug/logstream.hxx>
30 #include <Airports/runways.hxx>
31 #include <Main/globals.hxx>
33 #include "navrecord.hxx"
36 SG_USING_STD( string );
39 // load and initialize the navigational databases
40 bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
41 FGNavList *dmelist, FGNavList *mkrlist )
43 SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaid Databases");
44 // SG_LOG(SG_GENERAL, SG_INFO, " VOR/NDB");
45 // SGPath p_nav( globals->get_fg_root() );
46 // p_nav.append( "Navaids/default.nav" );
47 // navlist->init( p_nav );
49 // SG_LOG(SG_GENERAL, SG_INFO, " ILS and Marker Beacons");
51 // SGPath p_ils( globals->get_fg_root() );
52 // p_ils.append( "Navaids/default.ils" );
53 // ilslist->init( p_ils );
56 SGPath path( globals->get_fg_root() );
57 path.append( "Navaids/nav.dat" );
59 sg_gzifstream in( path.str() );
60 if ( !in.is_open() ) {
61 SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
65 // skip first two lines
72 while ( in.get(c) && c != '\0' ) {
75 while ( ! in.eof() ) {
78 FGNavRecord *r = new FGNavRecord;
80 if ( r->get_type() > 95 ) {
84 /* cout << "id = " << n.get_ident() << endl;
85 cout << " type = " << n.get_type() << endl;
86 cout << " lon = " << n.get_lon() << endl;
87 cout << " lat = " << n.get_lat() << endl;
88 cout << " elev = " << n.get_elev() << endl;
89 cout << " freq = " << n.get_freq() << endl;
90 cout << " range = " << n.get_range() << endl << endl; */
92 if ( r->get_type() == 2 || r->get_type() == 3 ) {
95 } else if ( r->get_type() == 4 || r->get_type() == 5 ) {
98 } else if ( r->get_type() == 6 ) {
101 } else if ( r->get_type() == 7 || r->get_type() == 8
102 || r->get_type() == 9 )
104 // Marker Beacon = 7,8,9
106 } else if ( r->get_type() == 12 ) {
114 // cout << "min freq = " << min << endl;
115 // cout << "max freq = " << max << endl;
121 // Given a localizer record and it's corresponding runway record,
122 // adjust the localizer position so it is in perfect alignment with
124 static void update_loc_position( FGNavRecord *loc, FGRunway *rwy ) {
126 double hdg = rwy->heading;
132 // calculate runway threshold point
133 double thresh_lat, thresh_lon, return_az;
134 geo_direct_wgs_84 ( 0.0, rwy->lat, rwy->lon, hdg,
135 rwy->length/2.0 * SG_FEET_TO_METER,
136 &thresh_lat, &thresh_lon, &return_az );
137 // cout << "Threshold = " << thresh_lat << "," << thresh_lon << endl;
139 // calculate distance from threshold to localizer
140 double az1, az2, dist_m;
141 geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
142 thresh_lat, thresh_lon,
143 &az1, &az2, &dist_m );
144 // cout << "Distance = " << dist_m << endl;
146 // back project that distance along the runway center line
147 double nloc_lat, nloc_lon;
148 geo_direct_wgs_84 ( 0.0, thresh_lat, thresh_lon, hdg + 180.0,
149 dist_m, &nloc_lat, &nloc_lon, &return_az );
150 // printf("New localizer = %.6f %.6f\n", nloc_lat, nloc_lon );
152 // sanity check, how far have we moved the localizer?
153 geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
155 &az1, &az2, &dist_m );
156 // cout << "Distance moved = " << dist_m << endl;
158 loc->set_lat( nloc_lat );
159 loc->set_lon( nloc_lon );
160 loc->set_multiuse( rwy->heading );
162 // cout << "orig heading = " << loc->get_multiuse() << endl;
163 // cout << "new heading = " << rwy->heading << endl;
167 // This routines traverses the localizer list and attempts to match
168 // each entry with it's corresponding runway. When it is successful,
169 // it then "moves" the localizer and updates it's heading so it
170 // *perfectly* aligns with the runway, but is still the same distance
171 // from the runway threshold.
172 void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist ) {
173 nav_map_type navmap = loclist->get_navaids();
175 nav_map_iterator freq = navmap.begin();
176 while ( freq != navmap.end() ) {
177 nav_list_type locs = freq->second;
178 nav_list_iterator loc = locs.begin();
179 while ( loc != locs.end() ) {
180 string name = (*loc)->get_name();
181 string::size_type pos1 = name.find(" ");
182 string id = name.substr(0, pos1);
183 name = name.substr(pos1+1);
184 string::size_type pos2 = name.find(" ");
185 string rwy = name.substr(0, pos2);
188 if ( runways->search(id, rwy, &r) ) {
189 update_loc_position( (*loc), &r );