]> git.mxchange.org Git - flightgear.git/blob - src/Navaids/fixlist.cxx
James Turner:
[flightgear.git] / src / Navaids / fixlist.cxx
1 // fixlist.cxx -- fix list management class
2 //
3 // Written by Curtis Olson, started April 2000.
4 //
5 // Copyright (C) 2000  Curtis L. Olson - http://www.flightgear.org/~curt
6 //
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.
11 //
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.
16 //
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <algorithm>
29
30 #include <simgear/debug/logstream.hxx>
31 #include <simgear/misc/sgstream.hxx>
32 #include <simgear/math/sg_geodesy.hxx>
33
34 #include "fixlist.hxx"
35 #include "Navaids/fix.hxx"
36 #include "Airports/simple.hxx"
37
38 FGFix::FGFix(const std::string& aIdent, const SGGeod& aPos) :
39   FGPositioned(FIX, aIdent, aPos)
40 {
41 }
42
43 // Constructor
44 FGFixList::FGFixList( void ) {
45 }
46
47
48 // Destructor
49 FGFixList::~FGFixList( void ) {
50 }
51
52
53 // load the navaids and build the map
54 bool FGFixList::init( SGPath path ) {
55     fixlist.erase( fixlist.begin(), fixlist.end() );
56
57     sg_gzifstream in( path.str() );
58     if ( !in.is_open() ) {
59         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
60         exit(-1);
61     }
62
63     // toss the first two lines of the file
64     in >> skipeol;
65     in >> skipeol;
66
67     // read in each remaining line of the file
68     while ( ! in.eof() ) {
69       double lat, lon;
70       string ident;
71       in >> lat >> lon >> ident;
72       if (lat > 95) break;
73
74       FGFix* fix = new FGFix(ident, SGGeod::fromDeg(lon, lat));
75       fixlist.insert(std::make_pair(fix->ident(), fix));
76       in >> skipcomment;
77     }
78     return true;
79 }
80
81
82 // query the database for the specified fix, lon and lat are in
83 // degrees, elev is in meters
84 bool FGFixList::query( const string& ident, FGFix* &fix ) {
85     fix_map_const_iterator it = fixlist.find(ident);
86     if ( it != fixlist.end() ) {
87         fix = it->second;
88         return true;
89     } else {
90         return false;
91     }
92 }
93
94
95 // query the database for the specified fix, lon and lat are in
96 // degrees, elev is in meters
97 bool FGFixList::query_and_offset( const string& ident, double lon, double lat,
98                                   double elev, FGFix* &fix, double *heading,
99                                   double *dist )
100 {
101     std::pair<fix_map_const_iterator, fix_map_const_iterator> range = fixlist.equal_range(ident);
102
103     if (range.first == range.second) {
104         return false;
105     }
106
107     double min_s = -1.0;
108     for (fix_map_const_iterator current = range.first; current != range.second; ++current) {
109         double az1, az2, s;
110         geo_inverse_wgs_84( elev, lat, lon,
111                         current->second->get_lat(), current->second->get_lon(),
112                         &az1, &az2, &s );
113         // cout << "  dist = " << s << endl;
114         if (min_s < 0 || s < min_s) {
115             *heading = az2;
116             *dist = s;
117             min_s = s;
118             fix = current->second;
119         }
120     }
121
122     return true;
123 }
124
125 const FGFix* FGFixList::search(const string& ident)
126 {
127   fix_map_iterator itr = fixlist.find(ident);
128   if (itr == fixlist.end()) {
129     return NULL;
130   }
131   
132   return itr->second;
133 }
134
135 class orderingFunctor
136 {
137 public:
138   orderingFunctor(FGIdentOrdering* aOrder) :
139     mOrdering(aOrder)
140   { assert(aOrder); }
141   
142   bool operator()(const fix_map_type::value_type& aA, const std::string& aB) const
143   {
144     return mOrdering->compare(aA.first,aB);
145   }
146
147   bool operator()(const std::string& aA, const fix_map_type::value_type& aB) const
148   {
149     return mOrdering->compare(aA, aB.first);
150   }
151
152   bool operator()(const fix_map_type::value_type& aA, const fix_map_type::value_type& aB) const
153   {
154     return mOrdering->compare(aA.first, aB.first);
155   }
156   
157 private:
158   FGIdentOrdering* mOrdering;
159 };
160
161 const FGFix* FGFixList::findFirstByIdent( const string& ident, FGIdentOrdering* aOrder)
162 {
163   fix_map_iterator itr;
164   if (aOrder) {
165     orderingFunctor func(aOrder);
166     itr = std::lower_bound(fixlist.begin(),fixlist.end(), ident, func);
167   } else {
168     itr = fixlist.lower_bound(ident);
169   }
170   
171   if (itr == fixlist.end()) {
172     return NULL;
173   }
174   
175   return itr->second;
176 }