]> git.mxchange.org Git - flightgear.git/blob - src/Airports/runwayprefs.cxx
- export font properties to the property tree again
[flightgear.git] / src / Airports / runwayprefs.cxx
1 // runwayprefs.cxx - class implementations corresponding to runwayprefs.hxx
2 // assignments by the AI code
3 //
4 // Written by Durk Talsma, started January 2005.
5 //
6 // Copyright (C) 2004 Durk Talsma.
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 // $Id$
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <math.h>
29 //#include <algorithm>
30
31 #include <simgear/compiler.h>
32
33 //#include <plib/sg.h>
34 //#include <plib/ul.h>
35
36 //#include <Environment/environment_mgr.hxx>
37 //#include <Environment/environment.hxx>
38 //#include <simgear/misc/sg_path.hxx>
39 //#include <simgear/props/props.hxx>
40 //#include <simgear/structure/subsystem_mgr.hxx>
41 #include <simgear/debug/logstream.hxx>
42 #include <Main/globals.hxx>
43 //#include <Main/fg_props.hxx>
44 #include <Airports/runways.hxx>
45
46 #include "runwayprefs.hxx"
47 #include "simple.hxx"
48
49 /******************************************************************************
50  * ScheduleTime
51  ***************e*************************************************************/
52 void ScheduleTime::clear()
53
54   start.clear();
55   end.clear();
56   scheduleNames.clear();
57 }
58
59
60 ScheduleTime::ScheduleTime(const ScheduleTime &other) 
61 {
62   //timeVec   start;
63   timeVecConstIterator i;
64   for (i = other.start.begin(); i != other.start.end(); i++)
65     start.push_back(*i);
66    for (i = other.end.begin(); i != other.end.end(); i++)
67     end.push_back(*i);
68    stringVecConstIterator k;
69    for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
70      scheduleNames.push_back(*k);
71   
72   //timeVec   end;
73   //stringVec scheduleNames;
74   tailWind = other.tailWind;
75   crssWind = other.tailWind;
76 }
77
78
79 ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other) 
80 {
81   //timeVec   start;
82   clear();
83   timeVecConstIterator i;
84   for (i = other.start.begin(); i != other.start.end(); i++)
85     start.push_back(*i);
86    for (i = other.end.begin(); i != other.end.end(); i++)
87     end.push_back(*i);
88    stringVecConstIterator k;
89    for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
90      scheduleNames.push_back(*k);
91   
92   //timeVec   end;
93   //stringVec scheduleNames;
94   tailWind = other.tailWind;
95   crssWind = other.tailWind;
96   return *this;
97 }
98 string ScheduleTime::getName(time_t dayStart)
99 {
100   if ((start.size() != end.size()) || (start.size() != scheduleNames.size()))
101     {
102       SG_LOG( SG_GENERAL, SG_INFO, "Unable to parse schedule times" );
103       exit(1);
104     }
105   else
106     {
107       int nrItems = start.size();
108       //cerr << "Nr of items to process: " << nrItems << endl;
109       if (nrItems > 0)
110         {
111           for (unsigned int i = 0; i < start.size(); i++)
112             {
113               //cerr << i << endl;
114               if ((dayStart >= start[i]) && (dayStart <= end[i]))
115                 return scheduleNames[i];
116             }
117         }
118       //couldn't find one so return 0;
119       //cerr << "Returning 0 " << endl;
120     }
121     return string(0);
122 }                             
123 /******************************************************************************
124  * RunwayList
125  *****************************************************************************/
126
127 RunwayList::RunwayList(const RunwayList &other)
128 {
129   type = other.type;
130   stringVecConstIterator i;
131   for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
132     preferredRunways.push_back(*i);
133 }
134 RunwayList& RunwayList::operator= (const RunwayList &other)
135 {
136   type = other.type;
137   preferredRunways.clear();
138   stringVecConstIterator i;
139   for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
140     preferredRunways.push_back(*i);
141   return *this;
142 }
143 void RunwayList::set(const string &tp, const string &lst)
144 {
145   //weekday          = atoi(timeCopy.substr(0,1).c_str());
146   //    timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
147   //    timeCopy = timeCopy.substr(2,timeCopy.length());
148   type = tp;
149   string rwys = lst;
150   string rwy;
151   while (rwys.find(",") != string::npos)
152     {
153       rwy = rwys.substr(0, rwys.find(",",0));
154       //cerr << "adding runway [" << rwy << "] to the list " << endl;
155       preferredRunways.push_back(rwy);
156       rwys.erase(0, rwys.find(",",0)+1); // erase until after the first whitspace
157       while (rwys[0] == ' ')
158         rwys.erase(0, 1); // Erase any leading whitespaces.
159       //cerr << "Remaining runway list " << rwys;
160     } 
161   preferredRunways.push_back(rwys);
162   //exit(1);
163 }
164
165 void RunwayList::clear() 
166 {
167   type = "";
168   preferredRunways.clear();
169 }
170 /****************************************************************************
171  *
172  ***************************************************************************/
173
174 RunwayGroup::RunwayGroup(const RunwayGroup &other)
175 {
176   name = other.name; 
177   RunwayListVecConstIterator i;
178   for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
179     rwyList.push_back(*i);
180   choice[0] = other.choice[0];
181   choice[1] = other.choice[1];
182   nrActive = other.nrActive;
183 }
184 RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
185
186   rwyList.clear();
187   name = other.name; 
188   RunwayListVecConstIterator i;
189   for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
190     rwyList.push_back(*i); 
191   choice[0] = other.choice[0];
192   choice[1] = other.choice[1];
193   nrActive = other.nrActive;
194   return *this;
195 }
196
197 void RunwayGroup::setActive(const string &aptId, 
198                             double windSpeed, 
199                             double windHeading, 
200                             double maxTail, 
201                             double maxCross,
202                             stringVec *currentlyActive)
203 {
204
205   FGRunway rwy;
206   int activeRwys = rwyList.size(); // get the number of runways active
207   int nrOfPreferences;
208   // bool found = true;
209   // double heading;
210   double hdgDiff;
211   double crossWind;
212   double tailWind;
213   string name;
214   //stringVec names;
215   int bestMatch = 0, bestChoice = 0;
216
217   if (activeRwys > 0)
218     {  
219       // Now downward iterate across all the possible preferences
220       // starting by the least preferred choice working toward the most preferred choice
221
222       nrOfPreferences = rwyList[0].getRwyList()->size();
223       bool validSelection = true;
224       bool foundValidSelection = false;
225       for (int i = nrOfPreferences-1; i >= 0; i--)
226         {
227           int match = 0;
228           
229
230           // Test each runway listed in the preference to see if it's possible to use
231           // If one runway of the selection isn't allowed, we need to exclude this
232           // preference, however, we don't want to stop right there, because we also
233           // don't want to randomly swap runway preferences, unless there is a need to. 
234           //
235           validSelection = true;
236           for (int j = 0; j < activeRwys; j++)
237             {
238              
239               name = rwyList[j].getRwyList(i);
240               //cerr << "Name of Runway: " << name;
241               if (globals->get_runways()->search( aptId, 
242                                                   name, 
243                                                   &rwy))
244                 {
245                   //cerr << "Succes" << endl;
246                   hdgDiff = fabs(windHeading - rwy._heading);
247                   //cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
248                   //cerr << "Wind Speed  : " << windSpeed << endl;
249                   if (hdgDiff > 180)
250                     hdgDiff = 360 - hdgDiff;
251                   //cerr << "Heading diff: " << hdgDiff << endl;
252                   hdgDiff *= ((2*M_PI)/360.0); // convert to radians
253                   crossWind = windSpeed * sin(hdgDiff);
254                   tailWind  = -windSpeed * cos(hdgDiff);
255                   //cerr << ". Tailwind : " << tailWind;
256                   //cerr << ". Crosswnd : " << crossWind;
257                   if ((tailWind > maxTail) || (crossWind > maxCross))
258                     {
259                       //cerr << ". [Invalid] " << endl;
260                       validSelection = false;
261                    }
262                   else 
263                     {
264                       //cerr << ". [Valid] ";
265                   }
266                 }else {
267                 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
268                 exit(1);
269               }
270               //cerr << endl;
271             }
272           if (validSelection) 
273             {
274               //cerr << "Valid selection  : " << i << endl;;
275               foundValidSelection = true;
276               for (stringVecIterator it = currentlyActive->begin(); 
277                    it != currentlyActive->end(); it++)
278                 {
279                   if ((*it) == name)
280                     match++;
281                 }
282               if (match >= bestMatch) {
283                 bestMatch = match;
284                 bestChoice = i;
285               }
286             } 
287           //cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
288         }
289       if (foundValidSelection)
290         {
291           //cerr << "Valid runay selection : " << bestChoice << endl;
292           nrActive = activeRwys;
293           active = bestChoice;
294           return;
295         }
296       // If this didn't work, due to heavy winds, try again
297       // but select only one landing and one takeoff runway. 
298       choice[0] = 0;
299       choice[1] = 0;
300       for (int i = activeRwys-1;  i; i--)
301         {
302           if (rwyList[i].getType() == string("landing"))
303             choice[0] = i;
304           if (rwyList[i].getType() == string("takeoff"))
305             choice[1] = i;
306         }
307       //cerr << "Choosing " << choice[0] << " for landing and " << choice[1] << "for takeoff" << endl;
308       nrOfPreferences = rwyList[0].getRwyList()->size();
309       for (int i = 0; i < nrOfPreferences; i++)
310         {
311           bool validSelection = true;
312           for (int j = 0; j < 2; j++)
313             {
314               //cerr << "I J " << i << " " << j << endl;
315               name = rwyList[choice[j]].getRwyList(i);
316               //cerr << "Name of Runway: " << name << endl;
317               if (globals->get_runways()->search( aptId, 
318                                                   name, 
319                                                   &rwy))
320                 {
321                   //cerr << "Succes" << endl;
322                   hdgDiff = fabs(windHeading - rwy._heading);
323                   if (hdgDiff > 180)
324                     hdgDiff = 360 - hdgDiff;
325                   hdgDiff *= ((2*M_PI)/360.0); // convert to radians
326                   crossWind = windSpeed * sin(hdgDiff);
327                   tailWind  = -windSpeed * cos(hdgDiff);
328                   if ((tailWind > maxTail) || (crossWind > maxCross))
329                     validSelection = false;
330                 }else {
331                   SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
332                   exit(1);
333                 }
334
335             }
336           if (validSelection)
337             {
338               //cerr << "Valid runay selection : " << i << endl;
339               active = i;
340               nrActive = 2;
341               return;
342             }
343         }
344     }
345   active = -1;
346   nrActive = 0;
347 }
348
349 void RunwayGroup::getActive(int i, string &name, string &type)
350 {
351   if (i == -1)
352     {
353       return;
354     }
355   if (nrActive == (int)rwyList.size())
356     {
357       name = rwyList[i].getRwyList(active);
358       type = rwyList[i].getType();
359     }
360   else
361     { 
362       name = rwyList[choice[i]].getRwyList(active);
363       type = rwyList[choice[i]].getType();
364     }
365 }
366 /*****************************************************************************
367  * FGRunway preference
368  ****************************************************************************/
369 FGRunwayPreference::FGRunwayPreference(FGAirport* ap) : 
370   _ap(ap)
371 {
372   //cerr << "Running default Constructor" << endl;
373   initialized = false;
374 }
375
376 FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other)
377 {
378   initialized = other.initialized;
379
380   comTimes = other.comTimes; // Commercial Traffic;
381   genTimes = other.genTimes; // General Aviation;
382   milTimes = other.milTimes; // Military Traffic;
383
384   PreferenceListConstIterator i;
385   for (i = other.preferences.begin(); i != other.preferences.end(); i++)
386     preferences.push_back(*i);
387 }
388   
389 FGRunwayPreference & FGRunwayPreference::operator= (const FGRunwayPreference &other)
390 {
391   initialized = other.initialized;
392   
393   comTimes = other.comTimes; // Commercial Traffic;
394   genTimes = other.genTimes; // General Aviation;
395   milTimes = other.milTimes; // Military Traffic;
396   
397   PreferenceListConstIterator i;
398   preferences.clear();
399   for (i = other.preferences.begin(); i != other.preferences.end(); i++)
400     preferences.push_back(*i);
401   return *this;
402 }
403
404 ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType)
405 {
406   if (!(strcmp(trafficType, "com"))) {
407     return &comTimes;
408   }
409   if (!(strcmp(trafficType, "gen"))) {
410     return &genTimes;
411   }
412   if (!(strcmp(trafficType, "mil"))) {
413     return &milTimes;
414   }
415   return 0;
416 }
417
418 RunwayGroup *FGRunwayPreference::getGroup(const string &groupName)
419 {
420   PreferenceListIterator i = preferences.begin();
421   if (preferences.begin() == preferences.end())
422     return 0;
423   while (!(i == preferences.end() || i->getName() == groupName))
424     i++;
425   if (i != preferences.end())
426     return &(*i);
427   else
428     return 0;
429 }
430
431  string FGRunwayPreference::getId() { 
432    return _ap->getId(); 
433  };