]> git.mxchange.org Git - flightgear.git/commitdiff
Major re-work of the comm frequency storage and lookup. Only a small core amount...
authordaveluff <daveluff>
Thu, 6 Feb 2003 10:42:43 +0000 (10:42 +0000)
committerdaveluff <daveluff>
Thu, 6 Feb 2003 10:42:43 +0000 (10:42 +0000)
18 files changed:
src/ATC/ATC.cxx
src/ATC/ATC.hxx
src/ATC/ATCmgr.cxx
src/ATC/ATCmgr.hxx
src/ATC/Makefile.am
src/ATC/approach.cxx
src/ATC/approach.hxx
src/ATC/approachlist.cxx
src/ATC/approachlist.hxx
src/ATC/atis.cxx
src/ATC/atis.hxx
src/ATC/atislist.cxx
src/ATC/atislist.hxx
src/ATC/commlist.cxx [new file with mode: 0644]
src/ATC/commlist.hxx [new file with mode: 0644]
src/ATC/tower.hxx
src/ATC/towerlist.cxx
src/ATC/towerlist.hxx

index 86055ff992ede3abf860b9787a2b08a47ca0aad5..24c0c0d605b609cb7c45274cdb0f7ddbed9e7ac8 100644 (file)
@@ -1,5 +1,4 @@
-// Implementation of FGATC - ATC subsystem abstract base class.
-// Nothing in here should ever get called.
+// Implementation of FGATC - ATC subsystem base class.
 //
 // Written by David Luff, started February 2002.
 //
