diff --git a/projects/VC90/FlightGear/FlightGear.vcproj b/projects/VC90/FlightGear/FlightGear.vcproj
index 98fde43d6..084a5531f 100644
--- a/projects/VC90/FlightGear/FlightGear.vcproj
+++ b/projects/VC90/FlightGear/FlightGear.vcproj
@@ -569,14 +569,6 @@
RelativePath="..\..\..\src\ATCDCL\atis.hxx"
>
-
-
-
-
-
-
-
-
@@ -2489,6 +2473,14 @@
RelativePath="..\..\..\src\FDM\NullFDM.hxx"
>
+
+
+
+
+
+
+
+
@@ -3220,7 +3220,7 @@
-
+
@@ -3381,6 +3381,14 @@
RelativePath="..\..\..\src\Environment\fgwind.hxx"
>
+
+
+
+
@@ -3405,6 +3413,14 @@
RelativePath="..\..\..\src\Environment\precipitation_mgr.hxx"
>
+
+
+
+
@@ -3429,22 +3445,6 @@
RelativePath="..\..\..\src\Environment\terrainsampler.hxx"
>
-
-
-
-
-
-
-
-
+
+
+
+
@@ -3800,14 +3808,6 @@
-
-
-
-
+
+#include
+
+namespace {
+
+typedef std::multimap FrequencyMap;
+static FrequencyMap static_frequencies;
+
+typedef std::pair 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
index 000000000..89c0d1f43
--- /dev/null
+++ b/src/ATC/CommStation.hxx
@@ -0,0 +1,39 @@
+#ifndef FG_ATC_COMM_STATION_HXX
+#define FG_ATC_COMM_STATION_HXX
+
+#include
+
+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
+
diff --git a/src/ATC/Makefile.am b/src/ATC/Makefile.am
index fd5302aac..522a82033 100644
--- a/src/ATC/Makefile.am
+++ b/src/ATC/Makefile.am
@@ -1,9 +1,9 @@
noinst_LIBRARIES = libATC.a
libATC_a_SOURCES = \
- atis_mgr.cxx atis_mgr.hxx \
atcdialog.cxx atcdialog.hxx \
atc_mgr.cxx atc_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
index 034a8358a..000000000
--- a/src/ATC/atis_mgr.cxx
+++ /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
-
-#include
-#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
index 12fc4fd07..000000000
--- a/src/ATC/atis_mgr.hxx
+++ /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
-
-class FGAtisManager : public SGSubsystem
-{
-private:
-
-public:
- FGAtisManager();
- ~FGAtisManager();
- void init();
- void update(double time);
-};
-
-#endif // _ATIS_HXX_
\ No newline at end of file
diff --git a/src/ATCDCL/ATC.cxx b/src/ATCDCL/ATC.cxx
index 30d3d23e8..4701a67ee 100644
--- a/src/ATCDCL/ATC.cxx
+++ b/src/ATCDCL/ATC.cxx
@@ -31,8 +31,8 @@
#include
#include
-
-
+#include
+#include
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
diff --git a/src/ATCDCL/ATC.hxx b/src/ATCDCL/ATC.hxx
index 2109b697b..17f743cd7 100644
--- a/src/ATCDCL/ATC.hxx
+++ b/src/ATCDCL/ATC.hxx
@@ -37,6 +37,11 @@
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;}
diff --git a/src/ATCDCL/ATCDialog.cxx b/src/ATCDCL/ATCDialog.cxx
index a1c3c5e84..026a65449 100644
--- a/src/ATCDCL/ATCDialog.cxx
+++ b/src/ATCDCL/ATCDialog.cxx
@@ -34,9 +34,9 @@
#include "ATCDialog.hxx"
#include "ATC.hxx"
#include "ATCmgr.hxx"
-#include "commlist.hxx"
#include "ATCutils.hxx"
#include
+#include
#include
@@ -287,21 +287,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() {
@@ -316,38 +312,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 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 )
- map::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; (rgetNode("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);
}
@@ -378,43 +361,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 )
- 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());
-
- 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';
-
- entry->setStringValue("text[1]/label", buf);
- n++;
- }
- }
- if(n == 0) {
- label = "No frequencies found for airport " + ident;
+ 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 )
+ SGPropertyNode *entry = freq_group->getNode("group", n, true);
+ copyProperties(freq_group->getNode("group-template", true), entry);
+ entry->removeChildren("enabled", true);
+
+ entry->setStringValue("text[0]/label", comm->ident());
+
+ 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;
+ }
_gui->showDialog(dialog_name);
}
diff --git a/src/ATCDCL/ATCmgr.cxx b/src/ATCDCL/ATCmgr.cxx
index 537bfddef..8d8a6fc58 100644
--- a/src/ATCDCL/ATCmgr.cxx
+++ b/src/ATCDCL/ATCmgr.cxx
@@ -24,29 +24,18 @@
#include
#include
+#include
#include
+#include
+#include
#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 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(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");
- }
}
diff --git a/src/ATCDCL/ATCmgr.hxx b/src/ATCDCL/ATCmgr.hxx
index 850fcc0a9..179f65fc3 100644
--- a/src/ATCDCL/ATCmgr.hxx
+++ b/src/ATCDCL/ATCmgr.hxx
@@ -24,31 +24,12 @@
#include
-#include
-#include
-
#include
#include
#include