+ elevM = twrNode->getDoubleValue("elev-m");
+// tower elevation is AGL, not AMSL. Since we don't want to depend on the
+// scenery for a precise terrain elevation, we use the field elevation
+// (this is also what the apt.dat code does)
+ double fieldElevationM = geod().getElevationM();
+
+ _tower_location = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM);
+}
+
+bool FGAirport::buildApproach(Waypt* aEnroute, STAR* aSTAR, FGRunway* aRwy, WayptVec& aRoute)
+{
+ loadProcedures();
+
+ if ((aRwy && (aRwy->airport() != this))) {
+ throw sg_exception("invalid parameters", "FGAirport::buildApproach");
+ }
+
+ if (aSTAR) {
+ bool ok = aSTAR->route(aRwy, aEnroute, aRoute);
+ if (!ok) {
+ SG_LOG(SG_GENERAL, SG_WARN, ident() << ": build approach, STAR " << aSTAR->ident()
+ << " failed to route from transition " << aEnroute->ident());
+ return false;
+ }
+ } else if (aEnroute) {
+ // no a STAR specified, just use enroute point directly
+ aRoute.push_back(aEnroute);
+ }
+
+ if (!aRwy) {
+ // no runway selected yet, but we loaded the STAR, so that's fine, we're done
+ return true;
+ }
+
+// build the approach (possibly including transition), and including the missed segment
+ vector<Approach*> aps;
+ for (unsigned int j=0; j<mApproaches.size();++j) {
+ if (mApproaches[j]->runway() == aRwy) {
+ aps.push_back(mApproaches[j]);
+ }
+ } // of approach filter by runway
+
+ if (aps.empty()) {
+ SG_LOG(SG_GENERAL, SG_INFO, ident() << "; no approaches defined for runway " << aRwy->ident());
+ // could build a fallback approach here
+ return false;
+ }
+
+ for (unsigned int k=0; k<aps.size(); ++k) {
+ if (aps[k]->route(aRoute.back(), aRoute)) {
+ return true;
+ }
+ } // of initial approach iteration
+
+ SG_LOG(SG_GENERAL, SG_INFO, ident() << ": unable to find transition to runway "
+ << aRwy->ident() << ", assume vectors");
+
+ WayptRef v(new ATCVectors(NULL, this));
+ aRoute.push_back(v);
+ return aps.front()->routeFromVectors(aRoute);
+}
+
+pair<flightgear::SID*, WayptRef>
+FGAirport::selectSID(const SGGeod& aDest, FGRunway* aRwy)
+{
+ loadProcedures();
+
+ WayptRef enroute;
+ flightgear::SID* sid = NULL;
+ double d = 1e9;
+
+ for (unsigned int i=0; i<mSIDs.size(); ++i) {
+ if (aRwy && !mSIDs[i]->isForRunway(aRwy)) {
+ continue;
+ }
+
+ WayptRef e = mSIDs[i]->findBestTransition(aDest);
+ if (!e) {
+ continue; // strange, but let's not worry about it
+ }