]> git.mxchange.org Git - flightgear.git/blobdiff - src/Instrumentation/mk_viii.cxx
Autopilot: clean up the helpers code (which drives the various /internal/) properties...
[flightgear.git] / src / Instrumentation / mk_viii.cxx
index da8cdb74404190c1fb0c28588280537986436790..64e187f6fb01db14c14341ed2e9278e20f6d57cb 100755 (executable)
 #include <simgear/sound/soundmgr_openal.hxx>
 #include <simgear/structure/exception.hxx>
 
-SG_USING_STD(string);
+using std::string;
 
-#include "Airports/runways.hxx"
-#include "Airports/simple.hxx"
-#include "Main/fg_props.hxx"
-#include "Main/globals.hxx"
+#include <Airports/runways.hxx>
+#include <Airports/simple.hxx>
+#ifndef _MSC_VER
+#  include <Include/version.h>
+#endif
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
 #include "instrument_mgr.hxx"
 #include "mk_viii.hxx"
 
@@ -165,35 +168,6 @@ get_reciprocal_heading (double h)
   return heading_add(h, 180);
 }
 
-// Searches for the closest airport whose Manhattan distance to
-// @lat,@lon is inferior to @min_manhattan_distance (expressed in
-// degrees) and for which @test_airport returns true. Returns NULL if
-// no airport was found.
-template <class C>
-static const FGAirport *
-get_closest_airport (double lat,
-                    double lon,
-                    double min_manhattan_distance,
-                    C &obj,
-                    bool (C::*test_airport) (const FGAirport *))
-{
-  const FGAirport *airport = NULL;
-  const airport_list *airport_list = globals->get_airports()->getAirportList();
-
-  for (size_t i = 0; i < airport_list->size(); i++)
-    {
-      const FGAirport *a = (*airport_list)[i];
-      double dist = fabs(lat - a->getLatitude()) + fabs(lon - a->getLongitude());
-      if (dist < min_manhattan_distance && (obj.*test_airport)(a))
-       {
-         airport = a;
-         min_manhattan_distance = dist;
-       }
-    }
-
-  return airport;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // PropertiesHandler //////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
@@ -232,7 +206,7 @@ MK_VIII::PropertiesHandler::init ()
 void
 MK_VIII::PropertiesHandler::unbind ()
 {
-  vector<SGPropertyNode *>::iterator iter;
+  vector<SGPropertyNode_ptr>::iterator iter;
 
   for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++)
     (*iter)->untie();
@@ -575,7 +549,7 @@ MK_VIII::ConfigurationModule::read_aircraft_mode_type_select (int value)
     { 255,     &m1_t1, &m2_t1, &m3_t1, &m4_t1, m6_t2, &f_fast, 2000 }
   };
 
-  for (int i = 0; i < n_elements(aircraft_types); i++)
+  for (size_t i = 0; i < n_elements(aircraft_types); i++)
     if (aircraft_types[i].type == value)
       {
        mk->mode1_handler.conf.envelopes = aircraft_types[i].m1;
@@ -651,7 +625,7 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value)
     { 101, { FIELD_500_ABOVE, 0 } }
   };
 
-  int i;
+  unsigned i;
 
   mk->mode6_handler.conf.minimums_enabled = false;
   mk->mode6_handler.conf.smart_500_enabled = false;
@@ -682,7 +656,7 @@ MK_VIII::ConfigurationModule::read_altitude_callouts (int value)
              break;
 
            default:
-             for (int k = 0; k < n_altitude_callouts; k++)
+             for (unsigned k = 0; k < n_altitude_callouts; k++)
                if (mk->mode6_handler.altitude_callout_definitions[k] == values[i].callouts[j])
                  mk->mode6_handler.conf.altitude_callouts_enabled[k] = true;
              break;
@@ -799,7 +773,7 @@ MK_VIII::ConfigurationModule::read_input_output_discrete_type_select (int value)
     { 255,     { false, false }, true, false, true }
   };
 
-  for (int i = 0; i < n_elements(io_types); i++)
+  for (size_t i = 0; i < n_elements(io_types); i++)
     if (io_types[i].type == value)
       {
        mk->io_handler.conf.lamp = &io_types[i].lamp_conf;
@@ -827,7 +801,7 @@ MK_VIII::ConfigurationModule::read_audio_output_level (int value)
     { 4, -24 }
   };
 
