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()
32 #include <strings.h> // memchr()
34 #include <simgear/constants.h>
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/misc/sgstream.hxx>
37 #include <simgear/misc/strutils.hxx>
42 #include "runways.hxx"
44 #include "apt_loader.hxx"
47 // Load the airport data base from the specified aptdb file. The
48 // metar file is used to mark the airports as having metar available
50 bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
51 const string &aptdb_file, const string &metar_file )
54 // Load the apt.dat file
57 sg_gzifstream in( aptdb_file );
58 if ( !in.is_open() ) {
59 SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << aptdb_file );
64 string last_apt_id = "";
65 double last_apt_elev = 0.0;
66 string last_apt_name = "";
67 string last_apt_info = "";
68 string last_apt_type = "";
72 char sp_pos = 0, lid = 0;
74 double rwy_lon_accum = 0.0;
75 double rwy_lat_accum = 0.0;
78 while ( ! in.eof() ) {
79 in.getline(tmp, 2048);
82 SG_LOG( SG_GENERAL, SG_BULK, "-> '" << line << "'" );
86 if (line.size() > 3) {
87 char *p = (char *)memchr(tmp, ' ', 3);
93 if ( tmp[0] == '#' || (tmp[0] == '/' && tmp[1] == '/') ) {
95 } else if ( tmp[0] == 'I' ) {
96 // First line, indicates IBM (i.e. DOS line endings I
99 // move past this line and read and discard the next line
100 // which is the version and copyright information
101 in.getline(tmp, 2048);
102 // vector<string> vers_token = simgear::strutils::split( tmp );
103 if ( strnlen(tmp, 2048) > 4 ) {
104 char *p = (char *)memchr(tmp, ' ', 4);
108 SG_LOG( SG_GENERAL, SG_INFO, "Data file version = "
110 } else if ( lid == 1 /* Airport */ ||
111 lid == 16 /* Seaplane base */ ||
112 lid == 17 /* Heliport */ ) {
115 token = simgear::strutils::split(line);
116 string id = token[4];
117 double elev = atof( token[1].c_str() );
118 SG_LOG( SG_GENERAL, SG_BULK, "Next airport = " << id << " "
121 if ( !last_apt_id.empty()) {
122 if ( rwy_count > 0 ) {
123 double lat = rwy_lat_accum / (double)rwy_count;
124 double lon = rwy_lon_accum / (double)rwy_count;
125 airports->add( last_apt_id, lon, lat, last_apt_elev,
126 last_apt_name, false );
128 if ( !last_apt_id.length() ) {
129 SG_LOG(SG_GENERAL, SG_ALERT,
130 "ERROR: No runways for " << last_apt_id
137 last_apt_elev = atof( token[1].c_str() );
141 for ( unsigned int i = 5; i < token.size() - 1; ++i ) {
142 last_apt_name += token[i];
143 last_apt_name += " ";
145 last_apt_name += token[token.size() - 1];
147 last_apt_info = line;
148 last_apt_type = token[0];
150 // clear runway list for start of next airport
154 } else if ( lid == 10 ) {
156 token = simgear::strutils::split(line);
159 double lat = atof( token[1].c_str() );
160 double lon = atof( token[2].c_str() );
161 rwy_lat_accum += lat;
162 rwy_lon_accum += lon;
165 string rwy_no = token[3];
167 double heading = atof( token[4].c_str() );
168 double length = atoi( token[5].c_str() );
169 double width = atoi( token[8].c_str() );
171 string rwy_displ_threshold = token[6];
173 = simgear::strutils::split( rwy_displ_threshold, "." );
174 double displ_thresh1 = atof( displ[0].c_str() );
175 double displ_thresh2 = atof( displ[1].c_str() );
177 string rwy_stopway = token[7];
179 = simgear::strutils::split( rwy_stopway, "." );
180 double stopway1 = atof( stop[0].c_str() );
181 double stopway2 = atof( stop[1].c_str() );
183 string lighting_flags = token[9];
184 int surface_code = atoi( token[10].c_str() );
185 string shoulder_code = token[11];
186 int marking_code = atoi( token[12].c_str() );
187 double smoothness = atof( token[13].c_str() );
188 bool dist_remaining = (atoi( token[14].c_str() ) == 1 );
190 runways->add( last_apt_id, rwy_no, lon, lat, heading, length,
191 width, displ_thresh1, displ_thresh2,
192 stopway1, stopway2, lighting_flags, surface_code,
193 shoulder_code, marking_code, smoothness,
195 } else if ( lid == 18 ) {
196 // beacon entry (ignore)
197 } else if ( lid == 14 ) {
198 // control tower entry (ignore)
199 } else if ( lid == 19 ) {
200 // windsock entry (ignore)
201 } else if ( lid == 15 ) {
202 // custom startup locations (ignore)
203 } else if ( lid >= 50 && lid <= 56 ) {
204 // frequency entries (ignore)
205 } else if ( lid == 99 ) {
206 SG_LOG( SG_GENERAL, SG_DEBUG, "End of file reached" );
208 SG_LOG( SG_GENERAL, SG_ALERT,
209 "Unknown line in file: " << line );
214 if ( !last_apt_id.empty()) {
215 if ( rwy_count > 0 ) {
216 double lat = rwy_lat_accum / (double)rwy_count;
217 double lon = rwy_lon_accum / (double)rwy_count;
218 airports->add( last_apt_id, lon, lat, last_apt_elev,
219 last_apt_name, false );
221 if ( !last_apt_id.length() ) {
222 SG_LOG(SG_GENERAL, SG_ALERT,
223 "ERROR: No runways for " << last_apt_id
230 // Load the metar.dat file and update apt db with stations that
234 sg_gzifstream metar_in( metar_file );
235 if ( !metar_in.is_open() ) {
236 SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << metar_file );
242 if ( ident == "#" || ident == "//" ) {
245 const FGAirport &a = airports->search( ident );
246 if ( a.getId() == ident ) {
247 airports->has_metar( ident );
252 SG_LOG(SG_GENERAL, SG_INFO, "[FINISHED LOADING]");