]> git.mxchange.org Git - flightgear.git/commitdiff
Removed DOS line endings
authordaveluff <daveluff>
Mon, 3 Mar 2003 10:38:13 +0000 (10:38 +0000)
committerdaveluff <daveluff>
Mon, 3 Mar 2003 10:38:13 +0000 (10:38 +0000)
src/ATC/approach.cxx
src/ATC/approach.hxx
src/ATC/transmission.cxx
src/ATC/transmission.hxx
src/ATC/transmissionlist.cxx
src/ATC/transmissionlist.hxx

index 11cbfb24b2a42061bb4203fd1f9b7d8efec5a6d2..a0c77b46a13a15a13330b12d8bc295845030c8b2 100644 (file)
-// FGApproach - a class to provide approach control at larger airports.\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-//\r
-// Copyright (C) 2002  Alexander Kappes\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-\r
-#include "approach.hxx"\r
-#include "transmission.hxx"\r
-#include "transmissionlist.hxx"\r
-#include "ATCdisplay.hxx"\r
-#include "ATCDialog.hxx"\r
-\r
-#include <Airports/runways.hxx>\r
-#include <simgear/misc/sg_path.hxx>\r
-\r
-#ifdef FG_WEATHERCM\r
-# include <WeatherCM/FGLocalWeatherDatabase.h>\r
-#else\r
-# include <Environment/environment_mgr.hxx>\r
-# include <Environment/environment.hxx>\r
-#endif\r
-\r
-\r
-#include <GUI/gui.h>\r
-\r
-//Constructor\r
-FGApproach::FGApproach(){\r
-  comm1_node = fgGetNode("/radios/comm[0]/frequencies/selected-mhz", true);\r
-  comm2_node = fgGetNode("/radios/comm[1]/frequencies/selected-mhz", true);\r
-\r
-  num_planes = 0;\r
-  lon_node   = fgGetNode("/position/longitude-deg", true);\r
-  lat_node   = fgGetNode("/position/latitude-deg", true);\r
-  elev_node  = fgGetNode("/position/altitude-ft", true);\r
-  hdg_node   = fgGetNode("/orientation/heading-deg", true);\r
-  speed_node = fgGetNode("/velocities/airspeed-kt", true);\r
-  etime_node = fgGetNode("/sim/time/elapsed-ms", true);\r
-\r
-  first = true;\r
-  active_runway = "";\r
-  int i;\r
-  for ( i=0; i<max_planes; i++) {\r
-    planes[i].contact   = 0;\r
-    planes[i].wpn       = 0;\r
-    planes[i].dnwp      = -999.;\r
-    planes[i].on_crs    = true;\r
-    planes[i].turn_rate = 10.0;\r
-    planes[i].desc_rate = 1000.0;\r
-    planes[i].clmb_rate = 500.0;\r
-    planes[i].tlm       = 0.0;\r
-    planes[i].lmc.c1    = 0;\r
-    planes[i].lmc.c2    = 0;\r
-    planes[i].lmc.c3    = -1;\r
-    planes[i].wp_change = false;\r
-  }\r
-}\r
-\r
-//Destructor\r
-FGApproach::~FGApproach(){\r
-}\r
-\r
-void FGApproach::Init() {\r
-  display    = false;\r
-}\r
-\r
-\r
-\r
-// ============================================================================\r
-// the main update function\r
-// ============================================================================\r
-void FGApproach::Update() {\r
-       \r
-       const int max_trans = 20;\r
-       FGTransmission tmissions[max_trans];\r
-       int    wpn;\r
-       int    station = 1;\r
-       TransCode code;\r
-       TransPar TPar;\r
-       int    i,j;\r
-       //double course, d, \r
-       double adif, datp;\r
-       //char   buf[10];\r
-       string message;\r
-       //static string atcmsg1[10];\r
-       //static string atcmsg2[10];\r
-       string mentry;\r
-       string transm;\r
-       TransPar tpars;\r
-       //static bool TransDisplayed = false;\r
-       \r
-       update_plane_dat();\r
-       if ( active_runway == "" ) get_active_runway();\r
-       \r
-       double comm1_freq = comm1_node->getDoubleValue();\r
-       \r
-       //bool DisplayTransmissions = true;\r
-       \r
-       for (i=0; i<num_planes; i++) {\r
-               if ( planes[i].ident == "Player") { \r
-                       station = 1;\r
-                       tpars.station = name;\r
-                       tpars.callsign = "Player";\r
-                       tpars.airport = ident;\r
-                       \r
-                       int num_trans = 0;\r
-                       // is the frequency of the station tuned in?\r
-                       if ( freq == (int)(comm1_freq*100.0 + 0.5) ) {\r
-                               current_transmissionlist->query_station( station, tmissions, max_trans, num_trans );\r
-                               // loop over all transmissions for station\r
-                               for ( j=0; j<=num_trans-1; j++ ) {\r
-                                       code = tmissions[j].get_code();\r
-                                       // select proper transmissions\r
-                                       if ( ( code.c2 == -1 && planes[i].lmc.c3 == 0 ) || \r
-                                               ( code.c1 == 0  && code.c2 == planes[i].lmc.c2 ) ) {\r
-                                               mentry = current_transmissionlist->gen_text(station, code, tpars, false);\r
-                                               transm = current_transmissionlist->gen_text(station, code, tpars, true);\r
-                                               // is the transmission already registered?\r
-                                               if (!current_atcdialog->trans_reg( ident, transm )) {\r
-                                                       current_atcdialog->add_entry( ident, transm, mentry );\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       \r
-       for ( i=0; i<num_planes; i++ ) {\r
-               \r
-               if ( planes[i].ident == TPar.callsign && name == TPar.airport && TPar.station == "approach" ) {\r
-                       \r
-                       if ( TPar.request && TPar.intention == "landing" && ident == TPar.intid) {\r
-                               planes[i].wpn = 0; \r
-                               // ===========================\r
-                               // === calculate waypoints ===\r
-                               // ===========================\r
-                               calc_wp( i );  \r
-                               update_param( i );\r
-                               wpn = planes[i].wpn-1;\r
-                               planes[i].aalt = planes[i].wpts[wpn-1][2];\r
-                               planes[i].ahdg = planes[i].wpts[wpn][4];\r
-                               \r
-                               // generate the message\r
-                               code.c1 = 1;\r
-                               code.c2 = 1;\r
-                               code.c3 = 0;\r
-                               adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );\r
-                               tpars.station = name;\r
-                               tpars.callsign = "Player";\r
-                               if ( adif < 0 ) tpars.tdir = 1;\r
-                               else            tpars.tdir = 2;\r
-                               tpars.heading = planes[i].ahdg;\r
-                               if      (planes[i].alt-planes[i].aalt > 100.0)  tpars.VDir = 1;\r
-                               else if (planes[i].alt-planes[i].aalt < -100.0) tpars.VDir = 3;\r
-                               else tpars.VDir = 2;\r
-                               tpars.alt = planes[i].aalt;\r
-                               message = current_transmissionlist->gen_text(station, code, tpars, true );\r
-                               globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                               planes[i].lmc = code;\r
-                               planes[i].tlm = etime_node->getDoubleValue();\r
-                               planes[i].on_crs = true;\r
-                               planes[i].contact = 1;\r
-                       }\r
-               }\r
-               \r
-               if ( planes[i].contact == 1 ) {\r
-                       // =========================\r
-                       // === update parameters ===\r
-                       // =========================\r
-                       update_param( i );\r
-                       //cout << planes[i].brg << " " << planes[i].dist << " " << planes[i].wpts[wpn+1][0] \r
-                       //<< " " << planes[i].wpts[wpn+1][1] << " " << planes[i].wpts[wpn+1][4] \r
-                       //cout << wpn << " distance to current course = " << planes[i].dcc << endl;\r
-                       //cout << etime_node->getDoubleValue() << endl;\r
-                       \r
-                       // =========================\r
-                       // === reached waypoint? ===\r
-                       // =========================\r
-                       wpn = planes[i].wpn-2;\r
-                       adif = angle_diff_deg( planes[i].hdg, planes[i].wpts[wpn][4] ) \r
-                       * SGD_DEGREES_TO_RADIANS;\r
-                       datp = 2*sin(fabs(adif)/2.0)*sin(fabs(adif)/2.0) *\r
-                       planes[i].spd/3600. * planes[i].turn_rate + \r
-                       planes[i].spd/3600. * 3.0;\r
-                       //cout << adif/SGD_DEGREES_TO_RADIANS << " " \r
-                       //     << datp << " " << planes[i].dnc << " " << planes[i].dcc <<endl;\r
-                       if ( fabs(planes[i].dnc) < datp ) {\r
-                       //if ( fabs(planes[i].dnc) < 0.3 && planes[i].dnwp < 1.0 ) {\r
-                               planes[i].wpn -= 1;\r
-                               wpn = planes[i].wpn-1;\r
-                               planes[i].ahdg = planes[i].wpts[wpn][4];\r
-                               planes[i].aalt = planes[i].wpts[wpn-1][2];\r
-                               planes[i].wp_change = true;\r
-                               \r
-                               // generate the message\r
-                               adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );\r
-                               tpars.station = name;\r
-                               tpars.callsign = "Player";\r
-                               if ( adif < 0 ) tpars.tdir = 1;\r
-                               else            tpars.tdir = 2;\r
-                               tpars.heading = planes[i].ahdg;\r
-                               \r
-                               if ( wpn-1 != 0) { \r
-                                       code.c1 = 1;\r
-                                       code.c2 = 1;\r
-                                       code.c3 = 0;\r
-                                       if      (planes[i].alt-planes[i].aalt > 100.0)  tpars.VDir = 1;\r
-                                       else if (planes[i].alt-planes[i].aalt < -100.0) tpars.VDir = 3;\r
-                                       else tpars.VDir = 2;\r
-                                       tpars.alt = planes[i].aalt;\r
-                                       message = current_transmissionlist->gen_text(station, code, tpars, true );\r
-                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                                       \r
-                               }\r
-                               else {\r
-                                       code.c1 = 1;\r
-                                       code.c2 = 3;\r
-                                       code.c3 = 0;\r
-                                       tpars.runway = active_runway;\r
-                                       message = current_transmissionlist->gen_text(station, code, tpars, true);\r
-                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                               }\r
-                               planes[i].lmc = code;\r
-                               planes[i].tlm = etime_node->getDoubleValue();\r
-                               planes[i].on_crs = true;\r
-                               \r
-                               update_param( i );\r
-                       }\r
-                       \r
-                       // =========================\r
-                       // === come off course ? ===\r
-                       // =========================\r
-                       if ( fabs(planes[i].dcc) > 1.0 && \r
-                               ( !planes[i].wp_change || \r
-                       etime_node->getDoubleValue() - planes[i].tlm > tbm ) ) {\r
-                               if ( planes[i].on_crs ) {\r
-                                       if ( planes[i].dcc < 0) {\r
-                                               planes[i].ahdg += 30.0;\r
-                                       }\r
-                                       else {\r
-                                               planes[i].ahdg -= 30.0;\r
-                                       }\r
-                                       if (planes[i].ahdg > 360.0) planes[i].ahdg -= 360.0;\r
-                                       else if (planes[i].ahdg < 0.0) planes[i].ahdg += 360.0;\r
-                               }\r
-                               //cout << planes[i].on_crs << " " \r
-                               //     << angle_diff_deg( planes[i].hdg, planes[i].ahdg) << " "\r
-                               //     << etime_node->getDoubleValue() << " "\r
-                               //     << planes[i].tlm << endl;\r
-                               // generate the message\r
-                               if ( planes[i].on_crs || \r
-                                       ( fabs(angle_diff_deg( planes[i].hdg, planes[i].ahdg )) >  30.0  && \r
-                               etime_node->getDoubleValue() - planes[i].tlm > tbm) ) {\r
-                                       // generate the message\r
-                                       code.c1 = 1;\r
-                                       code.c2 = 4;\r
-                                       code.c3 = 0;\r
-                                       adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );\r
-                                       tpars.station = name;\r
-                                       tpars.callsign = "Player";\r
-                                       tpars.miles   = fabs(planes[i].dcc);\r
-                                       if ( adif < 0 ) tpars.tdir = 1;\r
-                                       else            tpars.tdir = 2;\r
-                                       tpars.heading = planes[i].ahdg;\r
-                                       message = current_transmissionlist->gen_text(station, code, tpars, true);\r
-                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                                       planes[i].lmc = code;\r
-                                       planes[i].tlm = etime_node->getDoubleValue();\r
-                               }\r
-                               \r
-                               planes[i].on_crs = false;\r
-                       }\r
-                       else if ( !planes[i].on_crs ) {\r
-                               wpn = planes[i].wpn-1;\r
-                               adif = angle_diff_deg( planes[i].hdg, planes[i].wpts[wpn][4] ) \r
-                               * SGD_DEGREES_TO_RADIANS;\r
-                               datp = 2*sin(fabs(adif)/2.0)*sin(fabs(adif)/2.0) *\r
-                               planes[i].spd/3600. * planes[i].turn_rate + \r
-                               planes[i].spd/3600. * 3.0;\r
-                               if ( fabs(planes[i].dcc) < datp ) { \r
-                                       planes[i].ahdg = fabs(planes[i].wpts[wpn][4]);\r
-                                       \r
-                                       // generate the message\r
-                                       code.c1 = 1;\r
-                                       code.c2 = 2;\r
-                                       code.c3 = 0;\r
-                                       tpars.station = name;\r
-                                       tpars.callsign = "Player";\r
-                                       if ( adif < 0 ) tpars.tdir = 1;\r
-                                       else            tpars.tdir = 2;\r
-                                       tpars.heading = planes[i].ahdg;\r
-                                       message = current_transmissionlist->gen_text(station, code, tpars, true);\r
-                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                                       planes[i].lmc = code;\r
-                                       planes[i].tlm = etime_node->getDoubleValue();\r
-                                       \r
-                                       planes[i].on_crs = true;          \r
-                               } \r
-                       }\r
-                       else if ( planes[i].wp_change  ) {\r
-                               planes[i].wp_change = false;\r
-                       }\r
-                       \r
-                       // ===================================================================\r
-                       // === Less than two minutes away from touchdown? -> Contact Tower ===\r
-                       // ===================================================================\r
-                       if ( planes[i].wpn == 2 && planes[i].dnwp < planes[i].spd/60.*2.0 ) {\r
-                               \r
-                               double freq = 121.95;\r
-                               // generate message\r
-                               code.c1 = 1;\r
-                               code.c2 = 5;\r
-                               code.c3 = 0;\r
-                               tpars.station = name;\r
-                               tpars.callsign = "Player";\r
-                               tpars.freq    = freq;\r
-                               message = current_transmissionlist->gen_text(station, code, tpars, true);\r
-                               globals->get_ATC_display()->RegisterSingleMessage( message, 0 );\r
-                               planes[i].lmc = code;\r
-                               planes[i].tlm = etime_node->getDoubleValue();\r
-                               \r
-                               planes[i].contact = 2;\r
-                       }\r
-               }\r
-       }\r
-       \r
-}\r
-\r
-\r
-// ============================================================================\r
-// update course parameters\r
-// ============================================================================\r
-void FGApproach::update_param( const int &i ) {\r
-  \r
-  double course, d;\r
-\r
-  int wpn = planes[i].wpn-1;            // this is the current waypoint\r
-\r
-  planes[i].dcc  = calc_psl_dist(planes[i].brg, planes[i].dist,\r
-                                planes[i].wpts[wpn][0], planes[i].wpts[wpn][1],\r
-                                planes[i].wpts[wpn][4]);\r
-  planes[i].dnc  = calc_psl_dist(planes[i].brg, planes[i].dist,\r
-                                planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-                                planes[i].wpts[wpn-1][4]);\r
-  calc_hd_course_dist(planes[i].brg, planes[i].dist, \r
-                     planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-                     &course, &d);\r
-  planes[i].dnwp = d;\r
-\r
-}\r
-\r
-// ============================================================================\r
-// smallest difference between two angles in degree\r
-// difference is negative if a1 > a2 and positive if a2 > a1\r
-// ===========================================================================\r
-double FGApproach::angle_diff_deg( const double &a1, const double &a2) {\r
-  \r
-  double a3 = a2 - a1;\r
-  if (a3 < 180.0) a3 += 360.0;\r
-  if (a3 > 180.0) a3 -= 360.0;\r
-\r
-  return a3;\r
-}\r
-\r
-// ============================================================================\r
-// calculate waypoints\r
-// ============================================================================\r
-void FGApproach::calc_wp( const int &i ) {\r
-       \r
-       int j;\r
-       double course, d, cd, a1;\r
-       \r
-       int wpn = planes[i].wpn;\r
-       // waypoint 0: Threshold of active runway\r
-       calc_gc_course_dist(Point3D(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0.0),\r
-       Point3D(active_rw_lon*SGD_DEGREES_TO_RADIANS,active_rw_lat*SGD_DEGREES_TO_RADIANS, 0.0 ),\r
-       &course, &d);\r
-       double d1 = active_rw_hdg+180.0;\r
-       if ( d1 > 360.0 ) d1 -=360.0;\r
-       calc_cd_head_dist(360.0-course*SGD_RADIANS_TO_DEGREES, d/SG_NM_TO_METER, \r
-       d1, active_rw_len/SG_NM_TO_METER/2., \r
-       &planes[i].wpts[wpn][0], &planes[i].wpts[wpn][1]);\r
-       planes[i].wpts[wpn][2] = elev;\r
-       planes[i].wpts[wpn][4] = 0.0;\r
-       planes[i].wpts[wpn][5] = 0.0;\r
-       wpn += 1;\r
-       \r
-       // ======================\r
-       // horizontal navigation\r
-       // ======================\r
-       // waypoint 1: point for turning onto final\r
-       calc_cd_head_dist(planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1] , \r
-       d1, lfl,\r
-       &planes[i].wpts[wpn][0], &planes[i].wpts[wpn][1]);\r
-       calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],\r
-       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-       &course, &d);\r
-       planes[i].wpts[wpn][4] = course;\r
-       planes[i].wpts[wpn][5] = d;\r
-       wpn += 1;\r
-       \r
-       // calculate course and distance from plane position to waypoint 1\r
-       calc_hd_course_dist(planes[i].brg, planes[i].dist,\r
-       planes[i].wpts[1][0], planes[i].wpts[1][1],\r
-       &course, &d);\r
-       // check if airport is not between plane and waypoint 1 and\r
-       // DCA to airport on course to waypoint 1 is larger than 10 miles\r
-       double zero = 0.0;\r
-       if ( fabs(angle_diff_deg( planes[i].wpts[1][0], planes[i].brg  )) < 90.0 ||\r
-               calc_psl_dist( zero, zero, planes[i].brg, planes[i].dist, course ) > 10.0 ) {\r
-               // check if turning angle at waypoint 1 would be > max_ta\r
-               if ( fabs(angle_diff_deg( planes[i].wpts[1][4], course )) > max_ta ) {\r
-                       cd = calc_psl_dist(planes[i].brg, planes[i].dist,\r
-                       planes[i].wpts[1][0], planes[i].wpts[1][1],\r
-                       planes[i].wpts[1][4]);\r
-                       a1 = atan2(cd,planes[i].wpts[1][1]);\r
-                       planes[i].wpts[wpn][0] = planes[i].wpts[1][0] - a1/SGD_DEGREES_TO_RADIANS;\r
-                       if ( planes[i].wpts[wpn][0] < 0.0)   planes[i].wpts[wpn][0] += 360.0;   \r
-                       if ( planes[i].wpts[wpn][0] > 360.0) planes[i].wpts[wpn][0] -= 360.0;   \r
-                       planes[i].wpts[wpn][1] = fabs(cd) / sin(fabs(a1));\r
-                       calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],\r
-                       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-                       &course, &d);\r
-                       planes[i].wpts[wpn][4] = course;\r
-                       planes[i].wpts[wpn][5] = d;\r
-                       wpn += 1;\r
-                       \r
-                       calc_hd_course_dist(planes[i].brg, planes[i].dist,\r
-                       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-                       &course, &d);\r
-               }\r
-       } else {\r
-               double leg = 10.0;\r
-               a1 = atan2(planes[i].wpts[1][1], leg );\r
-               \r
-               if ( angle_diff_deg(planes[i].brg,planes[i].wpts[1][0]) < 0 ) \r
-                       planes[i].wpts[wpn][0] = planes[i].wpts[1][0] + a1/SGD_DEGREES_TO_RADIANS;\r
-               else planes[i].wpts[wpn][0] = planes[i].wpts[1][0] - a1/SGD_DEGREES_TO_RADIANS;\r
-               \r
-               planes[i].wpts[wpn][1] = sqrt( planes[i].wpts[1][1]*planes[i].wpts[1][1] + leg*leg );\r
-               calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],\r
-               planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-               &course, &d);\r
-               planes[i].wpts[wpn][4] = course;\r
-               planes[i].wpts[wpn][5] = d;\r
-               wpn += 1;\r
-               \r
-               calc_hd_course_dist(planes[i].brg, planes[i].dist,\r
-               planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],\r
-               &course, &d);\r
-       }\r
-       \r
-       planes[i].wpts[wpn][0] = planes[i].brg;\r
-       planes[i].wpts[wpn][1] = planes[i].dist;\r
-       planes[i].wpts[wpn][2] = planes[i].alt;\r
-       planes[i].wpts[wpn][4] = course;\r
-       planes[i].wpts[wpn][5] = d;\r
-       wpn += 1;\r
-       \r
-       planes[i].wpn = wpn;\r
-       \r
-       // Now check if legs are too short or if legs can be shortend\r
-       // legs must be at least 2 flight minutes long\r
-       double mdist = planes[i].spd / 60.0 * 2.0;\r
-       for ( j=2; j<wpn-1; ++j ) {\r
-               if ( planes[i].wpts[j][1] < mdist) {\r
-               }\r
-       }\r
-       \r
-       // ====================\r
-       // vertical navigation\r
-       // ====================\r
-       double alt = elev+3000.0;\r
-       planes[i].wpts[1][2] = round_alt( true, alt );\r
-       for ( j=2; j<wpn-1; ++j ) {\r
-               double dalt = planes[i].alt - planes[i].wpts[j-1][2];\r
-               if ( dalt > 0 ) {\r
-                       alt = planes[i].wpts[j-1][2] + \r
-                       (planes[i].wpts[j][5] / planes[i].spd) * 60.0 * planes[i].desc_rate;\r
-                       planes[i].wpts[j][2] = round_alt( false, alt );\r
-                       if ( planes[i].wpts[j][2] > planes[i].alt ) \r
-                               planes[i].wpts[j][2] = round_alt( false, planes[i].alt );\r
-               }\r
-               else {\r
-                       planes[i].wpts[j][2] = planes[i].wpts[1][2];\r
-               }\r
-       }\r
-       \r
-       cout << "Plane position: " << planes[i].brg << " " << planes[i].dist << endl;\r
-       for ( j=0; j<wpn; ++j ) {\r
-               cout << "Waypoint " << j << endl;\r
-               cout << "------------------" << endl;\r
-               cout << planes[i].wpts[j][0] << "   " << planes[i].wpts[j][1]\r
-               << "   " << planes[i].wpts[j][2] << "   " << planes[i].wpts[j][5]; \r
-               cout << endl << endl;\r
-       }\r
-       \r
-}\r
-\r
-\r
-// ============================================================================\r
-// round altitude value to next highest/lowest 500 feet\r
-// ============================================================================\r
-double FGApproach::round_alt( const bool hl, double alt ) {\r
-\r
-  alt = alt/1000.0;\r
-  if ( hl ) {\r
-    if ( alt > (int)(alt)+0.5 ) alt = ((int)(alt)+1)*1000.0;\r
-    else alt = ((int)(alt)+0.5)*1000.0;\r
-  }\r
-  else {\r
-    if ( alt > (int)(alt)+0.5 ) alt = ((int)(alt)+0.5)*1000.0;\r
-    else alt = ((int)(alt))*1000.0;\r
-  }\r
-  \r
-  return alt;\r
-}\r
-\r
-\r
-// ============================================================================\r
-// get active runway\r
-// ============================================================================\r
-void FGApproach::get_active_runway() {\r
-\r
-#ifdef FG_WEATHERCM\r
-  sgVec3 position = { lat, lon, elev };\r
-  FGPhysicalProperty stationweather = WeatherDatabase->get(position);\r
-#else\r
-  FGEnvironment stationweather =\r
-    globals->get_environment_mgr()->getEnvironment(lat, lon, elev);\r
-#endif\r
-\r
-  SGPath path( globals->get_fg_root() );\r
-  path.append( "Airports" );\r
-  path.append( "runways.mk4" );\r
-  FGRunways runways( path.c_str() );\r
-  \r
-#ifdef FG_WEATHERCM\r
-  //Set the heading to into the wind\r
-  double wind_x = stationweather.Wind[0];\r
-  double wind_y = stationweather.Wind[1];\r
-  \r
-  double speed = sqrt( wind_x*wind_x + wind_y*wind_y ) * SG_METER_TO_NM / (60.0*60.0);\r
-  double hdg;\r
-  \r
-  //If no wind use 270degrees\r
-  if(speed == 0) {\r
-    hdg = 270;\r
-  } else {\r
-    // //normalize the wind to get the direction\r
-    //wind_x /= speed; wind_y /= speed;\r
-    \r
-    hdg = - atan2 ( wind_x, wind_y ) * SG_RADIANS_TO_DEGREES ;\r
-    if (hdg < 0.0)\r
-      hdg += 360.0;\r
-  }\r
-#else\r
-  double hdg = stationweather.get_wind_from_heading_deg();\r
-#endif\r
-  \r
-  FGRunway runway;\r
-  if ( runways.search( ident, int(hdg), &runway) ) {\r
-    active_runway = runway.rwy_no;\r
-    active_rw_hdg = runway.heading;\r
-    active_rw_lon = runway.lon;\r
-    active_rw_lat = runway.lat;\r
-    active_rw_len = runway.length;\r
-    //cout << "Active runway is: " << active_runway << "  heading = " \r
-    // << active_rw_hdg \r
-    // << " lon = " << active_rw_lon \r
-    // << " lat = " << active_rw_lat <<endl;\r
-  }\r
-  else cout << "FGRunways search failed\n";\r
-\r
-}\r
-\r
-// ========================================================================\r
-// update infos about plane\r
-// ========================================================================\r
-void FGApproach::update_plane_dat() {\r
-  \r
-  //cout << "Update Approach " << ident << "   " << num_planes << " registered" << endl;\r
-  // update plane positions\r
-  int i;\r
-  for (i=0; i<num_planes; i++) {\r
-    planes[i].lon = lon_node->getDoubleValue();\r
-    planes[i].lat = lat_node->getDoubleValue();\r
-    planes[i].alt = elev_node->getDoubleValue();\r
-    planes[i].hdg = hdg_node->getDoubleValue();\r
-    planes[i].spd = speed_node->getDoubleValue();\r
-\r
-    /*Point3D aircraft = sgGeodToCart( Point3D(planes[i].lon*SGD_DEGREES_TO_RADIANS, \r
-                                            planes[i].lat*SGD_DEGREES_TO_RADIANS, \r
-                                            planes[i].alt*SG_FEET_TO_METER) );*/\r
-    double course, distance;\r
-    calc_gc_course_dist(Point3D(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0.0),\r
-                       Point3D(planes[i].lon*SGD_DEGREES_TO_RADIANS,planes[i].lat*SGD_DEGREES_TO_RADIANS, 0.0 ),\r
-                       &course, &distance);\r
-    planes[i].dist = distance/SG_NM_TO_METER;\r
-    planes[i].brg  = 360.0-course*SGD_RADIANS_TO_DEGREES;\r
-\r
-    //cout << "Plane Id: " << planes[i].ident << "  Distance to " << ident \r
-    // << " is " << planes[i].dist << " miles   " << "Bearing " << planes[i].brg << endl;\r
-    \r
-  }   \r
-}\r
-\r
-// =======================================================================\r
-// Add plane to Approach list\r
-// =======================================================================\r
-void FGApproach::AddPlane(string pid) {\r
-\r
-  int i;\r
-  for ( i=0; i<num_planes; i++) {\r
-    if ( planes[i].ident == pid) {\r
-      //cout << "Plane already registered: " << ident << " " << num_planes << endl;\r
-      return;\r
-    }\r
-  }\r
-  planes[num_planes].ident = pid;\r
-  ++num_planes;\r
-  //cout << "Plane added to list: " << ident << " " << num_planes << endl;\r
-  return;\r
-}\r
-\r
-// ================================================================================\r
-// closest distance between a point (h1,d1) and a straigt line (h2,d2,h3) in 2 dim.\r
-// ================================================================================\r
-double FGApproach::calc_psl_dist(const double &h1, const double &d1,\r
-                                const double &h2, const double &d2,\r
-                                const double &h3)\r
-{\r
-  double a1 = h1 * SGD_DEGREES_TO_RADIANS;\r
-  double a2 = h2 * SGD_DEGREES_TO_RADIANS;\r
-  double a3 = h3 * SGD_DEGREES_TO_RADIANS;\r
-  double x1 = cos(a1) * d1;\r
-  double y1 = sin(a1) * d1;\r
-  double x2 = cos(a2) * d2;\r
-  double y2 = sin(a2) * d2;\r
-  double x3 = cos(a3);\r
-  double y3 = sin(a3);\r
-  \r
-  // formula: dis = sqrt( (v1-v2)**2 - ((v1-v2)*v3)**2 ); vi = (xi,yi)\r
-  double val1   = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);\r
-  double val2   = ((x1-x2)*x3 + (y1-y2)*y3) * ((x1-x2)*x3 + (y1-y2)*y3);\r
-  double dis    = val1 - val2;\r
-  // now get sign for offset \r
-  //cout << x1 << " " << x2 << " " << y1 << " " << y2 << " " \r
-  //     << x3 << " " << y3 << " " \r
-  //     << val1 << " " << val2 << " " << dis << endl;\r
-  x3 *= sqrt(val2);\r
-  y3 *= sqrt(val2);\r
-  double da = fabs(atan2(y3,x3) - atan2(y1-y2,x1-x2));\r
-  if ( da > SGD_PI ) da -= 2*SGD_PI;\r
-  if ( fabs(da) > SGD_PI/2.) {\r
-    //if ( x3*(x1-x2) < 0.0 && y3*(y1-y2) < 0.0) {\r
-    x3 *= -1.0;\r
-    y3 *= -1.0;\r
-  }\r
-  //cout << x3 << " " << y3 << endl;\r
-  double dis1   = x1-x2-x3;\r
-  double dis2   = y1-y2-y3;\r
-  dis = sqrt(dis);\r
-  da = atan2(dis2,dis1);\r
-  if ( da < 0.0 ) da  += 2*SGD_PI;\r
-  if ( da < a3 )  dis *= -1.0;\r
-  //cout << dis1 << " " << dis2 << " " << da*SGD_RADIANS_TO_DEGREES << " " << h3\r
-  //     << " " << sqrt(dis1*dis1 + dis2*dis2) << " " << dis << endl;\r
-  //cout << atan2(dis2,dis1)*SGD_RADIANS_TO_DEGREES << " " << dis << endl;\r
-\r
-  return dis;\r
-}\r
-\r
-\r
-// ========================================================================\r
-// Calculate new bear/dist given starting bear/dis, and offset radial,\r
-// and distance.\r
-// ========================================================================\r
-void FGApproach::calc_cd_head_dist(const double &h1, const double &d1, \r
-                                  const double &course, const double &dist,\r
-                                  double *h2, double *d2)\r
-{\r
-  double a1 = h1 * SGD_DEGREES_TO_RADIANS;\r
-  double a2 = course * SGD_DEGREES_TO_RADIANS;\r
-  double x1 = cos(a1) * d1;\r
-  double y1 = sin(a1) * d1;\r
-  double x2 = cos(a2) * dist;\r
-  double y2 = sin(a2) * dist;\r
-    \r
-  *d2 = sqrt((x1+x2)*(x1+x2) + (y1+y2)*(y1+y2));\r
-  *h2 = atan2( (y1+y2), (x1+x2) ) * SGD_RADIANS_TO_DEGREES;\r
-  if ( *h2 < 0 ) *h2 = *h2+360;\r
-  }\r
-\r
-\r
-\r
-// ========================================================================\r
-// get heading and distance between two points; point1 ---> point2\r
-// ========================================================================\r
-void FGApproach::calc_hd_course_dist(const double &h1, const double &d1, \r
-                                    const double &h2, const double &d2,\r
-                                    double *course, double *dist)\r
-{\r
-  double a1 = h1 * SGD_DEGREES_TO_RADIANS;\r
-  double a2 = h2 * SGD_DEGREES_TO_RADIANS;\r
-  double x1 = cos(a1) * d1;\r
-  double y1 = sin(a1) * d1;\r
-  double x2 = cos(a2) * d2;\r
-  double y2 = sin(a2) * d2;\r
-          \r
-  *dist   = sqrt( (y2-y1)*(y2-y1) + (x2-x1)*(x2-x1) );\r
-  *course = atan2( (y2-y1), (x2-x1) ) * SGD_RADIANS_TO_DEGREES;\r
-  if ( *course < 0 ) *course = *course+360;\r
-  //cout << x1 << " " << y1 << " " << x2 << " " << y2 << " " << *dist << " " << *course << endl;\r
-}\r
-\r
-\r
-\r
-int FGApproach::RemovePlane() {\r
-\r
-  // first check if anything has to be done\r
-  bool rmplane = false;\r
-  int i;\r
-\r
-  for (i=0; i<num_planes; i++) {\r
-    if (planes[i].dist > range*SG_NM_TO_METER) {\r
-      rmplane = true;\r
-      break;\r
-    }\r
-  }\r
-  if (!rmplane) return num_planes;\r
-\r
-  // now make a copy of the plane list\r
-  PlaneApp tmp[max_planes];\r
-  for (i=0; i<num_planes; i++) {\r
-    tmp[i] = planes[i];\r
-  }\r
-  \r
-  int np = 0;\r
-  // now check which planes are still in range\r
-  for (i=0; i<num_planes; i++) {\r
-    if (tmp[i].dist <= range*SG_NM_TO_METER) {\r
-      planes[np] = tmp[i];\r
-      np += 1;\r
-    }\r
-  }\r
-  num_planes = np;\r
-\r
-  return num_planes;\r
-}\r
+// FGApproach - a class to provide approach control at larger airports.
+//
+// Written by Alexander Kappes, started March 2002.
+//
+// Copyright (C) 2002  Alexander Kappes
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include "approach.hxx"
+#include "transmission.hxx"
+#include "transmissionlist.hxx"
+#include "ATCdisplay.hxx"
+#include "ATCDialog.hxx"
+
+#include <Airports/runways.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#ifdef FG_WEATHERCM
+# include <WeatherCM/FGLocalWeatherDatabase.h>
+#else
+# include <Environment/environment_mgr.hxx>
+# include <Environment/environment.hxx>
+#endif
+
+
+#include <GUI/gui.h>
+
+//Constructor
+FGApproach::FGApproach(){
+  comm1_node = fgGetNode("/radios/comm[0]/frequencies/selected-mhz", true);
+  comm2_node = fgGetNode("/radios/comm[1]/frequencies/selected-mhz", true);
+
+  num_planes = 0;
+  lon_node   = fgGetNode("/position/longitude-deg", true);
+  lat_node   = fgGetNode("/position/latitude-deg", true);
+  elev_node  = fgGetNode("/position/altitude-ft", true);
+  hdg_node   = fgGetNode("/orientation/heading-deg", true);
+  speed_node = fgGetNode("/velocities/airspeed-kt", true);
+  etime_node = fgGetNode("/sim/time/elapsed-ms", true);
+
+  first = true;
+  active_runway = "";
+  int i;
+  for ( i=0; i<max_planes; i++) {
+    planes[i].contact   = 0;
+    planes[i].wpn       = 0;
+    planes[i].dnwp      = -999.;
+    planes[i].on_crs    = true;
+    planes[i].turn_rate = 10.0;
+    planes[i].desc_rate = 1000.0;
+    planes[i].clmb_rate = 500.0;
+    planes[i].tlm       = 0.0;
+    planes[i].lmc.c1    = 0;
+    planes[i].lmc.c2    = 0;
+    planes[i].lmc.c3    = -1;
+    planes[i].wp_change = false;
+  }
+}
+
+//Destructor
+FGApproach::~FGApproach(){
+}
+
+void FGApproach::Init() {
+  display    = false;
+}
+
+
+
+// ============================================================================
+// the main update function
+// ============================================================================
+void FGApproach::Update() {
+       
+       const int max_trans = 20;
+       FGTransmission tmissions[max_trans];
+       int    wpn;
+       int    station = 1;
+       TransCode code;
+       TransPar TPar;
+       int    i,j;
+       //double course, d, 
+       double adif, datp;
+       //char   buf[10];
+       string message;
+       //static string atcmsg1[10];
+       //static string atcmsg2[10];
+       string mentry;
+       string transm;
+       TransPar tpars;
+       //static bool TransDisplayed = false;
+       
+       update_plane_dat();
+       if ( active_runway == "" ) get_active_runway();
+       
+       double comm1_freq = comm1_node->getDoubleValue();
+       
+       //bool DisplayTransmissions = true;
+       
+       for (i=0; i<num_planes; i++) {
+               if ( planes[i].ident == "Player") { 
+                       station = 1;
+                       tpars.station = name;
+                       tpars.callsign = "Player";
+                       tpars.airport = ident;
+                       
+                       int num_trans = 0;
+                       // is the frequency of the station tuned in?
+                       if ( freq == (int)(comm1_freq*100.0 + 0.5) ) {
+                               current_transmissionlist->query_station( station, tmissions, max_trans, num_trans );
+                               // loop over all transmissions for station
+                               for ( j=0; j<=num_trans-1; j++ ) {
+                                       code = tmissions[j].get_code();
+                                       // select proper transmissions
+                                       if ( ( code.c2 == -1 && planes[i].lmc.c3 == 0 ) || 
+                                               ( code.c1 == 0  && code.c2 == planes[i].lmc.c2 ) ) {
+                                               mentry = current_transmissionlist->gen_text(station, code, tpars, false);
+                                               transm = current_transmissionlist->gen_text(station, code, tpars, true);
+                                               // is the transmission already registered?
+                                               if (!current_atcdialog->trans_reg( ident, transm )) {
+                                                       current_atcdialog->add_entry( ident, transm, mentry );
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       for ( i=0; i<num_planes; i++ ) {
+               
+               if ( planes[i].ident == TPar.callsign && name == TPar.airport && TPar.station == "approach" ) {
+                       
+                       if ( TPar.request && TPar.intention == "landing" && ident == TPar.intid) {
+                               planes[i].wpn = 0; 
+                               // ===========================
+                               // === calculate waypoints ===
+                               // ===========================
+                               calc_wp( i );  
+                               update_param( i );
+                               wpn = planes[i].wpn-1;
+                               planes[i].aalt = planes[i].wpts[wpn-1][2];
+                               planes[i].ahdg = planes[i].wpts[wpn][4];
+                               
+                               // generate the message
+                               code.c1 = 1;
+                               code.c2 = 1;
+                               code.c3 = 0;
+                               adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );
+                               tpars.station = name;
+                               tpars.callsign = "Player";
+                               if ( adif < 0 ) tpars.tdir = 1;
+                               else            tpars.tdir = 2;
+                               tpars.heading = planes[i].ahdg;
+                               if      (planes[i].alt-planes[i].aalt > 100.0)  tpars.VDir = 1;
+                               else if (planes[i].alt-planes[i].aalt < -100.0) tpars.VDir = 3;
+                               else tpars.VDir = 2;
+                               tpars.alt = planes[i].aalt;
+                               message = current_transmissionlist->gen_text(station, code, tpars, true );
+                               globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                               planes[i].lmc = code;
+                               planes[i].tlm = etime_node->getDoubleValue();
+                               planes[i].on_crs = true;
+                               planes[i].contact = 1;
+                       }
+               }
+               
+               if ( planes[i].contact == 1 ) {
+                       // =========================
+                       // === update parameters ===
+                       // =========================
+                       update_param( i );
+                       //cout << planes[i].brg << " " << planes[i].dist << " " << planes[i].wpts[wpn+1][0] 
+                       //<< " " << planes[i].wpts[wpn+1][1] << " " << planes[i].wpts[wpn+1][4] 
+                       //cout << wpn << " distance to current course = " << planes[i].dcc << endl;
+                       //cout << etime_node->getDoubleValue() << endl;
+                       
+                       // =========================
+                       // === reached waypoint? ===
+                       // =========================
+                       wpn = planes[i].wpn-2;
+                       adif = angle_diff_deg( planes[i].hdg, planes[i].wpts[wpn][4] ) 
+                       * SGD_DEGREES_TO_RADIANS;
+                       datp = 2*sin(fabs(adif)/2.0)*sin(fabs(adif)/2.0) *
+                       planes[i].spd/3600. * planes[i].turn_rate + 
+                       planes[i].spd/3600. * 3.0;
+                       //cout << adif/SGD_DEGREES_TO_RADIANS << " " 
+                       //     << datp << " " << planes[i].dnc << " " << planes[i].dcc <<endl;
+                       if ( fabs(planes[i].dnc) < datp ) {
+                       //if ( fabs(planes[i].dnc) < 0.3 && planes[i].dnwp < 1.0 ) {
+                               planes[i].wpn -= 1;
+                               wpn = planes[i].wpn-1;
+                               planes[i].ahdg = planes[i].wpts[wpn][4];
+                               planes[i].aalt = planes[i].wpts[wpn-1][2];
+                               planes[i].wp_change = true;
+                               
+                               // generate the message
+                               adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );
+                               tpars.station = name;
+                               tpars.callsign = "Player";
+                               if ( adif < 0 ) tpars.tdir = 1;
+                               else            tpars.tdir = 2;
+                               tpars.heading = planes[i].ahdg;
+                               
+                               if ( wpn-1 != 0) { 
+                                       code.c1 = 1;
+                                       code.c2 = 1;
+                                       code.c3 = 0;
+                                       if      (planes[i].alt-planes[i].aalt > 100.0)  tpars.VDir = 1;
+                                       else if (planes[i].alt-planes[i].aalt < -100.0) tpars.VDir = 3;
+                                       else tpars.VDir = 2;
+                                       tpars.alt = planes[i].aalt;
+                                       message = current_transmissionlist->gen_text(station, code, tpars, true );
+                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                                       
+                               }
+                               else {
+                                       code.c1 = 1;
+                                       code.c2 = 3;
+                                       code.c3 = 0;
+                                       tpars.runway = active_runway;
+                                       message = current_transmissionlist->gen_text(station, code, tpars, true);
+                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                               }
+                               planes[i].lmc = code;
+                               planes[i].tlm = etime_node->getDoubleValue();
+                               planes[i].on_crs = true;
+                               
+                               update_param( i );
+                       }
+                       
+                       // =========================
+                       // === come off course ? ===
+                       // =========================
+                       if ( fabs(planes[i].dcc) > 1.0 && 
+                               ( !planes[i].wp_change || 
+                       etime_node->getDoubleValue() - planes[i].tlm > tbm ) ) {
+                               if ( planes[i].on_crs ) {
+                                       if ( planes[i].dcc < 0) {
+                                               planes[i].ahdg += 30.0;
+                                       }
+                                       else {
+                                               planes[i].ahdg -= 30.0;
+                                       }
+                                       if (planes[i].ahdg > 360.0) planes[i].ahdg -= 360.0;
+                                       else if (planes[i].ahdg < 0.0) planes[i].ahdg += 360.0;
+                               }
+                               //cout << planes[i].on_crs << " " 
+                               //     << angle_diff_deg( planes[i].hdg, planes[i].ahdg) << " "
+                               //     << etime_node->getDoubleValue() << " "
+                               //     << planes[i].tlm << endl;
+                               // generate the message
+                               if ( planes[i].on_crs || 
+                                       ( fabs(angle_diff_deg( planes[i].hdg, planes[i].ahdg )) >  30.0  && 
+                               etime_node->getDoubleValue() - planes[i].tlm > tbm) ) {
+                                       // generate the message
+                                       code.c1 = 1;
+                                       code.c2 = 4;
+                                       code.c3 = 0;
+                                       adif = angle_diff_deg( planes[i].hdg, planes[i].ahdg );
+                                       tpars.station = name;
+                                       tpars.callsign = "Player";
+                                       tpars.miles   = fabs(planes[i].dcc);
+                                       if ( adif < 0 ) tpars.tdir = 1;
+                                       else            tpars.tdir = 2;
+                                       tpars.heading = planes[i].ahdg;
+                                       message = current_transmissionlist->gen_text(station, code, tpars, true);
+                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                                       planes[i].lmc = code;
+                                       planes[i].tlm = etime_node->getDoubleValue();
+                               }
+                               
+                               planes[i].on_crs = false;
+                       }
+                       else if ( !planes[i].on_crs ) {
+                               wpn = planes[i].wpn-1;
+                               adif = angle_diff_deg( planes[i].hdg, planes[i].wpts[wpn][4] ) 
+                               * SGD_DEGREES_TO_RADIANS;
+                               datp = 2*sin(fabs(adif)/2.0)*sin(fabs(adif)/2.0) *
+                               planes[i].spd/3600. * planes[i].turn_rate + 
+                               planes[i].spd/3600. * 3.0;
+                               if ( fabs(planes[i].dcc) < datp ) { 
+                                       planes[i].ahdg = fabs(planes[i].wpts[wpn][4]);
+                                       
+                                       // generate the message
+                                       code.c1 = 1;
+                                       code.c2 = 2;
+                                       code.c3 = 0;
+                                       tpars.station = name;
+                                       tpars.callsign = "Player";
+                                       if ( adif < 0 ) tpars.tdir = 1;
+                                       else            tpars.tdir = 2;
+                                       tpars.heading = planes[i].ahdg;
+                                       message = current_transmissionlist->gen_text(station, code, tpars, true);
+                                       globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                                       planes[i].lmc = code;
+                                       planes[i].tlm = etime_node->getDoubleValue();
+                                       
+                                       planes[i].on_crs = true;          
+                               } 
+                       }
+                       else if ( planes[i].wp_change  ) {
+                               planes[i].wp_change = false;
+                       }
+                       
+                       // ===================================================================
+                       // === Less than two minutes away from touchdown? -> Contact Tower ===
+                       // ===================================================================
+                       if ( planes[i].wpn == 2 && planes[i].dnwp < planes[i].spd/60.*2.0 ) {
+                               
+                               double freq = 121.95;
+                               // generate message
+                               code.c1 = 1;
+                               code.c2 = 5;
+                               code.c3 = 0;
+                               tpars.station = name;
+                               tpars.callsign = "Player";
+                               tpars.freq    = freq;
+                               message = current_transmissionlist->gen_text(station, code, tpars, true);
+                               globals->get_ATC_display()->RegisterSingleMessage( message, 0 );
+                               planes[i].lmc = code;
+                               planes[i].tlm = etime_node->getDoubleValue();
+                               
+                               planes[i].contact = 2;
+                       }
+               }
+       }
+       
+}
+
+
+// ============================================================================
+// update course parameters
+// ============================================================================
+void FGApproach::update_param( const int &i ) {
+  
+  double course, d;
+
+  int wpn = planes[i].wpn-1;            // this is the current waypoint
+
+  planes[i].dcc  = calc_psl_dist(planes[i].brg, planes[i].dist,
+                                planes[i].wpts[wpn][0], planes[i].wpts[wpn][1],
+                                planes[i].wpts[wpn][4]);
+  planes[i].dnc  = calc_psl_dist(planes[i].brg, planes[i].dist,
+                                planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+                                planes[i].wpts[wpn-1][4]);
+  calc_hd_course_dist(planes[i].brg, planes[i].dist, 
+                     planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+                     &course, &d);
+  planes[i].dnwp = d;
+
+}
+
+// ============================================================================
+// smallest difference between two angles in degree
+// difference is negative if a1 > a2 and positive if a2 > a1
+// ===========================================================================
+double FGApproach::angle_diff_deg( const double &a1, const double &a2) {
+  
+  double a3 = a2 - a1;
+  if (a3 < 180.0) a3 += 360.0;
+  if (a3 > 180.0) a3 -= 360.0;
+
+  return a3;
+}
+
+// ============================================================================
+// calculate waypoints
+// ============================================================================
+void FGApproach::calc_wp( const int &i ) {
+       
+       int j;
+       double course, d, cd, a1;
+       
+       int wpn = planes[i].wpn;
+       // waypoint 0: Threshold of active runway
+       calc_gc_course_dist(Point3D(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0.0),
+       Point3D(active_rw_lon*SGD_DEGREES_TO_RADIANS,active_rw_lat*SGD_DEGREES_TO_RADIANS, 0.0 ),
+       &course, &d);
+       double d1 = active_rw_hdg+180.0;
+       if ( d1 > 360.0 ) d1 -=360.0;
+       calc_cd_head_dist(360.0-course*SGD_RADIANS_TO_DEGREES, d/SG_NM_TO_METER, 
+       d1, active_rw_len/SG_NM_TO_METER/2., 
+       &planes[i].wpts[wpn][0], &planes[i].wpts[wpn][1]);
+       planes[i].wpts[wpn][2] = elev;
+       planes[i].wpts[wpn][4] = 0.0;
+       planes[i].wpts[wpn][5] = 0.0;
+       wpn += 1;
+       
+       // ======================
+       // horizontal navigation
+       // ======================
+       // waypoint 1: point for turning onto final
+       calc_cd_head_dist(planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1] , 
+       d1, lfl,
+       &planes[i].wpts[wpn][0], &planes[i].wpts[wpn][1]);
+       calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],
+       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+       &course, &d);
+       planes[i].wpts[wpn][4] = course;
+       planes[i].wpts[wpn][5] = d;
+       wpn += 1;
+       
+       // calculate course and distance from plane position to waypoint 1
+       calc_hd_course_dist(planes[i].brg, planes[i].dist,
+       planes[i].wpts[1][0], planes[i].wpts[1][1],
+       &course, &d);
+       // check if airport is not between plane and waypoint 1 and
+       // DCA to airport on course to waypoint 1 is larger than 10 miles
+       double zero = 0.0;
+       if ( fabs(angle_diff_deg( planes[i].wpts[1][0], planes[i].brg  )) < 90.0 ||
+               calc_psl_dist( zero, zero, planes[i].brg, planes[i].dist, course ) > 10.0 ) {
+               // check if turning angle at waypoint 1 would be > max_ta
+               if ( fabs(angle_diff_deg( planes[i].wpts[1][4], course )) > max_ta ) {
+                       cd = calc_psl_dist(planes[i].brg, planes[i].dist,
+                       planes[i].wpts[1][0], planes[i].wpts[1][1],
+                       planes[i].wpts[1][4]);
+                       a1 = atan2(cd,planes[i].wpts[1][1]);
+                       planes[i].wpts[wpn][0] = planes[i].wpts[1][0] - a1/SGD_DEGREES_TO_RADIANS;
+                       if ( planes[i].wpts[wpn][0] < 0.0)   planes[i].wpts[wpn][0] += 360.0;   
+                       if ( planes[i].wpts[wpn][0] > 360.0) planes[i].wpts[wpn][0] -= 360.0;   
+                       planes[i].wpts[wpn][1] = fabs(cd) / sin(fabs(a1));
+                       calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],
+                       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+                       &course, &d);
+                       planes[i].wpts[wpn][4] = course;
+                       planes[i].wpts[wpn][5] = d;
+                       wpn += 1;
+                       
+                       calc_hd_course_dist(planes[i].brg, planes[i].dist,
+                       planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+                       &course, &d);
+               }
+       } else {
+               double leg = 10.0;
+               a1 = atan2(planes[i].wpts[1][1], leg );
+               
+               if ( angle_diff_deg(planes[i].brg,planes[i].wpts[1][0]) < 0 ) 
+                       planes[i].wpts[wpn][0] = planes[i].wpts[1][0] + a1/SGD_DEGREES_TO_RADIANS;
+               else planes[i].wpts[wpn][0] = planes[i].wpts[1][0] - a1/SGD_DEGREES_TO_RADIANS;
+               
+               planes[i].wpts[wpn][1] = sqrt( planes[i].wpts[1][1]*planes[i].wpts[1][1] + leg*leg );
+               calc_hd_course_dist(planes[i].wpts[wpn][0],   planes[i].wpts[wpn][1],
+               planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+               &course, &d);
+               planes[i].wpts[wpn][4] = course;
+               planes[i].wpts[wpn][5] = d;
+               wpn += 1;
+               
+               calc_hd_course_dist(planes[i].brg, planes[i].dist,
+               planes[i].wpts[wpn-1][0], planes[i].wpts[wpn-1][1],
+               &course, &d);
+       }
+       
+       planes[i].wpts[wpn][0] = planes[i].brg;
+       planes[i].wpts[wpn][1] = planes[i].dist;
+       planes[i].wpts[wpn][2] = planes[i].alt;
+       planes[i].wpts[wpn][4] = course;
+       planes[i].wpts[wpn][5] = d;
+       wpn += 1;
+       
+       planes[i].wpn = wpn;
+       
+       // Now check if legs are too short or if legs can be shortend
+       // legs must be at least 2 flight minutes long
+       double mdist = planes[i].spd / 60.0 * 2.0;
+       for ( j=2; j<wpn-1; ++j ) {
+               if ( planes[i].wpts[j][1] < mdist) {
+               }
+       }
+       
+       // ====================
+       // vertical navigation
+       // ====================
+       double alt = elev+3000.0;
+       planes[i].wpts[1][2] = round_alt( true, alt );
+       for ( j=2; j<wpn-1; ++j ) {
+               double dalt = planes[i].alt - planes[i].wpts[j-1][2];
+               if ( dalt > 0 ) {
+                       alt = planes[i].wpts[j-1][2] + 
+                       (planes[i].wpts[j][5] / planes[i].spd) * 60.0 * planes[i].desc_rate;
+                       planes[i].wpts[j][2] = round_alt( false, alt );
+                       if ( planes[i].wpts[j][2] > planes[i].alt ) 
+                               planes[i].wpts[j][2] = round_alt( false, planes[i].alt );
+               }
+               else {
+                       planes[i].wpts[j][2] = planes[i].wpts[1][2];
+               }
+       }
+       
+       cout << "Plane position: " << planes[i].brg << " " << planes[i].dist << endl;
+       for ( j=0; j<wpn; ++j ) {
+               cout << "Waypoint " << j << endl;
+               cout << "------------------" << endl;
+               cout << planes[i].wpts[j][0] << "   " << planes[i].wpts[j][1]
+               << "   " << planes[i].wpts[j][2] << "   " << planes[i].wpts[j][5]; 
+               cout << endl << endl;
+       }
+       
+}
+
+
+// ============================================================================
+// round altitude value to next highest/lowest 500 feet
+// ============================================================================
+double FGApproach::round_alt( const bool hl, double alt ) {
+
+  alt = alt/1000.0;
+  if ( hl ) {
+    if ( alt > (int)(alt)+0.5 ) alt = ((int)(alt)+1)*1000.0;
+    else alt = ((int)(alt)+0.5)*1000.0;
+  }
+  else {
+    if ( alt > (int)(alt)+0.5 ) alt = ((int)(alt)+0.5)*1000.0;
+    else alt = ((int)(alt))*1000.0;
+  }
+  
+  return alt;
+}
+
+
+// ============================================================================
+// get active runway
+// ============================================================================
+void FGApproach::get_active_runway() {
+
+#ifdef FG_WEATHERCM
+  sgVec3 position = { lat, lon, elev };
+  FGPhysicalProperty stationweather = WeatherDatabase->get(position);
+#else
+  FGEnvironment stationweather =
+    globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
+#endif
+
+  SGPath path( globals->get_fg_root() );
+  path.append( "Airports" );
+  path.append( "runways.mk4" );
+  FGRunways runways( path.c_str() );
+  
+#ifdef FG_WEATHERCM
+  //Set the heading to into the wind
+  double wind_x = stationweather.Wind[0];
+  double wind_y = stationweather.Wind[1];
+  
+  double speed = sqrt( wind_x*wind_x + wind_y*wind_y ) * SG_METER_TO_NM / (60.0*60.0);
+  double hdg;
+  
+  //If no wind use 270degrees
+  if(speed == 0) {
+    hdg = 270;
+  } else {
+    // //normalize the wind to get the direction
+    //wind_x /= speed; wind_y /= speed;
+    
+    hdg = - atan2 ( wind_x, wind_y ) * SG_RADIANS_TO_DEGREES ;
+    if (hdg < 0.0)
+      hdg += 360.0;
+  }
+#else
+  double hdg = stationweather.get_wind_from_heading_deg();
+#endif
+  
+  FGRunway runway;
+  if ( runways.search( ident, int(hdg), &runway) ) {
+    active_runway = runway.rwy_no;
+    active_rw_hdg = runway.heading;
+    active_rw_lon = runway.lon;
+    active_rw_lat = runway.lat;
+    active_rw_len = runway.length;
+    //cout << "Active runway is: " << active_runway << "  heading = " 
+    // << active_rw_hdg 
+    // << " lon = " << active_rw_lon 
+    // << " lat = " << active_rw_lat <<endl;
+  }
+  else cout << "FGRunways search failed\n";
+
+}
+
+// ========================================================================
+// update infos about plane
+// ========================================================================
+void FGApproach::update_plane_dat() {
+  
+  //cout << "Update Approach " << ident << "   " << num_planes << " registered" << endl;
+  // update plane positions
+  int i;
+  for (i=0; i<num_planes; i++) {
+    planes[i].lon = lon_node->getDoubleValue();
+    planes[i].lat = lat_node->getDoubleValue();
+    planes[i].alt = elev_node->getDoubleValue();
+    planes[i].hdg = hdg_node->getDoubleValue();
+    planes[i].spd = speed_node->getDoubleValue();
+
+    /*Point3D aircraft = sgGeodToCart( Point3D(planes[i].lon*SGD_DEGREES_TO_RADIANS, 
+                                            planes[i].lat*SGD_DEGREES_TO_RADIANS, 
+                                            planes[i].alt*SG_FEET_TO_METER) );*/
+    double course, distance;
+    calc_gc_course_dist(Point3D(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0.0),
+                       Point3D(planes[i].lon*SGD_DEGREES_TO_RADIANS,planes[i].lat*SGD_DEGREES_TO_RADIANS, 0.0 ),
+                       &course, &distance);
+    planes[i].dist = distance/SG_NM_TO_METER;
+    planes[i].brg  = 360.0-course*SGD_RADIANS_TO_DEGREES;
+
+    //cout << "Plane Id: " << planes[i].ident << "  Distance to " << ident 
+    // << " is " << planes[i].dist << " miles   " << "Bearing " << planes[i].brg << endl;
+    
+  }   
+}
+
+// =======================================================================
+// Add plane to Approach list
+// =======================================================================
+void FGApproach::AddPlane(string pid) {
+
+  int i;
+  for ( i=0; i<num_planes; i++) {
+    if ( planes[i].ident == pid) {
+      //cout << "Plane already registered: " << ident << " " << num_planes << endl;
+      return;
+    }
+  }
+  planes[num_planes].ident = pid;
+  ++num_planes;
+  //cout << "Plane added to list: " << ident << " " << num_planes << endl;
+  return;
+}
+
+// ================================================================================
+// closest distance between a point (h1,d1) and a straigt line (h2,d2,h3) in 2 dim.
+// ================================================================================
+double FGApproach::calc_psl_dist(const double &h1, const double &d1,
+                                const double &h2, const double &d2,
+                                const double &h3)
+{
+  double a1 = h1 * SGD_DEGREES_TO_RADIANS;
+  double a2 = h2 * SGD_DEGREES_TO_RADIANS;
+  double a3 = h3 * SGD_DEGREES_TO_RADIANS;
+  double x1 = cos(a1) * d1;
+  double y1 = sin(a1) * d1;
+  double x2 = cos(a2) * d2;
+  double y2 = sin(a2) * d2;
+  double x3 = cos(a3);
+  double y3 = sin(a3);
+  
+  // formula: dis = sqrt( (v1-v2)**2 - ((v1-v2)*v3)**2 ); vi = (xi,yi)
+  double val1   = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
+  double val2   = ((x1-x2)*x3 + (y1-y2)*y3) * ((x1-x2)*x3 + (y1-y2)*y3);
+  double dis    = val1 - val2;
+  // now get sign for offset 
+  //cout << x1 << " " << x2 << " " << y1 << " " << y2 << " " 
+  //     << x3 << " " << y3 << " " 
+  //     << val1 << " " << val2 << " " << dis << endl;
+  x3 *= sqrt(val2);
+  y3 *= sqrt(val2);
+  double da = fabs(atan2(y3,x3) - atan2(y1-y2,x1-x2));
+  if ( da > SGD_PI ) da -= 2*SGD_PI;
+  if ( fabs(da) > SGD_PI/2.) {
+    //if ( x3*(x1-x2) < 0.0 && y3*(y1-y2) < 0.0) {
+    x3 *= -1.0;
+    y3 *= -1.0;
+  }
+  //cout << x3 << " " << y3 << endl;
+  double dis1   = x1-x2-x3;
+  double dis2   = y1-y2-y3;
+  dis = sqrt(dis);
+  da = atan2(dis2,dis1);
+  if ( da < 0.0 ) da  += 2*SGD_PI;
+  if ( da < a3 )  dis *= -1.0;
+  //cout << dis1 << " " << dis2 << " " << da*SGD_RADIANS_TO_DEGREES << " " << h3
+  //     << " " << sqrt(dis1*dis1 + dis2*dis2) << " " << dis << endl;
+  //cout << atan2(dis2,dis1)*SGD_RADIANS_TO_DEGREES << " " << dis << endl;
+
+  return dis;
+}
+
+
+// ========================================================================
+// Calculate new bear/dist given starting bear/dis, and offset radial,
+// and distance.
+// ========================================================================
+void FGApproach::calc_cd_head_dist(const double &h1, const double &d1, 
+                                  const double &course, const double &dist,
+                                  double *h2, double *d2)
+{
+  double a1 = h1 * SGD_DEGREES_TO_RADIANS;
+  double a2 = course * SGD_DEGREES_TO_RADIANS;
+  double x1 = cos(a1) * d1;
+  double y1 = sin(a1) * d1;
+  double x2 = cos(a2) * dist;
+  double y2 = sin(a2) * dist;
+    
+  *d2 = sqrt((x1+x2)*(x1+x2) + (y1+y2)*(y1+y2));
+  *h2 = atan2( (y1+y2), (x1+x2) ) * SGD_RADIANS_TO_DEGREES;
+  if ( *h2 < 0 ) *h2 = *h2+360;
+  }
+
+
+
+// ========================================================================
+// get heading and distance between two points; point1 ---> point2
+// ========================================================================
+void FGApproach::calc_hd_course_dist(const double &h1, const double &d1, 
+                                    const double &h2, const double &d2,
+                                    double *course, double *dist)
+{
+  double a1 = h1 * SGD_DEGREES_TO_RADIANS;
+  double a2 = h2 * SGD_DEGREES_TO_RADIANS;
+  double x1 = cos(a1) * d1;
+  double y1 = sin(a1) * d1;
+  double x2 = cos(a2) * d2;
+  double y2 = sin(a2) * d2;
+          
+  *dist   = sqrt( (y2-y1)*(y2-y1) + (x2-x1)*(x2-x1) );
+  *course = atan2( (y2-y1), (x2-x1) ) * SGD_RADIANS_TO_DEGREES;
+  if ( *course < 0 ) *course = *course+360;
+  //cout << x1 << " " << y1 << " " << x2 << " " << y2 << " " << *dist << " " << *course << endl;
+}
+
+
+
+int FGApproach::RemovePlane() {
+
+  // first check if anything has to be done
+  bool rmplane = false;
+  int i;
+
+  for (i=0; i<num_planes; i++) {
+    if (planes[i].dist > range*SG_NM_TO_METER) {
+      rmplane = true;
+      break;
+    }
+  }
+  if (!rmplane) return num_planes;
+
+  // now make a copy of the plane list
+  PlaneApp tmp[max_planes];
+  for (i=0; i<num_planes; i++) {
+    tmp[i] = planes[i];
+  }
+  
+  int np = 0;
+  // now check which planes are still in range
+  for (i=0; i<num_planes; i++) {
+    if (tmp[i].dist <= range*SG_NM_TO_METER) {
+      planes[np] = tmp[i];
+      np += 1;
+    }
+  }
+  num_planes = np;
+
+  return num_planes;
+}
index cdd06a68c20c1dff3e336818023e5cd9179e0319..debcd77d33eca318064f9e80f897edbb545c780d 100644 (file)
-// approach.hxx -- Approach class\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-//\r
-// Copyright (C) 2002  Alexander Kappes\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-\r
-\r
-#ifndef _FG_APPROACH_HXX\r
-#define _FG_APPROACH_HXX\r
-\r
-#include <stdio.h>\r
-\r
-#include <simgear/compiler.h>\r
-#include <simgear/math/sg_geodesy.hxx>\r
-#include <simgear/misc/sgstream.hxx>\r
-#include <simgear/magvar/magvar.hxx>\r
-#include <simgear/timing/sg_time.hxx>\r
-#include <simgear/bucket/newbucket.hxx>\r
-\r
-#include <Main/fg_props.hxx>\r
-\r
-#ifdef SG_HAVE_STD_INCLUDES\r
-#  include <istream>\r
-#include <iomanip>\r
-#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )\r
-#  include <iostream.h>\r
-#elif defined( __BORLANDC__ )\r
-#  include <iostream>\r
-#else\r
-#  include <istream.h>\r
-#include <iomanip.h>\r
-#endif\r
-\r
-#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )\r
-SG_USING_STD(istream);\r
-#endif\r
-\r
-SG_USING_STD(string);\r
-\r
-#include "ATC.hxx"\r
-#include "transmission.hxx"\r
-\r
-//DCL - a complete guess for now.\r
-#define FG_APPROACH_DEFAULT_RANGE 100\r
-\r
-// Contains all the information about a plane that the approach control needs\r
-const int    max_planes = 20;  // max number of planes on the stack\r
-const int    max_wp = 10;      // max number of waypoints for approach phase\r
-const double max_ta = 130;     // max turning angle for plane during approach\r
-const double tbm    = 20000.0; // min time (in ms) between two messages\r
-const double lfl    = 10.0;    // length of final leg\r
-\r
-struct PlaneApp {\r
-\r
-  // variables for plane if it's on the radar\r
-  string ident;          // indentification of plane\r
-  double lon;            // longitude in degrees\r
-  double lat;            // latitude in degrees\r
-  double alt;            // Altitute above sea level in feet\r
-  double hdg;            // heading of plane in degrees\r
-  double dist;           // distance to airport in miles\r
-  double brg;            // bearing relative to airport in degrees\r
-  double spd;            // speed above ground\r
-  int    contact;        // contact with approach established?\r
-                         // 0 = no contact yet\r
-                         // 1 = in contact\r
-                         // 2 = handed off to tower\r
-  double turn_rate;      // standard turning rate of the plane in seconds per degree\r
-  double desc_rate;      // standard descent rate of the plane in feets per minute\r
-  double clmb_rate;      // standard climb rate of the plane in feets per minute\r
-\r
-  // additional variables if contact has been established\r
-  int    wpn;                 // number of waypoints\r
-  double wpts[max_wp][6];     // assigned waypoints for approach phase \r
-                              // first wp in list is airport\r
-                              // last waypoint point at which contact was established\r
-                              // second index: 0 = bearing to airport\r
-                              // second index: 1 = distance to airport\r
-                              // second index: 2 = alt \r
-                              // second index: 3 = ETA\r
-                              // second index: 4 = heading to next waypoint\r
-                              // second index: 5 = distance to next waypoint\r
-\r
-  double dnwp;           // distance to next waypoint\r
-  double dcc;            // closest distance to current assigned course\r
-  double dnc;            // closest distance to course from next to next to next wp\r
-  double aalt;           // assigned altitude\r
-  double ahdg;           // assigned heading\r
-  bool   on_crs;         // is the plane on course?\r
-  bool   wp_change;      // way point has changed\r
-  double tlm;            // time when last message was sent\r
-  TransCode lmc;         // code of last message\r
-};\r
-\r
-\r
-class FGApproach : public FGATC {\r
-\r
-  int      bucket;\r
-\r
-  string active_runway;         \r
-  double active_rw_hdg;\r
-  double active_rw_lon;\r
-  double active_rw_lat;\r
-  double active_rw_len;\r
-\r
-  bool     display;            // Flag to indicate whether we should be outputting to the display.\r
-  bool     displaying;         // Flag to indicate whether we are outputting to the display.\r
-  int      num_planes;          // number of planes on the stack\r
-  PlaneApp planes[max_planes];  // Array of planes\r
-  string   transmission;\r
-  bool     first;\r
-\r
-  SGPropertyNode *comm1_node;\r
-  SGPropertyNode *comm2_node;\r
-\r
-  SGPropertyNode *atcmenu_node;\r
-  SGPropertyNode *atcopt0_node;\r
-  SGPropertyNode *atcopt1_node;\r
-  SGPropertyNode *atcopt2_node;\r
-  SGPropertyNode *atcopt3_node;\r
-  SGPropertyNode *atcopt4_node;\r
-  SGPropertyNode *atcopt5_node;\r
-  SGPropertyNode *atcopt6_node;\r
-  SGPropertyNode *atcopt7_node;\r
-  SGPropertyNode *atcopt8_node;\r
-  SGPropertyNode *atcopt9_node;\r
-\r
-  // for failure modeling\r
-  string trans_ident;  // transmitted ident\r
-  bool approach_failed;        // approach failed?\r
-\r
-public:\r
-\r
-  FGApproach(void);\r
-  ~FGApproach(void);\r
-\r
-  void Init();\r
-\r
-  void Update();\r
-\r
-  // Add new plane to stack if not already registered \r
-  // Input:  pid - id of plane (name) \r
-  // Output: "true" if added; "false" if already existend\r
-  void AddPlane(string pid);\r
-\r
-  // Remove plane from stack if out of range\r
-  int RemovePlane();\r
-  \r
-  //Indicate that this instance should be outputting to the ATC display\r
-  inline void SetDisplay(void) {display = true;}\r
-  \r
-  //Indicate that this instance should not be outputting to the ATC display\r
-  inline void SetNoDisplay(void) {display = false;}\r
-  \r
-  inline double get_bucket() const { return bucket; }\r
-  inline int get_pnum() const { return num_planes; }\r
-  inline string get_trans_ident() { return trans_ident; }\r
-  inline atc_type GetType() { return APPROACH; }\r
-  \r
-private:\r
-\r
-  void calc_wp( const int &i);\r
-\r
-  void update_plane_dat();\r
-\r
-  void get_active_runway();\r
-\r
-  void update_param(const int &i);\r
-\r
-  double round_alt( bool hl, double alt );\r
-\r
-  double angle_diff_deg( const double &a1, const double &a2);\r
-\r
-// ========================================================================\r
-// get point2 given starting point1 and course and distance\r
-// input:  point1 = heading in degrees, distance\r
-// input:  course in degrees, distance\r
-// output: point2 = heading in degrees, distance\r
-// ========================================================================\r
-  void calc_cd_head_dist(const double &h1, const double &d1,\r
-                        const double &course, const double &dist,\r
-                        double *h2, double *d2);\r
-\r
-\r
-// ========================================================================\r
-// get heading and distance between two points; point2 ---> point1\r
-// input:  point1 = heading in degrees, distance\r
-// input:  point2 = heading in degrees, distance\r
-// output: course in degrees, distance\r
-// ========================================================================\r
-  void calc_hd_course_dist(const double &h1, const double &d1,\r
-                          const double &h2, const double &d2,\r
-                          double *course, double *dist);\r
-\r
-\r
-\r
-// ========================================================================\r
-// closest distance between a point and a straigt line in 2 dim.\r
-// the input variables are given in (heading, distance) \r
-// relative to a common point\r
-// input:  point        = heading in degrees, distance\r
-// input:  straigt line = anker vector (heading in degrees, distance), \r
-//                        heading of direction vector\r
-// output: distance\r
-// ========================================================================\r
-  double calc_psl_dist(const double &h1, const double &d1,\r
-                      const double &h2, const double &d2,\r
-                      const double &h3);\r
-\r
-  // Pointers to current users position\r
-  SGPropertyNode *lon_node;\r
-  SGPropertyNode *lat_node;\r
-  SGPropertyNode *elev_node;\r
-  SGPropertyNode *hdg_node;\r
-  SGPropertyNode *speed_node;\r
-  SGPropertyNode *etime_node;\r
-  \r
-  //Update the transmission string\r
-  void UpdateTransmission(void);\r
-  \r
-  friend istream& operator>> ( istream&, FGApproach& );\r
-};\r
-\r
-#endif // _FG_APPROACH_HXX\r
+// approach.hxx -- Approach class
+//
+// Written by Alexander Kappes, started March 2002.
+//
+// Copyright (C) 2002  Alexander Kappes
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#ifndef _FG_APPROACH_HXX
+#define _FG_APPROACH_HXX
+
+#include <stdio.h>
+
+#include <simgear/compiler.h>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/magvar/magvar.hxx>
+#include <simgear/timing/sg_time.hxx>
+#include <simgear/bucket/newbucket.hxx>
+
+#include <Main/fg_props.hxx>
+
+#ifdef SG_HAVE_STD_INCLUDES
+#  include <istream>
+#include <iomanip>
+#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )
+#  include <iostream.h>
+#elif defined( __BORLANDC__ )
+#  include <iostream>
+#else
+#  include <istream.h>
+#include <iomanip.h>
+#endif
+
+#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )
+SG_USING_STD(istream);
+#endif
+
+SG_USING_STD(string);
+
+#include "ATC.hxx"
+#include "transmission.hxx"
+
+//DCL - a complete guess for now.
+#define FG_APPROACH_DEFAULT_RANGE 100
+
+// Contains all the information about a plane that the approach control needs
+const int    max_planes = 20;  // max number of planes on the stack
+const int    max_wp = 10;      // max number of waypoints for approach phase
+const double max_ta = 130;     // max turning angle for plane during approach
+const double tbm    = 20000.0; // min time (in ms) between two messages
+const double lfl    = 10.0;    // length of final leg
+
+struct PlaneApp {
+
+  // variables for plane if it's on the radar
+  string ident;          // indentification of plane
+  double lon;            // longitude in degrees
+  double lat;            // latitude in degrees
+  double alt;            // Altitute above sea level in feet
+  double hdg;            // heading of plane in degrees
+  double dist;           // distance to airport in miles
+  double brg;            // bearing relative to airport in degrees
+  double spd;            // speed above ground
+  int    contact;        // contact with approach established?
+                         // 0 = no contact yet
+                         // 1 = in contact
+                         // 2 = handed off to tower
+  double turn_rate;      // standard turning rate of the plane in seconds per degree
+  double desc_rate;      // standard descent rate of the plane in feets per minute
+  double clmb_rate;      // standard climb rate of the plane in feets per minute
+
+  // additional variables if contact has been established
+  int    wpn;                 // number of waypoints
+  double wpts[max_wp][6];     // assigned waypoints for approach phase 
+                              // first wp in list is airport
+                              // last waypoint point at which contact was established
+                              // second index: 0 = bearing to airport
+                              // second index: 1 = distance to airport
+                              // second index: 2 = alt 
+                              // second index: 3 = ETA
+                              // second index: 4 = heading to next waypoint
+                              // second index: 5 = distance to next waypoint
+
+  double dnwp;           // distance to next waypoint
+  double dcc;            // closest distance to current assigned course
+  double dnc;            // closest distance to course from next to next to next wp
+  double aalt;           // assigned altitude
+  double ahdg;           // assigned heading
+  bool   on_crs;         // is the plane on course?
+  bool   wp_change;      // way point has changed
+  double tlm;            // time when last message was sent
+  TransCode lmc;         // code of last message
+};
+
+
+class FGApproach : public FGATC {
+
+  int      bucket;
+
+  string active_runway;         
+  double active_rw_hdg;
+  double active_rw_lon;
+  double active_rw_lat;
+  double active_rw_len;
+
+  bool     display;            // Flag to indicate whether we should be outputting to the display.
+  bool     displaying;         // Flag to indicate whether we are outputting to the display.
+  int      num_planes;          // number of planes on the stack
+  PlaneApp planes[max_planes];  // Array of planes
+  string   transmission;
+  bool     first;
+
+  SGPropertyNode *comm1_node;
+  SGPropertyNode *comm2_node;
+
+  SGPropertyNode *atcmenu_node;
+  SGPropertyNode *atcopt0_node;
+  SGPropertyNode *atcopt1_node;
+  SGPropertyNode *atcopt2_node;
+  SGPropertyNode *atcopt3_node;
+  SGPropertyNode *atcopt4_node;
+  SGPropertyNode *atcopt5_node;
+  SGPropertyNode *atcopt6_node;
+  SGPropertyNode *atcopt7_node;
+  SGPropertyNode *atcopt8_node;
+  SGPropertyNode *atcopt9_node;
+
+  // for failure modeling
+  string trans_ident;  // transmitted ident
+  bool approach_failed;        // approach failed?
+
+public:
+
+  FGApproach(void);
+  ~FGApproach(void);
+
+  void Init();
+
+  void Update();
+
+  // Add new plane to stack if not already registered 
+  // Input:  pid - id of plane (name) 
+  // Output: "true" if added; "false" if already existend
+  void AddPlane(string pid);
+
+  // Remove plane from stack if out of range
+  int RemovePlane();
+  
+  //Indicate that this instance should be outputting to the ATC display
+  inline void SetDisplay(void) {display = true;}
+  
+  //Indicate that this instance should not be outputting to the ATC display
+  inline void SetNoDisplay(void) {display = false;}
+  
+  inline double get_bucket() const { return bucket; }
+  inline int get_pnum() const { return num_planes; }
+  inline string get_trans_ident() { return trans_ident; }
+  inline atc_type GetType() { return APPROACH; }
+  
+private:
+
+  void calc_wp( const int &i);
+
+  void update_plane_dat();
+
+  void get_active_runway();
+
+  void update_param(const int &i);
+
+  double round_alt( bool hl, double alt );
+
+  double angle_diff_deg( const double &a1, const double &a2);
+
+// ========================================================================
+// get point2 given starting point1 and course and distance
+// input:  point1 = heading in degrees, distance
+// input:  course in degrees, distance
+// output: point2 = heading in degrees, distance
+// ========================================================================
+  void calc_cd_head_dist(const double &h1, const double &d1,
+                        const double &course, const double &dist,
+                        double *h2, double *d2);
+
+
+// ========================================================================
+// get heading and distance between two points; point2 ---> point1
+// input:  point1 = heading in degrees, distance
+// input:  point2 = heading in degrees, distance
+// output: course in degrees, distance
+// ========================================================================
+  void calc_hd_course_dist(const double &h1, const double &d1,
+                          const double &h2, const double &d2,
+                          double *course, double *dist);
+
+
+
+// ========================================================================
+// closest distance between a point and a straigt line in 2 dim.
+// the input variables are given in (heading, distance) 
+// relative to a common point
+// input:  point        = heading in degrees, distance
+// input:  straigt line = anker vector (heading in degrees, distance), 
+//                        heading of direction vector
+// output: distance
+// ========================================================================
+  double calc_psl_dist(const double &h1, const double &d1,
+                      const double &h2, const double &d2,
+                      const double &h3);
+
+  // Pointers to current users position
+  SGPropertyNode *lon_node;
+  SGPropertyNode *lat_node;
+  SGPropertyNode *elev_node;
+  SGPropertyNode *hdg_node;
+  SGPropertyNode *speed_node;
+  SGPropertyNode *etime_node;
+  
+  //Update the transmission string
+  void UpdateTransmission(void);
+  
+  friend istream& operator>> ( istream&, FGApproach& );
+};
+
+#endif // _FG_APPROACH_HXX
index dbec738d1daab49f9945c5f06b8395682bf1b597..3e52c970ce7d5c3ce8a15db06a6493b9982116a5 100644 (file)
@@ -1,96 +1,96 @@
-// FGTransmission - a class to provide transmission control at larger airports.\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-// Based on ground.cxx by David Luff, started March 2002.\r
-//\r
-// Copyright (C) 2002  David C. Luff - david.luff@nottingham.ac.uk\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-\r
-#include "transmission.hxx"\r
-\r
-#include <simgear/misc/sg_path.hxx>\r
-\r
-\r
-//Constructor\r
-FGTransmission::FGTransmission(){\r
-}\r
-\r
-//Destructor\r
-FGTransmission::~FGTransmission(){\r
-}\r
-\r
-void FGTransmission::Init() {\r
-}\r
-\r
-// ============================================================================\r
-// extract parameters from transmission\r
-// ============================================================================\r
-TransPar FGTransmission::Parse() {\r
-  TransPar   tpar;\r
-  string     tokens[20];\r
-  int        msglen,toklen;\r
-  char       dum;\r
-  int        i,j,k;\r
-  const char *capl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";\r
-\r
-  msglen = strlen( TransText.c_str() );\r
-\r
-  int tkn  = 0;\r
-  for ( i=0; i < msglen; ++i ) {\r
-    if ( TransText.c_str()[i] != ' ' ) {\r
-      if ( TransText.c_str()[i] != ',' ) tokens[tkn] += TransText.c_str()[i];\r
-    } else if ( tokens[tkn] != "" ) {\r
-      if ( tkn <= 20 ) {\r
-       tkn += 1;\r
-      } else {\r
-       cout << "Too many tokens" << endl;\r
-      }\r
-    }\r
-  }\r
-\r
-  for ( i=0; i<20; ++i) {\r
-    \r
-    if ( tokens[i] == "request" ) {\r
-      tpar.request = true;\r
-    } else if ( tokens[i] == "approach"  ) { \r
-      tpar.station = "approach";\r
-      tpar.airport = tokens[i-1];\r
-    } else if ( tokens[i] == "landing"  ) { \r
-      tpar.intention = "landing";\r
-      for ( j=i+1; j<=i+2; ++j ) {\r
-       if ( tokens[j] != "" ) {\r
-         toklen = strlen( tokens[j].c_str() );\r
-         bool aid = true;\r
-         for ( k=0; k<toklen; ++k )\r
-           if ( ! strpbrk( &tokens[j].c_str()[k], capl )) {\r
-             aid = false;\r
-             break;\r
-           }\r
-         if ( aid ) tpar.intid = tokens[j];\r
-       }\r
-      }\r
-    } else if ( tokens[i] == "Player"  ) { \r
-      tpar.callsign = tokens[i];\r
-    }\r
-  }\r
-\r
-  //cout << tpar.airport << endl;\r
-  //cout << tpar.request << endl;\r
-  //cout << tpar.intention << endl;\r
-  //cout << tpar.intid << endl;\r
-\r
-  return tpar;\r
-}\r
+// FGTransmission - a class to provide transmission control at larger airports.
+//
+// Written by Alexander Kappes, started March 2002.
+// Based on ground.cxx by David Luff, started March 2002.
+//
+// Copyright (C) 2002  David C. Luff - david.luff@nottingham.ac.uk
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include "transmission.hxx"
+
+#include <simgear/misc/sg_path.hxx>
+
+
+//Constructor
+FGTransmission::FGTransmission(){
+}
+
+//Destructor
+FGTransmission::~FGTransmission(){
+}
+
+void FGTransmission::Init() {
+}
+
+// ============================================================================
+// extract parameters from transmission
+// ============================================================================
+TransPar FGTransmission::Parse() {
+  TransPar   tpar;
+  string     tokens[20];
+  int        msglen,toklen;
+  char       dum;
+  int        i,j,k;
+  const char *capl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+  msglen = strlen( TransText.c_str() );
+
+  int tkn  = 0;
+  for ( i=0; i < msglen; ++i ) {
+    if ( TransText.c_str()[i] != ' ' ) {
+      if ( TransText.c_str()[i] != ',' ) tokens[tkn] += TransText.c_str()[i];
+    } else if ( tokens[tkn] != "" ) {
+      if ( tkn <= 20 ) {
+       tkn += 1;
+      } else {
+       cout << "Too many tokens" << endl;
+      }
+    }
+  }
+
+  for ( i=0; i<20; ++i) {
+    
+    if ( tokens[i] == "request" ) {
+      tpar.request = true;
+    } else if ( tokens[i] == "approach"  ) { 
+      tpar.station = "approach";
+      tpar.airport = tokens[i-1];
+    } else if ( tokens[i] == "landing"  ) { 
+      tpar.intention = "landing";
+      for ( j=i+1; j<=i+2; ++j ) {
+       if ( tokens[j] != "" ) {
+         toklen = strlen( tokens[j].c_str() );
+         bool aid = true;
+         for ( k=0; k<toklen; ++k )
+           if ( ! strpbrk( &tokens[j].c_str()[k], capl )) {
+             aid = false;
+             break;
+           }
+         if ( aid ) tpar.intid = tokens[j];
+       }
+      }
+    } else if ( tokens[i] == "Player"  ) { 
+      tpar.callsign = tokens[i];
+    }
+  }
+
+  //cout << tpar.airport << endl;
+  //cout << tpar.request << endl;
+  //cout << tpar.intention << endl;
+  //cout << tpar.intid << endl;
+
+  return tpar;
+}
index 2b46becdd473a5f844cd200e711eb84232dd74c8..dbc0142010c63ea7b47533e92cfcf69530127eb7 100644 (file)
-// transmission.hxx -- Transmission class\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-// Based on nav.hxx by Curtis Olson, started April 2000.\r
-//\r
-// Copyright (C) 2001  David C. Luff - david.luff@nottingham.ac.uk\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-\r
-\r
-#ifndef _FG_TRANSMISSION_HXX\r
-#define _FG_TRANSMISSION_HXX\r
-\r
-#include <stdio.h>\r
-\r
-#include <simgear/compiler.h>\r
-#include <simgear/math/sg_geodesy.hxx>\r
-#include <simgear/misc/sgstream.hxx>\r
-#include <simgear/magvar/magvar.hxx>\r
-#include <simgear/timing/sg_time.hxx>\r
-#include <simgear/bucket/newbucket.hxx>\r
-\r
-#include <Main/fg_props.hxx>\r
-\r
-#ifdef SG_HAVE_STD_INCLUDES\r
-#  include <istream>\r
-#include <iomanip>\r
-#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )\r
-#  include <iostream.h>\r
-#elif defined( __BORLANDC__ )\r
-#  include <iostream>\r
-#else\r
-#  include <istream.h>\r
-#include <iomanip.h>\r
-#endif\r
-\r
-#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )\r
-SG_USING_STD(istream);\r
-#endif\r
-\r
-SG_USING_STD(string);\r
-\r
-struct TransCode {\r
-  int c1;\r
-  int c2;\r
-  int c3;\r
-};\r
-\r
-// TransPar - a representation of the logic of a parsed speech transmission\r
-struct TransPar {\r
-  string  station;\r
-  string  callsign;\r
-  string  airport;\r
-  string  intention;      // landing, crossing\r
-  string  intid;          // (airport) ID for intention\r
-  bool    request;        // is the transmission a request or an answer?\r
-  int     tdir;           // turning direction: 1=left, 2=right\r
-  double  heading;\r
-  int     VDir;           // vertical direction: 1=descent, 2=maintain, 3=climb\r
-  double  alt;\r
-  double  miles;\r
-  string  runway;\r
-  double  freq;\r
-  double  time;\r
-};\r
-\r
-// FGTransmission - a class to encapsulate a speech transmission\r
-class FGTransmission {\r
-\r
-  int       StationType;             // Type of ATC station: 1 Approach\r
-  TransCode Code;\r
-  string    TransText;\r
-  string    MenuText;\r
-\r
-public:\r
-\r
-  FGTransmission(void);\r
-  ~FGTransmission(void);\r
-\r
-  void Init();\r
-\r
-  inline int       get_station()   const { return StationType; }\r
-  inline TransCode get_code()     { return Code; }\r
-  inline string    get_transtext() { return TransText; }\r
-  inline string    get_menutext()  { return MenuText; }\r
-\r
-  // Return the parsed logic of the transmission  \r
-  TransPar Parse();\r
-\r
-private:\r
-\r
-  friend istream& operator>> ( istream&, FGTransmission& );\r
-\r
-};\r
-\r
-\r
-inline istream&\r
-operator >> ( istream& in, FGTransmission& a ) {\r
-       char ch;\r
-       \r
-       static bool first_time = true;\r
-       static double julian_date = 0;\r
-       static const double MJD0    = 2415020.0;\r
-       if ( first_time ) {\r
-               julian_date = sgTimeCurrentMJD(0, 0) + MJD0;\r
-               first_time = false;\r
-       }\r
-       in >> a.StationType;\r
-       in >> a.Code.c1;\r
-       in >> a.Code.c2;\r
-       in >> a.Code.c3;\r
-       a.TransText = "";\r
-       in >> ch;\r
-       if ( ch != '"' ) a.TransText += ch;\r
-       while(1) {\r
-               //in >> noskipws\r
-               in.unsetf(ios::skipws);\r
-               in >> ch;\r
-               if ( ch != '"' ) a.TransText += ch;\r
-               if((ch == '"') || (ch == 0x0A)) {\r
-                       break;\r
-               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "\r
-       }\r
-       in.setf(ios::skipws);\r
-       \r
-       a.MenuText = "";\r
-       in >> ch;\r
-       if ( ch != '"' ) a.MenuText += ch;\r
-       while(1) {\r
-               //in >> noskipws\r
-               in.unsetf(ios::skipws);\r
-               in >> ch;\r
-               if ( ch != '"' ) a.MenuText += ch;\r
-               if((ch == '"') || (ch == 0x0A)) {\r
-                       break;\r
-               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "\r
-       }\r
-       in.setf(ios::skipws);\r
-       \r
-       //cout << "Code = " << a.Code << "   Transmission text = " << a.TransText \r
-       //     << "   Menu text = " << a.MenuText << endl;\r
-       \r
-       return in >> skipeol;\r
-}\r
-\r
-\r
-#endif // _FG_TRANSMISSION_HXX\r
+// transmission.hxx -- Transmission class
+//
+// Written by Alexander Kappes, started March 2002.
+// Based on nav.hxx by Curtis Olson, started April 2000.
+//
+// Copyright (C) 2001  David C. Luff - david.luff@nottingham.ac.uk
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#ifndef _FG_TRANSMISSION_HXX
+#define _FG_TRANSMISSION_HXX
+
+#include <stdio.h>
+
+#include <simgear/compiler.h>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/magvar/magvar.hxx>
+#include <simgear/timing/sg_time.hxx>
+#include <simgear/bucket/newbucket.hxx>
+
+#include <Main/fg_props.hxx>
+
+#ifdef SG_HAVE_STD_INCLUDES
+#  include <istream>
+#include <iomanip>
+#elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )
+#  include <iostream.h>
+#elif defined( __BORLANDC__ )
+#  include <iostream>
+#else
+#  include <istream.h>
+#include <iomanip.h>
+#endif
+
+#if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )
+SG_USING_STD(istream);
+#endif
+
+SG_USING_STD(string);
+
+struct TransCode {
+  int c1;
+  int c2;
+  int c3;
+};
+
+// TransPar - a representation of the logic of a parsed speech transmission
+struct TransPar {
+  string  station;
+  string  callsign;
+  string  airport;
+  string  intention;      // landing, crossing
+  string  intid;          // (airport) ID for intention
+  bool    request;        // is the transmission a request or an answer?
+  int     tdir;           // turning direction: 1=left, 2=right
+  double  heading;
+  int     VDir;           // vertical direction: 1=descent, 2=maintain, 3=climb
+  double  alt;
+  double  miles;
+  string  runway;
+  double  freq;
+  double  time;
+};
+
+// FGTransmission - a class to encapsulate a speech transmission
+class FGTransmission {
+
+  int       StationType;             // Type of ATC station: 1 Approach
+  TransCode Code;
+  string    TransText;
+  string    MenuText;
+
+public:
+
+  FGTransmission(void);
+  ~FGTransmission(void);
+
+  void Init();
+
+  inline int       get_station()   const { return StationType; }
+  inline TransCode get_code()     { return Code; }
+  inline string    get_transtext() { return TransText; }
+  inline string    get_menutext()  { return MenuText; }
+
+  // Return the parsed logic of the transmission  
+  TransPar Parse();
+
+private:
+
+  friend istream& operator>> ( istream&, FGTransmission& );
+
+};
+
+
+inline istream&
+operator >> ( istream& in, FGTransmission& a ) {
+       char ch;
+       
+       static bool first_time = true;
+       static double julian_date = 0;
+       static const double MJD0    = 2415020.0;
+       if ( first_time ) {
+               julian_date = sgTimeCurrentMJD(0, 0) + MJD0;
+               first_time = false;
+       }
+       in >> a.StationType;
+       in >> a.Code.c1;
+       in >> a.Code.c2;
+       in >> a.Code.c3;
+       a.TransText = "";
+       in >> ch;
+       if ( ch != '"' ) a.TransText += ch;
+       while(1) {
+               //in >> noskipws
+               in.unsetf(ios::skipws);
+               in >> ch;
+               if ( ch != '"' ) a.TransText += ch;
+               if((ch == '"') || (ch == 0x0A)) {
+                       break;
+               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
+       }
+       in.setf(ios::skipws);
+       
+       a.MenuText = "";
+       in >> ch;
+       if ( ch != '"' ) a.MenuText += ch;
+       while(1) {
+               //in >> noskipws
+               in.unsetf(ios::skipws);
+               in >> ch;
+               if ( ch != '"' ) a.MenuText += ch;
+               if((ch == '"') || (ch == 0x0A)) {
+                       break;
+               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
+       }
+       in.setf(ios::skipws);
+       
+       //cout << "Code = " << a.Code << "   Transmission text = " << a.TransText 
+       //     << "   Menu text = " << a.MenuText << endl;
+       
+       return in >> skipeol;
+}
+
+
+#endif // _FG_TRANSMISSION_HXX
index 8d354cc718cdf86edef1f9b9ca7b9885a97cb154..fa50e7ea5a35579d78c89534a5d39ba290494dcd 100644 (file)
-// transmissionlist.cxx -- transmission management class\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-// Based on navlist.cxx by Curtis Olson, started April 2000.\r
-//\r
-// Copyright (C) 2000  Curtis L. Olson - curt@flightgear.org\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-//\r
-// $Id$\r
-\r
-\r
-#ifdef HAVE_CONFIG_H\r
-#  include <config.h>\r
-#endif\r
-\r
-#include <simgear/debug/logstream.hxx>\r
-#include <simgear/misc/sgstream.hxx>\r
-#include <simgear/math/sg_geodesy.hxx>\r
-\r
-#include "transmissionlist.hxx"\r
-\r
-#include <GUI/gui.h>\r
-\r
-static puDialogBox  *ATCMenuBox = 0;\r
-static puFrame      *ATCMenuFrame = 0;\r
-static puText       *ATCMenuBoxMessage = 0;\r
-\r
-FGTransmissionList *current_transmissionlist;\r
-\r
-\r
-// Constructor\r
-FGTransmissionList::FGTransmissionList( void ) {\r
-}\r
-\r
-\r
-// Destructor\r
-FGTransmissionList::~FGTransmissionList( void ) {\r
-}\r
-\r
-/*\r
-// ============================================================================\r
-// init menu window\r
-// ============================================================================\r
-void mkATCMenuInit (void)\r
-{\r
-  int dx = 400;\r
-  int dy = 100;\r
-  int y = (fgGetInt("/sim/startup/ysize") - 10 - dy);\r
-  ATCMenuBox = new puDialogBox (10, y);\r
-  {\r
-    ATCMenuFrame = new puFrame (0,0,400,100);\r
-    ATCMenuBoxMessage  =  new puText         (10, 70);\r
-    ATCMenuBoxMessage  -> setLabel           ("");\r
-  }\r
-  fgSetBool("/sim/atc/menu",false);\r
-  fgSetBool("/sim/atc/opt1",false);\r
-  fgSetBool("/sim/atc/opt2",false);\r
-  fgSetBool("/sim/atc/opt3",false);\r
-  fgSetBool("/sim/atc/opt4",false);\r
-  fgSetBool("/sim/atc/opt5",false);\r
-  fgSetBool("/sim/atc/opt6",false);\r
-  fgSetBool("/sim/atc/opt7",false);\r
-  fgSetBool("/sim/atc/opt8",false);\r
-  fgSetBool("/sim/atc/opt9",false);\r
-  fgSetBool("/sim/atc/opt0",false);\r
-}\r
-\r
-// ATC Menu Message Box\r
-void mkATCMenu ( const char *txt )\r
-{\r
-  ATCMenuBoxMessage  =  new puText   (10, 70);\r
-  ATCMenuBoxMessage->setLabel( txt );\r
-\r
-  FG_PUSH_PUI_DIALOG( ATCMenuBox );\r
-}\r
-*/\r
-\r
-// load default.transmissions\r
-bool FGTransmissionList::init( SGPath path ) {\r
-    FGTransmission a;\r
-\r
-    transmissionlist_station.erase( transmissionlist_station.begin(), transmissionlist_station.end() );\r
-\r
-    sg_gzifstream in( path.str() );\r
-    if ( !in.is_open() ) {\r
-        SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );\r
-        exit(-1);\r
-    }\r
-\r
-    // read in each line of the file\r
-\r
-    // in >> skipeol;\r
-    // in >> skipcomment;\r
-\r
-#ifdef __MWERKS__\r
-\r
-    char c = 0;\r
-    while ( in.get(c) && c != '\0' ) {\r
-        in.putback(c);\r
-        in >> a;\r
-       if ( a.get_type() != '[' ) {\r
-           transmissionlist_code[a.get_station()].push_back(a);\r
-       }\r
-        in >> skipcomment;\r
-    }\r
-\r
-#else\r
-\r
-    double min = 100000;\r
-    double max = 0;\r
-\r
-    while ( ! in.eof() ) {\r
-        in >> a;\r
-       transmissionlist_station[a.get_station()].push_back(a);\r
-       \r
-        in >> skipcomment;\r
-\r
-       if ( a.get_station() < min ) {\r
-         min = a.get_station();\r
-       }\r
-       if ( a.get_station() > max ) {\r
-         max = a.get_station();\r
-       }\r
-       cout << a.get_station() << " " << a.get_code().c1 << " " << a.get_code().c2 << " "\r
-            << a.get_code().c3 << " " << a.get_transtext() \r
-            << " " << a.get_menutext() << endl;\r
-    }\r
-    \r
-#endif\r
-\r
-    // init ATC menu\r
-    fgSetBool("/sim/atc/menu",false);\r
-\r
-    return true;\r
-}\r
-\r
-// query the database for the specified station type; \r
-// for station see FlightGear/ATC/default.transmissions\r
-bool FGTransmissionList::query_station( const int &station, FGTransmission *t,\r
-                                       int max_trans, int &num_trans ) \r
-{\r
-  transmission_list_type     tmissions = transmissionlist_station[station];\r
-  transmission_list_iterator current   = tmissions.begin();\r
-  transmission_list_iterator last      = tmissions.end();\r
-\r
-  for ( ; current != last ; ++current ) {\r
-    if (num_trans < max_trans) {\r
-      t[num_trans] = *current;\r
-      num_trans += 1;\r
-    }\r
-    else {\r
-      cout << "Transmissionlist error: Too many transmissions" << endl; \r
-    }\r
-  }\r
-\r
-  if ( num_trans != 0 ) return true;\r
-  else {\r
-    cout << "No transmission with station " << station << "found." << endl;\r
-    string empty;\r
-    return false;\r
-  }\r
-}\r
-\r
-string FGTransmissionList::gen_text(const int &station, const TransCode code, \r
-                                   const TransPar &tpars, const bool ttext )\r
-{\r
-  const int cmax = 100;\r
-  string message;\r
-  char tag[4];\r
-  char crej = '@';\r
-  char mes[cmax];\r
-  char dum[cmax];\r
-  char buf[10];\r
-  char *pos;\r
-  int len;\r
-  FGTransmission t;\r
-\r
-  //  if (current_transmissionlist->query_station( station, &t ) ) {  \r
-  transmission_list_type     tmissions = transmissionlist_station[station];\r
-  transmission_list_iterator current   = tmissions.begin();\r
-  transmission_list_iterator last      = tmissions.end();\r
-  \r
-  for ( ; current != last ; ++current ) {\r
-    if ( current->get_code().c1 == code.c1 &&  \r
-        current->get_code().c2 == code.c2 &&\r
-        current->get_code().c3 == code.c3 ) {\r
-      \r
-      if ( ttext ) message = current->get_transtext();\r
-      else message = current->get_menutext();\r
-      strcpy( &mes[0], message.c_str() ); \r
-      \r
-      while ( strchr(&mes[0], crej) != NULL  ) {\r
-       pos = strchr( &mes[0], crej );\r
-       bcopy(pos, &tag, 3);\r
-       tag[3] = '\0';\r
-       int i;\r
-       len = 0;\r
-       for ( i=0; i<cmax; i++ ) {\r
-         if ( mes[i] == crej ) {\r
-           len = i; \r
-           break;\r
-         }\r
-       }\r
-       strncpy( &dum[0], &mes[0], len );\r
-       dum[len] = '\0';\r
-       \r
-       if ( strcmp ( tag, "@ST" ) == 0 )\r
-         strcat( &dum[0], tpars.station.c_str() );\r
-       else if ( strcmp ( tag, "@AP" ) == 0 )\r
-         strcat( &dum[0], tpars.airport.c_str() );\r
-       else if ( strcmp ( tag, "@CS" ) == 0 ) \r
-         strcat( &dum[0], tpars.callsign.c_str() );\r
-       else if ( strcmp ( tag, "@TD" ) == 0 ) {\r
-         if ( tpars.tdir == 1 ) {\r
-           char buf[] = "left";\r
-           strcat( &dum[0], &buf[0] );\r
-         }\r
-         else {\r
-           char buf[] = "right";\r
-           strcat( &dum[0], &buf[0] );\r
-         }\r
-       }\r
-       else if ( strcmp ( tag, "@HE" ) == 0 ) {\r
-         char buf[10];\r
-         sprintf( buf, "%i", (int)(tpars.heading) );\r
-         strcat( &dum[0], &buf[0] );\r
-       }\r
-       else if ( strcmp ( tag, "@VD" ) == 0 ) {\r
-         if ( tpars.VDir == 1 ) {\r
-           char buf[] = "Descent and maintain";\r
-           strcat( &dum[0], &buf[0] );\r
-         }\r
-         else if ( tpars.VDir == 2 ) {\r
-           char buf[] = "Maintain";\r
-           strcat( &dum[0], &buf[0] );\r
-         }\r
-         else if ( tpars.VDir == 3 ) {\r
-           char buf[] = "Climb and maintain";\r
-           strcat( &dum[0], &buf[0] );\r
-         }  \r
-       }\r
-       else if ( strcmp ( tag, "@AL" ) == 0 ) {\r
-         char buf[10];\r
-         sprintf( buf, "%i", (int)(tpars.alt) );\r
-         strcat( &dum[0], &buf[0] );\r
-       }\r
-       else if ( strcmp ( tag, "@MI" ) == 0 ) {\r
-         char buf[10];\r
-         sprintf( buf, "%3.1f", tpars.miles );\r
-         strcat( &dum[0], &buf[0] );\r
-       }\r
-       else if ( strcmp ( tag, "@FR" ) == 0 ) {\r
-         char buf[10];\r
-         sprintf( buf, "%6.2f", tpars.freq );\r
-         strcat( &dum[0], &buf[0] );\r
-       }\r
-       else if ( strcmp ( tag, "@RW" ) == 0 )\r
-         strcat( &dum[0], tpars.runway.c_str() );\r
-       else {\r
-         cout << "Tag " << tag << " not found" << endl;\r
-         break;\r
-       }\r
-       strcat( &dum[0], &mes[len+3] );\r
-       strcpy( &mes[0], &dum[0] );\r
-      }\r
-\r
-      //cout << mes  << endl;  \r
-      break;\r
-    }\r
-  }\r
-  if ( mes != "" ) return mes;\r
-  else return "No transmission found";\r
-}\r
-\r
-\r
+// transmissionlist.cxx -- transmission management class
+//
+// Written by Alexander Kappes, started March 2002.
+// Based on navlist.cxx by Curtis Olson, started April 2000.
+//
+// Copyright (C) 2000  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+
+#include "transmissionlist.hxx"
+
+#include <GUI/gui.h>
+
+static puDialogBox  *ATCMenuBox = 0;
+static puFrame      *ATCMenuFrame = 0;
+static puText       *ATCMenuBoxMessage = 0;
+
+FGTransmissionList *current_transmissionlist;
+
+
+// Constructor
+FGTransmissionList::FGTransmissionList( void ) {
+}
+
+
+// Destructor
+FGTransmissionList::~FGTransmissionList( void ) {
+}
+
+/*
+// ============================================================================
+// init menu window
+// ============================================================================
+void mkATCMenuInit (void)
+{
+  int dx = 400;
+  int dy = 100;
+  int y = (fgGetInt("/sim/startup/ysize") - 10 - dy);
+  ATCMenuBox = new puDialogBox (10, y);
+  {
+    ATCMenuFrame = new puFrame (0,0,400,100);
+    ATCMenuBoxMessage  =  new puText         (10, 70);
+    ATCMenuBoxMessage  -> setLabel           ("");
+  }
+  fgSetBool("/sim/atc/menu",false);
+  fgSetBool("/sim/atc/opt1",false);
+  fgSetBool("/sim/atc/opt2",false);
+  fgSetBool("/sim/atc/opt3",false);
+  fgSetBool("/sim/atc/opt4",false);
+  fgSetBool("/sim/atc/opt5",false);
+  fgSetBool("/sim/atc/opt6",false);
+  fgSetBool("/sim/atc/opt7",false);
+  fgSetBool("/sim/atc/opt8",false);
+  fgSetBool("/sim/atc/opt9",false);
+  fgSetBool("/sim/atc/opt0",false);
+}
+
+// ATC Menu Message Box
+void mkATCMenu ( const char *txt )
+{
+  ATCMenuBoxMessage  =  new puText   (10, 70);
+  ATCMenuBoxMessage->setLabel( txt );
+
+  FG_PUSH_PUI_DIALOG( ATCMenuBox );
+}
+*/
+
+// load default.transmissions
+bool FGTransmissionList::init( SGPath path ) {
+    FGTransmission a;
+
+    transmissionlist_station.erase( transmissionlist_station.begin(), transmissionlist_station.end() );
+
+    sg_gzifstream in( path.str() );
+    if ( !in.is_open() ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
+        exit(-1);
+    }
+
+    // read in each line of the file
+
+    // in >> skipeol;
+    // in >> skipcomment;
+
+#ifdef __MWERKS__
+
+    char c = 0;
+    while ( in.get(c) && c != '\0' ) {
+        in.putback(c);
+        in >> a;
+       if ( a.get_type() != '[' ) {
+           transmissionlist_code[a.get_station()].push_back(a);
+       }
+        in >> skipcomment;
+    }
+
+#else
+
+    double min = 100000;
+    double max = 0;
+
+    while ( ! in.eof() ) {
+        in >> a;
+       transmissionlist_station[a.get_station()].push_back(a);
+       
+        in >> skipcomment;
+
+       if ( a.get_station() < min ) {
+         min = a.get_station();
+       }
+       if ( a.get_station() > max ) {
+         max = a.get_station();
+       }
+       cout << a.get_station() << " " << a.get_code().c1 << " " << a.get_code().c2 << " "
+            << a.get_code().c3 << " " << a.get_transtext() 
+            << " " << a.get_menutext() << endl;
+    }
+    
+#endif
+
+    // init ATC menu
+    fgSetBool("/sim/atc/menu",false);
+
+    return true;
+}
+
+// query the database for the specified station type; 
+// for station see FlightGear/ATC/default.transmissions
+bool FGTransmissionList::query_station( const int &station, FGTransmission *t,
+                                       int max_trans, int &num_trans ) 
+{
+  transmission_list_type     tmissions = transmissionlist_station[station];
+  transmission_list_iterator current   = tmissions.begin();
+  transmission_list_iterator last      = tmissions.end();
+
+  for ( ; current != last ; ++current ) {
+    if (num_trans < max_trans) {
+      t[num_trans] = *current;
+      num_trans += 1;
+    }
+    else {
+      cout << "Transmissionlist error: Too many transmissions" << endl; 
+    }
+  }
+
+  if ( num_trans != 0 ) return true;
+  else {
+    cout << "No transmission with station " << station << "found." << endl;
+    string empty;
+    return false;
+  }
+}
+
+string FGTransmissionList::gen_text(const int &station, const TransCode code, 
+                                   const TransPar &tpars, const bool ttext )
+{
+  const int cmax = 100;
+  string message;
+  char tag[4];
+  char crej = '@';
+  char mes[cmax];
+  char dum[cmax];
+  char buf[10];
+  char *pos;
+  int len;
+  FGTransmission t;
+
+  //  if (current_transmissionlist->query_station( station, &t ) ) {  
+  transmission_list_type     tmissions = transmissionlist_station[station];
+  transmission_list_iterator current   = tmissions.begin();
+  transmission_list_iterator last      = tmissions.end();
+  
+  for ( ; current != last ; ++current ) {
+    if ( current->get_code().c1 == code.c1 &&  
+        current->get_code().c2 == code.c2 &&
+        current->get_code().c3 == code.c3 ) {
+      
+      if ( ttext ) message = current->get_transtext();
+      else message = current->get_menutext();
+      strcpy( &mes[0], message.c_str() ); 
+      
+      while ( strchr(&mes[0], crej) != NULL  ) {
+       pos = strchr( &mes[0], crej );
+       bcopy(pos, &tag, 3);
+       tag[3] = '\0';
+       int i;
+       len = 0;
+       for ( i=0; i<cmax; i++ ) {
+         if ( mes[i] == crej ) {
+           len = i; 
+           break;
+         }
+       }
+       strncpy( &dum[0], &mes[0], len );
+       dum[len] = '\0';
+       
+       if ( strcmp ( tag, "@ST" ) == 0 )
+         strcat( &dum[0], tpars.station.c_str() );
+       else if ( strcmp ( tag, "@AP" ) == 0 )
+         strcat( &dum[0], tpars.airport.c_str() );
+       else if ( strcmp ( tag, "@CS" ) == 0 ) 
+         strcat( &dum[0], tpars.callsign.c_str() );
+       else if ( strcmp ( tag, "@TD" ) == 0 ) {
+         if ( tpars.tdir == 1 ) {
+           char buf[] = "left";
+           strcat( &dum[0], &buf[0] );
+         }
+         else {
+           char buf[] = "right";
+           strcat( &dum[0], &buf[0] );
+         }
+       }
+       else if ( strcmp ( tag, "@HE" ) == 0 ) {
+         char buf[10];
+         sprintf( buf, "%i", (int)(tpars.heading) );
+         strcat( &dum[0], &buf[0] );
+       }
+       else if ( strcmp ( tag, "@VD" ) == 0 ) {
+         if ( tpars.VDir == 1 ) {
+           char buf[] = "Descent and maintain";
+           strcat( &dum[0], &buf[0] );
+         }
+         else if ( tpars.VDir == 2 ) {
+           char buf[] = "Maintain";
+           strcat( &dum[0], &buf[0] );
+         }
+         else if ( tpars.VDir == 3 ) {
+           char buf[] = "Climb and maintain";
+           strcat( &dum[0], &buf[0] );
+         }  
+       }
+       else if ( strcmp ( tag, "@AL" ) == 0 ) {
+         char buf[10];
+         sprintf( buf, "%i", (int)(tpars.alt) );
+         strcat( &dum[0], &buf[0] );
+       }
+       else if ( strcmp ( tag, "@MI" ) == 0 ) {
+         char buf[10];
+         sprintf( buf, "%3.1f", tpars.miles );
+         strcat( &dum[0], &buf[0] );
+       }
+       else if ( strcmp ( tag, "@FR" ) == 0 ) {
+         char buf[10];
+         sprintf( buf, "%6.2f", tpars.freq );
+         strcat( &dum[0], &buf[0] );
+       }
+       else if ( strcmp ( tag, "@RW" ) == 0 )
+         strcat( &dum[0], tpars.runway.c_str() );
+       else {
+         cout << "Tag " << tag << " not found" << endl;
+         break;
+       }
+       strcat( &dum[0], &mes[len+3] );
+       strcpy( &mes[0], &dum[0] );
+      }
+
+      //cout << mes  << endl;  
+      break;
+    }
+  }
+  if ( mes != "" ) return mes;
+  else return "No transmission found";
+}
+
+
index 9c75723dc829a0c520f9abaa989ecc6780f29e1d..bec788b0cf93198cac670c42a6f7019fe717b301 100644 (file)
@@ -1,80 +1,80 @@
-// transmissionlist.hxx -- transmission management class\r
-//\r
-// Written by Alexander Kappes, started March 2002.\r
-// Based on navlist.hxx by Curtis Olson, started April 2000.\r
-//\r
-// Copyright (C) 2000  Curtis L. Olson - curt@flightgear.org\r
-//\r
-// This program is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU General Public License as\r
-// published by the Free Software Foundation; either version 2 of the\r
-// License, or (at your option) any later version.\r
-//\r
-// This program is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, write to the Free Software\r
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-//\r
-\r
-\r
-#ifndef _FG_TRANSMISSIONLIST_HXX\r
-#define _FG_TRANSMISSIONLIST_HXX\r
-\r
-\r
-#include <simgear/compiler.h>\r
-#include <simgear/misc/sg_path.hxx>\r
-\r
-#include <map>\r
-#include <vector>\r
-\r
-#include <plib/pu.h>\r
-\r
-#include "transmission.hxx"\r
-\r
-SG_USING_STD(map);\r
-SG_USING_STD(vector);\r
-\r
-class FGTransmissionList {\r
-\r
-  // convenience types\r
-  typedef vector < FGTransmission > transmission_list_type;\r
-  typedef transmission_list_type::iterator transmission_list_iterator;\r
-  typedef transmission_list_type::const_iterator transmission_list_const_iterator;\r
-  \r
-  // typedef map < int, transmission_list_type, less<int> > transmission_map_type;\r
-  typedef map < int, transmission_list_type > transmission_map_type;\r
-  typedef transmission_map_type::iterator transmission_map_iterator;\r
-  typedef transmission_map_type::const_iterator transmission_map_const_iterator;\r
-  \r
-  transmission_map_type transmissionlist_station;\r
-  \r
-public:\r
-  \r
-  FGTransmissionList();\r
-  ~FGTransmissionList();\r
-  \r
-  // load the transmission data and build the map\r
-  bool init( SGPath path );\r
-  \r
-  // query the database for the specified code,\r
-  bool query_station( const int &station, FGTransmission *a, int max_trans, int &num_trans );\r
-\r
-  // generate the transmission text given the code of the message \r
-  // and the parameters\r
-  string gen_text(const int &station, const TransCode code,\r
-                 const TransPar &tpars, const bool ttext);\r
-\r
-};\r
-\r
-\r
-void mkATCMenuInit (void);\r
-void mkATCMenu (void);\r
-\r
-extern FGTransmissionList *current_transmissionlist;\r
-\r
-\r
-#endif // _FG_TRANSMISSIONLIST_HXX\r
+// transmissionlist.hxx -- transmission management class
+//
+// Written by Alexander Kappes, started March 2002.
+// Based on navlist.hxx by Curtis Olson, started April 2000.
+//
+// Copyright (C) 2000  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+
+#ifndef _FG_TRANSMISSIONLIST_HXX
+#define _FG_TRANSMISSIONLIST_HXX
+
+
+#include <simgear/compiler.h>
+#include <simgear/misc/sg_path.hxx>
+
+#include <map>
+#include <vector>
+
+#include <plib/pu.h>
+
+#include "transmission.hxx"
+
+SG_USING_STD(map);
+SG_USING_STD(vector);
+
+class FGTransmissionList {
+
+  // convenience types
+  typedef vector < FGTransmission > transmission_list_type;
+  typedef transmission_list_type::iterator transmission_list_iterator;
+  typedef transmission_list_type::const_iterator transmission_list_const_iterator;
+  
+  // typedef map < int, transmission_list_type, less<int> > transmission_map_type;
+  typedef map < int, transmission_list_type > transmission_map_type;
+  typedef transmission_map_type::iterator transmission_map_iterator;
+  typedef transmission_map_type::const_iterator transmission_map_const_iterator;
+  
+  transmission_map_type transmissionlist_station;
+  
+public:
+  
+  FGTransmissionList();
+  ~FGTransmissionList();
+  
+  // load the transmission data and build the map
+  bool init( SGPath path );
+  
+  // query the database for the specified code,
+  bool query_station( const int &station, FGTransmission *a, int max_trans, int &num_trans );
+
+  // generate the transmission text given the code of the message 
+  // and the parameters
+  string gen_text(const int &station, const TransCode code,
+                 const TransPar &tpars, const bool ttext);
+
+};
+
+
+void mkATCMenuInit (void);
+void mkATCMenu (void);
+
+extern FGTransmissionList *current_transmissionlist;
+
+
+#endif // _FG_TRANSMISSIONLIST_HXX