+static PositionedID readNavFromStream(std::istream& aStream,
+ FGPositioned::Type type = FGPositioned::INVALID)
+{
+ NavDataCache* cache = NavDataCache::instance();
+
+ int rawType;
+ aStream >> rawType;
+ if (aStream.eof() || (rawType == 99)) {
+ return 0; // happens with, eg, carrier_nav.dat
+ }
+
+ double lat, lon, elev_ft, multiuse;
+ int freq, range;
+ std::string name, ident;
+ aStream >> lat >> lon >> elev_ft >> freq >> range >> multiuse >> ident;
+ getline(aStream, name);
+
+ SGGeod pos(SGGeod::fromDegFt(lon, lat, elev_ft));
+ name = simgear::strutils::strip(name);
+
+// the type can be forced by our caller, but normally we use th value
+// supplied in the .dat file
+ if (type == FGPositioned::INVALID) {
+ type = mapRobinTypeToFGPType(rawType);
+ }
+ if (type == FGPositioned::INVALID) {
+ return 0;
+ }
+
+ if ((type >= FGPositioned::OM) && (type <= FGPositioned::IM)) {
+ AirportRunwayPair arp(cache->findAirportRunway(name));
+ if (arp.second && (elev_ft < 0.01)) {
+ // snap to runway elevation
+ FGPositioned* runway = cache->loadById(arp.second);
+ assert(runway);
+ pos.setElevationFt(runway->geod().getElevationFt());
+ }
+
+ return cache->insertNavaid(type, string(), name, pos, 0, 0, 0,
+ arp.first, arp.second);
+ }
+
+ if (range < 0.01) {
+ range = defaultNavRange(ident, type);
+ }
+
+ AirportRunwayPair arp;
+ FGRunway* runway = NULL;
+ PositionedID navaid_dme = 0;
+
+ if (type == FGPositioned::DME) {
+ FGPositioned::TypeFilter f(FGPositioned::INVALID);
+ if ( name.find("VOR-DME") != std::string::npos ) {
+ f.addType(FGPositioned::VOR);
+ } else if ( name.find("DME-ILS") != std::string::npos ) {
+ f.addType(FGPositioned::ILS);
+ f.addType(FGPositioned::LOC);
+ } else if ( name.find("VORTAC") != std::string::npos ) {
+ f.addType(FGPositioned::VOR);
+ } else if ( name.find("NDB-DME") != std::string::npos ) {
+ f.addType(FGPositioned::NDB);
+ } else if ( name.find("TACAN") != std::string::npos ) {
+ f.addType(FGPositioned::VOR);
+ }
+
+ if (f.maxType() > 0) {
+ FGPositionedRef ref = FGPositioned::findClosestWithIdent(ident, pos, &f);
+ if (ref.valid()) {
+ string_list dme_part = simgear::strutils::split(name , 0 ,1);
+ string_list navaid_part = simgear::strutils::split(ref.get()->name(), 0 ,1);
+
+ if ( simgear::strutils::uppercase(navaid_part[0]) == simgear::strutils::uppercase(dme_part[0]) ) {
+ navaid_dme = ref.get()->guid();
+ }
+ }
+ }
+ }
+
+ if ((type >= FGPositioned::ILS) && (type <= FGPositioned::GS)) {
+ arp = cache->findAirportRunway(name);
+ if (arp.second) {
+ runway = FGPositioned::loadById<FGRunway>(arp.second);
+ assert(runway);
+#if 0
+ // code is disabled since it's causing some problems, see
+ // http://code.google.com/p/flightgear-bugs/issues/detail?id=926
+ if (elev_ft < 0.01) {
+ // snap to runway elevation
+ pos.setElevationFt(runway->geod().getElevationFt());
+ }
+#endif
+ } // of found runway in the DB
+ } // of type is runway-related
+
+ bool isLoc = (type == FGPositioned::ILS) || (type == FGPositioned::LOC);
+ if (runway && autoAlignLocalizers && isLoc) {
+ alignLocaliserWithRunway(runway, ident, pos, multiuse);
+ }
+
+ // silently multiply adf frequencies by 100 so that adf
+ // vs. nav/loc frequency lookups can use the same code.
+ if (type == FGPositioned::NDB) {
+ freq *= 100;
+ }
+
+ PositionedID r = cache->insertNavaid(type, ident, name, pos, freq, range, multiuse,
+ arp.first, arp.second);
+
+ if (isLoc) {
+ cache->setRunwayILS(arp.second, r);
+ }
+
+ if (navaid_dme) {
+ cache->setNavaidColocated(navaid_dme, r);
+ }
+
+ return r;
+}
+
+// load and initialize the navigational databases
+bool navDBInit(const SGPath& path)
+{