]> git.mxchange.org Git - flightgear.git/commitdiff
Expose FGPositioned data via property tree, and make comm-stations a real FGPositione...
authorJames Turner <zakalawe@mac.com>
Wed, 25 May 2011 06:50:15 +0000 (07:50 +0100)
committerJames Turner <zakalawe@mac.com>
Wed, 1 Jun 2011 16:45:22 +0000 (17:45 +0100)
34 files changed:
src/ATC/CMakeLists.txt
src/ATC/CommStation.cxx [new file with mode: 0644]
src/ATC/CommStation.hxx [new file with mode: 0644]
src/ATC/Makefile.am
src/ATC/atis_mgr.cxx [deleted file]
src/ATC/atis_mgr.hxx [deleted file]
src/ATCDCL/ATC.cxx
src/ATCDCL/ATC.hxx
src/ATCDCL/ATCDialog.cxx
src/ATCDCL/ATCmgr.cxx
src/ATCDCL/ATCmgr.hxx
src/ATCDCL/CMakeLists.txt
src/ATCDCL/Makefile.am
src/ATCDCL/atis.cxx
src/ATCDCL/atis.hxx
src/ATCDCL/commlist.cxx [deleted file]
src/ATCDCL/commlist.hxx [deleted file]
src/Airports/apt_loader.cxx
src/Airports/apt_loader.hxx
src/Airports/runwaybase.cxx
src/Airports/runwaybase.hxx
src/Airports/runways.cxx
src/Airports/runways.hxx
src/Airports/simple.cxx
src/Airports/simple.hxx
src/Instrumentation/KLN89/kln89_page_apt.cxx
src/Main/fg_init.cxx
src/Navaids/CMakeLists.txt
src/Navaids/PositionedBinding.cxx [new file with mode: 0644]
src/Navaids/PositionedBinding.hxx [new file with mode: 0644]
src/Navaids/navrecord.cxx
src/Navaids/navrecord.hxx
src/Navaids/positioned.cxx
src/Navaids/positioned.hxx

index 60c18e9961530106024cfc2cab2a81e9274f23d0..98b6a0d250a9521e341dc04369a7463fce9132f7 100644 (file)
@@ -1,8 +1,8 @@
 include(FlightGearComponent)
 
 set(SOURCES
-       atis_mgr.cxx
        trafficcontrol.cxx
+       CommStation.cxx
        )
        
 flightgear_component(ATC "${SOURCES}")
diff --git a/src/ATC/CommStation.cxx b/src/ATC/CommStation.cxx
new file mode 100644 (file)
index 0000000..45bc2cc
--- /dev/null
@@ -0,0 +1,67 @@
+#include "CommStation.hxx"
+
+#include <map>
+
+#include <Navaids/PositionedBinding.hxx>
+
+namespace {
+
+typedef std::multimap<int, flightgear::CommStation*> FrequencyMap;
+static FrequencyMap static_frequencies;
+
+typedef std::pair<FrequencyMap::const_iterator, FrequencyMap::const_iterator> FrequencyMapRange;
+
+} // of anonymous namespace
+
+namespace flightgear {
+
+CommStation::CommStation(const std::string& name, FGPositioned::Type t, const SGGeod& pos, int range, int freq) :
+    FGPositioned(t, name, pos),
+    mRangeNM(range),
+    mFreqKhz(freq),
+    mAirport(NULL)
+{
+    static_frequencies.insert(std::make_pair(freq, this));
+  
+    init(true);
+}
+
+void CommStation::setAirport(FGAirport* apt)
+{
+    mAirport = apt;
+}
+
+double CommStation::freqMHz() const
+{
+    return mFreqKhz / 100.0;
+}
+
+PositionedBinding*
+CommStation::createBinding(SGPropertyNode* nd) const
+{
+    return new CommStationBinding(this, nd);
+}
+
+CommStation*
+CommStation::findByFreq(int freqKhz, const SGGeod& pos, FGPositioned::Filter* filt)
+{
+    FrequencyMapRange range = static_frequencies.equal_range(freqKhz);
+    FGPositioned::List results;
+    for (; range.first != range.second; ++range.first) {
+        CommStation* sta = range.first->second;
+        if (filt && !filt->pass(sta)) {
+            continue; // filtered out
+        }
+        
+        results.push_back(sta);
+    }
+    
+    if (results.empty()) {
+        return NULL;
+    }
+    
+    FGPositioned::sortByRange(results, pos);
+    return (CommStation*) results.front().ptr();
+}
+
+} // of namespace flightgear
diff --git a/src/ATC/CommStation.hxx b/src/ATC/CommStation.hxx
new file mode 100644 (file)
index 0000000..89c0d1f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef FG_ATC_COMM_STATION_HXX
+#define FG_ATC_COMM_STATION_HXX
+
+#include <Navaids/positioned.hxx>
+
+class FGAirport;
+
+namespace flightgear
+{
+
+class CommStation : public FGPositioned
+{
+public:
+    CommStation(const std::string& name, FGPositioned::Type t, const SGGeod& pos, int range, int freq);
+
+    void setAirport(FGAirport* apt);
+    FGAirport* airport() const { return mAirport; }
+
+    virtual flightgear::PositionedBinding* createBinding(SGPropertyNode* nd) const;  
+    
+    int rangeNm() const
+        { return mRangeNM; }
+        
+    int freqKHz() const
+        { return mFreqKhz; }
+        
+    double freqMHz() const;
+    
+    static CommStation* findByFreq(int freqKhz, const SGGeod& pos, FGPositioned::Filter* filt = NULL);
+private:
+    int mRangeNM;
+    int mFreqKhz;
+    FGAirport* mAirport;
+}; 
+    
+} // of namespace flightgear
+
+#endif // of FG_ATC_COMM_STATION_HXX
+
index e3e52273733eb1f3572eaa67bff2936176d92235..046428e83c9368c0b868c95070db296fca066dfc 100644 (file)
@@ -1,7 +1,7 @@
 noinst_LIBRARIES = libATC.a
 
 libATC_a_SOURCES = \
-       atis_mgr.cxx atis_mgr.hxx \
+    CommStation.cxx CommStation.hxx \
        trafficcontrol.cxx trafficcontrol.hxx 
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
diff --git a/src/ATC/atis_mgr.cxx b/src/ATC/atis_mgr.cxx
deleted file mode 100644 (file)
index 034a835..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************************
- * atis.cxx
- * Written by Durk Talsma, started August 1, 2010.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *
- **************************************************************************/
-
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <iostream>
-
-#include <simgear/math/SGMath.hxx>
-#include "atis_mgr.hxx"
-
-FGAtisManager::FGAtisManager() {
-
-}
-
-FGAtisManager::~FGAtisManager() {
-
-}
-
-void FGAtisManager::init() {
-    SGSubsystem::init();
-}
-
-void FGAtisManager::update ( double time ) {
-    //cerr << "ATIS code is running at time: " << time << endl;
-}
diff --git a/src/ATC/atis_mgr.hxx b/src/ATC/atis_mgr.hxx
deleted file mode 100644 (file)
index 12fc4fd..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++ -*- *****************************************************
- * atic.hxx
- * Written by Durk Talsma. Started August 1, 2010; based on earlier work
- * by David C. Luff
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *
- **************************************************************************/
-
-#ifndef _ATIS_HXX_
-#define _ATIS_HXX_
-
-#include <simgear/structure/subsystem_mgr.hxx>
-
-class FGAtisManager : public SGSubsystem
-{
-private:
-  
-public:
-  FGAtisManager();
-  ~FGAtisManager();
-  void init();
-  void update(double time);    
-};
-  
-#endif // _ATIS_HXX_
\ No newline at end of file
index 30d3d23e8dc3ff82f9b4a0a94cfb5d93379fe8ef..4701a67eea64065ea0f88fb000672d49a726950f 100644 (file)
@@ -31,8 +31,8 @@
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
-
-
+#include <ATC/CommStation.hxx>
+#include <Airports/simple.hxx>
 
 FGATC::FGATC() :
        _playing(false),
@@ -181,14 +181,20 @@ void FGATC::NotifyTransmissionFinished(const string& rid) {
        }
 }
 
-void FGATC::SetData(ATCData* d) {
-       _type = d->type;
-       _geod = d->geod;
-       _cart = d->cart;
-       range = d->range;
-       ident = d->ident;
-       name = d->name;
-       freq = d->freq;
+void FGATC::SetStation(flightgear::CommStation* sta) {
+    switch (sta->type()) {
+        case FGPositioned::FREQ_ATIS:   _type = ATIS; break;
+        case FGPositioned::FREQ_AWOS:   _type = AWOS; break;
+        default:
+        throw sg_exception("unsupported comm station type");
+    }
+    
+    _geod = sta->geod();
+    _cart = sta->cart();
+    range = sta->rangeNm();
+    ident = sta->airport()->ident();
+    name = sta->airport()->name();
+    freq = sta->freqKHz();
 }
 
 // Render a transmission
index 2109b697be8c72bf556866d4eb33ad5e2ab5bb9e..17f743cd764ad5cddf1b0fa048dc243d3d0f0984 100644 (file)
 
 class SGSampleGroup;
 
+namespace flightgear
+{
+    class CommStation;
+}
+
 // Convert a frequency in MHz to tens of kHz
 // so we can use it e.g. as an index into commlist_freq
 //
@@ -140,7 +145,7 @@ public:
        inline atc_type GetType() { return _type; }
        
        // Set the core ATC data
-       void SetData(ATCData* d);
+    void SetStation(flightgear::CommStation* sta);
 
        inline int get_freq() const { return freq; }
        inline void set_freq(const int fq) {freq = fq;}
index f5f5ec935d3f337e7b1efe4ad1cb7b2e613d503b..ad6e0276321e2872111769bbb5e14ff3461e1a95 100644 (file)
@@ -34,9 +34,9 @@
 #include "ATCDialog.hxx"
 #include "ATC.hxx"
 #include "ATCmgr.hxx"
-#include "commlist.hxx"
 #include "ATCutils.hxx"
 #include <Airports/simple.hxx>
+#include <ATC/CommStation.hxx>
 
 #include <sstream>
 
@@ -286,21 +286,17 @@ void FGATCDialog::PopupCallback(int num) {
        }
 }
 
