#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/bucket/newbucket.hxx>
+#include <Airports/simple.hxx>
#include "commlist.hxx"
//#include "atislist.hxx"
+#include "ATCutils.hxx"
FGCommList *current_commlist;
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;
ATCData a;
fin >> a;
if(a.type == INVALID) {
- break;
- }
-
- // Push all stations onto frequency map
- commlist_freq[a.freq].push_back(a);
-
- // Push approach stations onto bucket map as well
- if(a.type == APPROACH) {
- // get bucket number
- SGBucket bucket(a.lon, a.lat);
- int bucknum = bucket.gen_index();
- commlist_bck[bucknum].push_back(a);
+ SG_LOG(SG_GENERAL, SG_ALERT, "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) {
+ // get bucket number
+ SGBucket bucket(a.lon, a.lat);
+ int bucknum = bucket.gen_index();
+ commlist_bck[bucknum].push_back(a);
+ //}
}
- fin >> skipcomment;
- }
- return true;
+ fin >> skipcomment;
+ }
+
+ fin.close();
+ return true;
}
lon *= SGD_DEGREES_TO_RADIANS;
lat *= SGD_DEGREES_TO_RADIANS;
- comm_list_type stations = commlist_freq[(int)(freq*100.0 + 0.5)];
+ // HACK - if freq > 1000 assume it's in KHz, otherwise assume MHz.
+ // A bit ugly but it works for now!!!!
+ comm_list_type stations;
+ if(freq > 1000.0) {
+ stations = commlist_freq[(int)freq];
+ } else {
+ stations = commlist_freq[(int)(freq*100.0 + 0.5)];
+ }
comm_list_iterator current = stations.begin();
comm_list_iterator last = stations.end();
return false;
}
-
-int FGCommList::FindByPos(double lon, double lat, double elev, comm_list_type* stations, atc_type tp)
+int FGCommList::FindByPos(double lon, double lat, double elev, double range, comm_list_type* stations, atc_type tp)
{
// number of relevant stations found within range
int found = 0;
SGBucket buck(lon, lat);
// get neigboring buckets
- int max_range = 100;
- int bx = (int)( max_range*SG_NM_TO_METER / buck.get_width_m() / 2);
- int by = (int)( max_range*SG_NM_TO_METER / buck.get_height_m() / 2 );
+ int bx = (int)( range*SG_NM_TO_METER / buck.get_width_m() / 2);
+ int by = (int)( range*SG_NM_TO_METER / buck.get_height_m() / 2 );
// loop over bucket range
- for ( int i=-bx; i<bx; i++) {
- for ( int j=-by; j<by; j++) {
+ for ( int i=-bx; i<=bx; i++) {
+ for ( int j=-by; j<=by; j++) {
buck = sgBucketOffset(lon, lat, i, j);
long int bucket = buck.gen_index();
comm_list_type Fstations = commlist_bck[bucket];
}
+// 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( double lon, double lat, double elev, 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(lon, lat, elev, 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;
+ //Point3D p1(*itr.lon, *itr.lat, *itr.elev);
+ Point3D p1(ad2.lon, ad2.lat, ad2.elev);
+ FGAirport a;
+ if(dclFindAirportID(ad2.ident, &a)) {
+ Point3D p2(lon, lat, elev);
+ tmp = dclGetHorizontalSeparation(p1, p2);
+ 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( string ICAO, ATCData& ad, atc_type tp ) {
+ FGAirport a;
+ if ( dclFindAirportID( ICAO, &a ) ) {
+ comm_list_type stations;
+ int found = FindByPos(a.longitude, a.latitude, a.elevation, 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;
+ return true;
+ }
+ ++itr;
+ }
+ }
+ } else {
+ return false;
+ }
+ return false;
+}
+
+
// TODO - this function should move somewhere else eventually!
// Return an appropriate call-sign for an ATIS transmission.
int FGCommList::GetCallSign( string apt_id, int hours, int mins )