@@ -40,14 +39,23 @@ void FGATC::SetDisplay() {
 void FGATC::SetNoDisplay() {
 }
 
-const char* FGATC::GetIdent() {
-    return("Error - base class function called in FGATC...");
-}
-
 atc_type FGATC::GetType() {
     return INVALID;
 }
 
+void FGATC::SetData(ATCData* d) {
+       lon = d->lon;
+       lat = d->lat;
+       elev = d->elev;
+       x = d->x;
+       y = d->y;
+       z = d->z;
+       range = d->range;
+       ident = d->ident;
+       name = d->name;
+       freq = d->freq;
+}
+
 ostream& operator << (ostream& os, atc_type atc) {
     switch(atc) {
     case(INVALID):
index 143b3080ae05bb8e77687f3a2203b2818738f0d2..1babf06f7208d7d74d27be09f56cfbcac290e5c7 100644 (file)
 #define _FG_ATC_HXX
 
 #include <simgear/compiler.h>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/debug/logstream.hxx>
 
 #include STL_IOSTREAM
 #include STL_STRING
 
 SG_USING_STD(ostream);
 SG_USING_STD(string);
+SG_USING_STD(ios);
 
 // Possible types of ATC type that the radios may be tuned to.
 // INVALID implies not tuned in to anything.
@@ -42,6 +46,19 @@ enum atc_type {
     ENROUTE
 }; 
 
+// DCL - new experimental ATC data store
+struct ATCData {
+       atc_type type;
+       float lon, lat, elev;
+       float x, y, z;
+       //int freq;
+       unsigned short int freq;
+       //int range;
+       unsigned short int range;
+       string ident;
+       string name;
+};
+
 ostream& operator << (ostream& os, atc_type atc);
 
 class FGATC {
@@ -65,11 +82,105 @@ public:
     // Indicate that this instance should not output to the display
     virtual void SetNoDisplay();
 
-    // Return the ATC station ident (generally the ICAO code of the airport)
-    virtual const char* GetIdent();
-
     // Return the type of ATC station that the class represents
     virtual atc_type GetType();
+       
+       // Set the core ATC data
+       void SetData(ATCData* d);
+       
+       inline double get_lon() const { return lon; }
+       inline void set_lon(const double ln) {lon = ln;}
+       inline double get_lat() const { return lat; }
+       inline void set_lat(const double lt) {lat = lt;}
+       inline double get_elev() const { return elev; }
+       inline void set_elev(const double ev) {elev = ev;}
+       inline double get_x() const { return x; }
+       inline void set_x(const double ecs) {x = ecs;}
+       inline double get_y() const { return y; }
+       inline void set_y(const double why) {y = why;}
+       inline double get_z() const { return z; }
+       inline void set_z(const double zed) {z = zed;}
+       inline int get_freq() const { return freq; }
+       inline void set_freq(const int fq) {freq = fq;}
+       inline int get_range() const { return range; }
+       inline void set_range(const int rg) {range = rg;}
+       inline const char* get_ident() { return ident.c_str(); }
+       inline void set_ident(const string id) {ident = id;}
+       inline const char* get_name() {return name.c_str();}
+       inline void set_name(const string nm) {name = nm;}
+       
+protected:
+
+       double lon, lat, elev;
+       double x, y, z;
+       int freq;
+       int range;
+       string ident;           // Code of the airport its at.
+       string name;            // Name transmitted in the broadcast.
 };
 
+inline istream&
+operator >> ( istream& fin, ATCData& a )
+{
+       double f;
+       char ch;
+       char tp;
+
+       fin >> tp;
+       
+       switch(tp) {
+       case 'I':
+               a.type = ATIS;
+               break;
+       case 'T':
+               a.type = TOWER;
+               break;
+       case 'G':
+               a.type = GROUND;
+               break;
+       case 'A':
+               a.type = APPROACH;
+               break;
+       case '[':
+               a.type = INVALID;
+               return fin >> skipeol;
+       default:
+               SG_LOG(SG_GENERAL, SG_ALERT, "Warning - unknown type \'" << tp << "\' found whilst reading ATC frequency data!\n");
+               a.type = INVALID;
+               return fin >> skipeol;
+       }
+
+       fin >> a.lat >> a.lon >> a.elev >> f >> a.range 
+       >> a.ident;
+       
+       a.name = "";
+       fin >> ch;
+       a.name += ch;
+       while(1) {
+               //in >> noskipws
+               fin.unsetf(ios::skipws);
+               fin >> ch;
+               a.name += ch;
+               if((ch == '"') || (ch == 0x0A)) {
+                       break;
+               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
+       }
+       fin.setf(ios::skipws);
+       //cout << "Comm name = " << a.name << '\n';
+       
+       a.freq = (int)(f*100.0 + 0.5);
+       
+       // cout << a.ident << endl;
+       
+       // generate cartesian coordinates
+       Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS, a.lat * SGD_DEGREES_TO_RADIANS, a.elev );
+       Point3D cart = sgGeodToCart( geod );
+       a.x = cart.x();
+       a.y = cart.y();
+       a.z = cart.z();
+       
+       return fin >> skipeol;
+}
+
+
 #endif  // _FG_ATC_HXX
index 8e0cb484321daf731317e95743eeed85eb93bfa4..485565e9f981615d7e908184374e5c7385d4e2a8 100644 (file)
 #include <simgear/debug/logstream.hxx>
 
 #include "ATCmgr.hxx"
-#include "atislist.hxx"
+#include "commlist.hxx"
+//#include "atislist.hxx"
 //#include "groundlist.hxx"
-#include "towerlist.hxx"
-#include "approachlist.hxx"
+//#include "towerlist.hxx"
+//#include "approachlist.hxx"
 #include "ATCdisplay.hxx"
 
 /*
@@ -158,34 +159,16 @@ static bool do_ATC_dialog(const SGPropertyNode* arg) {
 
 
 FGATCMgr::FGATCMgr() {
-       comm1_ident = "";
-       comm1_atis_ident = "";
-       comm1_tower_ident = "";
-       comm1_approach_ident = "";
-       last_comm1_ident = "";
-       last_comm1_atis_ident = "";
-       last_comm1_tower_ident = "";
-       last_comm1_approach_ident = "";
+       comm_ident[0] = "";
+       comm_ident[1] = "";
+       last_comm_ident[0] = "";
+       last_comm_ident[1] = "";
        approach_ident = "";
        last_in_range = false;
-       comm1_atis_valid = false;
-       comm1_tower_valid = false;
-       comm1_approach_valid = false;
-       comm1_type = INVALID;
-       comm1_atc_ptr = NULL;
-       comm2_ident = "";
-       comm2_atis_ident = "";
-       comm2_tower_ident = "";
-       comm2_approach_ident = "";
-       last_comm2_ident = "";
-       last_comm2_atis_ident = "";
-       last_comm2_tower_ident = "";
-       last_comm2_approach_ident = "";
-       comm2_atis_valid = false;
-       comm2_tower_valid = false;
-       comm2_approach_valid = false;
-       comm2_type = INVALID;
-       comm2_atc_ptr = NULL;
+       comm_type[0] = INVALID;
+       comm_type[1] = INVALID;
+       comm_atc_ptr[0] = NULL;
+       comm_atc_ptr[1] = NULL;
 }
 
 FGATCMgr::~FGATCMgr() {
@@ -198,8 +181,8 @@ void FGATCMgr::unbind() {
 }
 
 void FGATCMgr::init() {
-       comm1_node = fgGetNode("/radios/comm[0]/frequencies/selected-mhz", true);
-       comm2_node = fgGetNode("/radios/comm[1]/frequencies/selected-mhz", true);
+       comm_node[0] = fgGetNode("/radios/comm[0]/frequencies/selected-mhz", true);
+       comm_node[1] = fgGetNode("/radios/comm[1]/frequencies/selected-mhz", true);
        lon_node = fgGetNode("/position/longitude-deg", true);
        lat_node = fgGetNode("/position/latitude-deg", true);
        elev_node = fgGetNode("/position/altitude-ft", true);
@@ -209,6 +192,11 @@ void FGATCMgr::init() {
        //                  fgEVENT::FG_EVENT_READY, 800);
        // For some reason the above doesn't compile - including Time/event.hxx stops compilation.
        
+       // Initialise the frequency search map
+    current_commlist = new FGCommList;
+    SGPath p_comm( globals->get_fg_root() );
+    current_commlist->init( p_comm );
+       
        // Initialise the airport_atc_map - we'll cheat for now and just hardcode KEMT and any others that may be needed for development
        AirportATC *a = new AirportATC;
        a->lon = -118.034719;
@@ -245,6 +233,7 @@ void FGATCMgr::init() {
 }
 
 void FGATCMgr::update(double dt) {
+       //cout << "Entering update..." << endl;
        //Traverse the list of active stations.
        //Only update one class per update step to avoid the whole ATC system having to calculate between frames.
        //Eventually we should only update every so many steps.
@@ -253,25 +242,34 @@ void FGATCMgr::update(double dt) {
                if(atc_list_itr == atc_list.end()) {
                        atc_list_itr = atc_list.begin();
                }
+               //cout << "Updating " << (*atc_list_itr)->get_ident() << ' ' << (*atc_list_itr)->GetType() << '\n';
+               //cout << "Freq = " << (*atc_list_itr)->get_freq() << '\n';
                (*atc_list_itr)->Update();
+               //cout << "Done ATC update..." << endl;
                ++atc_list_itr;
        }
        
        // Search the tuned frequencies every now and then - this should be done with the event scheduler
        static int i = 0;
+       if(i == 7) {
+               AreaSearch();
+       }
        if(i == 15) {
-               Search(1);
+               //cout << "About to search(1)" << endl;
+               FreqSearch(1);
        }
        if(i == 30) {
-               Search(2);
+               //cout << "About to search(2)" << endl;
+               FreqSearch(2);
                i = 0;
        }
        ++i;
 }
-/*
-// Remove from list only if not needed by the AI system
-void FGATCMgr::CommRemoveFromList(const char* id, atc_type tp) {
-       AirportATC a;
+
+// Remove from list only if not needed by the AI system or the other comm channel
+// TODO - implement me!!
+void FGATCMgr::CommRemoveFromList(const char* id, atc_type tp, int chan) {
+       /*AirportATC a;
        if(GetAirportATCDetails((string)id, &a)) {
                if(a.set_by_AI) {
                        // Don't remove
@@ -281,19 +279,23 @@ void FGATCMgr::CommRemoveFromList(const char* id, atc_type tp) {
                } else {
                        // remove
                }
-       }
+       }*/
+       
+       // Hack - need to implement this properly
+       RemoveFromList(id, tp);
 }
-*/    
+    
 
 // Remove from list - should only be called from above or similar
+// This function *will* remove it from the list regardless of who else might want it.
 void FGATCMgr::RemoveFromList(const char* id, atc_type tp) {
        //cout << "Requested type = " << tp << '\n';
        //cout << "id = " << id << '\n';
        atc_list_itr = atc_list.begin();
        while(atc_list_itr != atc_list.end()) {
                //cout << "type = " << (*atc_list_itr)->GetType() << '\n';
-               //cout << "Ident = " << (*atc_list_itr)->GetIdent() << '\n';
-               if( (!strcmp((*atc_list_itr)->GetIdent(), id))
+               //cout << "Ident = " << (*atc_list_itr)->get_ident() << '\n';
+               if( (!strcmp((*atc_list_itr)->get_ident(), id))
                        && ((*atc_list_itr)->GetType() == tp) ) {
                                //Before removing it stop it transmitting!!
                                //cout << "OBLITERATING FROM LIST!!!\n";
@@ -308,19 +310,19 @@ void FGATCMgr::RemoveFromList(const char* id, atc_type tp) {
 }
 
 
-//DCL - this routine untested so far.
 // Find in list - return a currently active ATC pointer given ICAO code and type
+// Return NULL if the given service is not in the list
+// - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
 FGATC* FGATCMgr::FindInList(const char* id, atc_type tp) {
        atc_list_itr = atc_list.begin();
        while(atc_list_itr != atc_list.end()) {
-               if( (!strcmp((*atc_list_itr)->GetIdent(), id))
+               if( (!strcmp((*atc_list_itr)->get_ident(), id))
                && ((*atc_list_itr)->GetType() == tp) ) {
                        return(*atc_list_itr);
                }       // Note that that can upset where we are in the list but that shouldn't really matter
                ++atc_list_itr;
        }
-       // We need a fallback position
-       SG_LOG(SG_GENERAL, SG_ALERT, "*** Failed to find FGATC* in FGATCMgr::FindInList - this should not happen!");
+       // If we get here it's not in the list
        return(NULL);
 }
 
@@ -351,8 +353,9 @@ FGATC* FGATCMgr::GetATCPointer(string icao, atc_type type) {
                        return(FindInList(icao.c_str(), type)); // DCL - this untested so far.
                } else {
                        FGTower* t = new FGTower;
-                       if(current_towerlist->query(a->lon, a->lat, a->elev, a->tower_freq, &tower)) {
-                               *t = tower;
+                       ATCData data;
+                       if(current_commlist->FindByFreq(a->lon, a->lat, a->elev, a->tower_freq, &data, TOWER)) {
+                               t->SetData(&data);
                                atc_list.push_back(t);
                                a->tower_active = true;
                                airport_atc_map[icao] = a;
@@ -396,7 +399,9 @@ void FGATCMgr::Render(string msg, string refname, bool repeating) {
                unsigned char* buf = v1.WriteMessage((char*)msg.c_str(), len, voice);
                if(voice) {
                        FGSimpleSound* simple = new FGSimpleSound(buf, len);
-                       simple->set_volume(2.0);
+                       // TODO - at the moment the volume is always set off comm1 
+                       // and can't be changed after the transmission has started.
+                       simple->set_volume(5.0 * fgGetDouble("/radios/comm[0]/volume"));
                        globals->get_soundmgr()->add(simple, refname);
                        if(repeating) {
                                globals->get_soundmgr()->play_looped(refname);
@@ -446,7 +451,7 @@ void FGATCMgr::doStandardDialog() {
        //cout << "comm1_type = " << comm1_type << endl;
        
        // Second - customise the dialog box
-       switch(comm1_type) {
+       switch(comm_type[0]) {
        case INVALID:
                atcDialogCommunicationOptions->newList(NULL);
                atcDialogMessage->setLabel("Not tuned in to any ATC service.");
@@ -480,312 +485,144 @@ void FGATCMgr::doStandardDialog() {
        // This is in ATCDialogOK()
 }
 
-////////////////////////////////////////////////////////////////
-//
-// TODO - The whole ATC frequency storage and search is really
-//        really ugly and needs reworking at some point.
-//
-////////////////////////////////////////////////////////////////
-// Search the specified comm channel (1 or 2)
-void FGATCMgr::Search(int chan) {
+// Search for ATC stations by frequency
+void FGATCMgr::FreqSearch(int channel) {
+       int chan = channel - 1;         // Convert to zero-based for the arrays
+
+       ATCData data;   
+       double freq = comm_node[chan]->getDoubleValue();
+       lon = lon_node->getDoubleValue();
+       lat = lat_node->getDoubleValue();
+       elev = elev_node->getDoubleValue() * SG_FEET_TO_METER;
        
-       if(chan == 1) {
-               ////////////////////////////////////////////////////////////////////////
-               // Comm1.
-               ////////////////////////////////////////////////////////////////////////
-               //cout << "In FGATCMgr::Search() - atc_list.size = " << atc_list.size() << '\n';
-               
-               comm1_freq = comm1_node->getDoubleValue();
-               //cout << "************* comm1_freq = " << comm1_freq << '\n';
-               double lon = lon_node->getDoubleValue();
-               double lat = lat_node->getDoubleValue();
-               double elev = elev_node->getDoubleValue() * SG_FEET_TO_METER;
-               
-               // We must be able to generalise some of the repetetive searching below!
-               
-               //Search for ATIS first
-               if(current_atislist->query(lon, lat, elev, comm1_freq, &atis)) {
-                       //cout << "atis found in radiostack search !!!!" << endl;
-                       //cout << "last_comm1_atis_ident = " << last_comm1_atis_ident << '\n';
-                       //cout << "comm1_type " << comm1_type << '\n';
-                       comm1_atis_ident = atis.GetIdent();
-                       comm1_atis_valid = true;
-                       if(last_comm1_atis_ident != comm1_atis_ident) {
-                               if(last_comm1_atis_ident != "") {
-                                       RemoveFromList(last_comm1_atis_ident, ATIS);
-                               }
-                               last_comm1_atis_ident = comm1_atis_ident;
-                               //cout << "last_comm1_atis_ident = " << last_comm1_atis_ident << '\n';
-                               comm1_type = ATIS;
-                               comm1_elev = atis.get_elev();
-                               comm1_range = FG_ATIS_DEFAULT_RANGE;
-                               comm1_effective_range = comm1_range;
-                               comm1_x = atis.get_x();
-                               comm1_y = atis.get_y();
-                               comm1_z = atis.get_z();
-                               FGATIS* a = new FGATIS;
-                               *a = atis;
-                               comm1_atc_ptr = a;
-                               a->SetDisplay();
-                               a->set_refname("atis1");
-                               atc_list.push_back(a);
-                               //cout << "Found a new atis station in range" << endl;
-                               //cout << " id = " << atis.GetIdent() << endl;
-                               return;  //This rather assumes that we never have more than one type of station in range.
-                       }
-               } else {
-                       if(comm1_atis_valid) {
-                               //cout << "Removing ATIS " << comm1_atis_ident << " from list\n";
-                               RemoveFromList(comm1_atis_ident, ATIS);
-                               comm1_atis_valid = false;
-                               if(comm1_type == ATIS) {
-                                       comm1_type = INVALID;
-                               }
-                               comm1_atis_ident = "";
-                               //comm1_trans_ident = "";
-                               last_comm1_atis_ident = "";
-                               comm1_atc_ptr = NULL;
+       // Query the data store and get the closest match if any
+       if(current_commlist->FindByFreq(lon, lat, elev, freq, &data)) {
+               // We have a match
+               // What's the logic?
+               // If this channel not previously valid then easy - add ATC to list
+               // If this channel was valid then - Have we tuned to a different service?
+               // If so - de-register one and add the other
+               if(comm_valid[chan]) {
+                       if((comm_ident[chan] == data.ident) && (comm_type[chan] == data.type)) {
+                               // Then we're still tuned into the same service so do nought and return
+                               return;
+                       } else {
+                               // Something's changed - either the location or the service type
+                               // We need to feed the channel in so we're not removing it if we're also tuned in on the other channel
+                               CommRemoveFromList(comm_ident[chan], comm_type[chan], chan);
                        }
-                       //cout << "not picking up atis" << endl;
                }
+               // At this point we can assume that we need to add the service.
+               comm_ident[chan] = (data.ident).c_str();
+               comm_type[chan] = data.type;
+               comm_x[chan] = (double)data.x;
+               comm_y[chan] = (double)data.y;
+               comm_z[chan] = (double)data.z;
+               comm_lon[chan] = (double)data.lon;
+               comm_lat[chan] = (double)data.lat;
+               comm_elev[chan] = (double)data.elev;
+               comm_valid[chan] = true;
                
-               //Next search for tower
-               //cout << "comm1_freq = " << comm1_freq << '\n';
-               if(current_towerlist->query(lon, lat, elev, comm1_freq, &tower)) {
-                       //cout << "tower found in radiostack search !!!!" << endl;
-                       comm1_tower_ident = tower.GetIdent();
-                       //cout << "comm1_tower_ident = " << comm1_tower_ident << '\n';
-                       comm1_tower_valid = true;
-                       if(last_comm1_tower_ident != comm1_tower_ident) {
-                               if(last_comm1_tower_ident != "") {
-                                       RemoveFromList(last_comm1_tower_ident, TOWER);
-                               }
-                               last_comm1_tower_ident = comm1_tower_ident;
-                               comm1_type = TOWER;
-                               comm1_elev = tower.get_elev();
-                               comm1_range = FG_TOWER_DEFAULT_RANGE;
-                               comm1_effective_range = comm1_range;
-                               comm1_x = tower.get_x();
-                               comm1_y = tower.get_y();
-                               comm1_z = tower.get_z();
+               // This was a switch-case statement but the compiler didn't like the new variable creation with it. 
+               if(comm_type[chan] == ATIS) {
+                       FGATIS* a = new FGATIS;
+                       a->SetData(&data);
+                       comm_atc_ptr[chan] = a;
+                       a->SetDisplay();
+                       //a->set_refname((chan) ? "atis2" : "atis1");           // FIXME - that line is limited to 2 channels
+                       atc_list.push_back(a);
+               } else if (comm_type[chan] == TOWER) {
+                       FGATC* app = FindInList(comm_ident[chan], TOWER);
+                       if(app != NULL) {
+                               // The station is already in the ATC list
+                               app->SetDisplay();
+                       } else {
+                               // Generate the station and put in the ATC list
                                FGTower* t = new FGTower;
-                               *t = tower;
-                               comm1_atc_ptr = t;
+                               t->SetData(&data);
+                               comm_atc_ptr[chan] = t;
                                t->SetDisplay();
                                atc_list.push_back(t);
-                               //cout << "Found a new tower station in range" << endl;
-                               //cout << " id = " << tower.GetIdent() << endl;
-                               return;  //This rather assumes that we never have more than one type of station in range.
-                       }
-               } else {
-                       if(comm1_tower_valid) {
-                               //cout << "removing tower\n";
-                               RemoveFromList(comm1_tower_ident, TOWER);
-                               //comm1_valid = false;
-                               if(comm1_type == TOWER) {
-                                       comm1_type = INVALID;   // Only invalidate if we haven't switched it to something else
-                               }
-                               comm1_tower_valid = false;
-                               comm1_tower_ident = "";
-                               last_comm1_tower_ident = "";
-                               comm1_atc_ptr = NULL;
-                               //comm1_ident = "";
-                               //comm1_trans_ident = "";
-                               //last_comm1_ident = "";
-                       }
-                       //cout << "not picking up tower" << endl;
-               }
-               /*
-               //Next search for Ground control
-               if(current_groundlist->query(lon, lat, elev, comm1_freq, &ground)) {
-                       //cout << "Ground Control found in radiostack search !!!!" << endl;
-                       comm1_ident = ground.GetIdent();
-                       comm1_valid = true;
-                       if((last_comm1_ident != comm1_ident) || (comm1_type != GROUND)) {
-                               if(last_comm1_ident != "") {
-                                       RemoveFromList(last_comm1_ident, GROUND);
-                               }
-                               last_comm1_ident = comm1_ident;
-                               comm1_type = GROUND;
-                               comm1_elev = ground.get_elev();
-                               comm1_range = FG_GROUND_DEFAULT_RANGE;
-                               comm1_effective_range = comm1_range;
-                               comm1_x = ground.get_x();
-                               comm1_y = ground.get_y();
-                               comm1_z = ground.get_z();
-                               FGGround* g = new FGGround;
-                               *g = ground;
-                               g->SetDisplay();
-                               atc_list.push_back(g);
-                               // For now we will automatically make contact with ground when the radio is tuned.
-                               // This rather assumes that the user tunes the radio at the appropriate place
-                               // (ie. having just turned off the runway) and only uses ground control on arrival
-                               // but its a start!
-                               g->NewArrival(current_plane);
-                               //cout << "Found a new ground station in range" << endl;
-                               //cout << " id = " << ground.GetIdent() << endl;
-                               return;  //This rather assumes that we never have more than one type of station in range.
                        }
-               } else {
-                       if((comm1_valid) && (comm1_type == GROUND)) {
-                               RemoveFromList(comm1_ident, GROUND);
-                               comm1_valid = false;
-                               comm1_type = INVALID;
-                               comm1_ident = "";
-                               //comm1_trans_ident = "";
-                               last_comm1_ident = "";
+               } /*else if (comm_type[chan] == APPROACH) {
+                       // We have to be a bit more carefull here since approaches are also searched by area
+                       FGATC* app = FindInList(comm_ident[chan], APPROACH);
+                       if(app != NULL) {
+                               // The station is already in the ATC list
+                               app->AddPlane("Player");
+                               app->SetDisplay();
+                       } else {
+                               // Generate the station and put in the ATC list
+                               FGApproach* a = new FGApproach;
+                               a->SetData(&data);
+                               a->AddPlane("Player");
+                               atc_list.push_back(a);
+                       }                       
+               }*/
+       } else {
+               if(comm_valid[chan]) {
+                       if(comm_type[chan] != APPROACH) {
+                               // Currently approaches are removed by Alexander's out-of-range mechanism
+                               CommRemoveFromList(comm_ident[chan], comm_type[chan], chan);
                        }
-                       //cout << "not picking up ground control" << endl;
+                       // Note that we *don't* call SetNoDisplay() here because the other comm channel
+                       // might be tuned into the same station - this is handled by CommRemoveFromList(...)
+                       comm_type[chan] = INVALID;
+                       comm_atc_ptr[chan] = NULL;
+                       comm_valid[chan] = false;
                }
-               */
-               // ================================================================================
-               // Search for Approach stations
-               // ================================================================================
-               // init number of approach stations reachable by plane
-               int  num_app = 0;
+       }
+}
+
+
+// Search ATC stations by area in order that we appear 'on the radar'
+void FGATCMgr::AreaSearch() {
+       // Search for Approach stations
+       comm_list_type approaches;
+       comm_list_iterator app_itr;
+       
+       lon = lon_node->getDoubleValue();
+       lat = lat_node->getDoubleValue();
+       elev = elev_node->getDoubleValue() * SG_FEET_TO_METER;
+       
+       // search stations in range
+       int num_app = current_commlist->FindByPos(lon, lat, elev, &approaches, APPROACH);
+       if (num_app != 0) {
+               //cout << num_app << " approaches found in radiostack search !!!!" << endl;
                
-               // search stations in range
-               current_approachlist->query_bck(lon, lat, elev, approaches, max_app, num_app);
-               if (num_app != 0) {
-                       //cout << num_app << " approaches found in radiostack search !!!!" << endl;
+               for(app_itr = approaches.begin(); app_itr != approaches.end(); app_itr++) {
                        
-                       for ( int i=0; i<num_app; i++ ) {
-                               bool new_app = true;
-                               approach_ident = approaches[i].GetIdent();
-                               
-                               // check if station already exists on ATC stack
-                               atc_list_itr = atc_list.begin();
-                               while(atc_list_itr != atc_list.end()) {
-                                       //cout << "ATC list: " << (*atc_list_itr)->GetIdent() << endl;
-                                       if((!strcmp((*atc_list_itr)->GetIdent(), approach_ident))
-                                               && ((*atc_list_itr)->GetType() == APPROACH) ) {
-                                                       new_app = false;
-                                                       string pid = "Player";
-                                                       (*atc_list_itr)->AddPlane(pid);
-                                                       (*atc_list_itr)->Update();
-                                                       break;
-                                               }
-                                       ++atc_list_itr;
-                               }
-                               // generate new Approach on ATC stack
-                               if (new_app) {
-                                       FGApproach* a = new FGApproach;
-                                       *a = approaches[i];
-                                       string pid = "Player";
-                                       a->AddPlane(pid);
-                                       a->Update();
-                                       a->SetDisplay();
-                                       comm1_atc_ptr = a;
-                                       atc_list.push_back(a);
-                                       //cout << "Found a new approach station in range: Id = " 
-                                       //     << approaches[i].GetIdent() << endl;
-                               }
-                       }
-               }
-               
-               // remove planes which are out of range
-               atc_list_itr = atc_list.begin();
-               while(atc_list_itr != atc_list.end()) {
-                       if((*atc_list_itr)->GetType() == APPROACH ) {
-                               int np = (*atc_list_itr)->RemovePlane();
-                               // if approach has no planes left remove it from ATC list
-                               if ( np == 0) {
-                                       (*atc_list_itr)->SetNoDisplay();
-                                       (*atc_list_itr)->Update();
-                                       delete (*atc_list_itr);
-                                       atc_list_itr = atc_list.erase(atc_list_itr);
-                                       break;     // the other stations will be checked next time
-                               }
-                       }
-                       ++atc_list_itr;
-               }
-               
-       } else {        // chan = 2
-               
-               ////////////////////////////////////////////////////////////////////////
-               // Comm2.
-               ////////////////////////////////////////////////////////////////////////
-               //cout << "In FGATCMgr::Search() - atc_list.size = " << atc_list.size() << '\n';
-               
-               comm2_freq = comm2_node->getDoubleValue();
-               //cout << "************* comm1_freq = " << comm1_freq << '\n';
-               double lon = lon_node->getDoubleValue();
-               double lat = lat_node->getDoubleValue();
-               double elev = elev_node->getDoubleValue() * SG_FEET_TO_METER;
-               
-               if(current_atislist->query(lon, lat, elev, comm2_freq, &atis)) {
-                       comm2_atis_ident = atis.GetIdent();
-                       comm2_atis_valid = true;
-                       if(last_comm2_atis_ident != comm2_atis_ident) {
-                               if(last_comm2_atis_ident != "") {
-                                       RemoveFromList(last_comm2_atis_ident, ATIS);
-                               }
-                               last_comm2_atis_ident = comm2_atis_ident;
-                               comm2_type = ATIS;
-                               comm2_elev = atis.get_elev();
-                               comm2_range = FG_ATIS_DEFAULT_RANGE;
-                               comm2_effective_range = comm2_range;
-                               comm2_x = atis.get_x();
-                               comm2_y = atis.get_y();
-                               comm2_z = atis.get_z();
-                               FGATIS* a = new FGATIS;
-                               *a = atis;
-                               comm2_atc_ptr = a;
-                               a->SetDisplay();
-                               a->set_refname("atis2");
+                       FGATC* app = FindInList((app_itr->ident).c_str(), app_itr->type);
+                       if(app != NULL) {
+                               // The station is already in the ATC list
+                               app->AddPlane("Player");
+                               //app->Update();
+                       } else {
+                               // Generate the station and put in the ATC list
+                               FGApproach* a = new FGApproach;
+                               a->SetData(&(*app_itr));
+                               a->AddPlane("Player");
+                               //a->Update();
                                atc_list.push_back(a);
-                               //cout << "Found a new atis station in range" << endl;
-                               //cout << " id = " << atis.GetIdent() << endl;
-                               return;  //This rather assumes that we never have more than one type of station in range.
-                       }
-               } else {
-                       if(comm2_atis_valid) {
-                               RemoveFromList(comm2_atis_ident, ATIS);
-                               comm2_atis_valid = false;
-                               if(comm2_type == ATIS) {
-                                       comm2_type = INVALID;
-                               }
-                               comm2_atis_ident = "";
-                               //comm2_trans_ident = "";
-                               last_comm2_atis_ident = "";
-                               comm2_atc_ptr = NULL;
                        }
                }
-               
-               if(current_towerlist->query(lon, lat, elev, comm2_freq, &tower)) {
-                       //cout << "tower found in radiostack search !!!!" << endl;
-                       comm2_tower_ident = tower.GetIdent();
-                       comm2_tower_valid = true;
-                       if(last_comm2_tower_ident != comm2_tower_ident) {
-                               if(last_comm2_tower_ident != "") {
-                                       RemoveFromList(last_comm2_tower_ident, TOWER);
-                               }
-                               last_comm2_tower_ident = comm2_tower_ident;
-                               comm2_type = TOWER;
-                               comm2_elev = tower.get_elev();
-                               comm2_range = FG_TOWER_DEFAULT_RANGE;
-                               comm2_effective_range = comm2_range;
-                               comm2_x = tower.get_x();
-                               comm2_y = tower.get_y();
-                               comm2_z = tower.get_z();
-                               FGTower* t = new FGTower;
-                               *t = tower;
-                               comm2_atc_ptr = t;
-                               t->SetDisplay();
-                               atc_list.push_back(t);
-                               return;
-                       }
-               } else {
-                       if(comm2_tower_valid) {
-                               RemoveFromList(comm2_tower_ident, TOWER);
-                               if(comm2_type == TOWER) {
-                                       comm2_type = INVALID;   // Only invalidate if we haven't switched it to something else
-                               }
-                               comm2_tower_valid = false;
-                               comm2_tower_ident = "";
-                               last_comm2_tower_ident = "";
-                               comm2_atc_ptr = NULL;
+       }
+       
+       // remove planes which are out of range
+       // TODO - I'm not entirely sure that this belongs here.
+       atc_list_itr = atc_list.begin();
+       while(atc_list_itr != atc_list.end()) {
+               if((*atc_list_itr)->GetType() == APPROACH ) {
+                       int np = (*atc_list_itr)->RemovePlane();
+                       // if approach has no planes left remove it from ATC list
+                       if ( np == 0) {
+                               (*atc_list_itr)->SetNoDisplay();
+                               (*atc_list_itr)->Update();
+                               delete (*atc_list_itr);
+                               atc_list_itr = atc_list.erase(atc_list_itr);
+                               break;     // the other stations will be checked next time
                        }
                }
+               ++atc_list_itr;
        }
 }
index 3628044103c2f76740b98d1c0f82ab4b1f160640..3e45af4bd996c38c4977caf17544102b943ee2d1 100644 (file)
@@ -42,8 +42,6 @@ SG_USING_STD(string);
 SG_USING_STD(list);
 SG_USING_STD(map);
 
-const int max_app = 20;
-
 // Structure for holding details of the ATC frequencies at a given airport, and whether they are in the active list or not.
 // These can then be cross referenced with the [atis][tower][etc]lists which are stored by frequency.
 // Non-available services are denoted by a frequency of zero.
@@ -100,19 +98,15 @@ private:
     double elev;
 
     // Type of ATC control that the user's radios are tuned to.
-    atc_type comm1_type;
-    atc_type comm2_type;
+    atc_type comm_type[2];
        
        // Pointer to the ATC station that the user is currently tuned into.
-       FGATC* comm1_atc_ptr;
-       FGATC* comm2_atc_ptr;
+       FGATC* comm_atc_ptr[2];
 
-    double comm1_freq;
-    double comm2_freq;
+    double comm_freq[2];
 
     // Pointers to users current communication frequencies.
-    SGPropertyNode* comm1_node;
-    SGPropertyNode* comm2_node;
+    SGPropertyNode* comm_node[2];
 
     // Pointers to current users position
     SGPropertyNode* lon_node;
@@ -121,44 +115,19 @@ private:
 
     // Position of the ATC that the comm radios are tuned to in order to decide 
        // whether transmission will be received.
-    double comm1_x, comm1_y, comm1_z, comm1_elev;
-    double comm2_x, comm2_y, comm2_z, comm2_elev;
-
-    double comm1_range, comm1_effective_range;
-    bool comm1_valid; 
-    bool comm1_atis_valid;
-    bool comm1_tower_valid;
-    bool comm1_approach_valid;
-    const char* comm1_ident;
-    const char* comm1_atis_ident;
-    const char* comm1_tower_ident;
-    const char* comm1_approach_ident;
-    const char* last_comm1_ident;
-    const char* last_comm1_atis_ident;
-    const char* last_comm1_tower_ident;
-    const char* last_comm1_approach_ident;
-       
-    double comm2_range, comm2_effective_range;
-    bool comm2_valid;
-    bool comm2_atis_valid;
-    bool comm2_tower_valid;
-    bool comm2_approach_valid;
-    const char* comm2_ident;
-    const char* comm2_atis_ident;
-    const char* comm2_tower_ident;
-    const char* comm2_approach_ident;
-    const char* last_comm2_ident;
-    const char* last_comm2_atis_ident;
-    const char* last_comm2_tower_ident;
-    const char* last_comm2_approach_ident;
-       
+    double comm_x[2], comm_y[2], comm_z[2], comm_lon[2], comm_lat[2], comm_elev[2];
+
+    double comm_range[2], comm_effective_range[2];
+    bool comm_valid[2]; 
+    const char* comm_ident[2];
+    const char* last_comm_ident[2];
+
     const char* approach_ident;
     bool last_in_range;
 
-    FGATIS atis;
+    //FGATIS atis;
     //FGGround ground;
     FGTower tower;
-    FGApproach approaches[max_app];
     FGApproach approach;
     //FGDeparture departure;
 
@@ -202,21 +171,32 @@ public:
        // Display a dialog box with options relevant to the currently tuned ATC service.
        void doStandardDialog();
        
-       atc_type GetComm1ATCType() { return(comm1_type); }
-       FGATC* GetComm1ATCPointer() { return(comm1_atc_ptr); }
-       atc_type GetComm2ATCType() { return(comm2_type); }
-       FGATC* GetComm2ATCPointer() { return(comm2_atc_ptr); }
+       atc_type GetComm1ATCType() { return(comm_type[0]); }
+       FGATC* GetComm1ATCPointer() { return(comm_atc_ptr[0]); }
+       atc_type GetComm2ATCType() { return(comm_type[1]); }
+       FGATC* GetComm2ATCPointer() { return(comm_atc_ptr[1]); }
        
 private:
 
     // Remove a class from the atc_list and delete it from memory
+       // *if* no other comm channel or AI plane is using it.
+    void CommRemoveFromList(const char* id, atc_type tp, int chan);
+
+    // Remove a class from the atc_list and delete it from memory
+       // Should be called from the above - not directly!!
     void RemoveFromList(const char* id, atc_type tp);
 
-    // Return a pointer to a class in the list (external interface to this is through GetATCPointer)
+    // Return a pointer to a class in the list given ICAO code and type
+       // (external interface to this is through GetATCPointer) 
+       // Return NULL if the given service is not in the list
+       // - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
     FGATC* FindInList(const char* id, atc_type tp);
 
     // Search the specified channel for stations on the same frequency and in range.
-    void Search(int chan);
+    void FreqSearch(int channel);
+       
+       // Search ATC stations by area in order that we appear 'on the radar'
+       void AreaSearch(); 
 
 };
 
index 261e24ee76f547d68c1ad533993b58f65b51c44d..c176199ce866fd7f7a52043c2020fc3292476c6d 100644 (file)
@@ -5,7 +5,8 @@ libATC_a_SOURCES = \
        atis.hxx atis.cxx atislist.hxx atislist.cxx \
        tower.hxx tower.cxx towerlist.hxx towerlist.cxx \
        approach.hxx approach.cxx approachlist.hxx approachlist.cxx \
-       ground.hxx ground.cxx groundlist.hxx groundlist.cxx \
+       ground.hxx ground.cxx \
+       commlist.hxx commlist.cxx \
        ATCdisplay.hxx ATCdisplay.cxx \
        ATCVoice.hxx ATCVoice.cxx \
        ATCmgr.hxx ATCmgr.cxx \
index c3b2390fc125604d423d860b8a73a9522215c094..273fd82ab2bdf346cac39ce6744566cd22eecf4a 100644 (file)
@@ -55,19 +55,12 @@ PlaneApp::PlaneApp()
 }
 
 //Constructor
-FGApproach::FGApproach()
-: type(0),
-  lon(0.0), lat(0.0), elev(0.0),
-  x(0.0), y(0.0), z(0.0),
-  freq(0),
+FGApproach::FGApproach() :
   bucket(0),
-  range(0.0),
   active_runway(""),
   active_rw_hdg(0.0),
   display(false),
   displaying(false),
-  ident(""),
-  name(""),
   num_planes(0),
   transmission(""),
   first(true),
@@ -106,6 +99,7 @@ void FGApproach::Update() {
     if ( planes[i].contact == 0) {
       double comm1_freq = comm1_node->getDoubleValue();
       if ( (int)(comm1_freq*100.0 + 0.5) == freq ) planes[i].contact = 1;
+         //cout << "comm1 = " << (int)(comm1_freq*100.0 + 0.5) << " freq = " << freq << '\n';
     }
     else if ( planes[i].contact == 1 ) {
       if ( planes[i].wpn == 0 ) {    // calculate initial waypoints
@@ -256,8 +250,9 @@ void FGApproach::get_active_runway() {
 #else
   double hdg = stationweather.get_wind_from_heading_deg();
 #endif
-  
+
   FGRunway runway;
+  //if ( runways.search( "EGNX", int(hdg), &runway) ) {
   if ( runways.search( ident, int(hdg), &runway) ) {
     active_runway = runway.rwy_no;
     active_rw_hdg = runway.heading;
index 0dfe949aeac0a43af00be82efad947b457ffea94..a5217abf595aa282b14caf3f5101069242a7da2c 100644 (file)
@@ -96,21 +96,12 @@ struct PlaneApp {
 
 class FGApproach : public FGATC {
 
-  char     type;
-  double   lon, lat;
-  double   elev;
-  double   x, y, z;
-  int      freq;
   int      bucket;
-  double   range;
-
   string active_runway;         
   double active_rw_hdg;
 
   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.
-  string   ident;              // Code of the airport its at.
-  string   name;               // Name transmitted in the broadcast.
   int      num_planes;          // number of planes on the stack
   PlaneApp planes[max_planes];  // Array of planes
   string   transmission;
@@ -146,20 +137,9 @@ public:
   //Indicate that this instance should not be outputting to the ATC display
   inline void SetNoDisplay(void) {display = false;}
   
-  inline char get_type() const { return type; }
-  inline double get_lon() const { return lon; }
-  inline double get_lat() const { return lat; }
-  inline double get_elev() const { return elev; }
-  inline double get_x() const { return x; }
-  inline double get_y() const { return y; }
-  inline double get_z() const { return z; }
   inline double get_bucket() const { return bucket; }
-  inline int get_freq() const { return freq; }
-  inline double get_range() const { return range; }
   inline int get_pnum() const { return num_planes; }
-  inline const char* GetIdent() { return ident.c_str(); }
   inline string get_trans_ident() { return trans_ident; }
-  inline string get_name() { return name; }
   inline atc_type GetType() { return APPROACH; }
   
 private:
@@ -198,66 +178,8 @@ private:
   
   //Update the transmission string
   void UpdateTransmission(void);
-  
-  friend istream& operator>> ( istream&, FGApproach& );
-};
 
-
-inline istream&
-operator >> ( istream& in, FGApproach& a )
-{
-    double f;
-    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.type;
-    
-    if ( a.type == '[' )
-      return in >> skipeol;
-
-    in >> a.lat >> a.lon >> a.elev >> f >> a.range 
-       >> a.ident;
-
-    a.name = "";
-    in >> ch;
-    a.name += ch;
-    while(1) {
-       //in >> noskipws
-       in.unsetf(ios::skipws);
-       in >> ch;
-       a.name += 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 << "approach.name = " << a.name << '\n';
-
-    a.freq = (int)(f*100.0 + 0.5);
-
-    // generate cartesian coordinates
-    Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS , a.lat * SGD_DEGREES_TO_RADIANS, 
-                 a.elev * SG_FEET_TO_METER );
-    Point3D cart = sgGeodToCart( geod );
-    a.x = cart.x();
-    a.y = cart.y();
-    a.z = cart.z();
-
-    // get bucket number
-    SGBucket buck(a.lon, a.lat);
-    a.bucket = buck.gen_index();
-
-    a.trans_ident = a.ident;
-    a.approach_failed = false;
-
-    return in >> skipeol;
-}
+};
 
 #endif // _FG_APPROACH_HXX
+
index 4da9521a8a69f28bf262aaabedbd7758adb00e46..f40cc72f8114c862d7907735586e5e9033416684 100644 (file)
@@ -48,187 +48,6 @@ FGApproachList::~FGApproachList( void ) {
 
 // load the approach data and build the map
 bool FGApproachList::init( SGPath path ) {
-
-    approachlist_freq.erase( approachlist_freq.begin(), approachlist_freq.end() );
-    approachlist_bck.erase( approachlist_bck.begin(), approachlist_bck.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;
-
-    cout << " APPROACH " << endl;
-#ifdef __MWERKS__
-    char c = 0;
-    while ( in.get(c) && c != '\0' ) {
-        in.putback(c);
-#else
-    while ( !in.eof() ) {
-#endif
-
-       FGApproach a;
-        in >> a;
-       if ( a.get_type() == '[' ) {
-           break;
-       }
-       //cout << " type = " << a.get_type() << endl;
-       //cout << " lon = " << a.get_lon() << endl;
-       //cout << " lat = " << a.get_lat() << endl;
-       //cout << " elev = " << a.get_elev() << endl;
-       //cout << " freq = " << a.get_freq() << endl;
-       //cout << " Airport Code = " << a.GetIdent() << endl; 
-       //cout << " Name = " << a.get_name() << endl; 
-
-       approachlist_freq[a.get_freq()].push_back(a);
-       approachlist_bck[int(a.get_bucket())].push_back(a);
-        in >> skipcomment;
-
-    }
-
     return true;
 }
 
-
-// query the database for the specified frequency, lon and lat are in
-// degrees, elev is in meters
-bool FGApproachList::query_freq( double lon, double lat, double elev, double freq,
-                           FGApproach *a )
-{
-  lon *= SGD_DEGREES_TO_RADIANS;
-  lat *= SGD_DEGREES_TO_RADIANS;
-
-  approach_list_type stations = approachlist_freq[(int)(freq*100.0 + 0.5)];
-  
-  approach_list_iterator current = stations.begin();
-  approach_list_iterator last = stations.end();
-  
-  // double az1, az2, s;
-  Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
-  Point3D station;
-  double d;
-  for ( ; current != last ; ++current ) {
-    //cout << "testing " << current->GetIdent() << endl;
-    station = Point3D(current->get_x(), current->get_y(), current->get_z());
-    //cout << "aircraft = " << aircraft << endl;
-    //cout << "station = " << station << endl;
-    
-    d = aircraft.distance3Dsquared( station );
-    
-    //cout << "  dist = " << sqrt(d)
-    //     << "  range = " << current->get_range() * SG_NM_TO_METER << endl;
-    //cout << "  Aircraft: lon = " << lon << "  lat = " << lat 
-    //     << "  elev = " << elev << endl;
-    //cout << "  Airport:  lon = " << current->get_lon() 
-    //     << "  lat = " << current->get_lat() 
-    //     << "  elev = " << current->get_elev() 
-    //     << "  z = " << current->get_z() << endl;
-    
-    // match up to twice the published range so we can model
-    // reduced signal strength
-    if ( d < (2 * current->get_range() * SG_NM_TO_METER 
-             * 2 * current->get_range() * SG_NM_TO_METER ) ) {
-      //cout << "matched = " << current->GetIdent() << endl;
-      *a = *current;
-      return true;
-    }
-  }
-  return false;
-}
-
-// query the database for the specified frequency, lon and lat are in
-// degrees, elev is in meters
-bool FGApproachList::query_bck( double lon, double lat, double elev, FGApproach *a, 
-                               int max_app, int &num_app)
-{
-
-  // get bucket number for plane position
-  SGBucket buck(lon, lat);
-
-  //cout << "plane bucket" << bucket << endl;
-
-  // get neigboring buckets
-  double max_range = 100;
-  int bx = int ( max_range*SG_NM_TO_METER / buck.get_width_m() / 2);
-  int by = int ( max_range*SG_NM_TO_METER / buck.get_height_m() / 2 );
-
-  // loop over bucket range 
-  for ( int i=-bx; i<bx; i++) {
-    for ( int j=-by; j<by; j++) {
-      buck = sgBucketOffset(lon, lat, i, j);
-      long int bucket = buck.gen_index();
-      //cout << "bucket number = " << bucket << endl;
-      approach_list_type stations = approachlist_bck[bucket];
-      approach_list_iterator current = stations.begin();
-      approach_list_iterator last = stations.end();
-      double rlon = lon * SGD_DEGREES_TO_RADIANS;
-      double rlat = lat * SGD_DEGREES_TO_RADIANS;
-      // double az1, az2, s;
-      Point3D aircraft = sgGeodToCart( Point3D(rlon, rlat, elev) );
-      Point3D station;
-      double d;
-      for ( ; current != last ; ++current ) {
-       station = Point3D(current->get_x(), current->get_y(), current->get_z());
-       d = aircraft.distance3Dsquared( station );
-       /*
-         cout << "  dist = " << sqrt(d)
-         << "  range = " << current->get_range() * SG_NM_TO_METER << endl;
-         cout << "  Aircraft: lon = " << lon
-         << "  lat = " << lat/SGD_DEGREES_TO_RADIANS 
-         << "  bucket = " << bucket
-         << "  elev = " << elev << endl;
-         cout << "  Airport:  Id = " << current->GetIdent() 
-         << "  lon = " << current->get_lon() 
-         << "  lat = " << current->get_lat() 
-         << "  elev = " << current->get_elev() 
-         << "  bucket = " << current->get_bucket() 
-         << "  z = " << current->get_z() << endl;
-       */
-       // match up to twice the published range so we can model
-       // reduced signal strength
-       if ( d < (current->get_range() * SG_NM_TO_METER 
-                 * current->get_range() * SG_NM_TO_METER ) ) {
-         //cout << "matched = " << current->GetIdent() << endl;
-         if (num_app < max_app) {
-           a[num_app] = *current;
-           num_app += 1;
-         }
-         else {
-           cout << "Approachlist error: Too many stations in range" << endl; 
-         }
-         
-         //return true;
-       }
-      }
-    }
-  }
-  return true; //DCL - added this to prevent a compiler warning
-}
-
-
-bool FGApproachList::get_name( string apt_id )
-{
-  string name;
-  double freq = 125.22;
-
-  approach_list_type stations = approachlist_freq[(int)(freq*100.0 + 0.5)];
-  
-  approach_list_iterator current = stations.begin();
-  approach_list_iterator last    = stations.end();
-
-  if(current != last) {  
-    cout << "ApproachList" << endl;
-    cout << "name" << current->get_name() << endl;
-    cout << "bucket" << current->get_bucket() << endl;
-  }
-
-  return 0;
-
-}
index cc53bd4f4ada9f4566d10b46a4899d3974dea7dd..d84b346e99708aeac12e2309e4c030c8be4b4db0 100644 (file)
@@ -59,16 +59,6 @@ public:
   
   // load the approach data and build the map
   bool init( SGPath path );
-  
-  // query the database for the specified frequency, lon and lat are
-  // in degrees, elev is in meters
-  bool query_freq( double lon, double lat, double elev, double freq, FGApproach *a );
-
-  // query the database for the specified bucket number, lon and lat are
-  // in degrees
-  bool query_bck( double lon, double lat, double elev, FGApproach *a, int max_app, int &num_app );
-
-  bool get_name( string apt_id  );
 
 };
 
index 25eba6d104d275d9a33b568928690c6861122140..344a3bc2ea39544a29fe2bb808a51ccf0cb5c9bc 100644 (file)
@@ -50,27 +50,21 @@ SG_USING_STD(cout);
 #include <Airports/runways.hxx>
 
 #include "atis.hxx"
-#include "atislist.hxx"
+#include "commlist.hxx"
+//#include "atislist.hxx"
 #include "ATCdisplay.hxx"
 #include "ATCutils.hxx"
 #include "ATCmgr.hxx"
 
 // Constructor
-FGATIS::FGATIS()
-: type(0),
-lon(0.0), lat(0.0),
-elev(0.0),
-x(0.0), y(0.0), z(0.0),
-freq(0),
-range(0),
+FGATIS::FGATIS() :
 display(false),
 displaying(false),
-ident(""),
-name(""),
 transmission(""),
 trans_ident(""),
 atis_failed(false),
 refname("atis")
+//type(ATIS)
 {
 }
 
@@ -136,7 +130,7 @@ void FGATIS::UpdateTransmission() {
        hours = atoi((time_str.substr(1,2)).c_str());   //Warning - this is fragile if the 
        //time string format changes
        //cout << "In atis.cxx, hours = " << hours << endl;
-       phonetic_id = current_atislist->GetCallSign(ident, hours, 0);
+       phonetic_id = current_commlist->GetCallSign(ident, hours, 0);
        phonetic_id_string = GetPhoneticIdent(phonetic_id);
        transmission += " ";
        transmission += phonetic_id_string;
index e5b785d8f270ccbfa4dfdf4876d969beff6b8506..d74c6ef19f84c2fde40e31cfd604aa0a9d29726e 100644 (file)
@@ -49,18 +49,12 @@ SG_USING_STD(string);
 
 //DCL - a complete guess for now.
 #define FG_ATIS_DEFAULT_RANGE 30
-
+       
 class FGATIS : public FGATC {
        
-       char type;
-       double lon, lat, elev;
-       double x, y, z;
-       int freq;
-       int range;
+       //atc_type type;
        bool display;           // Flag to indicate whether we should be outputting to the ATC display.
        bool displaying;                // Flag to indicate whether we are outputting to the ATC display.
-       string ident;           // Code of the airport its at.
-       string name;            // Name transmitted in the broadcast.
        string transmission;    // The actual ATIS transmission
        // This is not stored in default.atis but is generated
        // from the prevailing conditions when required.
@@ -92,18 +86,9 @@ class FGATIS : public FGATC {
        //Indicate that this instance should not be outputting to the ATC display
        inline void SetNoDisplay(void) {display = false;}
        
-       inline char get_type() const { return type; }
-       inline double get_lon() const { return lon; }
-       inline double get_lat() const { return lat; }
-       inline double get_elev() const { return elev; }
-       inline double get_x() const { return x; }
-       inline double get_y() const { return y; }
-       inline double get_z() const { return z; }
-       inline int get_freq() const { return freq; }
-       inline int get_range() const { return range; }
-       inline const char* GetIdent() { return ident.c_str(); }
-       inline string get_trans_ident() { return trans_ident; }
        inline atc_type GetType() { return ATIS; }
+       //inline void set_type(const atc_type tp) {type = tp;}
+       inline string get_trans_ident() { return trans_ident; }
        inline void set_refname(string r) { refname = r; } 
        
        private:
@@ -113,71 +98,7 @@ class FGATIS : public FGATC {
        //Update the transmission string
        void UpdateTransmission(void);
        
-       /* inline void set_type( char t ) { type = t; }
-       inline void set_lon( double l ) { lon = l; }
-       inline void set_lat( double l ) { lat = l; }
-       inline void set_elev( double e ) { elev = e; }
-       inline void set_freq( int f ) { freq = f; }
-       inline void set_range( int r ) { range = r; }
-       inline void set_dme( bool b ) { dme = b; }
-       inline void set_ident( char *i ) { strncpy( ident, i, 5 ); } */
-       
        friend istream& operator>> ( istream&, FGATIS& );
 };
 
-
-inline istream&
-operator >> ( istream& in, FGATIS& a )
-{
-       double f;
-       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.type;
-       
-       if ( a.type == '[' )
-               return in >> skipeol;
-       
-       in >> a.lat >> a.lon >> a.elev >> f >> a.range 
-       >> a.ident;
-       
-       a.name = "";
-       in >> ch;
-       a.name += ch;
-       while(1) {
-               //in >> noskipws
-               in.unsetf(ios::skipws);
-               in >> ch;
-               a.name += 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 << "atis.name = " << a.name << '\n';
-       
-       a.freq = (int)(f*100.0 + 0.5);
-       
-       // cout << a.ident << endl;
-       
-       // generate cartesian coordinates
-       Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS, a.lat * SGD_DEGREES_TO_RADIANS, a.elev );
-       Point3D cart = sgGeodToCart( geod );
-       a.x = cart.x();
-       a.y = cart.y();
-       a.z = cart.z();
-       
-       a.trans_ident = a.ident;
-       a.atis_failed = false;
-       
-       return in >> skipeol;
-}
-
 #endif // _FG_ATIS_HXX
index 08e440fec85fa851b3191aa795f11a738637cde2..e713ad15c25d9b372f1b0b5e2acf457d19e3a598 100644 (file)
 #  include <config.h>
 #endif
 
-#include <simgear/debug/logstream.hxx>
-#include <simgear/misc/sgstream.hxx>
-#include <simgear/math/sg_geodesy.hxx>
-#include <simgear/math/sg_random.h>
-
 #include "atislist.hxx"
 
 
@@ -47,137 +42,6 @@ FGATISList::~FGATISList( void ) {
 
 // load the navaids and build the map
 bool FGATISList::init( SGPath path ) {
-
-    atislist.erase( atislist.begin(), atislist.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 >> skipcomment;
-
-#ifdef __MWERKS__
-    char c = 0;
-    while ( in.get(c) && c != '\0' ) {
-        in.putback(c);
-#else
-    while ( !in.eof() ) {
-#endif
-    
-        FGATIS a;
-        in >> a;
-       if ( a.get_type() == '[' ) {
-            break;
-        }
-       
-       /* cout << "id = " << a.GetIdent() << endl;
-       cout << " type = " << a.get_type() << endl;
-       cout << " lon = " << a.get_lon() << endl;
-       cout << " lat = " << a.get_lat() << endl;
-       cout << " elev = " << a.get_elev() << endl;
-       cout << " freq = " << a.get_freq() << endl;
-       cout << " range = " << a.get_range() << endl << endl; */
-
-        atislist[a.get_freq()].push_back(a);
-        in >> skipcomment;
-
-    }
-
     return true;
 }
 
-
-// query the database for the specified frequency, lon and lat are in
-// degrees, elev is in meters
-bool FGATISList::query( double lon, double lat, double elev, double freq,
-                      FGATIS *a )
-{
-    lon *= SGD_DEGREES_TO_RADIANS;
-    lat *= SGD_DEGREES_TO_RADIANS;
-
-    atis_list_type stations = atislist[(int)(freq*100.0 + 0.5)];
-
-    atis_list_iterator current = stations.begin();
-    atis_list_iterator last = stations.end();
-
-    // double az1, az2, s;
-    Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
-    Point3D station;
-    double d;
-    for ( ; current != last ; ++current ) {
-       //cout << "testing " << current->get_ident() << endl;
-       station = Point3D(current->get_x(), current->get_y(), current->get_z());
-       //cout << "aircraft = " << aircraft << endl;
-       //cout << "station = " << station << endl;
-
-       d = aircraft.distance3Dsquared( station );
-
-       //cout << "  dist = " << sqrt(d)
-       //     << "  range = " << current->get_range() * SG_NM_TO_METER << endl;
-
-       // match up to twice the published range so we can model
-       // reduced signal strength
-       if ( d < (2 * current->get_range() * SG_NM_TO_METER 
-                 * 2 * current->get_range() * SG_NM_TO_METER ) ) {
-           //cout << "matched = " << current->get_ident() << endl;
-           *a = *current;
-           return true;
-       }
-    }
-
-    return false;
-}
-
-
-int FGATISList::GetCallSign( string apt_id, int hours, int mins )
-{
-    atis_transmission_type tran;
-
-    if(atislog.find(apt_id) == atislog.end()) {
-       // This station has not transmitted yet - return a random identifier
-       // and add the transmission to the log
-       tran.hours = hours;
-       tran.mins = mins;
-       sg_srandom_time();
-       tran.callsign = int(sg_random() * 25) + 1;      // This *should* give a random int between 1 and 26
-       //atislog[apt_id].push_back(tran);
-       atislog[apt_id] = tran;
-    } else {
-       // This station has transmitted - calculate the appropriate identifier
-       // and add the transmission to the log if it has changed
-       tran = atislog[apt_id];
-       // This next bit assumes that no-one comes back to the same ATIS station
-       // after running FlightGear for more than 24 hours !!
-       if((tran.hours == hours) && (tran.mins == mins)) {
-           return(tran.callsign);
-       } else {
-           if(tran.hours == hours) {
-               // The minutes must have changed
-               tran.mins = mins;
-               tran.callsign++;
-           } else {
-               if(hours < tran.hours) {
-                   hours += 24;
-               }
-               tran.callsign += (hours - tran.hours);
-               if(mins != 0) {
-                   // Assume transmissions were made on every hour
-                   tran.callsign++;
-               }
-               tran.hours = hours;
-               tran.mins = mins;
-           }
-           // Wrap if we've exceeded Zulu
-           if(tran.callsign > 26) {
-               tran.callsign -= 26;
-           }
-           // And write the new transmission to the log
-           atislog[apt_id] = tran;
-       }
-    }
-    return(tran.callsign);
-}
index f0f5474a8d10ed4707a7ff94606e4c670c94f0c1..3370aaf86214c36ccf90eea52748bd2c955be3cf 100644 (file)
@@ -52,21 +52,6 @@ class FGATISList {
 
     atis_map_type atislist;
 
-    // Add structure and map for storing a log of atis transmissions
-    // made in this session of FlightGear.  This allows the callsign
-    // to be allocated correctly wrt time.
-    typedef struct {
-       int hours;
-       int mins;
-       int callsign;
-    } atis_transmission_type;
-
-    typedef map < string, atis_transmission_type > atis_log_type;
-    typedef atis_log_type::iterator atis_log_iterator;
-    typedef atis_log_type::const_iterator atis_log_const_iterator;
-
-    atis_log_type atislog;
-
 public:
 
     FGATISList();
@@ -74,13 +59,6 @@ public:
 
     // load all atis and build the map
     bool init( SGPath path );
-
-    // query the database for the specified frequency, lon and lat are
-    // in degrees, elev is in meters
-    bool query( double lon, double lat, double elev, double freq, FGATIS *a );
-
-    // Return the callsign for a transmission given transmission time and airpord id
-    int GetCallSign( string apt_id, int hours, int mins );
 };
 
 
diff --git a/src/ATC/commlist.cxx b/src/ATC/commlist.cxx
new file mode 100644 (file)
index 0000000..1799055
--- /dev/null
@@ -0,0 +1,252 @@
+// commlist.cxx -- comm frequency lookup class
+//
+// Written by David Luff and Alexander Kappes, started Jan 2003.
+// 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.
+
+
+#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 <simgear/math/sg_random.h>
+#include <simgear/bucket/newbucket.hxx>
+
+#include "commlist.hxx"
+//#include "atislist.hxx"
+
+
+FGCommList *current_commlist;
+
+
+// Constructor
+FGCommList::FGCommList( void ) {
+}
+
+
+// Destructor
+FGCommList::~FGCommList( void ) {
+}
+
+
+// load the navaids and build the map
+bool FGCommList::init( SGPath path ) {
+
+       SGPath temp = path;
+    commlist_freq.erase(commlist_freq.begin(), commlist_freq.end());
+       commlist_bck.erase(commlist_bck.begin(), commlist_bck.end());
+    temp.append( "ATC/default.atis" );
+       LoadComms(temp);
+       temp = path;
+       temp.append( "ATC/default.tower" );
+       LoadComms(temp);
+       temp = path;
+       temp.append( "ATC/default.approach" );
+       LoadComms(temp);
+       return true;
+}
+       
+
+bool FGCommList::LoadComms(SGPath path) {
+
+    sg_gzifstream fin( path.str() );
+    if ( !fin.is_open() ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
+        exit(-1);
+    }
+       
+    // read in each line of the file
+    fin >> skipcomment;
+
+#ifdef __MWERKS__
+    char c = 0;
+    while ( fin.get(c) && c != '\0' ) {
+        fin.putback(c);
+#else
+    while ( !fin.eof() ) {
+#endif
+        ATCData a;
+               fin >> a;
+               if(a.type == INVALID) {
+            break;
+        }
+               
+               // Push all stations onto frequency map
+        commlist_freq[a.freq].push_back(a);
+               
+               // Push approach stations onto bucket map as well
+               if(a.type == APPROACH) {
+                       // get bucket number
+               SGBucket bucket(a.lon, a.lat);
+               int bucknum = bucket.gen_index();
+                       commlist_bck[bucknum].push_back(a);
+               }
+               
+        fin >> skipcomment;
+    }
+    return true;       
+}
+
+
+// query the database for the specified frequency, lon and lat are in
+// degrees, elev is in meters
+// If no atc_type is specified, it returns true if any non-invalid type is found
+// If atc_type is specifed, returns true only if the specified type is found
+bool FGCommList::FindByFreq( double lon, double lat, double elev, double freq,
+                                               ATCData* ad, atc_type tp )
+{
+       lon *= SGD_DEGREES_TO_RADIANS;
+       lat *= SGD_DEGREES_TO_RADIANS;
+       
+       comm_list_type stations = commlist_freq[(int)(freq*100.0 + 0.5)];
+       comm_list_iterator current = stations.begin();
+       comm_list_iterator last = stations.end();
+       
+       // double az1, az2, s;
+       Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
+       Point3D station;
+       double d;
+       // TODO - at the moment this loop returns the first match found in range
+       // We want to return the closest match in the event of a frequency conflict
+       for ( ; current != last ; ++current ) {
+               //cout << "testing " << current->get_ident() << endl;
+               station = Point3D(current->x, current->y, current->z);
+               //cout << "aircraft = " << aircraft << endl;
+               //cout << "station = " << station << endl;
+               
+               d = aircraft.distance3Dsquared( station );
+               
+               //cout << "  dist = " << sqrt(d)
+               //     << "  range = " << current->get_range() * SG_NM_TO_METER << endl;
+               
+               // match up to twice the published range so we can model
+               // reduced signal strength
+               if ( d < (2 * current->range * SG_NM_TO_METER 
+               * 2 * current->range * SG_NM_TO_METER ) ) {
+                       //cout << "matched = " << current->get_ident() << endl;
+                       if((tp == INVALID) || (tp == (*current).type)) {
+                               *ad = *current;
+                               return true;
+                       }
+               }
+       }
+       
+       return false;
+}
+
+
+int FGCommList::FindByPos(double lon, double lat, double elev, comm_list_type* stations, atc_type tp)
+{
+       // number of relevant stations found within range
+       int found = 0;
+       stations->erase(stations->begin(), stations->end());
+       
+       // get bucket number for plane position
+       SGBucket buck(lon, lat);
+
+       // get neigboring buckets
+       int max_range = 100;
+       int bx = (int)( max_range*SG_NM_TO_METER / buck.get_width_m() / 2);
+       int by = (int)( max_range*SG_NM_TO_METER / buck.get_height_m() / 2 );
+       
+       // loop over bucket range 
+       for ( int i=-bx; i<bx; i++) {
+               for ( int j=-by; j<by; j++) {
+                       buck = sgBucketOffset(lon, lat, i, j);
+                       long int bucket = buck.gen_index();
+                       comm_list_type Fstations = commlist_bck[bucket];
+                       comm_list_iterator current = Fstations.begin();
+                       comm_list_iterator last = Fstations.end();
+                       
+                       double rlon = lon * SGD_DEGREES_TO_RADIANS;
+                       double rlat = lat * SGD_DEGREES_TO_RADIANS;
+                       
+                       // double az1, az2, s;
+                       Point3D aircraft = sgGeodToCart( Point3D(rlon, rlat, elev) );
+                       Point3D station;
+                       double d;
+                       for(; current != last; ++current) {
+                               if((current->type == tp) || (tp == INVALID)) {
+                                       station = Point3D(current->x, current->y, current->z);
+                                       d = aircraft.distance3Dsquared( station );
+                                       if ( d < (current->range * SG_NM_TO_METER 
+                                       * current->range * SG_NM_TO_METER ) ) {
+                                               stations->push_back(*current);
+                                               ++found;
+                                       }
+                               }
+                       }
+               }
+       }
+       return found;
+}
+
+
+// TODO - this function should move somewhere else eventually!
+// Return an appropriate call-sign for an ATIS transmission.
+int FGCommList::GetCallSign( string apt_id, int hours, int mins )
+{
+       atis_transmission_type tran;
+       
+       if(atislog.find(apt_id) == atislog.end()) {
+               // This station has not transmitted yet - return a random identifier
+               // and add the transmission to the log
+               tran.hours = hours;
+               tran.mins = mins;
+               sg_srandom_time();
+               tran.callsign = int(sg_random() * 25) + 1;      // This *should* give a random int between 1 and 26
+               //atislog[apt_id].push_back(tran);
+               atislog[apt_id] = tran;
+       } else {
+               // This station has transmitted - calculate the appropriate identifier
+               // and add the transmission to the log if it has changed
+               tran = atislog[apt_id];
+               // This next bit assumes that no-one comes back to the same ATIS station
+               // after running FlightGear for more than 24 hours !!
+               if((tran.hours == hours) && (tran.mins == mins)) {
+                       return(tran.callsign);
+               } else {
+                       if(tran.hours == hours) {
+                               // The minutes must have changed
+                               tran.mins = mins;
+                               tran.callsign++;
+                       } else {
+                               if(hours < tran.hours) {
+                                       hours += 24;
+                               }
+                               tran.callsign += (hours - tran.hours);
+                               if(mins != 0) {
+                                       // Assume transmissions were made on every hour
+                                       tran.callsign++;
+                               }
+                               tran.hours = hours;
+                               tran.mins = mins;
+                       }
+                       // Wrap if we've exceeded Zulu
+                       if(tran.callsign > 26) {
+                               tran.callsign -= 26;
+                       }
+                       // And write the new transmission to the log
+                       atislog[apt_id] = tran;
+               }
+       }
+       return(tran.callsign);
+}
diff --git a/src/ATC/commlist.hxx b/src/ATC/commlist.hxx
new file mode 100644 (file)
index 0000000..482ad6a
--- /dev/null
@@ -0,0 +1,124 @@
+// commlist.hxx -- comm frequency lookup class
+//
+// Written by David Luff and Alexander Kappes, started Jan 2003.
+// 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.
+
+/*****************************************************************
+*
+* FGCommList is used to store communication frequency information
+* for the ATC and AI subsystems.  Two maps are maintained - one
+* searchable by location and one searchable by frequency.  The
+* data structure returned from the search is the ATCData struct
+* defined in ATC.hxx, containing location, frequency, name, range
+* and type of the returned station.
+*
+******************************************************************/
+
+#ifndef _FG_COMMLIST_HXX
+#define _FG_COMMLIST_HXX
+
+
+#include <simgear/compiler.h>
+#include <simgear/misc/sg_path.hxx>
+
+#include <map>
+#include <list>
+#include <string>
+
+#include "ATC.hxx"
+#include "atis.hxx"
+
+SG_USING_STD(map);
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+// A list of ATC stations
+typedef list < ATCData > comm_list_type;
+typedef comm_list_type::iterator comm_list_iterator;
+typedef comm_list_type::const_iterator comm_list_const_iterator;
+
+// A map of ATC station lists
+typedef map < int, comm_list_type > comm_map_type;
+typedef comm_map_type::iterator comm_map_iterator;
+typedef comm_map_type::const_iterator comm_map_const_iterator;
+
+
+class FGCommList {
+       
+public:
+
+    FGCommList();
+    ~FGCommList();
+
+    // load all comm frequencies and build the map
+    bool init( SGPath path );
+
+    // query the database for the specified frequency, lon and lat are
+    // in degrees, elev is in meters
+       // If no atc_type is specified, it returns true if any non-invalid type is found
+       // If atc_type is specifed, returns true only if the specified type is found
+       // The data found is written into the passed-in ATCData structure.
+    bool FindByFreq( double lon, double lat, double elev, double freq, ATCData* ad, atc_type tp = INVALID );
+       
+    // query the database by location, lon and lat are
+    // in degrees, elev is in meters
+       // Returns the number of stations of the specified type that are in range, and pushes them into stations
+       // If atc_type is specifed, returns the number of all stations in range, and pushes them into stations
+       // ** stations is erased before use **
+    int FindByPos( double lon, double lat, double elev, comm_list_type* stations, atc_type tp = INVALID );
+
+    // Return the callsign for an ATIS transmission given transmission time and airpord id
+       // This maybe should get moved somewhere else!!
+    int GetCallSign( string apt_id, int hours, int mins );
+       
+private:
+       
+       // Comm stations mapped by frequency
+       comm_map_type commlist_freq;    
+       
+       // Comm stations mapped by bucket
+       comm_map_type commlist_bck;
+
+       // Load comms from a specified path (which must include the filename)   
+       bool LoadComms(SGPath path);
+
+//----------- This stuff is left over from atislist.[ch]xx and maybe should move somewhere else
+       // Add structure and map for storing a log of atis transmissions
+       // made in this session of FlightGear.  This allows the callsign
+       // to be allocated correctly wrt time.
+       typedef struct {
+               int hours;
+               int mins;
+               int callsign;
+       } atis_transmission_type;
+
+    typedef map < string, atis_transmission_type > atis_log_type;
+    typedef atis_log_type::iterator atis_log_iterator;
+    typedef atis_log_type::const_iterator atis_log_const_iterator;
+
+    atis_log_type atislog;
+//-----------------------------------------------------------------------------------------------
+
+};
+
+
+extern FGCommList *current_commlist;
+
+
+#endif // _FG_COMMLIST_HXX
index 1aa78d040e8eddcfd4a390bb602c840e29c016ea..cd4b1e46a3f2f8ad92ba47a0a843d2ffc1b1b686 100644 (file)
@@ -99,18 +99,7 @@ class FGTower : public FGATC {
        inline void SetDisplay() {display = true;}
        inline void SetNoDisplay() {display = false;}
        
-       inline char get_type() const { return type; }
-       inline double get_lon() const { return lon; }
-       inline double get_lat() const { return lat; }
-       inline double get_elev() const { return elev; }
-       inline double get_x() const { return x; }
-       inline double get_y() const { return y; }
-       inline double get_z() const { return z; }
-       inline int get_freq() const { return freq; }
-       inline int get_range() const { return range; }
-       inline const char* GetIdent() { return ident.c_str(); }
        inline string get_trans_ident() { return trans_ident; }
-       inline string get_name() { return name; }
        inline atc_type GetType() { return TOWER; }
        
        // Make a request of tower control
@@ -122,17 +111,8 @@ class FGTower : public FGATC {
        void IssueGoAround(TowerPlaneRec* tpr);
        void IssueDepartureClearance(TowerPlaneRec* tpr);
        
-       char type;
-       double lon, lat;
-       double elev;
-       double x, y, z;
-       int freq;
-       int range;
        bool display;           // Flag to indicate whether we should be outputting to the ATC display.
        bool displaying;                // Flag to indicate whether we are outputting to the ATC display.
-       string ident;           // Code of the airport its at.
-       string name;            // Name generally used in transmissions.
-
        
        // Need a data structure to hold details of the various active planes
        // or possibly another data structure with the positions of the inactive planes.
@@ -166,52 +146,4 @@ class FGTower : public FGATC {
        friend istream& operator>> ( istream&, FGTower& );
 };
 
-
-inline istream&
-operator >> ( istream& in, FGTower& t )
-{
-       double f;
-       char ch;
-       
-       in >> t.type;
-       
-       if ( t.type == '[' )
-               return in >> skipeol;
-       
-       in >> t.lat >> t.lon >> t.elev >> f >> t.range 
-       >> t.ident;
-       
-       t.name = "";
-       in >> ch;
-       t.name += ch;
-       while(1) {
-               //in >> noskipws
-               in.unsetf(ios::skipws);
-               in >> ch;
-               t.name += 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 << "tower.name = " << t.name << '\n';
-       
-       t.freq = (int)(f*100.0 + 0.5);
-       
-       // cout << t.ident << endl;
-       
-       // generate cartesian coordinates
-       Point3D geod( t.lon * SGD_DEGREES_TO_RADIANS, t.lat * SGD_DEGREES_TO_RADIANS, t.elev );
-       Point3D cart = sgGeodToCart( geod );
-       t.x = cart.x();
-       t.y = cart.y();
-       t.z = cart.z();
-       
-       t.trans_ident = t.ident;
-       t.tower_failed = false;
-       
-       return in >> skipeol;
-}
-
-
 #endif  //_FG_TOWER_HXX
index 1ffba040501aced92604bbac0c518fc6da22f3ac..6b262a6e4cfd44f25437cd9f568a2ef9b166c34b 100644 (file)
@@ -45,90 +45,6 @@ FGTowerList::~FGTowerList( void ) {
 
 // load the navaids and build the map
 bool FGTowerList::init( SGPath path ) {
-
-    towerlist.erase( towerlist.begin(), towerlist.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 >> skipcomment;
-
-#ifdef __MWERKS__
-    char c = 0;
-    while ( in.get(c) && c != '\0' ) {
-        in.putback(c);
-#else
-    while ( !in.eof() ) {
-#endif
-
-       FGTower t;
-        in >> t;
-       if ( t.get_type() == '[' ) {
-           break;
-       }
-
-       //cout << "id = " << t.GetIdent() << endl;
-       //cout << " type = " << t.get_type() << endl;
-       //cout << " lon = " << t.get_lon() << endl;
-       //cout << " lat = " << t.get_lat() << endl;
-       //cout << " elev = " << t.get_elev() << endl;
-       //cout << " freq = " << t.get_freq() << endl;
-       //cout << " range = " << t.get_range() << endl;
-
-       towerlist[t.get_freq()].push_back(t);
-        in >> skipcomment;
-    }
-
     return true;
 }
 
-
-// query the database for the specified frequency, lon and lat are in
-// degrees, elev is in meters
-bool FGTowerList::query( double lon, double lat, double elev, double freq,
-                      FGTower *t )
-{
-    lon *= SGD_DEGREES_TO_RADIANS;
-    lat *= SGD_DEGREES_TO_RADIANS;
-    //cout << "lon = " << lon << '\n';
-    //cout << "lat = " << lat << '\n';
-    //cout << "elev = " << elev << '\n';
-    //cout << "freq = " << freq << '\n';
-
-    tower_list_type stations = towerlist[(int)(freq*100.0 + 0.5)];
-
-    tower_list_iterator current = stations.begin();
-    tower_list_iterator last = stations.end();
-
-    // double az1, az2, s;
-    Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
-    Point3D station;
-    double d;
-    for ( ; current != last ; ++current ) {
-       //cout << "testing " << current->GetIdent() << endl;
-       station = Point3D(current->get_x(), current->get_y(), current->get_z());
-       //cout << "aircraft = " << aircraft << endl;
-       //cout << "station = " << station << endl;
-
-       d = aircraft.distance3Dsquared( station );
-
-       //cout << "  dist = " << sqrt(d)
-       //     << "  range = " << current->get_range() * SG_NM_TO_METER << endl;
-
-       // match up to twice the published range so we can model
-       // reduced signal strength
-       if ( d < (2 * current->get_range() * SG_NM_TO_METER 
-                 * 2 * current->get_range() * SG_NM_TO_METER ) ) {
-           //cout << "matched = " << current->GetIdent() << endl;
-           *t = *current;
-           return true;
-       }
-    }
-
-    return false;
-}
index 599f76967cd14de5d8703ae710d314227824572a..380d124c227a899835222ed083da8da592ea462d 100644 (file)
@@ -61,10 +61,6 @@ public:
     // load all atis and build the map
     bool init( SGPath path );
 
-    // query the database for the specified frequency, lon and lat are
-    // in degrees, elev is in meters
-    bool query( double lon, double lat, double elev, double freq, FGTower *t );
-
 };