]> git.mxchange.org Git - flightgear.git/blob - src/Airports/simple.cxx
Fix my mailing address by replacing it with my web page.
[flightgear.git] / src / Airports / simple.cxx
1 //
2 // simple.cxx -- a really simplistic class to manage airport ID,
3 //               lat, lon of the center of one of it's runways, and 
4 //               elevation in feet.
5 //
6 // Written by Curtis Olson, started April 1998.
7 //
8 // Copyright (C) 1998  Curtis L. Olson  - http://www.flightgear.org/~curt
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 //
24 // $Id$
25
26 #ifdef HAVE_CONFIG_H
27 #  include <config.h>
28 #endif
29
30 #include <math.h>
31
32 #include <simgear/compiler.h>
33
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/sgstream.hxx>
36
37 #include STL_STRING
38 #include STL_IOSTREAM
39
40 #include "simple.hxx"
41
42 SG_USING_NAMESPACE(std);
43 SG_USING_STD(istream);
44
45
46 inline istream&
47 operator >> ( istream& in, FGAirport& a )
48 {
49     string junk;
50     in >> junk >> a.id >> a.latitude >> a.longitude >> a.elevation
51        >> a.code;
52
53     getline( in,a.name );
54
55     // Remove the space before the name
56     if ( a.name.substr(0,1) == " " ) {
57         a.name = a.name.erase(0,1);
58     }
59
60     a.has_metar = false;
61
62 #if 0
63     // As a quick seed for the has_metar value, only airports with
64     // four-letter codes can have metar stations
65     a.has_metar = (isalpha(a.id[0]) && isalpha(a.id[1]) && isalpha(a.id[2])
66         && isalpha(a.id[3]) && !a.id[4]);
67 #endif
68
69     return in;
70 }
71
72
73 FGAirportList::FGAirportList( const string &airport_file,
74                               const string &metar_file ) {
75     SG_LOG( SG_GENERAL, SG_INFO, "Reading simple airport list: "
76             << airport_file );
77
78     // open the specified file for reading
79     sg_gzifstream apt_in( airport_file );
80     if ( !apt_in.is_open() ) {
81         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << airport_file );
82         exit(-1);
83     }
84
85     // skip header line
86     apt_in >> skipeol;
87
88     FGAirport a;
89     while ( apt_in ) {
90         apt_in >> a;
91         airports_by_id[a.id] = a;
92         airports_array.push_back( &airports_by_id[a.id] );
93     }
94
95
96     SG_LOG( SG_GENERAL, SG_INFO, "Reading simple metar station list: "
97             << metar_file );
98
99     // open the specified file for reading
100     sg_gzifstream metar_in( metar_file );
101     if ( !metar_in.is_open() ) {
102         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << metar_file );
103     }
104
105     string ident;
106     while ( metar_in ) {
107         metar_in >> ident;
108         if ( ident == "#" || ident == "//" ) {
109             metar_in >> skipeol;
110         } else {
111             airport_map_iterator apt = airports_by_id.find( ident );
112             if ( apt == airports_by_id.end() ) {
113                 SG_LOG( SG_GENERAL, SG_DEBUG, "no apt = " << ident );
114             } else {
115                 SG_LOG( SG_GENERAL, SG_DEBUG, "metar = " << ident );
116                 airports_by_id[ident].has_metar = true;
117             }
118         }
119     }
120 }
121
122
123 // search for the specified id
124 FGAirport FGAirportList::search( const string& id) {
125     return airports_by_id[id];
126 }
127
128
129 // search for the airport nearest the specified position
130 FGAirport FGAirportList::search( double lon_deg, double lat_deg,
131                                  bool with_metar ) {
132     int closest = 0;
133     double min_dist = 360.0;
134     unsigned int i;
135     for ( i = 0; i < airports_array.size(); ++i ) {
136         // crude manhatten distance based on lat/lon difference
137         double d = fabs(lon_deg - airports_array[i]->longitude)
138             + fabs(lat_deg - airports_array[i]->latitude);
139         if ( d < min_dist ) {
140             if ( !with_metar || (with_metar && airports_array[i]->has_metar) ) {
141                 closest = i;
142                 min_dist = d;
143             }
144         }
145     }
146
147     return *airports_array[closest];
148 }
149
150
151 // Destructor
152 FGAirportList::~FGAirportList( void ) {
153 }
154
155 int
156 FGAirportList::size () const
157 {
158     return airports_array.size();
159 }
160
161 const FGAirport *FGAirportList::getAirport( int index ) const
162 {
163     return airports_array[index];
164 }
165
166
167 /**
168  * Mark the specified airport record as not having metar
169  */
170 void FGAirportList::no_metar( const string &id ) {
171     airports_by_id[id].has_metar = false;
172 }