-// map() key data type (removes duplicates and sorts by distance)
-struct atcdata {
-       atcdata() {}
-       atcdata(const string i, const string n, const double d) {
-               id = i, name = n, distance = d;
-       }
-       bool operator<(const atcdata& a) const {
-               return id != a.id && distance < a.distance;
-       }
-       bool operator==(const atcdata& a) const {
-               return id == a.id && distance == a.distance;
-       }
-       string id;
-       string name;
-       double distance;
+class AirportsWithATC : public FGAirport::AirportFilter
+{
+public:
+    virtual FGPositioned::Type maxType() const {
+      return FGPositioned::SEAPORT;
+    }
+  
+    virtual bool passAirport(FGAirport* aApt) const
+    {
+      return (!aApt->commStations().empty());
+    }
 };
 
 void FGATCDialog::FreqDialog() {
@@ -315,38 +311,25 @@ void FGATCDialog::FreqDialog() {
        // remove all dynamic airport/ATC buttons
        button_group->removeChildren("button", false);
 
-       // Find the ATC stations within a reasonable range
-       comm_list_type atc_stations;
-       comm_list_iterator atc_stat_itr;
 
   SGGeod geod(SGGeod::fromDegFt(fgGetDouble("/position/longitude-deg"),
     fgGetDouble("/position/latitude-deg"), fgGetDouble("/position/altitude-ft")));
-       SGVec3d aircraft = SGVec3d::fromGeod(geod);
-
-       // search stations in range
-       int num_stat = current_commlist->FindByPos(geod, 50.0, &atc_stations);
-       if (num_stat != 0) {
-               map<atcdata, bool> uniq;
-               // fill map (sorts by distance and removes duplicates)
-               comm_list_iterator itr = atc_stations.begin();
-               for (; itr != atc_stations.end(); ++itr) {
-                       double distance = distSqr(aircraft, itr->cart);
-                       uniq[atcdata(itr->ident, itr->name, distance)] = true;
-               }
-               // create button per map entry (modified copy of <button-template>)
-               map<atcdata, bool>::iterator uit = uniq.begin();
-               for (int n = 0; uit != uniq.end() && n < 6; ++uit, ++n) { // max 6 buttons
-                       SGPropertyNode *entry = button_group->getNode("button", n, true);
-                       copyProperties(button_group->getNode("button-template", true), entry);
-                       entry->removeChildren("enabled", true);
-                       entry->setStringValue("legend", uit->first.id.c_str());
-                       entry->setStringValue("binding[0]/value", uit->first.id.c_str());
-               }
-       }
 
+    AirportsWithATC filt;
+    FGPositioned::List results = FGPositioned::findWithinRange(geod, 50.0, &filt);
+    FGPositioned::sortByRange(results, geod);
+    for (unsigned int r=0; (r<results.size()) && (r < 6); ++r) {
+      
+        SGPropertyNode *entry = button_group->getNode("button", r, true);
+               copyProperties(button_group->getNode("button-template", true), entry);
+               entry->removeChildren("enabled", true);
+               entry->setStringValue("legend", results[r]->ident());
+               entry->setStringValue("binding[0]/value", results[r]->ident());
+    }
+    
        // (un)hide message saying no things in range
        SGPropertyNode_ptr range_error = getNamedNode(dlg, "no-atc-in-range");
-       range_error->setBoolValue("enabled", !num_stat);
+       range_error->setBoolValue("enabled", !results.empty());
 
        _gui->showDialog(dialog_name);
 }
@@ -377,43 +360,33 @@ void FGATCDialog::FreqDisplay(string& ident) {
        label = ident + " Frequencies";
        dlg->setStringValue("text/label", label.c_str());
 
-       int n = 0;      // Number of ATC frequencies at this airport
-
-       comm_list_type stations;
-       int found = current_commlist->FindByPos(a->geod(), 20.0, &stations);
-       if(found) {
-               comm_list_iterator itr = stations.begin();
-               for (n = 0; itr != stations.end(); ++itr) {
-                       if(itr->ident != ident)
-                               continue;
-
-                       if(itr->type == INVALID)
-                               continue;
-
-                       // add frequency line (modified copy of <group-template>)
-                       SGPropertyNode *entry = freq_group->getNode("group", n, true);
-                       copyProperties(freq_group->getNode("group-template", true), entry);
-                       entry->removeChildren("enabled", true);
+    const flightgear::CommStationList& comms(a->commStations());
+    if (comms.empty()) {
+        label = "No frequencies found for airport " + ident;
+               mkDialog(label.c_str());
+               return;
+    }
+    
+    int n = 0;
+    for (unsigned int c=0; c < comms.size(); ++c) {
+        flightgear::CommStation* comm = comms[c];
+        
+        // add frequency line (modified copy of <group-template>)
+               SGPropertyNode *entry = freq_group->getNode("group", n, true);
+               copyProperties(freq_group->getNode("group-template", true), entry);
+               entry->removeChildren("enabled", true);
 
-                       ostringstream ostr;
-                       ostr << itr->type;
-                       entry->setStringValue("text[0]/label", ostr.str());
+        entry->setStringValue("text[0]/label", comm->ident());
 
-                       char buf[8];
-                       snprintf(buf, 8, "%.2f", (itr->freq / 100.0));  // Convert from KHz to MHz
-                       if(buf[5] == '3') buf[5] = '2';
-                       if(buf[5] == '8') buf[5] = '7';
-                       buf[7] = '\0';
+               char buf[8];
+               snprintf(buf, 8, "%.2f", comm->freqMHz());
+               if(buf[5] == '3') buf[5] = '2';
+               if(buf[5] == '8') buf[5] = '7';
+               buf[7] = '\0';
 
-                       entry->setStringValue("text[1]/label", buf);
-                       n++;
-               }
-       }
-       if(n == 0) {
-               label = "No frequencies found for airport " + ident;
-               mkDialog(label.c_str());
-               return;
-       }
+               entry->setStringValue("text[1]/label", buf);
+        ++n;
+    }
 
        _gui->showDialog(dialog_name);
 }
index 537bfddefe2a22fb37fb2cf5d4875fccec6bd545..8d8a6fc5815987df5026e478eafa9053fca57b3b 100644 (file)
 
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
 
 #include <Airports/simple.hxx>
+#include <ATC/CommStation.hxx>
+#include <Main/fg_props.hxx>
 
 #include "ATCmgr.hxx"
-#include "commlist.hxx"
 #include "ATCDialog.hxx"
 #include "ATCutils.hxx"
+#include "atis.hxx"
 
-
-/*
-// periodic radio station search wrapper
-static void fgATCSearch( void ) {
-    globals->get_ATC_mgr()->Search();
-}
-*/ //This wouldn't compile - including Time/event.hxx breaks it :-(
-   // Is this still true?? -EMH-
-
-AirportATC::AirportATC() :
-    atis_freq(0.0),
-    atis_active(false)
-    //airport_atc_map.clear();
-{
-}
+using flightgear::CommStation;
 
 FGATCMgr::FGATCMgr() :
     initDone(false),
@@ -148,44 +137,6 @@ void FGATCMgr::update(double dt) {
     //cout << "Leaving update..." << endl;
 }
 
-
-// Returns frequency in KHz - should I alter this to return in MHz?
-unsigned short int FGATCMgr::GetFrequency(const string& ident, const atc_type& tp) {
-    ATCData test;
-    bool ok = current_commlist->FindByCode(ident, test, tp);
-    return(ok ? test.freq : 0);
-}   
-
-// Register the fact that the comm radio is tuned to an airport
-// Channel is zero based
-bool FGATCMgr::CommRegisterAirport(const string& ident, int chan, const atc_type& tp) {
-    SG_LOG(SG_ATC, SG_BULK, "Comm channel " << chan << " registered airport " << ident);
-    //cout << "Comm channel " << chan << " registered airport " << ident << ' ' << tp << '\n';
-    if(airport_atc_map.find(ident) != airport_atc_map.end()) {
-        if(tp == ATIS || tp == AWOS) {
-            airport_atc_map[ident]->atis_active = true;
-        }
-        return(true);
-    } else {
-        //cout << "NOT IN MAP - creating new..." << endl;
-        const FGAirport *ap = fgFindAirportID(ident);
-        if (ap) {
-            AirportATC *a = new AirportATC;
-            // I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
-            a->geod = ap->geod();
-            a->atis_freq = GetFrequency(ident, ATIS)
-                    || GetFrequency(ident, AWOS);
-            a->atis_active = false;
-            if(tp == ATIS || tp == AWOS) {
-                a->atis_active = true;
-            }
-            airport_atc_map[ident] = a;
-            return(true);
-        }
-    }
-    return(false);
-}
-
 typedef map<string,int> MSI;
 
 void FGATCMgr::ZapOtherService(const string ncunit, const string svc_name){
@@ -224,16 +175,6 @@ FGATC* FGATCMgr::FindInList(const string& id, const atc_type& tp) {
   return (*atc_list)[ndx];
 }
 
-// Returns true if the airport is found in the map
-bool FGATCMgr::GetAirportATCDetails(const string& icao, AirportATC* a) {
-    if(airport_atc_map.find(icao) != airport_atc_map.end()) {
-        *a = *airport_atc_map[icao];
-        return(true);
-    } else {
-        return(false);
-    }
-}
-
 // Return a pointer to an appropriate voice for a given type of ATC
 // creating the voice if necessary - ie. make sure exactly one copy
 // of every voice in use exists in memory.
@@ -303,49 +244,44 @@ void FGATCMgr::FreqSearch(const string navcomm, const int unit) {
     if (!comm_node) return; // no such radio unit
 
     ATCData data;   
-    double freq = comm_node->getDoubleValue();
+    // Note:  122.375 must be rounded DOWN to 12237 
+    // in order to be consistent with apt.dat et cetera.
+    int freqKhz = static_cast<int>(comm_node->getDoubleValue() * 100.0 + 0.25);
+    
     _aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
         lat_node->getDoubleValue(), elev_node->getDoubleValue());
     
-    // Query the data store and get the closest match if any
-    //cout << "Will FindByFreq: " << lat << " " << lon << " " << elev
-    //      << "  freq: " << freq << endl;
-    if(current_commlist->FindByFreq(_aircraftPos, freq, &data)) {
-        //cout << "FoundByFreq: " << freq
-        //  << "  ident: " << data.ident
-        //  << "  type: " << data.type << " ***" << endl;
-        // We are in range of something.
-
+    CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos);
+    if (!sta) {
+        ZapOtherService(ncunit, "x x x");
+        return;
+    }
+    
+    // Get rid of any *other* service that was on this radio unit:
+    FGPositioned::Type ty = sta->type();
+    string svc_name = sta->ident() + FGPositioned::nameForType(ty);
+    ZapOtherService(ncunit, svc_name);
+    // See if the service already exists, possibly connected to
+    // some other radio unit:
+    if (atc_list->count(svc_name)) {
+        // make sure the service knows it's tuned on this radio:
+        FGATC* svc = (*atc_list)[svc_name];
+        svc->active_on[ncunit] = 1;
+        svc->SetDisplay();
+        return;
+    }
 
-        // Get rid of any *other* service that was on this radio unit:
-        string svc_name = data.ident+decimalNumeral(data.type);
-        ZapOtherService(ncunit, svc_name);
-        // See if the service already exists, possibly connected to
-        // some other radio unit:
-        if (atc_list->count(svc_name)) {
-            // make sure the service knows it's tuned on this radio:
-            FGATC* svc = (*atc_list)[svc_name];
+    // This was a switch-case statement but the compiler didn't like
+    // the new variable creation with it.
+    if(ty == FGPositioned::FREQ_ATIS || ty == FGPositioned::FREQ_AWOS) {
+        (*atc_list)[svc_name] = new FGATIS;
+        FGATC* svc = (*atc_list)[svc_name];
+        if(svc != NULL) {
+            svc->SetStation(sta);
             svc->active_on[ncunit] = 1;
             svc->SetDisplay();
-            return;
+            svc->Init();
         }
+    }
 
-        CommRegisterAirport(data.ident, unit, data.type);
-
-        // This was a switch-case statement but the compiler didn't like
-        // the new variable creation with it.
-        if(data.type == ATIS || data.type == AWOS) {
-            (*atc_list)[svc_name] = new FGATIS;
-            FGATC* svc = (*atc_list)[svc_name];
-            if(svc != NULL) {
-                svc->SetData(&data);
-                svc->active_on[ncunit] = 1;
-                svc->SetDisplay();
-                svc->Init();
-            }
-        }
-    } else {
-        // No services in range.  Zap any service on this unit.
-        ZapOtherService(ncunit, "x x x");
-    } 
 }
index 850fcc0a9be6af818c6708cf4f6a760fe05256a7..179f65fc3dc08456b615e8052f6acb6faa2bd59a 100644 (file)
 
 #include <simgear/structure/subsystem_mgr.hxx>
 
-#include <Main/fg_props.hxx>
-#include <GUI/gui.h>
-
 #include <string>
 #include <list>
 #include <map>
 
 #include "ATC.hxx"
 
-using std::string;
-using std::list;
-using std::map;
-
-// 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 commlists which are stored by frequency or bucket.
-// Non-available services are denoted by a frequency of zero.
-// These structures are only intended to be created for in-use airports, and removed when no longer needed. 
-struct AirportATC {
-       AirportATC();
-       
-    SGGeod geod;
-    float atis_freq;
-    bool atis_active;
-};
-
 class FGATCMgr : public SGSubsystem
 {
 
@@ -56,16 +37,8 @@ private:
 
     bool initDone;     // Hack - guard against update getting called before init
 
-    // A map of airport ID vs frequencies and ATC provision
-    typedef map < string, AirportATC* > airport_atc_map_type;
-    typedef airport_atc_map_type::iterator airport_atc_map_iterator;
-    typedef airport_atc_map_type::const_iterator airport_atc_map_const_iterator;
-
-    airport_atc_map_type airport_atc_map;
-    airport_atc_map_iterator airport_atc_map_itr;
-
     // A list of pointers to all currently active ATC classes
-    typedef map<string,FGATC*> atc_list_type;
+    typedef std::map<std::string,FGATC*> atc_list_type;
     typedef atc_list_type::iterator atc_list_iterator;
     typedef atc_list_type::const_iterator atc_list_const_iterator;
 
@@ -107,9 +80,7 @@ public:
 
     void update(double dt);
 
-    // Returns true if the airport is found in the map
-    bool GetAirportATCDetails(const string& icao, AirportATC* a);
-       
+
     // Return a pointer to an appropriate voice for a given type of ATC
     // creating the voice if necessary - ie. make sure exactly one copy
     // of every voice in use exists in memory.
@@ -124,26 +95,20 @@ public:
     atc_type GetComm2ATCType() { return(INVALID); }
     FGATC* GetComm2ATCPointer() { return(0/* kludge */); }
     
-    // Get the frequency of a given service at a given airport
-    // Returns zero if not found
-    unsigned short int GetFrequency(const string& ident, const atc_type& tp);
-    
-    // Register the fact that the comm radio is tuned to an airport
-    bool CommRegisterAirport(const string& ident, int chan, const atc_type& tp);
-       
+
 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 ZapOtherService(const string ncunit, const string svc_name);
+    void ZapOtherService(const std::string ncunit, const std::string svc_name);
 
     // Return a pointer to a class in the list given ICAO code and type
     // Return NULL if the given service is not in the list
     // - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
-    FGATC* FindInList(const string& id, const atc_type& tp);
+    FGATC* FindInList(const std::string& id, const atc_type& tp);
 
     // Search the specified radio for stations on the same frequency and in range.
-    void FreqSearch(const string navcomm, const int unit);
+    void FreqSearch(const std::string navcomm, const int unit);
 };
 
 #endif  // _FG_ATCMGR_HXX
index 72c1da6a9d31565547a3d3fd7c1dbe1d147813a1..d9e8db69bc62fdaf206531c428c2deda0fc36048 100644 (file)
@@ -3,7 +3,6 @@ include(FlightGearComponent)
 set(SOURCES
        ATC.cxx
        atis.cxx
-       commlist.cxx
        ATCDialog.cxx
        ATCVoice.cxx
        ATCmgr.cxx
index d268da1e5e1bb7ba0b8a9279f2b2b8c9f18dde4b..8c2a2b74b02040802ec6e9e2a41f37a8a7607826 100644 (file)
@@ -3,7 +3,6 @@ noinst_LIBRARIES = libATCDCL.a
 libATCDCL_a_SOURCES = \
        ATC.hxx ATC.cxx \
        atis.hxx atis.cxx \
-       commlist.hxx commlist.cxx \
        ATCDialog.hxx ATCDialog.cxx \
        ATCVoice.hxx ATCVoice.cxx \
        ATCmgr.hxx ATCmgr.cxx \
index 53973a7a752b3272085fa85b1edd12cc9eabe9cd..b2f35862022349091cacd02cc7aac5ea4a249e75 100644 (file)
@@ -34,6 +34,8 @@
 #include "atis_lexicon.hxx"
 
 #include <simgear/compiler.h>
+#include <simgear/math/sg_random.h>
+#include <simgear/misc/sg_path.hxx>
 
 #include <stdlib.h> // atoi()
 #include <stdio.h>  // sprintf
@@ -44,9 +46,6 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/case_conv.hpp>
 
-
-#include <simgear/misc/sg_path.hxx>
-
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
 #include <Environment/atmosphere.hxx>
@@ -56,7 +55,6 @@
 #include <Airports/runways.hxx>
 
 
-#include "commlist.hxx"
 #include "ATCutils.hxx"
 #include "ATCmgr.hxx"
 
@@ -230,6 +228,47 @@ int Apt_US_CA(const string id) {
   return 0;
 }
 
+// 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 {
+        double tstamp;
+    int sequence;
+} atis_transmission_type;
+
+typedef std::map < std::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;
+
+static atis_log_type atislog;
+
+int FGATIS::GetAtisSequence( const string& apt_id, 
+        const double tstamp, const int interval, const int special)
+{
+    atis_transmission_type tran;
+    
+    if(atislog.find(apt_id) == atislog.end()) { // New station
+      tran.tstamp = tstamp - interval;
+// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes:
+      tran.sequence = int(sg_random() * LTRS);
+      atislog[apt_id] = tran;
+      //cout << "New ATIS station: " << apt_id << " seq-1: "
+      //      << tran.sequence << endl;
+    } 
+
+// calculate the appropriate identifier and update the log
+    tran = atislog[apt_id];
+
+    int delta = int((tstamp - tran.tstamp) / interval);
+    tran.tstamp += delta * interval;
+    if (special && !delta) delta++;     // a "special" ATIS update is required
+    tran.sequence = (tran.sequence + delta) % LTRS;
+    atislog[apt_id] = tran;
+    //if (delta) cout << "New ATIS sequence: " << tran.sequence
+    //      << "  Delta: " << delta << endl;
+    return(tran.sequence + (delta ? 0 : LTRS*1000));
+}
+
 // Generate the actual broadcast ATIS transmission.
 // Regen means regenerate the /current/ transmission.
 // Special means generate a new transmission, with a new sequence.
@@ -245,8 +284,8 @@ int FGATIS::GenTransmission(const int regen, const int special) {
   int interval = _type == ATIS ?
         ATIS_interval   // ATIS updated hourly
       : 2*minute;      // AWOS updated more frequently
-  int sequence = current_commlist->GetAtisSequence(ident, 
-                       tstamp, interval, special);
+  
+  int sequence = GetAtisSequence(ident, tstamp, interval, special);
   if (!regen && sequence > LTRS) {
 //xx      if (msg_OK) cout << "ATIS:  no change: " << sequence << endl;
 //xx      msg_time = cur_time;
index 76809eb095cb8fd9d87d590ad2e25e7bc6538e7c..189b11106a567b722ae5d32cd344022c5a8f9989 100644 (file)
@@ -95,6 +95,9 @@ class FGATIS : public FGATC {
        void TreeOut(int msgOK);
 
        friend std::istream& operator>> ( std::istream&, FGATIS& );
+       
+       int GetAtisSequence( const std::string& apt_id, 
+        const double tstamp, const int interval, const int special);
 };
 
 typedef int (FGATIS::*int_getter)() const;
diff --git a/src/ATCDCL/commlist.cxx b/src/ATCDCL/commlist.cxx
deleted file mode 100644 (file)
index ef5c8d7..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-// 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 - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "commlist.hxx"
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/misc/sgstream.hxx>
-#include <simgear/math/sg_geodesy.hxx>
-#include <simgear/math/sg_random.h>
-#include <simgear/bucket/newbucket.hxx>
-#include <Airports/simple.hxx>
-
-#include "ATCutils.hxx"
-
-
-FGCommList *current_commlist;
-
-
-// Constructor
-FGCommList::FGCommList( void ) {
-      sg_srandom_time();
-}
-
-
-// Destructor
-FGCommList::~FGCommList( void ) {
-}
-
-
-// load the navaids and build the map
-bool FGCommList::init( const 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.ground" );
-    LoadComms(temp);
-    temp = path;
-    temp.append( "ATC/default.approach" );
-    LoadComms(temp);
-    return true;
-}
-    
-
-bool FGCommList::LoadComms(const 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;
-
-    while ( !fin.eof() ) {
-        ATCData a;
-        fin >> a;
-        if(a.type == INVALID) {
-            SG_LOG(SG_GENERAL, SG_DEBUG, "WARNING - INVALID type found in " << path.str() << '\n');
-        } else {        
-            // Push all stations onto frequency map
-            commlist_freq[a.freq].push_back(a);
-            
-            // Push non-atis stations onto bucket map as well
-            // In fact, push all stations onto bucket map for now so FGATCMgr::GetFrequency() works.
-            //if(a.type != ATIS and/or AWOS?) {
-                // get bucket number
-                SGBucket bucket(a.geod);
-                int bucknum = bucket.gen_index();
-                commlist_bck[bucknum].push_back(a);
-            //}
-        }
-        
-        fin >> skipcomment;
-    }
-    
-    fin.close();
-    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(const SGGeod& aPos, double freq,
-                                               ATCData* ad, atc_type tp )
-{
-    comm_list_type stations;
-    stations = commlist_freq[kHz10(freq)];
-    comm_list_iterator current = stations.begin();
-    comm_list_iterator last = stations.end();
-    
-    // double az1, az2, s;
-    SGVec3d aircraft = SGVec3d::fromGeod(aPos);
-    const double orig_max_d = 1e100; 
-    double max_d = orig_max_d;
-    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 ) {
-        d = distSqr(aircraft, current->cart);
-        
-        //cout << "  dist = " << sqrt(d)
-        //     << "  range = " << current->range * SG_NM_TO_METER << endl;
-        
-        // TODO - match up to twice the published range so we can model
-        // reduced signal strength
-        // NOTE The below is squared since we match to distance3Dsquared (above) to avoid a sqrt.
-        if ( d < (current->range * SG_NM_TO_METER 
-             * current->range * SG_NM_TO_METER ) ) {
-            //cout << "matched = " << current->ident << endl;
-            if((tp == INVALID) || (tp == (*current).type)) {
-                if(d < max_d) {
-                    max_d = d;
-                    *ad = *current;
-                }
-            }
-        }
-    }
-    
-    if(max_d < orig_max_d) {
-        return true;
-    } else {
-        return false;
-    }
-}
-
-int FGCommList::FindByPos(const SGGeod& aPos, double range, 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(aPos);
-     // get neigboring buckets
-     int bx = (int)( range*SG_NM_TO_METER / buck.get_width_m() / 2) + 1;
-     int by = (int)( range*SG_NM_TO_METER / buck.get_height_m() / 2 ) + 1;
-     
-     // loop over bucket range 
-     for ( int i=-bx; i<=bx; i++) {
-         for ( int j=-by; j<=by; j++) {
-             buck = sgBucketOffset(aPos.getLongitudeDeg(), aPos.getLatitudeDeg(), i, j);
-             long int bucket = buck.gen_index();
-             comm_map_const_iterator Fstations = commlist_bck.find(bucket);
-             if (Fstations == commlist_bck.end()) continue;
-             comm_list_const_iterator current = Fstations->second.begin();
-             comm_list_const_iterator last = Fstations->second.end();
-             
-             
-             // double az1, az2, s;
-             SGVec3d aircraft = SGVec3d::fromGeod(aPos);
-             double d;
-             for(; current != last; ++current) {
-                 if((current->type == tp) || (tp == INVALID)) {
-                     d = distSqr(aircraft, current->cart);
-                     // NOTE The below is squared since we match to distance3Dsquared (above) to avoid a sqrt.
-                     if ( d < (current->range * SG_NM_TO_METER
-                          * current->range * SG_NM_TO_METER ) ) {
-                         stations->push_back(*current);
-                         ++found;
-                     }
-                 }
-             }
-         }
-     }
-     return found;
-}
-
-
-// Returns the distance in meters to the closest station of a given type,
-// with the details written into ATCData& ad.  If no type is specifed simply
-// returns the distance to the closest station of any type.
-// Returns -9999 if no stations found within max_range in nautical miles (default 100 miles).
-// Note that the search algorithm starts at 10 miles and multiplies by 10 thereafter, so if
-// say 300 miles is specifed 10, then 100, then 1000 will be searched, breaking at first result 
-// and giving up after 1000.
-double FGCommList::FindClosest(const SGGeod& aPos, ATCData& ad, atc_type tp, double max_range) {
-    int num_stations = 0;
-    int range = 10;
-    comm_list_type stations;
-    comm_list_iterator itr;
-    double distance = -9999.0;
-    
-    while(num_stations == 0) {
-        num_stations = FindByPos(aPos, range, &stations, tp);
-        if(num_stations) {
-            double closest = max_range * SG_NM_TO_METER;
-            double tmp;
-            for(itr = stations.begin(); itr != stations.end(); ++itr) { 
-                ATCData ad2 = *itr;    
-                const FGAirport *a = fgFindAirportID(ad2.ident);
-                if (a) {
-                    tmp = dclGetHorizontalSeparation(ad2.geod, aPos);
-                    if(tmp <= closest) {
-                        closest = tmp;
-                        distance = tmp;
-                        ad = *itr;
-                    }
-                }
-            }
-            //cout << "Closest station is " << ad.ident << " at a range of " << distance << " meters\n";
-            return(distance);
-        }
-        if(range > max_range) {
-            break;
-        }
-        range *= 10;
-    }
-    return(-9999.0);
-}
-
-
-// Find by Airport code.
-// This is basically a wrapper for a call to the airport database to get the airport
-// position followed by a call to FindByPos(...)
-bool FGCommList::FindByCode( const string& ICAO, ATCData& ad, atc_type tp ) {
-    const FGAirport *a = fgFindAirportID( ICAO);
-    if ( a) {
-        comm_list_type stations;
-        int found = FindByPos(a->geod(), 10.0, &stations, tp);
-        if(found) {
-            comm_list_iterator itr = stations.begin();
-            while(itr != stations.end()) {
-                if(((*itr).ident == ICAO) && ((*itr).type == tp)) {
-                    ad = *itr;
-                    //cout << "FindByCode returns " << ICAO
-                    //     << "  type: " << tp
-                    //   << "  freq: " << itr->freq
-                    //   << endl;
-                    return true;
-                }
-                ++itr;
-            }
-        }
-    }
-    return false;
-}
-
-// TODO - this function should move somewhere else eventually!
-// Return an appropriate sequence number for an ATIS transmission.
-// Return sequence number + 2600 if sequence is unchanged since 
-// last time.
-int FGCommList::GetAtisSequence( const string& apt_id, 
-        const double tstamp, const int interval, const int special)
-{
-    atis_transmission_type tran;
-    
-    if(atislog.find(apt_id) == atislog.end()) { // New station
-      tran.tstamp = tstamp - interval;
-// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes:
-      tran.sequence = int(sg_random() * LTRS);
-      atislog[apt_id] = tran;
-      //cout << "New ATIS station: " << apt_id << " seq-1: "
-      //      << tran.sequence << endl;
-    } 
-
-// calculate the appropriate identifier and update the log
-    tran = atislog[apt_id];
-
-    int delta = int((tstamp - tran.tstamp) / interval);
-    tran.tstamp += delta * interval;
-    if (special && !delta) delta++;     // a "special" ATIS update is required
-    tran.sequence = (tran.sequence + delta) % LTRS;
-    atislog[apt_id] = tran;
-    //if (delta) cout << "New ATIS sequence: " << tran.sequence
-    //      << "  Delta: " << delta << endl;
-    return(tran.sequence + (delta ? 0 : LTRS*1000));
-}
diff --git a/src/ATCDCL/commlist.hxx b/src/ATCDCL/commlist.hxx
deleted file mode 100644 (file)
index c5066f3..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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 - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 <map>
-#include <list>
-#include <string>
-
-#include "ATC.hxx"
-#include "atis.hxx"
-
-class SGPath;
-
-// A list of ATC stations
-typedef std::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 std::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( const SGPath& path );
-
-    // query the database for the specified frequency, lon and lat are
-    // 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.
-    // Returns the station closest to the supplied position.
-    // The data found is written into the passed-in ATCData structure.
-    bool FindByFreq(const SGGeod& aPos, double freq, ATCData* ad, atc_type tp = INVALID );
-    
-    // query the database by location, lon and lat are in degrees, elev is in meters, range is in nautical miles.
-    // Returns the number of stations of the specified atc_type tp that are in range of the position defined by 
-    // lon, lat and elev, and pushes them into stations.
-    // If no atc_type is specifed, returns the number of all stations in range, and pushes them into stations
-    // ** stations is erased before use **
-    int FindByPos(const SGGeod& aPos, double range, comm_list_type* stations, atc_type tp = INVALID );
-    
-    // Returns the distance in meters to the closest station of a given type,
-    // with the details written into ATCData& ad.  If no type is specifed simply
-    // returns the distance to the closest station of any type.
-    // Returns -9999 if no stations found within max_range in nautical miles (default 100 miles).
-    // Note that the search algorithm starts at 10 miles and multiplies by 10 thereafter, so if
-    // say 300 miles is specifed 10, then 100, then 1000 will be searched, breaking at first result 
-    // and giving up after 1000.
-    // !!!Be warned that searching anything over 100 miles will pause the sim unacceptably!!!
-    //  (The ability to search longer ranges should be used during init only).
-    double FindClosest(const SGGeod& aPos, ATCData& ad, atc_type tp = INVALID, double max_range = 100.0 );
-    
-    // Find by Airport code.
-    bool FindByCode( const std::string& ICAO, ATCData& ad, atc_type tp = INVALID );
-
-    // Return the sequence letter for an ATIS transmission given transmission time and airport id
-    // This maybe should get moved somewhere else!!
-    int GetAtisSequence( const std::string& apt_id, const double tstamp, 
-                    const int interval, const int flush=0);
-    
-    // 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)   
-private:
-
-    bool LoadComms(const 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 {
-            double tstamp;
-        int sequence;
-    } atis_transmission_type;
-
-    typedef std::map < std::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 8bb9924e6a94e8269015683f7d3304ef3b8f3150..5698eb16b09d24714dea273501c9b3b84a1134e3 100644 (file)
@@ -46,7 +46,8 @@
 #include "simple.hxx"
 #include "runways.hxx"
 #include "pavement.hxx"
-#include <ATCDCL/commlist.hxx>
+
+#include <ATC/CommStation.hxx>
 
 #include <iostream>
 
@@ -78,7 +79,7 @@ public:
 
 
 
-  void parseAPT(const string &aptdb_file, FGCommList *comm_list)
+  void parseAPT(const string &aptdb_file)
   {
     sg_gzifstream in( aptdb_file );
 
@@ -157,12 +158,8 @@ public:
           // custom startup locations (ignore)
       } else if ( line_id == 0 ) {
           // ??
-      } else if ( line_id == 50 ) {
-
-        parseATISLine(comm_list, simgear::strutils::split(line));
-
-      } else if ( line_id >= 51 && line_id <= 56 ) {
-        // other frequency entries (ignore)
+      } else if ( line_id >= 50 && line_id <= 56) {
+        parseCommLine(line_id, simgear::strutils::split(line));
       } else if ( line_id == 110 ) {
         pavement = true;
         parsePavementLine850(simgear::strutils::split(line, 0, 4));
@@ -206,6 +203,7 @@ private:
   vector<FGRunwayPtr> runways;
   vector<FGTaxiwayPtr> taxiways;
   vector<FGPavementPtr> pavements;
+  vector<flightgear::CommStation*> commStations;
   
   void addAirport()
   {  
@@ -235,6 +233,7 @@ private:
     FGAirport* apt = new FGAirport(last_apt_id, pos, tower, last_apt_name, false,
         fptypeFromRobinType(atoi(last_apt_type.c_str())));
     apt->setRunwaysAndTaxiways(runways, taxiways, pavements);
+    apt->setCommStations(commStations);
   }
   
   void parseAirportLine(const vector<string>& token)
@@ -466,48 +465,38 @@ private:
     }
   }
 
-  void parseATISLine(FGCommList *comm_list, const vector<string>& token) 
+  void parseCommLine(int lineId, const vector<string>& token) 
   {
     if ( rwy_count <= 0 ) {
-      SG_LOG( SG_GENERAL, SG_ALERT, 
-        "No runways; skipping AWOS for " + last_apt_id);
+      SG_LOG( SG_GENERAL, SG_ALERT, "No runways; skipping comm for " + last_apt_id);
     }
-     
-// This assumes/requires that any code-50 line (ATIS or AWOS)
- // applies to the preceding code-1 line (airport ID and name)
- // and that a full set of code-10 lines (runway descriptors)
- // has come between the code-1 and code-50 lines.
-           // typical code-50 lines:
-           // 50 11770 ATIS
-           // 50 11770 AWOS 3
- // This code parallels code found in "operator>>" in ATC.hxx;
- // FIXME: unify the code.      
-    ATCData a;
-    a.geod = SGGeod::fromDegFt(rwy_lon_accum / (double)rwy_count, 
-      rwy_lat_accum / (double)rwy_count, last_apt_elev);
-    a.range = 50;      // give all ATISs small range
-    a.ident = last_apt_id;
-    a.name = last_apt_name;
+    SGGeod pos = SGGeod::fromDegFt(rwy_lon_accum / (double)rwy_count, 
+        rwy_lat_accum / (double)rwy_count, last_apt_elev);
+    
     // short int representing tens of kHz:
-    a.freq = atoi(token[1].c_str());
-    if (token[2] == "ATIS") a.type = ATIS;
-    else a.type = AWOS;                // ASOS same as AWOS
-
-    // generate cartesian coordinates
-    a.cart = SGVec3d::fromGeod(a.geod);
-    comm_list->commlist_freq[a.freq].push_back(a);
-
-    SGBucket bucket(a.geod);
-    int bucknum = bucket.gen_index();
-    comm_list->commlist_bck[bucknum].push_back(a);
-#if 0
-   SG_LOG( SG_GENERAL, SG_ALERT, 
-     "Loaded ATIS/AWOS for airport: " << a.ident
-    << "  lat: "  << a.geod.getLatitudeDeg()
-    << "  lon: "  << a.geod.getLongitudeDeg()
-    << "  freq: " << a.freq
-    << "  type: " << a.type );
-#endif
+    int freqKhz = atoi(token[1].c_str());
+    int rangeNm = 50;
+    FGPositioned::Type ty;
+    switch (lineId) {
+    case 50:
+        ty = FGPositioned::FREQ_AWOS;
+        if (token[2] == "ATIS") {
+            ty = FGPositioned::FREQ_ATIS;
+        }
+        break;
+        
+    case 51:    ty = FGPositioned::FREQ_UNICOM; break;
+    case 52:    ty = FGPositioned::FREQ_CLEARANCE; break;
+    case 53:    ty = FGPositioned::FREQ_GROUND; break;
+    case 54:    ty = FGPositioned::FREQ_TOWER; break;
+    case 55:    
+    case 56:    ty = FGPositioned::FREQ_APP_DEP; break;   
+    default:
+        throw sg_range_exception("unupported apt.dat comm station type");
+    }
+
+    commStations.push_back(new flightgear::CommStation(token[2], ty, pos, rangeNm, freqKhz));
   }
 
 };
@@ -516,12 +505,11 @@ private:
 // Load the airport data base from the specified aptdb file.  The
 // metar file is used to mark the airports as having metar available
 // or not.
-bool fgAirportDBLoad( const string &aptdb_file, 
-        FGCommList *comm_list, const std::string &metar_file )
+bool fgAirportDBLoad( const string &aptdb_file, const std::string &metar_file )
 {
 
    APTLoader ld;
-   ld.parseAPT(aptdb_file, comm_list);
+   ld.parseAPT(aptdb_file);
     //
     // Load the metar.dat file and update apt db with stations that
     // have metar data.
index 7e2405638dffe21c05d866361d4419dac2ccd77c..106268f542b0c410ade9a9cd3c806c33b94d3c4e 100644 (file)
 
 #include <string>
 
-// forward decls
-class FGCommList;
-
 // Load the airport data base from the specified aptdb file.  The
 // metar file is used to mark the airports as having metar available
 // or not.
 
 bool fgAirportDBLoad( const std::string &aptdb_file, 
-        FGCommList *comm_list, const std::string &metar_file );
+        const std::string &metar_file );
 
 #endif // _FG_APT_LOADER_HXX
index 01855347c620c407ed5695a9f639a0621d54eda0..951f860e1db1594c1b583297672152bcccd90924 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <simgear/compiler.h>
+#include <simgear/props/props.hxx>
 
 #include "runwaybase.hxx"
 
index 745d4cb86b43d6d577d1bebb58424bda7b0e548f..ca0a9fb6a4adeedcf61341a75b706f07566d3910 100644 (file)
@@ -85,6 +85,7 @@ public:
   { return _surface_code; }
   
 protected:
+    
   double _heading;
   double _length;
   double _width;
index c3e48ecbbd67325b2993498d3f893fe002124b00..bd2df3038ceddcb1c9d7fa2528a24a9958ab5d53 100644 (file)
@@ -39,6 +39,8 @@
 
 #include <Airports/simple.hxx>
 #include <Navaids/procedure.hxx>
+#include <Navaids/navrecord.hxx>
+#include <Navaids/PositionedBinding.hxx>
 
 using std::string;
 
@@ -197,4 +199,9 @@ std::vector<flightgear::STAR*> FGRunway::getSTARs()
   return result;
 }
 
+flightgear::PositionedBinding*
+FGRunway::createBinding(SGPropertyNode* nd) const
+{
+    return new flightgear::RunwayBinding(this, nd);
+}
 
index 1c5ab85b1071607b60f4d330f1b1ba963f2d62dd..2cdc2e495095f0300cba26f02a8a0e5661ceba38 100644 (file)
@@ -116,6 +116,8 @@ public:
   { return _reciprocal; }
   void setReciprocalRunway(FGRunway* other);
   
+  virtual flightgear::PositionedBinding* createBinding(SGPropertyNode* nd) const;
+  
   /**
    * Helper to process property data loaded from an ICAO.threshold.xml file
    */
@@ -130,6 +132,7 @@ public:
    * Get STARs associared with this runway
    */ 
   std::vector<flightgear::STAR*> getSTARs();
+  
 };
 
 #endif // _FG_RUNWAYS_HXX
index a085fab57ab7804084100bb8cea4983decb7672a..f4f3d1adbfd87538eded3dcdf35fba315934378a 100644 (file)
@@ -47,6 +47,8 @@
 #include <Airports/xmlloader.hxx>
 #include <Navaids/procedure.hxx>
 #include <Navaids/waypoint.hxx>
+#include <Navaids/PositionedBinding.hxx>
+#include <ATC/CommStation.hxx>
 
 using std::vector;
 using namespace flightgear;
@@ -662,6 +664,61 @@ Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
   return mApproaches[aIndex];
 }
 
