]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATC/AILocalTraffic.cxx
try to fix yet another crash bug (don't worry, there's one for anybody!)
[flightgear.git] / src / ATC / AILocalTraffic.cxx
index 76a294f60c1547f80c60233b800d23ea03cd48bd..15eb6a3d3c1c7ccfc25d0041ab44e96eb5fabb66 100644 (file)
@@ -17,7 +17,7 @@
 //
 // 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 /*==========================================================
 
@@ -38,6 +38,7 @@ during descent to avoid occasionally landing short or long.
 
 #include <Airports/runways.hxx>
 #include <Main/globals.hxx>
+#include <Main/viewer.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
 #include <simgear/math/point3d.hxx>
@@ -60,7 +61,6 @@ FGAILocalTraffic::FGAILocalTraffic() {
                                          globals->get_sim_time_sec() );
        *//*
        _model = model;
-       _model->ref();
        _aip.init(_model);
        */
        //SetModel(model);
@@ -106,6 +106,7 @@ FGAILocalTraffic::FGAILocalTraffic() {
        contactTower = false;
        contactGround = false;
        _taxiToGA = false;
+       _removeSelf = false;
        
        descending = false;
        targetDescentRate = 0.0;
@@ -118,17 +119,18 @@ FGAILocalTraffic::FGAILocalTraffic() {
        _savedSlope = 0.0;
        
        _controlled = false;
+       
+       _invisible = false;
 }
 
 FGAILocalTraffic::~FGAILocalTraffic() {
-       //_model->deRef();
 }
 
-void FGAILocalTraffic::GetAirportDetails(string id) {
+void FGAILocalTraffic::GetAirportDetails(const string& id) {
        AirportATC a;
        if(ATC->GetAirportATCDetails(airportID, &a)) {
                if(a.tower_freq) {      // Has a tower - TODO - check the opening hours!!!
-                       tower = (FGTower*)ATC->GetATCPointer(airportID, TOWER); // Maybe need some error checking here
+                       tower = (FGTower*)ATC->GetATCPointer(airportID, TOWER);
                        if(tower == NULL) {
                                // Something has gone wrong - abort or carry on with un-towered operation?
                                SG_LOG(SG_ATC, SG_ALERT, "ERROR - can't get a tower pointer from tower control for " << airportID << " in FGAILocalTraffic::GetAirportDetails() :-(");
@@ -152,7 +154,7 @@ void FGAILocalTraffic::GetAirportDetails(string id) {
                _controlled = false;
        }
        // Get the airport elevation
-       aptElev = dclGetAirportElev(airportID.c_str());
+       aptElev = fgGetAirportElev(airportID.c_str());
        //cout << "Airport elev in AILocalTraffic = " << aptElev << '\n';
        // WARNING - we use this elev for the whole airport - some assumptions in the code 
        // might fall down with very slopey airports.
@@ -160,30 +162,35 @@ void FGAILocalTraffic::GetAirportDetails(string id) {
 
 // Get details of the active runway
 // It is assumed that by the time this is called the tower control and airport code will have been set up.
-void FGAILocalTraffic::GetRwyDetails(string id) {
+void FGAILocalTraffic::GetRwyDetails(const string& id) {
        //cout << "GetRwyDetails called" << endl;
        
-       rwy.rwyID = tower->GetActiveRunway();
+       if(_controlled) {
+               rwy.rwyID = tower->GetActiveRunway();
+       } else {
+               // TODO - get a proper runway ID from uncontrolled airports
+               rwy.rwyID = "00";
+       }
        
        // Now we need to get the threshold position and rwy heading
        
        FGRunway runway;
        bool rwyGood = globals->get_runways()->search(id, rwy.rwyID, &runway);
        if(rwyGood) {
-       double hdg = runway.heading;
+       double hdg = runway._heading;
                double other_way = hdg - 180.0;
                while(other_way <= 0.0) {
                        other_way += 360.0;
                }
 
        // move to the +l end/center of the runway
-               //cout << "Runway center is at " << runway.lon << ", " << runway.lat << '\n';
-       Point3D origin = Point3D(runway.lon, runway.lat, aptElev);
+               //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n';
+       Point3D origin = Point3D(runway._lon, runway._lat, aptElev);
                Point3D ref = origin;
        double tshlon, tshlat, tshr;
                double tolon, tolat, tor;
-               rwy.length = runway.length * SG_FEET_TO_METER;
-               rwy.width = runway.width * SG_FEET_TO_METER;
+               rwy.length = runway._length * SG_FEET_TO_METER;
+               rwy.width = runway._width * SG_FEET_TO_METER;
        geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, 
                                rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr );
        geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), hdg, 
@@ -201,7 +208,7 @@ void FGAILocalTraffic::GetRwyDetails(string id) {
                rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos);        // should come out as zero
                rwy.end2ortho = ortho.ConvertToLocal(takeoff_end);
        } else {
-               SG_LOG(SG_ATC, SG_ALERT, "Help  - can't get good runway in FGAILocalTraffic!!\n");
+               SG_LOG(SG_ATC, SG_ALERT, "Help  - can't get good runway at airport " << id << " in FGAILocalTraffic!!");
        }
 }
 
@@ -217,7 +224,7 @@ To a certain extent it's FGAIMgr that has to worry about this, but we need to pr
 sufficient initialisation functionality within the plane classes to allow the manager
 to initially position them where and how required.
 */
-bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState initialState, PatternLeg initialLeg) {
+bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, OperatingState initialState, PatternLeg initialLeg) {
        //cout << "FGAILocalTraffic.Init(...) called" << endl;
        airportID = ICAO;
        
@@ -239,11 +246,15 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1);
        }
        
-       // TODO - this assumes a controlled airport - make sure we revert to CTAF etc if uncontrolled or after-hours.
-       if((initialState == PARKED) || (initialState == TAXIING)) {
-               freq = (double)ground->get_freq() / 100.0;
+       if(_controlled) {
+               if((initialState == PARKED) || (initialState == TAXIING)) {
+                       freq = (double)ground->get_freq() / 100.0;
+               } else {
+                       freq = (double)tower->get_freq() / 100.0;
+               }
        } else {
-               freq = (double)tower->get_freq() / 100.0;
+               freq = 122.8;
+               // TODO - find the proper freq if CTAF or unicom or after-hours.
        }
 
        //cout << "In Init(), initialState = " << initialState << endl;
@@ -266,20 +277,24 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                _pos = ourGate->pos;
                _pos.setelev(aptElev);
                _hdg = ourGate->heading;
+               Transform();
                
                // Now we've set the position we can do the ground elev
                elevInitGood = false;
                inAir = false;
                DoGroundElev();
                
-               Transform();
                break;
        case TAXIING:
                //tuned_station = ground;
                // FIXME - implement this case properly
                // For now we'll assume that the plane should start at the hold short in this case
                // and that we're working without ground network elements.  Ie. an airport with no facility file.
-               tuned_station = tower;
+               if(_controlled) {
+                       tuned_station = tower;
+               } else {
+                       tuned_station = NULL;
+               }
                freeTaxi = true;
                // Set a position and orientation in an approximate place for hold short.
                //cout << "rwy.width = " << rwy.width << '\n';
@@ -295,8 +310,9 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                slope = 0.0;
                elevInitGood = false;
                inAir = false;
-               DoGroundElev();
                Transform();
+               DoGroundElev();
+               //Transform();
                
                responseCounter = 0.0;
                contactTower = false;
@@ -315,7 +331,11 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                
                //cout << "Starting in pattern...\n";
                
-               tuned_station = tower;
+               if(_controlled) {
+                       tuned_station = tower;
+               } else {
+                       tuned_station = NULL;
+               }
                
                circuitsToFly = 0;              // ie just fly this circuit and then stop
                touchAndGo = false;
@@ -327,14 +347,17 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                        leg = DOWNWIND;
                        elevInitGood = false;
                        inAir = true;
-                       track = rwy.hdg - (180 * patternDirection);     //should tend to bring track back into the 0->360 range
+                       SetTrack(rwy.hdg - (180 * patternDirection));
                        slope = 0.0;
                        _pitch = 0.0;
                        _roll = 0.0;
                        IAS = 90.0;
                        descending = false;
                        _aip.setVisible(true);
-                       tower->RegisterAIPlane(plane, this, CIRCUIT, DOWNWIND);
+                       if(_controlled) {
+                               tower->RegisterAIPlane(plane, this, CIRCUIT, DOWNWIND);
+                       }
+                       Transform();
                } else {                        
                        // Default to initial position on threshold for now
                        _pos.setlat(rwy.threshold_pos.lat());
@@ -346,18 +369,19 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState
                        // This might not always be necessary if we implement in-air start
                        elevInitGood = false;
                        inAir = false;
-                       DoGroundElev();
                        
                        _pitch = 0.0;
                        _roll = 0.0;
                        leg = TAKEOFF_ROLL;
                        vel = 0.0;
                        slope = 0.0;
+                       
+                       Transform();
+                       DoGroundElev();
                }
        
                operatingState = IN_PATTERN;
                
-               Transform();
                break;
        case EN_ROUTE:
                // This implies we're being init'd by AIGAVFRTraffic - simple return now
@@ -380,7 +404,7 @@ void FGAILocalTraffic::DownwindEntry() {
        leg = DOWNWIND;
        elevInitGood = false;
        inAir = true;
-       track = rwy.hdg - (180 * patternDirection);     //should tend to bring track back into the 0->360 range
+       SetTrack(rwy.hdg - (180 * patternDirection));
        slope = 0.0;
        _pitch = 0.0;
        _roll = 0.0;
@@ -396,7 +420,7 @@ void FGAILocalTraffic::StraightInEntry(bool des) {
        leg = FINAL;
        elevInitGood = false;
        inAir = true;
-       track = rwy.hdg;
+       SetTrack(rwy.hdg);
        transmitted = true;     // TODO - fix this hack.
        // TODO - set up the next 5 properly for a descent!
        slope = -5.5;
@@ -445,6 +469,16 @@ void FGAILocalTraffic::FlyCircuits(int numCircuits, bool tag) {
 // Run the internal calculations
 void FGAILocalTraffic::Update(double dt) {
        //cout << "U" << flush;
+       
+       // we shouldn't really need this since there's a LOD of 10K on the whole plane anyway I think.
+       // At the moment though I need to to avoid DList overflows - the whole plane LOD obviously isn't getting picked up.
+       if(!_invisible) {
+               if(dclGetHorizontalSeparation(_pos, Point3D(fgGetDouble("/position/longitude-deg"), fgGetDouble("/position/latitude-deg"), 0.0)) > 8000) _aip.setVisible(false);
+               else _aip.setVisible(true);
+       } else {
+               _aip.setVisible(false);
+       }
+       
        //double responseTime = 10.0;           // seconds - this should get more sophisticated at some point
        responseCounter += dt;
        if((contactTower) && (responseCounter >= 8.0)) {
@@ -486,16 +520,28 @@ void FGAILocalTraffic::Update(double dt) {
                string trns = "GA Parking, Thank you and Good Day";
                //double f = globals->get_ATC_mgr()->GetFrequency(airportID, GROUND) / 100.0;   
                pending_transmission = trns;
-               ConditionalTransmit(5.0);
-               tower->DeregisterAIPlane(plane.callsign);
+               ConditionalTransmit(5.0, 99);
                _taxiToGA = false;
-               // HACK - check if we are at a simple airport or not first
-               globals->get_AI_mgr()->ScheduleRemoval(plane.callsign);
-       }               
+               if(_controlled) {
+                       tower->DeregisterAIPlane(plane.callsign);
+               }
+               // NOTE - we can't delete this instance yet since then the frequency won't get release when the message display finishes.
+       }
+
+       if((_removeSelf) && (responseCounter >= 8.0)) {
+               _removeSelf = false;
+               // MEGA HACK - check if we are at a simple airport or not first instead of simply hardwiring KEMT as the only non-simple airport.
+               // TODO FIXME TODO FIXME !!!!!!!
+               if(airportID != "KEMT") globals->get_AI_mgr()->ScheduleRemoval(plane.callsign);
+       }
        
        if((changeFreq) && (responseCounter > 8.0)) {
                switch(changeFreqType) {
                case TOWER:
+                       if(!tower) {
+                               SG_LOG(SG_ATC, SG_ALERT, "ERROR: Trying to change frequency to tower in FGAILocalTraffic, but tower is NULL!!!");
+                               break;
+                       }
                        tuned_station = tower;
                        freq = (double)tower->get_freq() / 100.0;
                        //Transmit("DING!");
@@ -513,12 +559,17 @@ void FGAILocalTraffic::Update(double dt) {
                        Transmit(2);
                        break;
                case GROUND:
+                       if(!tower) {
+                               SG_LOG(SG_ATC, SG_ALERT, "ERROR: Trying to change frequency to ground in FGAILocalTraffic, but tower is NULL!!!");
+                               break;
+                       }
+                       if(!ground) {
+                               SG_LOG(SG_ATC, SG_ALERT, "ERROR: Trying to change frequency to ground in FGAILocalTraffic, but ground is NULL!!!");
+                               break;
+                       }
                        tower->DeregisterAIPlane(plane.callsign);
                        tuned_station = ground;
                        freq = (double)ground->get_freq() / 100.0;
-                       // HACK - check if we are at a simple airport or not first
-                       // TODO FIXME TODO FIXME !!!!!!!
-                       if(airportID != "KEMT") globals->get_AI_mgr()->ScheduleRemoval(plane.callsign);
                        break;
                // And to avoid compiler warnings...
                case APPROACH:  break;
@@ -662,8 +713,13 @@ void FGAILocalTraffic::Update(double dt) {
                                // Do some communication
                                // airport name + tower + airplane callsign + location + request taxi for + operation type + ?
                                string trns = "";
-                               trns += tower->get_name();
-                               trns += " tower ";
+                               if(_controlled) {
+                                       trns += tower->get_name();
+                                       trns += " tower ";
+                               } else {
+                                       trns += "Traffic ";
+                                       // TODO - get the airport name somehow if uncontrolled
+                               }
                                trns += plane.callsign;
                                trns += " on apron parking request taxi for traffic pattern";
                                //cout << "trns = " << trns << endl;
@@ -692,12 +748,14 @@ void FGAILocalTraffic::Update(double dt) {
        }
        //cout << "I " << flush;
        
+       //cout << "Update _pos = " << _pos << ", vis = " << _aip.getVisible() << '\n';
+       
        // Convienience output for AI debugging using the property logger
        //fgSetDouble("/AI/Local1/ortho-x", (ortho.ConvertToLocal(_pos)).x());
        //fgSetDouble("/AI/Local1/ortho-y", (ortho.ConvertToLocal(_pos)).y());
        //fgSetDouble("/AI/Local1/elev", _pos.elev() * SG_METER_TO_FEET);
        
-       // And finally, call parent for transmission rendering
+       // And finally, call parent.
        FGAIPlane::Update(dt);
 }
 
@@ -795,6 +853,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                IAS = vel + (cos((_hdg - wind_from) * DCL_DEGREES_TO_RADIANS) * wind_speed);
                if(IAS >= 70) {
                        leg = CLIMBOUT;
+                       SetTrack(rwy.hdg);      // Hands over control of turning to AIPlane
                        _pitch = 10.0;
                        IAS = best_rate_of_climb_speed;
                        //slope = 7.0;  
@@ -803,7 +862,6 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }
                break;
        case CLIMBOUT:
-               track = rwy.hdg;
                // Turn to crosswind if above 700ft AND if other traffic allows
                // (decided in FGTower and accessed through GetCrosswindConstraint(...)).
                // According to AIM, traffic should climb to within 300ft of pattern altitude before commencing crosswind turn.
@@ -838,16 +896,13 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }               
                break;
        case TURN1:
-               track += (360.0 / turn_time) * dt * patternDirection;
-               Bank(25.0 * patternDirection);
+               SetTrack(rwy.hdg + (90.0 * patternDirection));
                if((track < (rwy.hdg - 89.0)) || (track > (rwy.hdg + 89.0))) {
                        leg = CROSSWIND;
                }
                break;
        case CROSSWIND:
                goAround = false;
-               LevelWings();
-               track = rwy.hdg + (90.0 * patternDirection);
                if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
                        slope = 0.0;
                        _pitch = 0.0;
@@ -868,8 +923,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }
                break;
        case TURN2:
-               track += (360.0 / turn_time) * dt * patternDirection;
-               Bank(25.0 * patternDirection);
+               SetTrack(rwy.hdg - (180 * patternDirection));
                // just in case we didn't make height on crosswind
                if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
                        slope = 0.0;
@@ -879,12 +933,9 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                if((track < (rwy.hdg - 179.0)) || (track > (rwy.hdg + 179.0))) {
                        leg = DOWNWIND;
                        transmitted = false;
-                       //roll = 0.0;
                }
                break;
        case DOWNWIND:
-               LevelWings();
-               track = rwy.hdg - (180 * patternDirection);     //should tend to bring track back into the 0->360 range
                // just in case we didn't make height on crosswind
                if(((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 995) && ((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET < 1015)) {
                        slope = 0.0;
@@ -942,14 +993,12 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }
                break;
        case TURN3:
-               track += (360.0 / turn_time) * dt * patternDirection;
-               Bank(25.0 * patternDirection);
+               SetTrack(rwy.hdg - (90 * patternDirection));
                if(fabs(rwy.hdg - track) < 91.0) {
                        leg = BASE;
                }
                break;
        case BASE:
-               LevelWings();
                if(!transmitted) {
                        // Base report should only be transmitted at uncontrolled airport - not towered.
                        if(!_controlled) TransmitPatternPositionReport();
@@ -972,8 +1021,6 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        IAS = 70.0;
                }
                
-               track = rwy.hdg - (90 * patternDirection);
-
                // Try and arrange to turn nicely onto final
                turn_circumference = IAS * 0.514444 * turn_time;        
                //Hmmm - this is an interesting one - ground vs airspeed in relation to turn radius
@@ -986,8 +1033,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }
                break;
        case TURN4:
-               track += (360.0 / turn_time) * dt * patternDirection;
-               Bank(25.0 * patternDirection);
+               SetTrack(rwy.hdg);
                if(fabs(track - rwy.hdg) < 0.6) {
                        leg = FINAL;
                        vel = nominal_final_speed;
@@ -1021,8 +1067,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                if(descending) {
                        if(orthopos.y() < -50.0) {
                                double thesh_offset = 30.0;
-                               slope = atan((_pos.elev() - dclGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
-                               //cout << "slope = " << slope << ", elev = " << _pos.elev() << ", apt_elev = " << dclGetAirportElev(airportID) << ", op.y = " << orthopos.y() << '\n';
+                               slope = atan((_pos.elev() - fgGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
+                               //cout << "slope = " << slope << ", elev = " << _pos.elev() << ", apt_elev = " << fgGetAirportElev(airportID) << ", op.y = " << orthopos.y() << '\n';
                                if(slope < -10.0) slope = -10.0;
                                _savedSlope = slope;
                                _pitch = -4.0;
@@ -1057,7 +1103,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        }
                }
                // Try and track the extended centreline
-               track = rwy.hdg - (0.2 * orthopos.x());
+               SetTrack(rwy.hdg - (0.2 * orthopos.x()));
                //cout << "orthopos.x() = " << orthopos.x() << " hdg = " << hdg << '\n';
                if(_pos.elev() < (rwy.threshold_pos.elev()+20.0+wheelOffset)) {
                        DoGroundElev(); // Need to call it here expicitly on final since it's only called
@@ -1072,6 +1118,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                                        _pitch = 0.0;
                                        leg = LANDING_ROLL;
                                        inAir = false;
+                                       LevelWings();
+                                       ClearTrack();   // Take over explicit track handling since AIPlane currently always banks when changing course 
                                }
                        }       // else need a fallback position based on arpt elev in case ground elev determination fails?
                } else {
@@ -1257,10 +1305,14 @@ void FGAILocalTraffic::ProcessCallback(int code) {
                tower->ReportDownwind(plane.callsign);
        } else if(code == 13) {
                tower->ReportFinal(plane.callsign);
+       } else if(code == 99) { // Flag this instance for deletion
+               responseCounter = 0;
+               _removeSelf = true;
+               SG_LOG(SG_ATC, SG_INFO, "AI local traffic " << plane.callsign << " delete instance callback called.");
        }
 }
 
-void FGAILocalTraffic::ExitRunway(Point3D orthopos) {
+void FGAILocalTraffic::ExitRunway(const Point3D& orthopos) {
        //cout << "In ExitRunway" << endl;
        //cout << "Runway ID is " << rwy.ID << endl;
        
@@ -1326,9 +1378,10 @@ void FGAILocalTraffic::ExitRunway(Point3D orthopos) {
        } else {
                // Something must have gone wrong with the ground network file - or there is only a rwy here and no exits defined
                SG_LOG(SG_ATC, SG_INFO, "No exits found by FGAILocalTraffic from runway " << rwy.rwyID << " at " << airportID << '\n');
-               //cout << "No exits found by " << plane.callsign << " from runway " << rwy.rwyID << " at " << airportID << '\n';
+               //if(airportID == "KRHV") cout << "No exits found by " << plane.callsign << " from runway " << rwy.rwyID << " at " << airportID << '\n';
                // What shall we do - just remove the plane from sight?
                _aip.setVisible(false);
+               _invisible = true;
                //cout << "Setting visible false\n";
                //tower->ReportRunwayVacated(plane.callsign);
                string trns = "Clear of the runway ";
@@ -1512,30 +1565,32 @@ void FGAILocalTraffic::Taxi(double dt) {
 // Either this function or the logic of how often it is called
 // will almost certainly change.
 void FGAILocalTraffic::DoGroundElev() {
-
        // It would be nice if we could set the correct tile center here in order to get a correct
        // answer with one call to the function, but what I tried in the two commented-out lines
        // below only intermittently worked, and I haven't quite groked why yet.
        //SGBucket buck(pos.lon(), pos.lat());
        //aip.getSGLocation()->set_tile_center(Point3D(buck.get_center_lon(), buck.get_center_lat(), 0.0));
        
+       // Only do the proper hitlist stuff if we are within visible range of the viewer.
        double visibility_meters = fgGetDouble("/environment/visibility-m");
-       //globals->get_tile_mgr()->prep_ssg_nodes( acmodel_location,
-       globals->get_tile_mgr()->prep_ssg_nodes( _aip.getSGLocation(),  visibility_meters );
-        Point3D scenery_center = globals->get_scenery()->get_center();
-       globals->get_tile_mgr()->update( _aip.getSGLocation(), visibility_meters, (_aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
-       // save results of update in SGLocation for fdm...
-       
-       //if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-       //      acmodel_location->
-       //      set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-       //}
-       
-       // The need for this here means that at least 2 consecutive passes are needed :-(
-       _aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
-       
-       //cout << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
-       _aip.getSGLocation()->set_cur_elev_m(globals->get_scenery()->get_cur_elev());
-       //return(globals->get_scenery()->get_cur_elev());
+       FGViewer* vw = globals->get_current_view();
+       if(dclGetHorizontalSeparation(_pos, Point3D(vw->getLongitude_deg(), vw->getLatitude_deg(), 0.0)) > visibility_meters) {
+               _aip.getSGLocation()->set_cur_elev_m(aptElev);
+               return;
+       }
+
+        // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+        double range = 500.0;
+        double lat = _aip.getSGLocation()->getLatitude_deg();
+        double lon = _aip.getSGLocation()->getLongitude_deg();
+        if (!globals->get_tile_mgr()->scenery_available(lat, lon, range)) {
+          // Try to shedule tiles for that position.
+          globals->get_tile_mgr()->update( _aip.getSGLocation(), range );
+        }
+
+        // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+        double alt;
+        if (globals->get_scenery()->get_elevation_m(lat, lon, 20000.0, alt, 0))
+          _aip.getSGLocation()->set_cur_elev_m(alt);
 }