-  for (int i = 0; i < n_elements(values); i++)
+  for (size_t i = 0; i < n_elements(values); i++)
     if (values[i].id == value)
       {
        mk->voice_player.set_volume(mk->voice_player.conf.volume = modify_amplitude(1.0, values[i].relative_dB));
@@ -1005,7 +979,7 @@ MK_VIII::IOHandler::TerrainClearanceFilter::update (double agl)
   // [PILOT] page 20 specifies that the terrain clearance is equal to
   // 75% of the radio altitude, averaged over the previous 15 seconds.
 
-  deque< Sample<double> >::iterator iter;
+  samples_type::iterator iter;
 
   // remove samples older than 15 seconds
   for (iter = samples.begin(); iter != samples.end() && globals->get_sim_time_sec() - (*iter).timestamp >= 15; iter = samples.begin())
@@ -1264,8 +1238,8 @@ MK_VIII::IOHandler::update_inputs ()
   // Erase everything from the beginning of the list up to the sample
   // preceding the most recent sample whose age is >= 1 second.
 
-  deque< Sample< Parameter<double> > >::iterator erase_last = altitude_samples.begin();
-  deque< Sample< Parameter<double> > >::iterator iter;
+  altitude_samples_type::iterator erase_last = altitude_samples.begin();
+  altitude_samples_type::iterator iter;
 
   for (iter = altitude_samples.begin(); iter != altitude_samples.end(); iter++)
     if (globals->get_sim_time_sec() - (*iter).timestamp >= 1)
@@ -1576,7 +1550,7 @@ MK_VIII::IOHandler::update_egpws_alert_discrete_1 ()
        { 19, mk_voice(minimums_minimums) }
       };
 
-      for (int i = 0; i < n_elements(voices); i++)
+      for (size_t i = 0; i < n_elements(voices); i++)
        if (voices[i].voice == mk->voice_player.voice)
          {
            mk_aoutput(egpws_alert_discrete_1) = 1 << voices[i].bit;
@@ -1610,7 +1584,7 @@ MK_VIII::IOHandler::update_egpwc_logic_discretes ()
     { 25, mk_alert(MODE5_SOFT) | mk_alert(MODE5_HARD) }
   };
 
-  for (int i = 0; i < n_elements(logic); i++)
+  for (size_t i = 0; i < n_elements(logic); i++)
     if (mk_test_alerts(logic[i].alerts))
       mk_aoutput(egpwc_logic_discretes) |= 1 << logic[i].bit;
 }
@@ -1636,7 +1610,7 @@ MK_VIII::IOHandler::update_mode6_callouts_discrete_1 ()
        { 25, mk_altitude_voice(Mode6Handler::ALTITUDE_CALLOUT_300) }
       };
 
-      for (int i = 0; i < n_elements(voices); i++)
+      for (size_t i = 0; i < n_elements(voices); i++)
        if (voices[i].voice == mk->voice_player.voice)
          {
            mk_aoutput(mode6_callouts_discrete_1) = 1 << voices[i].bit;
@@ -1665,7 +1639,7 @@ MK_VIII::IOHandler::update_mode6_callouts_discrete_2 ()
        { 23, mk_voice(five_hundred_above) }
       };
 
-      for (int i = 0; i < n_elements(voices); i++)
+      for (size_t i = 0; i < n_elements(voices); i++)
        if (voices[i].voice == mk->voice_player.voice)
          {
            mk_aoutput(mode6_callouts_discrete_2) = 1 << voices[i].bit;
@@ -2075,7 +2049,7 @@ MK_VIII::IOHandler::present_status ()
            "TCF INPUTS INVALID"
          };
 
-         for (int i = 0; i < n_elements(fault_names); i++)
+         for (size_t i = 0; i < n_elements(fault_names); i++)
            if (mk->fault_handler.faults[i])
              present_status_subitem(fault_names[i]);
        }
@@ -2101,7 +2075,7 @@ MK_VIII::IOHandler::present_status ()
     "VOLUME SELECT"
   };
 
