]> git.mxchange.org Git - flightgear.git/blob - src/Airports/simple.cxx
Roy Vegard Ovesen:
[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  - curt@me.umn.edu
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     char name[256];             // should never be longer than this, right? :-)
54     in.getline( name, 256 );
55     a.name = name;
56
57     a.has_metar = false;
58
59 #if 0
60     // As a quick seed for the has_metar value, only airports with
61     // four-letter codes can have metar stations
62     a.has_metar = (isalpha(a.id[0]) && isalpha(a.id[1]) && isalpha(a.id[2])
63         && isalpha(a.id[3]) && !a.id[4]);
64 #endif
65
66     return in;
67 }
68
69
70 FGAirportList::FGAirportList( const string &airport_file,
71                               const string &metar_file ) {
72     SG_LOG( SG_GENERAL, SG_INFO, "Reading simple airport list: "
73             << airport_file );
74
75     // open the specified file for reading
76     sg_gzifstream apt_in( airport_file );
77     if ( !apt_in.is_open() ) {
78         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << airport_file );
79         exit(-1);
80     }
81
82     // skip header line
83     apt_in >> skipeol;
84
85     FGAirport a;
86     while ( apt_in ) {
87         apt_in >> a;
88         airports_by_id[a.id] = a;
89         airports_array.push_back( &airports_by_id[a.id] );
90     }
91
92
93     SG_LOG( SG_GENERAL, SG_INFO, "Reading simple metar station list: "
94             << metar_file );
95
96     // open the specified file for reading
97     sg_gzifstream metar_in( metar_file );
98     if ( !metar_in.is_open() ) {
99         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << metar_file );
100     }
101
102     string ident;
103     while ( metar_in ) {
104         metar_in >> ident;
105         if ( ident == "#" || ident == "//" ) {
106             metar_in >> skipeol;
107         } else {
108             airport_map_iterator apt = airports_by_id.find( ident );
109             if ( apt == airports_by_id.end() ) {
110                 SG_LOG( SG_GENERAL, SG_DEBUG, "no apt = " << ident );
111             } else {
112                 SG_LOG( SG_GENERAL, SG_DEBUG, "metar = " << ident );
113                 airports_by_id[ident].has_metar = true;
114             }
115         }
116     }
117 }
118
119
120 // search for the specified id
121 FGAirport FGAirportList::search( const string& id) {
122     
123     return airports_by_id[id];
124 }
125
126
127 // search for the airport nearest the specified position
128 FGAirport FGAirportList::search( double lon_deg, double lat_deg,
129                                  bool with_metar ) {
130     int closest = 0;
131     double min_dist = 360.0;
132     unsigned int i;
133     for ( i = 0; i < airports_array.size(); ++i ) {
134         // crude manhatten distance based on lat/lon difference
135         double d = fabs(lon_deg - airports_array[i]->longitude)
136             + fabs(lat_deg - airports_array[i]->latitude);
137         if ( d < min_dist ) {
138             if ( !with_metar || (with_metar && airports_array[i]->has_metar) ) {
139                 closest = i;
140                 min_dist = d;
141             }
142         }
143     }
144
145     return *airports_array[closest];
146 }
147
148
149 // Destructor
150 FGAirportList::~FGAirportList( void ) {
151 }
152
153 int
154 FGAirportList::size () const
155 {
156     return airports_array.size();
157 }
158
159 const FGAirport *FGAirportList::getAirport( int index ) const
160 {
161     return airports_array[index];
162 }
163
164
165 /**
166  * Mark the specified airport record as not having metar
167  */
168 void FGAirportList::no_metar( const string &id ) {
169     airports_by_id[id].has_metar = false;
170 }