+class AirportNodeListener : public SGPropertyChangeListener
+{
+public:
+    AirportNodeListener()
+    {
+        SGPropertyNode* airports = fgGetNode("/sim/airport");
+        airports->addChangeListener(this, false);
+    }
+
+    virtual void valueChanged(SGPropertyNode*)
+    {
+    }
+
+    virtual void childAdded(SGPropertyNode* pr, SGPropertyNode* child)
+    {
+       FGAirport* apt = FGAirport::findByIdent(child->getName());
+       if (!apt) {
+           return;
+       }
+       
+       flightgear::PositionedBinding::bind(apt, child);
+    }
+};
+    
+void FGAirport::installPropertyListener()
+{
+    new AirportNodeListener;  
+}
+
+flightgear::PositionedBinding*
+FGAirport::createBinding(SGPropertyNode* nd) const
+{
+    return new flightgear::AirportBinding(this, nd);
+}
+
+void FGAirport::setCommStations(CommStationList& comms)
+{
+    mCommStations.swap(comms);
+    for (unsigned int c=0; c<mCommStations.size(); ++c) {
+        mCommStations[c]->setAirport(this);
+    }
+}
+
+CommStationList
+FGAirport::commStationsOfType(FGPositioned::Type aTy) const
+{
+    CommStationList result;
+    for (unsigned int c=0; c<mCommStations.size(); ++c) {
+        if (mCommStations[c]->type() == aTy) {
+            result.push_back(mCommStations[c]);
+        }
+    }
+    return result;
+}
+
 // get airport elevation
 double fgGetAirportElev( const string& id )
 {
index db5c738a45b227055433e09988d712f908d1ed77..03d66a190a6093b4c2cdef862576c74081519301 100644 (file)
@@ -50,10 +50,12 @@ namespace flightgear {
   class STAR;
   class Approach;
   class Waypt;
-
+  class CommStation;
 
   typedef SGSharedPtr<Waypt> WayptRef;
   typedef std::vector<WayptRef> WayptVec;
+  
+  typedef std::vector<CommStation*> CommStationList;
 }
 
 
@@ -185,6 +187,8 @@ public:
       unsigned int numApproaches() const;
       flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
 
+      static void installPropertyListener();
+      
      /**
       * Syntactic wrapper around FGPositioned::findClosest - find the closest
       * match for filter, and return it cast to FGAirport. The default filter
@@ -228,6 +232,14 @@ public:
      */
     std::pair<flightgear::STAR*, flightgear::WayptRef> selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy);
     
