1 // apt_loader.cxx -- a front end loader of the apt.dat file. This loader
2 // populates the runway and basic classes.
4 // Written by Curtis Olson, started August 2000.
6 // Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <simgear/compiler.h>
31 #include <stdlib.h> // atof(), atoi()
33 #include <simgear/constants.h>
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/sgstream.hxx>
36 #include <simgear/misc/strutils.hxx>
41 #include "runways.hxx"
43 #include "apt_loader.hxx"
46 // Load the airport data base from the specified aptdb file. The
47 // metar file is used to mark the airports as having metar available
49 bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
50 const string &aptdb_file, const string &metar_file )
53 // Load the apt.dat file
56 sg_gzifstream in( aptdb_file );
57 if ( !in.is_open() ) {
58 SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << aptdb_file );
63 string last_apt_id = "";
64 double last_apt_elev = 0.0;
65 string last_apt_name = "";
66 string last_apt_info = "";
67 string last_apt_type = "";
71 double rwy_lon_accum = 0.0;
72 double rwy_lat_accum = 0.0;
75 while ( ! in.eof() ) {
76 in.getline(tmp, 2048);
78 SG_LOG( SG_GENERAL, SG_DEBUG, "-> '" << line << "'" );
79 if ( line.length() ) {
80 token = simgear::strutils::split( line );
82 SG_LOG( SG_GENERAL, SG_DEBUG, "token[0] " << token[0] );
88 if ( !line.length() || !token.size() ) {
90 } else if ( (token[0] == "#") || (token[0] == "//") ) {
92 } else if ( token[0] == "I" ) {
93 // First line, indicates IBM (i.e. DOS line endings I
96 // move past this line and read and discard the next line
97 // which is the version and copyright information
98 in.getline(tmp, 2048);
99 vector<string> vers_token = simgear::strutils::split( tmp );
100 SG_LOG( SG_GENERAL, SG_INFO, "Data file version = "
102 } else if ( token[0] == "1" /* Airport */ ||
103 token[0] == "16" /* Seaplane base */ ||
104 token[0] == "17" /* Heliport */ ) {
106 string id = token[4];
107 double elev = atof( token[1].c_str() );
108 SG_LOG( SG_GENERAL, SG_DEBUG, "Next airport = " << id << " "
111 if ( !last_apt_id.empty()) {
112 if ( rwy_count > 0 ) {
113 double lat = rwy_lat_accum / (double)rwy_count;
114 double lon = rwy_lon_accum / (double)rwy_count;
115 airports->add( last_apt_id, lon, lat, last_apt_elev,
116 last_apt_name, false );
118 if ( !last_apt_id.length() ) {
119 SG_LOG(SG_GENERAL, SG_ALERT,
120 "ERROR: No runways for " << last_apt_id
127 last_apt_elev = atof( token[1].c_str() );
131 for ( unsigned int i = 5; i < token.size() - 1; ++i ) {
132 last_apt_name += token[i];
133 last_apt_name += " ";
135 last_apt_name += token[token.size() - 1];
137 last_apt_info = line;
138 last_apt_type = token[0];
140 // clear runway list for start of next airport
144 } else if ( token[0] == "10" ) {
146 double lat = atof( token[1].c_str() );
147 double lon = atof( token[2].c_str() );
148 rwy_lat_accum += lat;
149 rwy_lon_accum += lon;
152 string rwy_no = token[3];
154 double heading = atof( token[4].c_str() );
155 double length = atoi( token[5].c_str() );
156 double width = atoi( token[8].c_str() );
158 string rwy_displ_threshold = token[6];
160 = simgear::strutils::split( rwy_displ_threshold, "." );
161 double displ_thresh1 = atof( displ[0].c_str() );
162 double displ_thresh2 = atof( displ[1].c_str() );
164 string rwy_stopway = token[7];
166 = simgear::strutils::split( rwy_stopway, "." );
167 double stopway1 = atof( stop[0].c_str() );
168 double stopway2 = atof( stop[1].c_str() );
170 string lighting_flags = token[9];
171 int surface_code = atoi( token[10].c_str() );
172 string shoulder_code = token[11];
173 int marking_code = atoi( token[12].c_str() );
174 double smoothness = atof( token[13].c_str() );
175 bool dist_remaining = (atoi( token[14].c_str() ) == 1 );
177 runways->add( last_apt_id, rwy_no, lon, lat, heading, length,
178 width, displ_thresh1, displ_thresh2,
179 stopway1, stopway2, lighting_flags, surface_code,
180 shoulder_code, marking_code, smoothness,
182 } else if ( token[0] == "18" ) {
183 // beacon entry (ignore)
184 } else if ( token[0] == "14" ) {
185 // control tower entry (ignore)
186 } else if ( token[0] == "19" ) {
187 // windsock entry (ignore)
188 } else if ( token[0] == "15" ) {
189 // custom startup locations (ignore)
190 } else if ( token[0] == "50" || token[0] == "51" || token[0] == "52"
191 || token[0] == "53" || token[0] == "54" || token[0] == "55"
192 || token[0] == "56" )
194 // frequency entries (ignore)
195 } else if ( token[0] == "99" ) {
196 SG_LOG( SG_GENERAL, SG_DEBUG, "End of file reached" );
198 SG_LOG( SG_GENERAL, SG_ALERT,
199 "Unknown line in file: " << line );
204 if ( !last_apt_id.empty()) {
205 if ( rwy_count > 0 ) {
206 double lat = rwy_lat_accum / (double)rwy_count;
207 double lon = rwy_lon_accum / (double)rwy_count;
208 airports->add( last_apt_id, lon, lat, last_apt_elev,
209 last_apt_name, false );
211 if ( !last_apt_id.length() ) {
212 SG_LOG(SG_GENERAL, SG_ALERT,
213 "ERROR: No runways for " << last_apt_id
220 // Load the metar.dat file and update apt db with stations that
224 sg_gzifstream metar_in( metar_file );
225 if ( !metar_in.is_open() ) {
226 SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << metar_file );
232 if ( ident == "#" || ident == "//" ) {
235 FGAirport a = airports->search( ident );
236 if ( a._id == ident ) {
237 airports->has_metar( ident );
242 SG_LOG(SG_GENERAL, SG_INFO, "[FINISHED LOADING]");