-  for (int i = 0; i < n_elements(category_names); i++)
+  for (size_t i = 0; i < n_elements(category_names); i++)
     {
       std::ostringstream value;
       value << "= " << mk->configuration_module.effective_categories[i];
@@ -2280,7 +2254,7 @@ MK_VIII::VoicePlayer::init ()
   make_voice(&voices.too_low_gear, "too-low-gear");
   make_voice(&voices.too_low_terrain, "too-low-terrain");
 
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     {
       std::ostringstream name;
       name << "altitude-" << mk->mode6_handler.altitude_callout_definitions[i];
@@ -2296,7 +2270,13 @@ MK_VIII::VoicePlayer::get_sample (const char *name)
   std::ostringstream refname;
   refname << mk->name << "[" << mk->num << "]" << "/" << name;
 
-  SGSoundSample *sample = globals->get_soundmgr()->find(refname.str());
+  SGSoundMgr *soundmgr = globals->get_soundmgr();
+  if (soundmgr->is_working() == false)
+    {
+      return NULL;
+    }
+
+  SGSoundSample *sample = soundmgr->find(refname.str());
   if (! sample)
     {
       SGPath sample_path(globals->get_fg_root());
@@ -2313,7 +2293,7 @@ MK_VIII::VoicePlayer::get_sample (const char *name)
          exit(1);
        }
 
-      globals->get_soundmgr()->add(sample, refname.str());
+      soundmgr->add(sample, refname.str());
       samples[refname.str()] = sample;
     }
 
@@ -2607,7 +2587,7 @@ MK_VIII::SelfTestHandler::run ()
       if (mk->mode6_handler.conf.above_field_voice)
        return play(mk->mode6_handler.conf.above_field_voice);
     }
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     if (! was_here_offset(i))
       {
        if (mk->mode6_handler.conf.altitude_callouts_enabled[i])
@@ -4031,14 +4011,14 @@ MK_VIII::Mode6Handler::reset_minimums ()
 void
 MK_VIII::Mode6Handler::reset_altitude_callouts ()
 {
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     altitude_callouts_issued[i] = false;
 }
 
 bool
 MK_VIII::Mode6Handler::is_playing_altitude_callout ()
 {
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     if (mk->voice_player.voice == mk_altitude_voice(i)
        || mk->voice_player.next_voice == mk_altitude_voice(i))
       return true;
@@ -4112,7 +4092,7 @@ MK_VIII::Mode6Handler::boot ()
   last_radio_altitude.set(&mk_data(radio_altitude));
 
   // [SPEC] 6.4.2
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     altitude_callouts_issued[i] = ! mk_data(radio_altitude).ncd
       && mk_data(radio_altitude).get() <= altitude_callout_definitions[i];
 
@@ -4154,7 +4134,7 @@ MK_VIII::Mode6Handler::set_volume (double volume)
 {
   mk_voice(minimums_minimums)->set_volume(volume);
   mk_voice(five_hundred_above)->set_volume(volume);
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     mk_altitude_voice(i)->set_volume(volume);
 }
 
@@ -4164,7 +4144,7 @@ MK_VIII::Mode6Handler::altitude_callouts_enabled ()
   if (conf.minimums_enabled || conf.smart_500_enabled || conf.above_field_voice)
     return true;
 
-  for (int i = 0; i < n_altitude_callouts; i++)
+  for (unsigned i = 0; i < n_altitude_callouts; i++)
     if (conf.altitude_callouts_enabled[i])
       return true;
 
@@ -4217,7 +4197,7 @@ MK_VIII::Mode6Handler::update_altitude_callouts ()
   if (! mk->io_handler.gpws_inhibit()
       && ! mk->state_handler.ground // [1]
       && ! mk_data(radio_altitude).ncd)
-    for (int i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++)
+    for (unsigned i = 0; i < n_altitude_callouts && mk_data(radio_altitude).get() <= altitude_callout_definitions[i]; i++)
       if ((conf.altitude_callouts_enabled[i]
           || (altitude_callout_definitions[i] == 500
               && conf.smart_500_enabled))
@@ -4226,7 +4206,7 @@ MK_VIII::Mode6Handler::update_altitude_callouts ()
              || last_radio_altitude.get() > altitude_callout_definitions[i]))
        {
          // lock out all callouts superior or equal to this one
-         for (int j = 0; j <= i; j++)
+         for (unsigned j = 0; j <= i; j++)
            altitude_callouts_issued[j] = true;
 
          altitude_callouts_issued[i] = true;
@@ -4250,76 +4230,59 @@ MK_VIII::Mode6Handler::update_altitude_callouts ()
 bool
 MK_VIII::Mode6Handler::test_runway (const FGRunway *_runway)
 {
-  if (_runway->_length < mk->conf.runway_database)
+  if (_runway->lengthFt() < mk->conf.runway_database)
     return false;
 
-  // get position of threshold
-  double latitude, longitude, az;
-  geo_direct_wgs_84(0,
-                   _runway->_lat,
-                   _runway->_lon,
-                   get_reciprocal_heading(_runway->_heading),
-                   _runway->_length / 2 * SG_FEET_TO_METER,
-                   &latitude,
-                   &longitude,
-                   &az);
-
+  SGGeod pos(
+    SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()));
+  
   // get distance to threshold
   double distance, az1, az2;
-  geo_inverse_wgs_84(0,
-                    mk_data(gps_latitude).get(),
-                    mk_data(gps_longitude).get(),
-                    latitude,
-                    longitude,
-                    &az1, &az2, &distance);
-
+  SGGeodesy::inverse(pos, _runway->threshold(), az1, az2, distance);
   return distance * SG_METER_TO_NM <= 5;
 }
 
 bool
 MK_VIII::Mode6Handler::test_airport (const FGAirport *airport)
 {
-  FGRunway r;
-  if (globals->get_runways()->search(airport->getId(), &r))
-    do
-      {
-       if (test_runway(&r))
-         return true;
-
-       // reciprocal runway
-       r._heading = get_reciprocal_heading(r._heading);
-       if (test_runway(&r))
-         return true;
-      }
-    while (globals->get_runways()->next(&r) && r._id == airport->getId());
+  for (unsigned int r=0; r<airport->numRunways(); ++r) {
+    FGRunway* rwy(airport->getRunwayByIndex(r));
+    
+    if (test_runway(rwy)) return true;
+  }
 
   return false;
 }
 
+bool MK_VIII::Mode6Handler::AirportFilter::passAirport(FGAirport* a) const
+{
+  bool ok = self->test_airport(a);
+  return ok;
+}
+
 void
 MK_VIII::Mode6Handler::update_runway ()
 {
-  if (! mk_data(gps_latitude).ncd && ! mk_data(gps_longitude).ncd)
-    {
-      // Search for the closest runway threshold in range 5
-      // nm. Passing 0.5 degrees (approximatively 30 nm) to
-      // get_closest_airport() provides enough margin for large
-      // airports, which may have a runway located far away from the
-      // airport's reference point.
-
-      const FGAirport *airport = get_closest_airport(mk_data(gps_latitude).get(),
-                                                    mk_data(gps_longitude).get(),
-                                                    0.5,
-                                                    *this,
-                                                    &MK_VIII::Mode6Handler::test_airport);
-
-      if (airport)
-       runway.elevation = airport->getElevation();
-
-      has_runway.set(airport != NULL);
-    }
-  else
-    has_runway.unset();
+  if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) {
+     has_runway.unset();
+     return;
+  }
+
+  // Search for the closest runway threshold in range 5
+  // nm. Passing 30nm to
+  // get_closest_airport() provides enough margin for large
+  // airports, which may have a runway located far away from the
+  // airport's reference point.
+  AirportFilter filter(this);
+  FGPositionedRef apt = FGPositioned::findClosest(
+    SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
+    30.0, &filter);
+  if (apt) {
+    runway.elevation = apt->elevation();
+  }
+  
+  has_runway.set(apt != NULL);
 }
 
 void