+    virtual flightgear::PositionedBinding* createBinding(SGPropertyNode* nd) const;
+    
+    void setCommStations(flightgear::CommStationList& comms);
+    
+    flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const;
+    
+    const flightgear::CommStationList& commStations() const
+        { return mCommStations; }
 private:
     typedef std::vector<FGRunwayPtr>::const_iterator Runway_iterator;
     /**
@@ -275,6 +287,8 @@ private:
     std::vector<flightgear::SID*> mSIDs;
     std::vector<flightgear::STAR*> mSTARs;
     std::vector<flightgear::Approach*> mApproaches;
+    
+    flightgear::CommStationList mCommStations;
 };
 
 // find basic airport location info from airport database
index be9a4d721f886831860f21b01c5481411704b537..95b34cfe6eee977337058fb0882af3ac73f4d8ca 100644 (file)
 
 #include "kln89_page_apt.hxx"
 
+#include <simgear/structure/exception.hxx>
 #include <cassert>
 
-#include <ATCDCL/commlist.hxx>
+#include <ATC/CommStation.hxx>
 #include <Main/globals.hxx>
 #include <Airports/runways.hxx>
 #include <Airports/simple.hxx>
 
-// This function is copied from Airports/runways.cxx
-// TODO - Make the original properly available and remove this instance!!!!
-// Return reverse rwy number
-// eg 01 -> 19
-// 03L -> 21R
-static string GetReverseRunwayNo(string rwyno) {       
-    // cout << "Original rwyno = " << rwyNo << '\n';
-    
-    // standardize input number
-    string tmp = rwyno.substr(1, 1);
-    if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
-               tmp = rwyno;
-               rwyno = "0" + tmp;
-               SG_LOG( SG_GENERAL, SG_INFO,
-                       "Standardising rwy number from " << tmp << " to " << rwyno );
-    }
-    
-    char buf[4];
-    int rn = atoi(rwyno.substr(0,2).c_str());
-    rn += 18;
-    while(rn > 36) {
-               rn -= 36;
-    }
-    sprintf(buf, "%02i", rn);
-    if(rwyno.size() == 3) {
-               if(rwyno.substr(2,1) == "L") {
-                       buf[2] = 'R';
-                       buf[3] = '\0';
-               } else if (rwyno.substr(2,1) == "R") {
-                       buf[2] = 'L';
-                       buf[3] = '\0';
-               } else if (rwyno.substr(2,1) == "C") {
-                       buf[2] = 'C';
-                       buf[3] = '\0';
-               } else if (rwyno.substr(2,1) == "T") {
-                       buf[2] = 'T';
-                       buf[3] = '\0';
-               } else {
-                       SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
-                       << rwyno << " passed to GetReverseRunwayNo(...)");
-               }
-    }
-    return(buf);
-}
-
 KLN89AptPage::KLN89AptPage(KLN89* parent) 
 : KLN89Page(parent) {
        _nSubPages = 8;
@@ -230,7 +186,8 @@ void KLN89AptPage::Update(double dt) {
                                string s = _aptRwys[i]->ident();
                                _kln89->DrawText(s, 2, 9, 3);
                                _kln89->DrawText("/", 2, 12, 3);
-                               _kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 3);
+                string recipIdent = _aptRwys[i]->reciprocalRunway()->ident();
+                               _kln89->DrawText(recipIdent, 2, 13, 3);
                                // Length
                                s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
                                _kln89->DrawText(s, 2, 5 - s.size(), 2);
@@ -278,7 +235,8 @@ void KLN89AptPage::Update(double dt) {
                                string s = _aptRwys[i]->ident();
                                _kln89->DrawText(s, 2, 9, 1);
                                _kln89->DrawText("/", 2, 12, 1);
-                               _kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 1);
+                string recip = _aptRwys[i]->reciprocalRunway()->ident();
+                               _kln89->DrawText(recip, 2, 13, 1);
                                // Length
                                s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
                                _kln89->DrawText(s, 2, 5 - s.size(), 0);
@@ -499,38 +457,35 @@ void KLN89AptPage::SetId(const string& s) {
 // Update the cached airport details
 void KLN89AptPage::UpdateAirport(const string& id) {
        // Frequencies
-       _aptFreqs.clear();
-       ATCData ad;
-       AptFreq aq;
-       //cout << "UpdateAirport called, id = " << id << '\n';
-       // TODO - the logic below only returns one service per type per airport - they can be on more than one freq though.
-       if(current_commlist->FindByCode(id, ad, ATIS)) {
-               //cout << "Found ATIS\n";
-               aq.service = "ATIS*";
-               aq.freq = ad.freq;
-               _aptFreqs.push_back(aq);
-       }
-       if(current_commlist->FindByCode(id, ad, GROUND)) {
-               aq.service = "GRND*";
-               aq.freq = ad.freq;
-               _aptFreqs.push_back(aq);
-       }
-       if(current_commlist->FindByCode(id, ad, TOWER)) {
-               aq.service = "TWR *";
-               aq.freq = ad.freq;
-               _aptFreqs.push_back(aq);
-       }
-       if(current_commlist->FindByCode(id, ad, APPROACH)) {
-               aq.service = "APR";
-               aq.freq = ad.freq;
-               _aptFreqs.push_back(aq);
-       }
+       _aptFreqs.clear();      
+       
+    const FGAirport* apt = fgFindAirportID(id);
+    if (!apt) {
+        throw sg_exception("UpdateAirport: unknown airport id " + id);
+    }
+       
+    for (unsigned int c=0; c<apt->commStations().size(); ++c) {
+        flightgear::CommStation* comm = apt->commStations()[c];
+        AptFreq aq;
+        aq.freq = comm->freqKHz();
+        switch (comm->type()) {
+        case FGPositioned::FREQ_ATIS:
+            aq.service = "ATIS*"; break;
+        case FGPositioned::FREQ_GROUND:
+            aq.service = "GRND*"; break;
+        case FGPositioned::FREQ_TOWER:
+            aq.service = "TWR *"; break;
+        case FGPositioned::FREQ_APP_DEP:
+            aq.service = "APR *"; break;
+        default:
+            continue;
+        }
+    }
+
        _nFreqPages = (unsigned int)ceil((float(_aptFreqs.size())) / 3.0f);
        
        // Runways
        _aptRwys.clear();
-  const FGAirport* apt = fgFindAirportID(id);
-  assert(apt);
   
   // build local array, longest runway first
   for (unsigned int r=0; r<apt->numRunways(); ++r) {
index 50329b39f48506467809f5d548a0face5ee1e64e..9fd101b65f7319b5296bf97dc727ff9615e0e34e 100644 (file)
@@ -75,8 +75,6 @@
 #include <AIModel/AIManager.hxx>
 
 #include <ATCDCL/ATCmgr.hxx>
-#include <ATCDCL/commlist.hxx>
-#include <ATC/atis_mgr.hxx>
 
 #include <Autopilot/route_mgr.hxx>
 #include <Autopilot/autopilotgroup.hxx>
@@ -1084,15 +1082,10 @@ fgInitNav ()
     SGPath p_metar( globals->get_fg_root() );
     p_metar.append( "Airports/metar.dat" );
 
-// Initialise the frequency search map BEFORE reading
-// the airport database:
-
-
-
-    current_commlist = new FGCommList;
-    current_commlist->init( globals->get_fg_root() );
-    fgAirportDBLoad( aptdb.str(), current_commlist, p_metar.str() );
-
+    fgAirportDBLoad( aptdb.str(), p_metar.str() );
+    FGAirport::installPropertyListener();
+    FGPositioned::installCommands();
+    
     FGNavList *navlist = new FGNavList;
     FGNavList *loclist = new FGNavList;
     FGNavList *gslist = new FGNavList;
@@ -1423,12 +1416,6 @@ bool fgInitSubsystems() {
     globals->set_ATC_mgr(new FGATCMgr);
     globals->get_ATC_mgr()->init(); 
 
-    ////////////////////////////////////////////////////////////////////
-    // Initialise the ATIS Manager
-    ////////////////////////////////////////////////////////////////////
-    globals->add_subsystem("atis", new FGAtisManager, SGSubsystemMgr::POST_FDM);
-
-
     ////////////////////////////////////////////////////////////////////
     // Initialize multiplayer subsystem
     ////////////////////////////////////////////////////////////////////
index cf8ce4ad77c99b5343851b89020d93b472211fb8..8f27472701659101d62304d701990b097022ccbe 100644 (file)
@@ -13,6 +13,7 @@ set(SOURCES
        route.cxx
        routePath.cxx
        waypoint.cxx
+       PositionedBinding.cxx
        )
 
 flightgear_component(Navaids "${SOURCES}")
\ No newline at end of file
diff --git a/src/Navaids/PositionedBinding.cxx b/src/Navaids/PositionedBinding.cxx
new file mode 100644 (file)
index 0000000..758491c
--- /dev/null
@@ -0,0 +1,169 @@
+#include "PositionedBinding.hxx"
+
+#include <map>
+
+#include <simgear/props/props.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include <Main/fg_props.hxx>
+#include <Navaids/navrecord.hxx>
+#include <Airports/simple.hxx>
+#include <Airports/runways.hxx>
+#include <ATC/CommStation.hxx>
+
+typedef std::map<SGPropertyNode*, flightgear::PositionedBinding*> BindingMap;
+static BindingMap static_bindings;
+    
+namespace {
+    
+class PropertyDeleteObserver : public SGPropertyChangeListener
+{
+public:
+    virtual void childRemoved(SGPropertyNode*, SGPropertyNode* node)
+    {
+        BindingMap::iterator it = static_bindings.find(node);
+        if (it != static_bindings.end()) {
+            SG_LOG(SG_GENERAL, SG_INFO, "saw remove of:" << node->getPath() << ", deleting binding");
+            delete it->second;
+            static_bindings.erase(it);
+        }
+    }
+};
+    
+static PropertyDeleteObserver* static_deleteObserver = NULL;
+    
+} // of anonymous namespace
+    
+namespace flightgear
+{
+
+PositionedBinding::PositionedBinding(const FGPositioned* pos, SGPropertyNode* nd) :
+    p(const_cast<FGPositioned*>(pos)),
+    tied(nd)
+{
+    if (!static_deleteObserver) {
+        static_deleteObserver = new PropertyDeleteObserver;
+        globals->get_props()->addChangeListener(static_deleteObserver, false);
+    }
+    
+    nd->setDoubleValue("latitude-deg", p->latitude());
+    nd->setDoubleValue("longitude-deg", p->longitude());
+    
+    if (p->elevation() > -1000) {
+        nd->setDoubleValue("elevation-ft", p->elevation());
+    }
+    
+    nd->setStringValue("ident", p->ident());
+    if (!p->name().empty()) {
+        nd->setStringValue("name", p->name());
+    }
+    
+    nd->setStringValue("type", FGPositioned::nameForType(p->type()));
+}
+
+PositionedBinding::~PositionedBinding()
+{
+    tied.Untie();
+}
+
+void PositionedBinding::bind(FGPositioned* pos, SGPropertyNode* node)
+{
+    BindingMap::iterator it = static_bindings.find(node);
+    if (it != static_bindings.end()) {
+        throw sg_exception("duplicate positioned binding", node->getPath());
+    }
+    
+    PositionedBinding* binding = pos->createBinding(node);
+    static_bindings.insert(it, std::make_pair(node, binding));
+}
+
+NavaidBinding::NavaidBinding(const FGNavRecord* nav, SGPropertyNode* nd) :
+    PositionedBinding(nav, nd)
+{
+    FGPositioned::Type ty = nav->type();
+    if (ty == FGPositioned::NDB) {
+        nd->setDoubleValue("frequency-khz", nav->get_freq() / 100.0);
+    } else {
+        nd->setDoubleValue("frequency-mhz", nav->get_freq() / 100.0);
+    }
+    
+    if ((ty == FGPositioned::LOC) || (ty == FGPositioned::ILS)) {
+      nd->setDoubleValue("loc-course-deg", nav->get_multiuse());
+    }
+    
+    if (ty == FGPositioned::GS) {
+        nd->setDoubleValue("gs-angle-deg", nav->get_multiuse());
+    }
+    
+    nd->setDoubleValue("range-nm", nav->get_range());
+    
+    if (nav->runway()) {
+        // don't want to create a cycle in the graph, so we don't re-bind
+        // the airport/runway node here - just expose the IDs
+        nd->setStringValue("airport", nav->runway()->airport()->ident());
+        nd->setStringValue("runway", nav->runway()->ident());
+    }
+};
+
+RunwayBinding::RunwayBinding(const FGRunway* rwy, SGPropertyNode* nd) :
+    PositionedBinding(rwy, nd)
+{
+    nd->setDoubleValue("length-ft", rwy->lengthFt());
+    nd->setDoubleValue("length-m", rwy->lengthM());
+    nd->setDoubleValue("width-ft", rwy->widthFt());
+    nd->setDoubleValue("width-m", rwy->widthM());
+    nd->setDoubleValue("heading-deg", rwy->headingDeg());
+    nd->setBoolValue("hard-surface", rwy->isHardSurface());
+    
+    nd->setDoubleValue("threshold-displacement-m", rwy->displacedThresholdM());
+    nd->setDoubleValue("stopway-m", rwy->stopwayM());
+    
+    if (rwy->ILS()) {
+        SGPropertyNode* ilsNode = nd->getChild("ils", 0, true);
+        PositionedBinding::bind(rwy->ILS(), ilsNode);
+    }
+}
+
+AirportBinding::AirportBinding(const FGAirport* apt, SGPropertyNode* nd) :
+    PositionedBinding(apt, nd)
+{
+    nd->setIntValue("num-runways", apt->numRunways());
+    
+    SGGeod tower = apt->getTowerLocation();
+    nd->setDoubleValue("tower/latitude-deg", tower.getLatitudeDeg());
+    nd->setDoubleValue("tower/longitude-deg", tower.getLongitudeDeg());
+    nd->setDoubleValue("tower/elevation-ft", tower.getElevationFt());
+    
+    for (unsigned int r=0; r<apt->numRunways(); ++r) {
+        SGPropertyNode* rn = nd->getChild("runway", r, true);
+        FGRunway* rwy = apt->getRunwayByIndex(r);
+        PositionedBinding::bind(rwy, rn);
+    }
+    
+    for (unsigned int c=0; c<apt->commStations().size(); ++c) {
+        flightgear::CommStation* comm = apt->commStations()[c];
+        std::string tynm = FGPositioned::nameForType(comm->type());
+        int count = nd->getChildren(tynm).size();
+        
+        SGPropertyNode* commNode = nd->getChild(tynm, count, true);
+        commNode->setStringValue("ident", comm->ident());
+        commNode->setDoubleValue("frequency-mhz", comm->freqMHz());
+    }
+}
+
+CommStationBinding::CommStationBinding(const CommStation* sta, SGPropertyNode* node) :
+    PositionedBinding(sta, node)
+{
+    node->setIntValue("range-nm", sta->rangeNm());
+    node->setDoubleValue("frequency-mhz", sta->freqMHz());
+    
+    if (sta->airport()) {
+        // don't want to create a cycle in the graph, so we don't re-bind
+        // the airport/runway node here - just expose the IDs
+        node->setStringValue("airport", sta->airport()->ident());
+    }
+}
+
+} // of namespace flightgear
+
diff --git a/src/Navaids/PositionedBinding.hxx b/src/Navaids/PositionedBinding.hxx
new file mode 100644 (file)
index 0000000..ee4df7d
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef FG_POSITIONED_BINDING_HXX
+#define FG_POSITIONED_BINDING_HXX
+
+#include <simgear/props/tiedpropertylist.hxx>
+
+#include "positioned.hxx"
+
+// forward decls
+class FGNavRecord;
+class FGRunway;
+class FGAirport;
+
+namespace flightgear
+{
+
+// forward decls
+class CommStation;
+
+class PositionedBinding
+{
+public:
+    virtual ~PositionedBinding();
+    
+    static void bind(FGPositioned* pos, SGPropertyNode* node);
+    
+
+    PositionedBinding(const FGPositioned* pos, SGPropertyNode* node);
+
+protected:
+    FGPositionedRef p; // bindings own a reference to their positioned
+    simgear::TiedPropertyList tied;
+    
+private:
+
+};
+
+class NavaidBinding : public PositionedBinding
+{
+public:
+    NavaidBinding(const FGNavRecord* nav, SGPropertyNode* node);  
+};
+
+class RunwayBinding : public PositionedBinding
+{
+public:
+    RunwayBinding(const FGRunway* rwy, SGPropertyNode* node);   
+};
+
+class AirportBinding : public PositionedBinding
+{
+public:
+    AirportBinding(const FGAirport* apt, SGPropertyNode* node);   
+};
+
+class CommStationBinding : public PositionedBinding
+{
+public:
+    CommStationBinding(const CommStation* sta, SGPropertyNode* node);  
+};
+
+} // of namespace flightgear
+
+#endif // of FG_POSITIONED_BINDING_HXX
index 03317a57d3342f62cd68718c36d1cc88e910ae5c..5edc64ef180c2babd21b71e19b06eb617eea3de3 100644 (file)
@@ -41,6 +41,7 @@
 #include <Airports/xmlloader.hxx>
 
 #include <Main/fg_props.hxx>
+#include <Navaids/PositionedBinding.hxx>
 
 FGNavRecord::FGNavRecord(Type aTy, const std::string& aIdent, 
   const std::string& aName, const SGGeod& aPos,
@@ -187,6 +188,13 @@ double FGNavRecord::localizerWidth() const
 
 }
 
+flightgear::PositionedBinding*
+FGNavRecord::createBinding(SGPropertyNode* nd) const
+{
+    return new flightgear::NavaidBinding(this, nd);
+}
+
+
 FGTACANRecord::FGTACANRecord(void) :
     channel(""),
     freq(0)
index 09abb6e9786a1589d6961ec089fc3eab8e8a84d3..f58d5a1671daf2521c09ff92e9b54430f32d15a6 100644 (file)
@@ -89,12 +89,17 @@ public:
    */
   FGRunway* runway() const { return mRunway; }
   
