]> git.mxchange.org Git - flightgear.git/blob - src/ATC/AIMgr.cxx
Moved some of the low level scene graph construction code over to simgear.
[flightgear.git] / src / ATC / AIMgr.cxx
1 // AIMgr.cxx - implementation of FGAIMgr 
2 // - a global management class for FlightGear generated AI traffic
3 //
4 // Written by David Luff, started March 2002.
5 //
6 // Copyright (C) 2002  David C Luff - david.luff@nottingham.ac.uk
7 //
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.
12 //
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.
17 //
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.
21
22 #include <Main/fgfs.hxx>
23 #include <Main/fg_props.hxx>
24 #include <Main/globals.hxx>
25 #include <simgear/misc/sg_path.hxx>
26
27 #include <list>
28
29 #ifdef _MSC_VER
30 #  include <io.h>
31 #else
32 #  include <sys/types.h>        // for directory reading
33 #  include <dirent.h>           // for directory reading
34 #endif
35
36 #include "AIMgr.hxx"
37 #include "AILocalTraffic.hxx"
38 #include "ATCutils.hxx"
39
40 SG_USING_STD(list);
41 SG_USING_STD(cout);
42
43 FGAIMgr::FGAIMgr() {
44         ATC = globals->get_ATC_mgr();
45 }
46
47 FGAIMgr::~FGAIMgr() {
48 }
49
50 void FGAIMgr::init() {
51         // Pointers to user's position
52         lon_node = fgGetNode("/position/longitude-deg", true);
53         lat_node = fgGetNode("/position/latitude-deg", true);
54         elev_node = fgGetNode("/position/altitude-ft", true);
55
56         lon = lon_node->getDoubleValue();
57         lat = lat_node->getDoubleValue();
58         elev = elev_node->getDoubleValue();
59         
60         // go through the $FG_ROOT/ATC directory and find all *.taxi files
61         SGPath path(globals->get_fg_root());
62         path.append("ATC/");
63         string dir = path.dir();
64     string ext;
65     string file, f_ident;
66         int pos;
67         
68         // WARNING - I (DCL) haven't tested this on MSVC - this is simply cribbed from TerraGear
69 #ifdef _MSC_VER 
70         long hfile;
71         struct _finddata_t de;
72         string path_str;
73         
74         path_str = dir + "\\*.*";
75         
76         if ( ( hfile = _findfirst( path.c_str(), &de ) ) == -1 ) {
77                 cout << "cannot open directory " << dir << "\n";
78         } else {                
79                 // load all .taxi files
80                 do {
81                         file = de.name;
82                         pos = file.find(".");
83                         ext = file.substr(pos + 1);
84                         if(ext == "taxi") {
85                                 cout << "TAXI FILE FOUND!!!\n";
86                                 f_ident = file.substr(0, pos);
87                                 FGAirport a;
88                                 if(dclFindAirportID(f_ident, &a)) {
89                                         SGBucket sgb(a.longitude, a.latitude);
90                                         int idx = sgb.gen_index();
91                                         if(airports.find(idx) != airports.end()) {
92                                                 airports[idx]->push_back(f_ident);
93                                         } else {
94                                                 aptID_list_type* apts = new aptID_list_type;
95                                                 apts->push_back(f_ident);
96                                                 airports[idx] = apts;
97                                         }
98                                         cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
99                                 }
100                         }
101                 } while ( _findnext( hfile, &de ) == 0 );
102         }
103 #else
104
105     DIR *d;
106     struct dirent *de;
107
108     if ( (d = opendir( dir.c_str() )) == NULL ) {
109                 cout << "cannot open directory " << dir << "\n";
110         } else {
111                 cout << "Opened directory " << dir << " OK :-)\n";
112                 cout << "Contents are:\n";
113                 // load all .taxi files
114                 while ( (de = readdir(d)) != NULL ) {
115                         file = de->d_name;
116                         pos = file.find(".");
117                         cout << file << '\n';
118
119                         ext = file.substr(pos + 1);
120                         if(ext == "taxi") {
121                                 cout << "TAXI FILE FOUND!!!\n";
122                                 f_ident = file.substr(0, pos);
123                                 FGAirport a;
124                                 if(dclFindAirportID(f_ident, &a)) {
125                                         SGBucket sgb(a.longitude, a.latitude);
126                                         int idx = sgb.gen_index();
127                                         if(airports.find(idx) != airports.end()) {
128                                                 airports[idx]->push_back(f_ident);
129                                         } else {
130                                                 aptID_list_type* apts = new aptID_list_type;
131                                                 apts->push_back(f_ident);
132                                                 airports[idx] = apts;
133                                         }
134                                         cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
135                                 }
136                         }
137                 }               
138                 closedir(d);
139         }
140 #endif
141         
142         // See if are in range at startup and activate if necessary
143         SearchByPos(10.0);
144 }
145
146 void FGAIMgr::bind() {
147 }
148
149 void FGAIMgr::unbind() {
150 }
151
152 void FGAIMgr::update(double dt) {
153         static int i = 0;
154         static int j = 0;
155
156         // Don't update any planes for first 50 runs through - this avoids some possible initialisation anomalies
157         // Might not need it now we have fade-in though?
158         if(i < 50) {
159                 ++i;
160                 return;
161         }
162         
163         if(j == 215) {
164                 SearchByPos(15.0);
165                 j = 0;
166         }
167         
168         ++j;
169         
170         // TODO - need to add a check of if any activated airports have gone out of range
171         
172         // Traverse the list of active planes and run all their update methods
173         // TODO - spread the load - not all planes should need updating every frame.
174         // Note that this will require dt to be calculated for each plane though
175         // since they rely on it to calculate distance travelled.
176         ai_list_itr = ai_list.begin();
177         while(ai_list_itr != ai_list.end()) {
178                 (*ai_list_itr)->Update(dt);
179                 ++ai_list_itr;
180         }
181 }
182
183
184 // Activate AI traffic at an airport
185 void FGAIMgr::ActivateAirport(string ident) {
186         ATC->AIRegisterAirport(ident);
187         // TODO - need to start the traffic more randomly
188         FGAILocalTraffic* local_traffic = new FGAILocalTraffic;
189         //local_traffic->Init(ident, IN_PATTERN, TAKEOFF_ROLL);
190         local_traffic->Init(ident);
191         local_traffic->FlyCircuits(1, true);    // Fly 2 circuits with touch & go in between
192         ai_list.push_back(local_traffic);
193         activated[ident] = 1;
194 }       
195
196
197 // Search for valid airports in the vicinity of the user and activate them if necessary
198 void FGAIMgr::SearchByPos(double range)
199 {
200         //cout << "In SearchByPos(...)" << endl;
201         
202         // get bucket number for plane position
203         lon = lon_node->getDoubleValue();
204         lat = lat_node->getDoubleValue();
205         SGBucket buck(lon, lat);
206
207         // get neigboring buckets
208         int bx = (int)( range*SG_NM_TO_METER / buck.get_width_m() / 2);
209         //cout << "bx = " << bx << endl;
210         int by = (int)( range*SG_NM_TO_METER / buck.get_height_m() / 2 );
211         //cout << "by = " << by << endl;
212         
213         // loop over bucket range 
214         for ( int i=-bx; i<=bx; i++) {
215                 //cout << "i loop\n";
216                 for ( int j=-by; j<=by; j++) {
217                         //cout << "j loop\n";
218                         buck = sgBucketOffset(lon, lat, i, j);
219                         long int bucket = buck.gen_index();
220                         //cout << "bucket is " << bucket << endl;
221                         if(airports.find(bucket) != airports.end()) {
222                                 aptID_list_type* apts = airports[bucket];
223                                 aptID_list_iterator current = apts->begin();
224                                 aptID_list_iterator last = apts->end();
225                                 
226                                 //cout << "Size of apts is " << apts->size() << endl;
227                                 
228                                 //double rlon = lon * SGD_DEGREES_TO_RADIANS;
229                                 //double rlat = lat * SGD_DEGREES_TO_RADIANS;
230                                 //Point3D aircraft = sgGeodToCart( Point3D(rlon, rlat, elev) );
231                                 //Point3D airport;
232                                 for(; current != last; ++current) {
233                                         //cout << "Found " << *current << endl;;
234                                         if(activated.find(*current) == activated.end()) {
235                                                 //cout << "Activating " << *current << endl;
236                                                 //FGAirport a;
237                                                 //if(dclFindAirportID(*current, &a)) {
238                                                         //      // We can do something here based on distance from the user if we wish.
239                                                 //}
240                                                 ActivateAirport(*current);
241                                                 //cout << "Activation done" << endl;
242                                         } else {
243                                                 //cout << *current << " already activated" << endl;
244                                         }
245                                 }
246                         }
247                 }
248         }
249 }