@@ -4498,9 +4461,9 @@ MK_VIII::TCFHandler::get_azimuth_difference (const FGRunway *_runway)
 {
   return get_azimuth_difference(mk_data(gps_latitude).get(),
                                mk_data(gps_longitude).get(),
-                               _runway->_lat,
-                               _runway->_lon,
-                               _runway->_heading);
+                               _runway->latitude(),
+                               _runway->longitude(),
+                               _runway->headingDeg());
 }
 
 // Selects the most likely intended destination runway of @airport,
@@ -4512,84 +4475,59 @@ MK_VIII::TCFHandler::get_azimuth_difference (const FGRunway *_runway)
 // This selection algorithm is not specified in [SPEC], but
 // http://www.egpws.com/general_information/description/runway_select.htm
 // talks about automatic runway selection.
-void
-MK_VIII::TCFHandler::select_runway (const FGAirport *airport,
-                                   FGRunway *_runway)
+FGRunway*
+MK_VIII::TCFHandler::select_runway (const FGAirport *airport)
 {
-  FGRunway r;
-  bool status = globals->get_runways()->search(airport->getId(), &r);
-  assert(status);
-
+  FGRunway* _runway = 0;
   double min_diff = 360;
-  do
-    {
-      double diff;
-
-      diff = get_azimuth_difference(&r);
-      if (diff < min_diff)
-       {
-         min_diff = diff;
-         *_runway = r;
-       }
-
-      // reciprocal runway
-      r._heading = get_reciprocal_heading(r._heading);
-      diff = get_azimuth_difference(&r);
-      if (diff < min_diff)
-       {
-         min_diff = diff;
-         *_runway = r;
-       }
+  
+  for (unsigned int r=0; r<airport->numRunways(); ++r) {
+    FGRunway* rwy(airport->getRunwayByIndex(r));
+    double diff = get_azimuth_difference(rwy);
+    if (diff < min_diff)
+         {
+      min_diff = diff;
+      _runway = rwy;
     }
-  while (globals->get_runways()->next(&r) && r._id == airport->getId());
+  } // of airport runways iteration
+  return _runway;
 }
 
-bool
-MK_VIII::TCFHandler::test_airport (const FGAirport *airport)
+bool MK_VIII::TCFHandler::AirportFilter::passAirport(FGAirport* aApt) const
 {
-  FGRunway r;
-  if (globals->get_runways()->search(airport->getId(), &r))
-    do
-      {
-       if (r._length >= mk->conf.runway_database)
-         return true;
-      }
-    while (globals->get_runways()->next(&r) && r._id == airport->getId());
-
-  return false;
+  return aApt->hasHardRunwayOfLengthFt(mk->conf.runway_database);
 }
-
+   
 void
 MK_VIII::TCFHandler::update_runway ()
 {
   has_runway = false;
-  if (! mk_data(gps_latitude).ncd && ! mk_data(gps_longitude).ncd)
-    {
-      // Search for the intended destination runway of the closest
-      // airport in range 15 nm. Passing 0.5 degrees (approximatively
-      // 30 nm) to get_closest_airport() provides enough margin for
-      // large airports, which may have a runway located far away from
-      // the airport's reference point.
-
-      const FGAirport *airport = get_closest_airport(mk_data(gps_latitude).get(),
-                                                    mk_data(gps_longitude).get(),
-                                                    0.5,
-                                                    *this,
-                                                    &MK_VIII::TCFHandler::test_airport);
-
-      if (airport)
-       {
+  if (mk_data(gps_latitude).ncd || mk_data(gps_longitude).ncd) {
+    return;
+  }
+
+  // Search for the intended destination runway of the closest
+  // airport in range 15 nm. Passing 30nm to get_closest_airport() 
+  // provides enough margin for
+  // large airports, which may have a runway located far away from
+  // the airport's reference point.
+  AirportFilter filter(mk);
+  FGAirport* apt = FGAirport::findClosest(
+    SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
+    30.0, &filter);
+      
+  if (!apt) return;
+  
          has_runway = true;
 
-         FGRunway _runway;
-         select_runway(airport, &_runway);
-
-         runway.center.latitude = _runway._lat;
-         runway.center.longitude = _runway._lon;
+         FGRunway* _runway = select_runway(apt);
+    
+         runway.center.latitude = _runway->latitude();
+         runway.center.longitude = _runway->longitude();
 
-         runway.elevation = airport->getElevation();
+         runway.elevation = apt->elevation();
 
-         double half_length_m = _runway._length / 2 * SG_FEET_TO_METER;
+         double half_length_m = _runway->lengthM() * 0.5;
          runway.half_length = half_length_m * SG_METER_TO_NM;
 
          //        b3 ________________ b0
@@ -4599,8 +4537,8 @@ MK_VIII::TCFHandler::update_runway ()
          //        b2                  b1
 
          // get heading to runway threshold (h0) and end (h1)
-         runway.edges[0].heading = _runway._heading;
-         runway.edges[1].heading = get_reciprocal_heading(_runway._heading);
+         runway.edges[0].heading = _runway->headingDeg();
+         runway.edges[1].heading = get_reciprocal_heading(_runway->headingDeg());
 
          double az;
 
@@ -4624,7 +4562,7 @@ MK_VIII::TCFHandler::update_runway ()
                            &runway.edges[1].position.longitude,
                            &az);
 
-         double half_width_m = _runway._width / 2 * SG_FEET_TO_METER;
+         double half_width_m = _runway->widthM() * 0.5;
 
          // get position of threshold bias area edges (b0 and b1)
          get_bias_area_edges(&runway.edges[0].position,
@@ -4639,8 +4577,6 @@ MK_VIII::TCFHandler::update_runway ()
                              half_width_m,
                              &runway.bias_area[2],
                              &runway.bias_area[3]);
-       }
-    }
 }
 
 void
@@ -4651,7 +4587,7 @@ MK_VIII::TCFHandler::get_bias_area_edges (Position *edge,
                                          Position *bias_edge2)
 {
   double half_bias_width_m = k * SG_NM_TO_METER + half_width_m;
-  double tmp_latitude, tmp_longitude, az;
+  double tmp_latitude = 0.0, tmp_longitude = 0.0, az = 0.0;
 
   geo_direct_wgs_84(0,
                    edge->latitude,
@@ -4904,10 +4840,9 @@ MK_VIII::TCFHandler::update ()
 ///////////////////////////////////////////////////////////////////////////////
 
 MK_VIII::MK_VIII (SGPropertyNode *node)
-  : name("mk-viii"),
+  : properties_handler(this),
+    name("mk-viii"),
     num(0),
-
-    properties_handler(this),
     power_handler(this),
     system_handler(this),
     configuration_module(this),