+  virtual flightgear::PositionedBinding* createBinding(SGPropertyNode* nd) const;
+
   /**
    * return the localizer width, in degrees
    * computation is based up ICAO stdandard width at the runway threshold
    * see implementation for further details.
    */
   double localizerWidth() const;
+  
+  void bindToNode(SGPropertyNode* nd) const;
+  void unbindFromNode(SGPropertyNode* nd) const;
 };
 
 class FGTACANRecord : public SGReferenced {
index b74e4e877b1a5390a8ce0ae180035559b05f14e7..045839da3398229236db5bd3b3f83147730aabbd 100644 (file)
 #include <osg/Math> // for osg::isNaN
 
 #include <simgear/timing/timestamp.hxx>
+#include <simgear/props/props.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/structure/exception.hxx>
 #include <simgear/math/SGGeometry.hxx>
+#include <simgear/sg_inlines.h>
+#include <simgear/structure/commands.hxx>
 
-
+#include "PositionedBinding.hxx"
+#include "Airports/simple.hxx"
+#include "Main/fg_props.hxx"
 
 typedef std::multimap<std::string, FGPositioned*> NamedPositionedIndex;
 typedef std::pair<NamedPositionedIndex::const_iterator, NamedPositionedIndex::const_iterator> NamedIndexRange;
@@ -628,7 +633,15 @@ FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
     {"fix", FIX},
     {"tacan", TACAN},
     {"dme", DME},
+    {"atis", FREQ_ATIS},
+    {"awos", FREQ_AWOS},
+    {"tower", FREQ_TOWER},
+    {"ground", FREQ_GROUND},
+    {"approach", FREQ_APP_DEP},
+    {"departure", FREQ_APP_DEP},
   // aliases
+    {"gnd", FREQ_GROUND},
+    {"twr", FREQ_TOWER},
     {"waypoint", WAYPOINT},
     {"apt", AIRPORT},
     {"arpt", AIRPORT},
@@ -672,11 +685,24 @@ const char* FGPositioned::nameForType(Type aTy)
  case WAYPOINT: return "waypoint";
  case DME: return "dme";
  case TACAN: return "tacan";
+ case FREQ_TOWER: return "tower";
+ case FREQ_ATIS: return "atis";
+ case FREQ_AWOS: return "awos";
+ case FREQ_GROUND: return "ground";
+ case FREQ_CLEARANCE: return "clearance";
+ case FREQ_UNICOM: return "unicom";
+ case FREQ_APP_DEP: return "approach-departure";
  default:
   return "unknown";
  }
 }
 
+flightgear::PositionedBinding*
+FGPositioned::createBinding(SGPropertyNode* node) const
+{
+    return new flightgear::PositionedBinding(this, node);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // search / query functions
 
@@ -811,3 +837,145 @@ FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
     aResult[i] = r[i].get();
   }
 }
+
+FGPositioned::Filter* createSearchFilter(const SGPropertyNode* arg)
+{
+    string sty(arg->getStringValue("type", 0));
+    FGPositioned::Type ty = FGPositioned::typeFromName(sty);
+    double minRunwayLenFt = arg->getDoubleValue("min-runway-length-ft", -1.0);
+    
+    if ((ty == FGPositioned::AIRPORT) && (minRunwayLenFt > 0.0)) {
+        return new FGAirport::HardSurfaceFilter(minRunwayLenFt);
+    } else if (ty != FGPositioned::INVALID) {
+        FGPositioned::TypeFilter* tf = new FGPositioned::TypeFilter(ty);
+        
+        for (int t=1; arg->hasChild("type", t); ++t) {
+            sty = arg->getChild("type", t)->getStringValue();
+            tf->addType(FGPositioned::typeFromName(sty));
+        }
+        
+        return tf;
+    }
+    
+    return NULL;
+}
+
+SGGeod commandSearchPos(const SGPropertyNode* arg)
+{
+    if (arg->hasChild("longitude-deg") && arg->hasChild("latitude-deg")) {
+        return SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"),
+            arg->getDoubleValue("latitude-deg"));
+    }
+    
+    // use current viewer/aircraft position
+    return SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"), 
+            fgGetDouble("/position/latitude-deg"));
+}
+
+void commandClearExisting(const SGPropertyNode* arg)
+{
+    if (arg->getBoolValue("clear", true)) {
+    // delete all existing result children from their parent
+        string resultPath = arg->getStringValue("results");
+        SGPropertyNode* n = fgGetNode(resultPath.c_str(), 0, true);
+        SGPropertyNode* pr = n->getParent();
+        pr->removeChildren(n->getName(), false /* keep=false, i.e delete nodes */);
+    }
+}
+
+bool commandFindClosest(const SGPropertyNode* arg)
+{
+    int n = arg->getIntValue("max-results", 1);
+    if ((n < 1) || (n > 100)) {
+        SG_LOG(SG_GENERAL, SG_WARN, "commandFindClosest: max-results invalid:" << n);
+        return false;
+    }
+    
+    string resultPath = arg->getStringValue("results");
+    if (resultPath.empty()) {
+        SG_LOG(SG_GENERAL, SG_WARN, "commandFindClosest: no results path defined");
+        return false;
+    }
+
+    std::auto_ptr<FGPositioned::Filter> filt(createSearchFilter(arg));    
+// cap search range, since huge ranges will overload everything
+    double cutoff = arg->getDoubleValue("cutoff-nm", 400.0);
+    SG_CLAMP_RANGE(cutoff, 0.0, 1000.0);
+    
+    SGGeod pos = commandSearchPos(arg);
+    commandClearExisting(arg);
+    
+    FGPositioned::List results = FGPositioned::findClosestN(pos, n, cutoff, filt.get());
+    for (unsigned int i=0; i<results.size(); ++i) {
+       SGPropertyNode* resultsNode = fgGetNode(resultPath.c_str(), i, true);
+       flightgear::PositionedBinding::bind(results[i], resultsNode);
+    }
+    
+    return true;
+}
+
+bool commandFindByIdent(const SGPropertyNode* arg)
+{
+    string resultPath = arg->getStringValue("results");
+    if (resultPath.empty()) {
+        SG_LOG(SG_GENERAL, SG_WARN, "commandFindByIdent: no results path defined");
+        return false;
+    }
+    
+    std::auto_ptr<FGPositioned::Filter> filt(createSearchFilter(arg));    
+    SGGeod pos = commandSearchPos(arg);
+    commandClearExisting(arg);
+    
+    FGPositioned::List results;
+    bool exact = arg->getBoolValue("exact", true);
+    if (arg->hasChild("name")) {
+        results = FGPositioned::findAllWithName(arg->getStringValue("name"), filt.get(), exact);
+    } else if (arg->hasChild("ident")) {
+        results = FGPositioned::findAllWithName(arg->getStringValue("ident"), filt.get(), exact);
+    } else {
+        SG_LOG(SG_GENERAL, SG_WARN, "commandFindByIdent: no search term defined");
+        return false;
+    }
+    
+    bool orderByRange = arg->getBoolValue("order-by-distance", true);
+    if (orderByRange) {
+        FGPositioned::sortByRange(results, pos);
+    }
+      
+    for (unsigned int i=0; i<results.size(); ++i) {
+       SGPropertyNode* resultsNode = fgGetNode(resultPath.c_str(), i, true);
+       flightgear::PositionedBinding::bind(results[i], resultsNode);
+    }
+      
+    return true;
+}
+
+void
+FGPositioned::installCommands()
+{
+    SGCommandMgr::instance()->addCommand("find-nearest", commandFindClosest);
+    SGCommandMgr::instance()->addCommand("find-by-ident", commandFindByIdent);
+}
+
+FGPositioned::TypeFilter::TypeFilter(Type aTy)
+{
+    types.push_back(aTy);
+}
+
+void FGPositioned::TypeFilter::addType(Type aTy)
+{
+    types.push_back(aTy);
+}
+
+bool
+FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
+{
+    std::vector<Type>::const_iterator it = types.begin(),
+        end = types.end();
+    for (; it != end; ++it) {
+        return aPos->type() == *it;
+    }
+    
+    return false;
+}
+
index f6f61229a78750118aea77e719e12f5ceefacdcc..de5a31322ac2940ae32ae07da23961573a753fc7 100644 (file)
 #include <simgear/math/SGMath.hxx>
 
 class FGPositioned;
+class SGPropertyNode;
 
 typedef SGSharedPtr<FGPositioned> FGPositionedRef;
 
+namespace flightgear
+{
+    class PositionedBinding;
+}
+
 class FGPositioned : public SGReferenced
 {
 public:
@@ -56,9 +62,14 @@ public:
     DME,
     TACAN,
     OBSTACLE,
-    FREQ_GND,
-    FREQ_TWR,
+    FREQ_GROUND,
+    FREQ_TOWER,
     FREQ_ATIS,
+    FREQ_AWOS,
+    FREQ_APP_DEP,
+    FREQ_ENROUTE,
+    FREQ_CLEARANCE,
+    FREQ_UNICOM,
     LAST_TYPE
   } Type;
 
@@ -97,6 +108,9 @@ public:
   double elevation() const
   { return mPosition.getElevationFt(); }
   
+
+  virtual flightgear::PositionedBinding* createBinding(SGPropertyNode* nd) const;
+
   /**
    * Predicate class to support custom filtering of FGPositioned queries
    * Default implementation of this passes any FGPositioned instance.
@@ -135,13 +149,15 @@ public:
   class TypeFilter : public Filter
   {
   public:
-    TypeFilter(Type aTy) : mType(aTy) { ; }
-    virtual bool pass(FGPositioned* aPos) const
-    { return (mType == aPos->type()); }
+    TypeFilter(Type aTy);
+    virtual bool pass(FGPositioned* aPos) const;
+    void addType(Type aTy);
   private:
-    const Type mType;
+      std::vector<Type> types;
   };
   
+  static void installCommands();
+  
   static List findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter = NULL);
         
   static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL);