]> git.mxchange.org Git - flightgear.git/commitdiff
James Turner: Improved runway management code:
authordurk <durk>
Thu, 14 Aug 2008 18:13:39 +0000 (18:13 +0000)
committerdurk <durk>
Thu, 14 Aug 2008 18:13:39 +0000 (18:13 +0000)
 - Runways are now part of an airport, instead of a separate list
 - Runways are no longer represented as a boring struct, but as a class
   of their own.
 -Improved runway access to unify various runway access methods.

43 files changed:
src/AIModel/AIAircraft.cxx
src/AIModel/AIAircraft.hxx
src/AIModel/AIFlightPlan.cxx
src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/AIModel/AIFlightPlanCreateCruise.cxx
src/AIModel/AIFlightPlanCreatePushBack.cxx
src/ATC/trafficcontrol.cxx
src/ATCDCL/AILocalTraffic.cxx
src/ATCDCL/AIMgr.cxx
src/ATCDCL/approach.cxx
src/ATCDCL/atis.cxx
src/ATCDCL/ground.cxx
src/ATCDCL/tower.cxx
src/Airports/apt_loader.cxx
src/Airports/apt_loader.hxx
src/Airports/dynamics.cxx
src/Airports/groundnetwork.cxx
src/Airports/runwayprefs.cxx
src/Airports/runwayprefs.hxx
src/Airports/runways.cxx
src/Airports/runways.hxx
src/Airports/simple.cxx
src/Airports/simple.hxx
src/Cockpit/hud_rwy.cxx
src/Cockpit/panel.cxx
src/Environment/environment_mgr.cxx
src/Environment/environment_mgr.hxx
src/Instrumentation/HUD/HUD_runway.cxx
src/Instrumentation/KLN89/kln89_page_apt.cxx
src/Instrumentation/KLN89/kln89_page_fpl.cxx
src/Instrumentation/groundradar.cxx
src/Instrumentation/groundradar.hxx
src/Instrumentation/mk_viii.cxx
src/Main/fg_init.cxx
src/Main/globals.cxx
src/Main/globals.hxx
src/Main/main.cxx
src/Main/options.cxx
src/MultiPlayer/multiplaymgr.cxx
src/Navaids/navdb.cxx
src/Navaids/navdb.hxx
src/Scripting/NasalSys.cxx

index 7d6d0d2c58a6f14f8398f4cd54c8c11457651601..c9f185bf0c60920b8983273692afb369ac5e25e5 100644 (file)
@@ -29,6 +29,7 @@
 #include <Main/viewer.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <string>
 #include <math.h>
index d609ef92aa74cff62a7b780b27692579f385acc5..9722e355693f323c462c381df082360f497fbe93 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <Traffic/SchedFlight.hxx>
 #include <Traffic/Schedule.hxx>
+#include <ATC/trafficcontrol.hxx>
 
 #include <string>
 using std::string;
index 6f3f3dc41d0f0378515c4f3454873bab31e712a0..e9035eddb0bb9e8fce55ac90c122e2cf33422f9f 100644 (file)
@@ -20,6 +20,8 @@
 #  include <config.h>
 #endif
 
+#include <iostream>
+
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/route/waypoint.hxx>
 #include <Main/fg_init.hxx>
 #include <Airports/simple.hxx>
 #include <Airports/runways.hxx>
-
+#include <Airports/groundnetwork.hxx>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
 
 #include "AIFlightPlan.hxx"
 
+using std::cerr;
+
 
 FGAIFlightPlan::FGAIFlightPlan(const string& filename)
 {
index 1525c662183e68d67344c03f4b8eedf7ef777979..fba78887f68fa5454649199ce172978486a0a434 100644 (file)
@@ -32,6 +32,7 @@
 using std::vector;
 using std::string;
 
+class FGTaxiRoute;
 
 class FGAIFlightPlan {
 
index 98da9247cc6f3ea53705d2ce4d25b7feece8cffa..89797696f3b7ac0d931fe287b7d0394b58328dc8 100644 (file)
@@ -20,6 +20,7 @@
 #include "AIFlightPlan.hxx"
 #include <simgear/math/sg_geodesy.hxx>
 #include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
@@ -137,16 +138,8 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
        }
       string rwyClass = getRunwayClassFromTrafficType(fltType);
       apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
-      if (!(globals->get_runways()->search(apt->getId(), 
-                                           activeRunway, 
-                                           &rwy)))
-       {
-          SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
-                 activeRunway << 
-                 " at airport     " << apt->getId() << " of class " << rwyClass << " (1)");
-          exit(1);
-       } 
-
+      rwy = apt->getRunwayByIdent(activeRunway);
+      
       // Determine the beginning of he runway
       heading = rwy._heading;
       double azimuth = heading + 180.0;
@@ -503,15 +496,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
       //string name;
       string rwyClass = getRunwayClassFromTrafficType(fltType);
       apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
-       if (!(globals->get_runways()->search(apt->getId(), 
-                                             activeRunway, 
-                                             &rwy)))
-         {
-           SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
-                  activeRunway << 
-                  " at airport     " << apt->getId()<< " of class " << rwyClass << " (2)");
-           exit(1);
-         }
+      rwy = apt->getRunwayByIdent(activeRunway);
     }
   // Acceleration point, 105 meters into the runway,
   heading = rwy._heading;
@@ -637,15 +622,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
       //string name;
       string rwyClass = getRunwayClassFromTrafficType(fltType);
       apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
-       if (!(globals->get_runways()->search(apt->getId(), 
-                                             activeRunway, 
-                                             &rwy)))
-         {
-           SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
-                  activeRunway << 
-                  " at airport     " << apt->getId()<< " of class " << rwyClass << " (3)");
-           exit(1);
-         }
+      rwy = apt->getRunwayByIdent(activeRunway);
     }
   
   
@@ -774,16 +751,8 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
   // allow "mil" and "gen" as well
   string rwyClass = getRunwayClassFromTrafficType(fltType);
   apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
-  if (!(globals->get_runways()->search(apt->getId(), 
-                                      activeRunway, 
-                                      &rwy)))
-    {
-      SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
-            activeRunway << 
-            " at airport     " << apt->getId()<< " of class " << rwyClass << " (4)");
-      exit(1);
-    }
-  
+  rwy = apt->getRunwayByIdent(activeRunway);
+     
   heading = rwy._heading;
   azimuth = heading + 180.0;
   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
index 28f0b8de677dc162a666f3eb4eb4e42c0a4a5c3e..d6d790978c940faf7b53183a8bb54da2b305537d 100755 (executable)
@@ -27,6 +27,7 @@
 
 #include <Navaids/awynet.hxx>
 #include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
@@ -334,15 +335,8 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
  
   string rwyClass = getRunwayClassFromTrafficType(fltType);
   arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
-  if (!(globals->get_runways()->search(arr->getId(), 
-                                      activeRunway, 
-                                      &rwy)))
-    {
-      SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
-            activeRunway << 
-            " at airport     " << arr->getId()<< " of class " << rwyClass << " (5)");
-      exit(1);
-    }
+  rwy = arr->getRunwayByIdent(activeRunway);
+  
   heading = rwy._heading;
   azimuth = heading + 180.0;
   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
index a2deb0a3c2e22292f00d496003d27c1d4553f611..cc2a141e8f0dfbc4c4c126fb60031552f04c41f9 100644 (file)
@@ -20,6 +20,7 @@
 #include "AIFlightPlan.hxx"
 #include <simgear/math/sg_geodesy.hxx>
 #include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
index c5a3c45e5439a14ce5761d2e8c157a64978d022c..99c833c3c9aaf3305f37ba7a1b75bdfd404b072d 100644 (file)
@@ -28,7 +28,8 @@
 #include <AIModel/AIAircraft.hxx>
 #include <AIModel/AIFlightPlan.hxx>
 #include <Traffic/TrafficMgr.hxx>
-
+#include <Airports/groundnetwork.hxx>
+#include <Airports/dynamics.hxx>
 
 /***************************************************************************
  * FGTrafficRecord
index 2afd62ea9f064bebc05e253ecc06ecb9b75f7f94..2156fbe13b249cd711ceb9bbb242f8a8b8cf13ed 100644 (file)
@@ -174,15 +174,16 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
        
        // 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 other_way = hdg - 180.0;
-               while(other_way <= 0.0) {
-                       other_way += 360.0;
-               }
+  const FGAirport* apt = fgFindAirportID(id);
+  assert(apt);
+  FGRunway runway(apt->getRunwayByIdent(rwy.rwyID));
 
+  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);
@@ -207,9 +208,6 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
                ortho.Init(rwy.threshold_pos, rwy.hdg); 
                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 at airport " << id << " in FGAILocalTraffic!!");
-       }
 }
 
 
index c8f7b8b028fb8f67bc953774755b480ea9acc802..5d4da1d862370b8c93f46fa7a9c1ea4848e98d54 100644 (file)
@@ -23,6 +23,8 @@
 #  include <config.h>
 #endif
 
+#include <iostream>
+
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 #include <simgear/misc/sg_path.hxx>
index 296e3446b102337ac349cd4c060b43bfe566cf35..c935cbc2903045ee537c534b1a835c7a340f45b5 100644 (file)
@@ -30,6 +30,8 @@
 #include "ATCDialog.hxx"
 
 #include <Airports/runways.hxx>
+#include <Airports/simple.hxx>
+
 #include <simgear/constants.h>
 #include <simgear/math/polar3d.hxx>
 #include <simgear/misc/sg_path.hxx>
@@ -559,26 +561,15 @@ double FGApproach::round_alt( const bool hl, double alt ) {
 void FGApproach::get_active_runway() {
        //cout << "Entering FGApproach::get_active_runway()\n";
 
-  FGEnvironment stationweather =
-      ((FGEnvironmentMgr *)globals->get_subsystem("environment"))
-        ->getEnvironment(lat, lon, elev);
-
-  double hdg = stationweather.get_wind_from_heading_deg();
-  
-  FGRunway runway;
-  if ( globals->get_runways()->search( ident, int(hdg), &runway) ) {
-    active_runway = runway._rwy_no;
-    active_rw_hdg = runway._heading;
-    active_rw_lon = runway._lon;
-    active_rw_lat = runway._lat;
-    active_rw_len = runway._length;
-    //cout << "Active runway is: " << active_runway << "  heading = " 
-    // << active_rw_hdg 
-    // << " lon = " << active_rw_lon 
-    // << " lat = " << active_rw_lat <<endl;
-  }
-  else cout << "FGRunways search failed\n";
+  const FGAirport* apt = fgFindAirportID(ident);
+  assert(apt);
+  FGRunway runway = apt->getActiveRunwayForUsage();
 
+  active_runway = runway._rwy_no;
+  active_rw_hdg = runway._heading;
+  active_rw_lon = runway._lon;
+  active_rw_lat = runway._lat;
+  active_rw_len = runway._length;
 }
 
 // ========================================================================
index 30a7f5af723ce790e45fc1fbf59a2929e5424e51..4f9d93de4047be78d906c1a5f86b64645ac598bd 100644 (file)
@@ -210,8 +210,10 @@ void FGATIS::UpdateTransmission() {
                                            + ConvertNumToSpokenDigits(tempstr2) + " degrees";
        }
        
-       string rwy_no = globals->get_runways()->search(ident, int(hdg));
-       if(rwy_no != "NN") {
+  const FGAirport* apt = fgFindAirportID(ident);
+  assert(apt);
+       string rwy_no = apt->getActiveRunwayForUsage()._rwy_no;
+  if(rwy_no != "NN") {
                transmission += " / Landing_and_departing_runway ";
                transmission += ConvertRwyNumToSpokenString(atoi(rwy_no.c_str()));
                //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl;
index e1909885c5da6000e0eb57862b1e5ffa4a0fc385..2a6643e00565a415427b3429249555dfeb380390 100644 (file)
@@ -22,6 +22,8 @@
 #  include <config.h>
 #endif
 
+#include <iostream>
+
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/math/sg_random.h>
 #include <simgear/debug/logstream.hxx>
@@ -358,53 +360,42 @@ void FGGround::Update(double dt) {
 // will be initialised before ground so we can't do that.
 void FGGround::DoRwyDetails() {
        //cout << "GetRwyDetails called" << endl;
-       
-       // Based on the airport-id and wind get the active runway
-       
-       //wind
-       double hdg = wind_from_hdg->getDoubleValue();
-       double speed = wind_speed_knots->getDoubleValue();
-       hdg = (speed == 0.0 ? 270.0 : hdg);
-       //cout << "Heading = " << hdg << '\n';
-       
-       FGRunway runway;
-       bool rwyGood = globals->get_runways()->search(ident, int(hdg), &runway);
-       if(rwyGood) {
-               activeRwy = runway._rwy_no;
-               rwy.rwyID = runway._rwy_no;
-               SG_LOG(SG_ATC, SG_INFO, "In FGGround, active runway for airport " << ident << " is " << activeRwy);
                
-               // Get the threshold position
-               double other_way = runway._heading - 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);
-               Point3D ref = origin;
-       double tshlon, tshlat, tshr;
-               double tolon, tolat, tor;
-               rwy.length = runway._length * 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(), runway._heading, 
-                               rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor );
-               // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user.
-               // now copy what we need out of runway into rwy
-       rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev);
-               Point3D takeoff_end = Point3D(tolon, tolat, aptElev);
-               //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n';
-               //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n';
-               rwy.hdg = runway._heading;
-               // Set the projection for the local area based on this active runway
-               ortho.Init(rwy.threshold_pos, rwy.hdg); 
-               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 FGTower!!");
-               activeRwy = "NN";
-       }
+  const FGAirport* apt = fgFindAirportID(ident);
+  assert(apt);
+       FGRunway runway = apt->getActiveRunwayForUsage();
+
+  activeRwy = runway._rwy_no;
+  rwy.rwyID = runway._rwy_no;
+  SG_LOG(SG_ATC, SG_INFO, "In FGGround, active runway for airport " << ident << " is " << activeRwy);
+  
+  // Get the threshold position
+  double other_way = runway._heading - 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);
+  Point3D ref = origin;
+    double tshlon, tshlat, tshr;
+  double tolon, tolat, tor;
+  rwy.length = runway._length * 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(), runway._heading, 
+                        rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor );
+  // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user.
+  // now copy what we need out of runway into rwy
+    rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev);
+  Point3D takeoff_end = Point3D(tolon, tolat, aptElev);
+  //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n';
+  //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n';
+  rwy.hdg = runway._heading;
+  // Set the projection for the local area based on this active runway
+  ortho.Init(rwy.threshold_pos, rwy.hdg);      
+  rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos);     // should come out as zero
+  rwy.end2ortho = ortho.ConvertToLocal(takeoff_end);
 }
 
 // Return a random gate ID of an unused gate.
index e61109bfb10ef6072bf28112b6013ff94f0861f3..e2b2ce605cdc72a0b5e657882ad2d8db7b8cb8f7 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <sstream>
 #include <iomanip>
+#include <iostream>
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/sg_geodesy.hxx>
@@ -1510,61 +1511,53 @@ void FGTower::DoRwyDetails() {
        
        // Based on the airport-id and wind get the active runway
        
-       //wind
-       double hdg = wind_from_hdg->getDoubleValue();
-       double speed = wind_speed_knots->getDoubleValue();
-       hdg = (speed == 0.0 ? 270.0 : hdg);
-       //cout << "Heading = " << hdg << '\n';
-       
-       FGRunway runway;
-       bool rwyGood = globals->get_runways()->search(ident, int(hdg), &runway);
-       if(rwyGood) {
-               //cout << "RUNWAY GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD\n";
-               activeRwy = runway._rwy_no;
-               rwy.rwyID = runway._rwy_no;
-               SG_LOG(SG_ATC, SG_INFO, "Active runway for airport " << ident << " is " << activeRwy);
-               
-               // Get the threshold position
-               double other_way = runway._heading - 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);
-               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;
-       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(), runway._heading, 
-                               rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor );
-               // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user.
-               // now copy what we need out of runway into rwy
-       rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev);
-               Point3D takeoff_end = Point3D(tolon, tolat, aptElev);
-               //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n';
-               //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n';
-               rwy.hdg = runway._heading;
-               // Set the projection for the local area based on this active runway
-               ortho.Init(rwy.threshold_pos, rwy.hdg); 
-               rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos);        // should come out as zero
-               rwy.end2ortho = ortho.ConvertToLocal(takeoff_end);
-               
-               // Set the pattern direction
-               // TODO - we'll check for a facilities file with this in eventually - for now assume left traffic except
-               // for certain circumstances (RH parallel rwy).
-               rwy.patternDirection = -1;              // Left
-               if(rwy.rwyID.size() == 3) {
-                       rwy.patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1);
-               }
-               //cout << "Doing details, rwy.patterDirection is " << rwy.patternDirection << '\n';
-       } else {
-               SG_LOG(SG_ATC, SG_ALERT, "Help  - can't get good runway in FGTower!!");
-               activeRwy = "NN";
-       }
+  const FGAirport* apt = fgFindAirportID(ident);
+  assert(apt);
+       FGRunway runway = apt->getActiveRunwayForUsage();
+  
+  //cout << "RUNWAY GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD\n";
+
+  activeRwy = runway._rwy_no;
+  rwy.rwyID = runway._rwy_no;
+  SG_LOG(SG_ATC, SG_INFO, "Active runway for airport " << ident << " is " << activeRwy);
+  
+  // Get the threshold position
+  double other_way = runway._heading - 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);
+  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;
+    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(), runway._heading, 
+                        rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor );
+  // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user.
+  // now copy what we need out of runway into rwy
+    rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev);
+  Point3D takeoff_end = Point3D(tolon, tolat, aptElev);
+  //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n';
+  //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n';
+  rwy.hdg = runway._heading;
+  // Set the projection for the local area based on this active runway
+  ortho.Init(rwy.threshold_pos, rwy.hdg);      
+  rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos);     // should come out as zero
+  rwy.end2ortho = ortho.ConvertToLocal(takeoff_end);
+  
+  // Set the pattern direction
+  // TODO - we'll check for a facilities file with this in eventually - for now assume left traffic except
+  // for certain circumstances (RH parallel rwy).
+  rwy.patternDirection = -1;           // Left
+  if(rwy.rwyID.size() == 3) {
+    rwy.patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1);
+  }
+  //cout << "Doing details, rwy.patterDirection is " << rwy.patternDirection << '\n';
 }
 
 
@@ -1596,28 +1589,27 @@ bool FGTower::OnAnyRunway(const Point3D& pt, bool onGround) {
        }
        
        // Based on the airport-id, go through all the runways and check for a point in them
-       
-       // TODO - do we actually need to search for the airport - surely we already know our ident and
-       // can just search runways of our airport???
-       //cout << "Airport ident is " << ad.ident << '\n';
-       FGRunway runway;
-       bool rwyGood = globals->get_runways()->search(ad.ident, &runway);
-       if(!rwyGood) {
-               SG_LOG(SG_ATC, SG_WARN, "Unable to find any runways for airport ID " << ad.ident << " in FGTower");
-       }
-       bool on = false;
-       while(runway._id == ad.ident) {
-               on = OnRunway(pt, runway);
-               //cout << "Runway " << runway._rwy_no << ": On = " << (on ? "true\n" : "false\n");
-               if(on) {
-                       if(onGround == false)
-                               return(true);
-                       if(runway._rwy_no != "xx")
-                               return(true);
-               }
-               globals->get_runways()->next(&runway);
-       }
-       return(on);
+
+  const FGAirport* apt = fgFindAirportID(ad.ident);
+  assert(apt);
+  
+  for (unsigned int i=0; i<apt->numRunways(); ++i) {
+    if (OnRunway(pt, apt->getRunwayByIndex(i))) {
+      return true;
+    }
+  }
+
+  // if onGround is true, we only match real runways, so we're done
+  if (onGround) return false;
+
+  // try taxiways as well
+  for (unsigned int i=0; i<apt->numTaxiways(); ++i) {
+    if (OnRunway(pt, apt->getTaxiwayByIndex(i))) {
+      return true;
+    }
+  }
+  
+       return false;
 }
 
 
index 896be4ea1b4b737cad102182d3dc698e1f89c688..8ea854f70c2f486c829bc10fb67cc0dd10263d93 100644 (file)
 
 #include "apt_loader.hxx"
 
-static void addAirport(FGAirportList *airports, const string& apt_id, const string& apt_name,
+FGAirport* addAirport(FGAirportList *airports, const string& apt_id, const string& apt_name,
     int rwy_count, double rwy_lat_accum, double rwy_lon_accum, double last_rwy_heading,
     double apt_elev, SGGeod& tower, bool got_tower, int type)
 {
     if (apt_id.empty())
-        return;
+        return NULL;
 
     if (!rwy_count) {
         SG_LOG(SG_GENERAL, SG_ALERT, "ERROR: No runways for " << apt_id
                 << ", skipping." );
-        return;
+        return NULL;
     }
 
     double lat = rwy_lat_accum / (double)rwy_count;
@@ -69,14 +69,14 @@ static void addAirport(FGAirportList *airports, const string& apt_id, const stri
         tower = SGGeod::fromDegFt(lon + fudge_lon, lat + fudge_lat, apt_elev + tower_height);
     }
 
-    airports->add(apt_id, SGGeod::fromDegFt(lon, lat, apt_elev), tower, apt_name, false,
+    return airports->add(apt_id, SGGeod::fromDegFt(lon, lat, apt_elev), tower, apt_name, false,
             type == 1/*airport*/, type == 16/*seaport*/, type == 17/*heliport*/);
 }
 
 // Load the airport data base from the specified aptdb file.  The
 // metar file is used to mark the airports as having metar available
 // or not.
-bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
+bool fgAirportDBLoad( FGAirportList *airports, 
                       const string &aptdb_file, const string &metar_file )
 {
     //
@@ -100,7 +100,8 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
     string line;
     char tmp[2049];
     tmp[2048] = 0;
-
+    vector<FGRunway> runways;
+    
     unsigned int line_id = 0;
     unsigned int line_num = 0;
     double rwy_lon_accum = 0.0;
@@ -150,9 +151,15 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
             SG_LOG( SG_GENERAL, SG_BULK, "Next airport = " << id << " "
                     << elev );
 
-            addAirport(airports, last_apt_id, last_apt_name, rwy_count, rwy_lat_accum, rwy_lon_accum,
+            FGAirport* apt = addAirport(airports, last_apt_id, last_apt_name, rwy_count, rwy_lat_accum, rwy_lon_accum,
                 last_rwy_heading, last_apt_elev, last_tower, got_tower, last_apt_type);
 
+            for (unsigned int r=0; r< runways.size(); ++r) {
+              apt->addRunway(runways[r]);
+            }
+
+            runways.clear();
+            
             last_apt_id = id;
             last_apt_elev = elev;
             last_apt_name = "";
@@ -210,11 +217,12 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
             double smoothness = atof( token[13].c_str() );
             bool dist_remaining = (atoi( token[14].c_str() ) == 1 );
 
-            runways->add( last_apt_id, rwy_no, lon, lat, heading, length,
+            FGRunway rwy(last_apt_id, rwy_no, lon, lat, heading, length,
                           width, displ_thresh1, displ_thresh2,
                           stopway1, stopway2, lighting_flags, surface_code,
                           shoulder_code, marking_code, smoothness,
-                          dist_remaining );
+                          dist_remaining);
+            runways.push_back(rwy);
         } else if ( line_id == 18 ) {
             // beacon entry (ignore)
         } else if ( line_id == 14 ) {
index ea13216a5afc730c4124d81b1e76338bfa81709e..883e0384d56fd8906d353689d2df12850491e7ec 100644 (file)
 #ifndef _FG_APT_LOADER_HXX
 #define _FG_APT_LOADER_HXX
 
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #include <simgear/compiler.h>
 
 #include <string>
 
-using std::string;
-
 #include "simple.hxx"
-#include "runways.hxx"
 
 
 // Load the airport data base from the specified aptdb file.  The
 // metar file is used to mark the airports as having metar available
 // or not.
-bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
-                      const string &aptdb_file, const string &metar_file );
+bool fgAirportDBLoad( FGAirportList *airports, const string &aptdb_file, const std::string &metar_file );
 
 
 #endif // _FG_APT_LOADER_HXX
index 39c305cca9f24f3f911757d02a82176d564ef15a..41b77bae1663f773d3b7a0bcb8ec7afecbf3a6e4 100644 (file)
@@ -419,7 +419,7 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
           currentlyActive = &ulActive;
         }
          // 
-         currRunwayGroup->setActive(_ap->getId()
+         currRunwayGroup->setActive(_ap, 
                                     windSpeed, 
                                     windHeading, 
                                     maxTail, 
@@ -485,20 +485,8 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
 
 string FGAirportDynamics::chooseRunwayFallback()
 {   
-  FGEnvironment 
-    stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
-    ->getEnvironment(getLatitude(), 
-                    getLongitude(),
-                    getElevation());
-  
-  double windSpeed = stationweather.get_wind_speed_kt();
-  double windHeading = stationweather.get_wind_from_heading_deg();
-  if (windSpeed == 0) {
-    windHeading = 270; // This forces West-facing rwys to be used in no-wind situations
-    //which is consistent with Flightgear's initial setup.
-  }
-  
-   return globals->get_runways()->search(_ap->getId(), int(windHeading));
+  FGRunway rwy = _ap->getActiveRunwayForUsage();
+  return rwy._rwy_no;
 }
 
 void FGAirportDynamics::addParking(FGParking& park) {
index a4cefee0dab9a7c45a52edac952068b5f03c5f16..b4f48caeeea2f158dc3a8d0042933d1fb94efb99 100644 (file)
@@ -41,6 +41,8 @@
 //#include <Main/fg_props.hxx>
 //#include <Airports/runways.hxx>
 
+#include <Airports/dynamics.hxx>
+
 #include <AIModel/AIFlightPlan.hxx>
 
 //#include <string>
index a6112e44e569252c23bd641d38b2bda4a7df8b9b..ae204474e46dc2a68b5cfce948006da5c51e4445 100644 (file)
@@ -194,7 +194,7 @@ RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
   return *this;
 }
 
-void RunwayGroup::setActive(const string &aptId
+void RunwayGroup::setActive(const FGAirport* airport
                            double windSpeed, 
                            double windHeading, 
                            double maxTail, 
@@ -234,15 +234,10 @@ void RunwayGroup::setActive(const string &aptId,
          //
          validSelection = true;
          for (int j = 0; j < activeRwys; j++)
-           {
-            
-             name = rwyList[j].getRwyList(i);
-             //cerr << "Name of Runway: " << name;
-             if (globals->get_runways()->search( aptId, 
-                                                 name, 
-                                                 &rwy))
-               {
-                 //cerr << "Succes" << endl;
+    {
+            rwy = airport->getRunwayByIdent(rwyList[j].getRwyList(i));
+       
+                         //cerr << "Succes" << endl;
                  hdgDiff = fabs(windHeading - rwy._heading);
                  //cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
                  //cerr << "Wind Speed  : " << windSpeed << endl;
@@ -263,12 +258,9 @@ void RunwayGroup::setActive(const string &aptId,
                    {
                      //cerr << ". [Valid] ";
                  }
-               }else {
-               SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
-               exit(1);
-             }
-              //cerr << endl;
-           }
+                             //cerr << endl;
+    } // of active runways iteration
+      
          if (validSelection) 
            {
              //cerr << "Valid selection  : " << i << endl;;
@@ -311,13 +303,9 @@ void RunwayGroup::setActive(const string &aptId,
          bool validSelection = true;
          for (int j = 0; j < 2; j++)
            {
-             //cerr << "I J " << i << " " << j << endl;
-             name = rwyList[choice[j]].getRwyList(i);
-             //cerr << "Name of Runway: " << name << endl;
-             if (globals->get_runways()->search( aptId, 
-                                                 name, 
-                                                 &rwy))
-               {
+        name = rwyList[choice[j]].getRwyList(i);
+        rwy = airport->getRunwayByIdent(name);
+        
                  //cerr << "Succes" << endl;
                  hdgDiff = fabs(windHeading - rwy._heading);
                  if (hdgDiff > 180)
@@ -327,10 +315,7 @@ void RunwayGroup::setActive(const string &aptId,
                  tailWind  = -windSpeed * cos(hdgDiff);
                  if ((tailWind > maxTail) || (crossWind > maxCross))
                    validSelection = false;
-               }else {
-                 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
-                 exit(1);
-               }
+               
 
            }
          if (validSelection)
index d3fccdcc224add5f2892fc0baedffc6b2684d13d..c9ac72709c82e4e0c0e00c8ead197a5ac155bebf 100644 (file)
@@ -112,7 +112,7 @@ public:
 
   void setName(const string& nm) { name = nm;                };
   void add(const RunwayList& list) { rwyList.push_back(list);};
-  void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr);
+  void setActive(const FGAirport* airport, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr);
 
   int getNrActiveRunways() { return nrActive;};
   void getActive(int i, string& name, string& type);
index 3ea0b64cf5c43a2f50d37ae900fd01ae5b9f5d7a..fa92e91d5539d86b7e248fd97af464c781188260 100644 (file)
 
 using std::istream;
 using std::multimap;
+using std::string;
 
+FGRunway::FGRunway()
+{
+}
 
-// add an entry to the list
-void FGRunwayList::add( const string& id, const string& rwy_no,
+FGRunway::FGRunway( const string& id, const string& rwy_no,
                         const double longitude, const double latitude,
                         const double heading, const double length,
                         const double width,
@@ -53,267 +56,92 @@ void FGRunwayList::add( const string& id, const string& rwy_no,
                         const string& shoulder_code, const int marking_code,
                         const double smoothness, const bool dist_remaining )
 {
-    FGRunway rwy;
-
-    rwy._id = id;
-    rwy._rwy_no = rwy_no;
-    // strip trailing "x" if it exists in runway number
-    string tmp = rwy._rwy_no.substr(2, 1);
-    if ( tmp == "x" ) {
-        rwy._rwy_no = rwy._rwy_no.substr(0, 2);
+  _rwy_no = rwy_no;
+  if (rwy_no[0] == 'x') {
+    _type = "taxiway";
+  } else {
+    _type = "runway";
+    
+  // canonicalise runway ident
+    if ((rwy_no.size() == 1) || !isdigit(rwy_no[1])) {
+         _rwy_no = "0" + rwy_no;
     }
 
-    rwy._lon = longitude;
-    rwy._lat = latitude;
-    rwy._heading = heading;
-    rwy._length = length;
-    rwy._width = width;
-    rwy._displ_thresh1 = displ_thresh1;
-    rwy._displ_thresh2 = displ_thresh2;
-    rwy._stopway1 = stopway1;
-    rwy._stopway2 = stopway2;
-
-    rwy._lighting_flags = lighting_flags;
-    rwy._surface_code = surface_code;
-    rwy._shoulder_code = shoulder_code;
-    rwy._marking_code = marking_code;
-    rwy._smoothness = smoothness;
-    rwy._dist_remaining = dist_remaining;
-
-    if ( rwy_no[0] == 'x' ) {
-        rwy._type = "taxiway";
-    } else {
-        rwy._type = "runway";
+    if ((_rwy_no.size() > 2) && (_rwy_no[2] == 'x')) {
+      _rwy_no = _rwy_no.substr(0, 2);
     }
-    runways.insert(pair<const string, FGRunway>(rwy._id, rwy));
+  }
+
+  _id = id;
+  _lon = longitude;
+  _lat = latitude;
+  _heading = heading;
+  _length = length;
+  _width = width;
+  _displ_thresh1 = displ_thresh1;
+  _displ_thresh2 = displ_thresh2;
+  _stopway1 = stopway1;
+  _stopway2 = stopway2;
+
+  _lighting_flags = lighting_flags;
+  _surface_code = surface_code;
+  _shoulder_code = shoulder_code;
+  _marking_code = marking_code;
+  _smoothness = smoothness;
+  _dist_remaining = dist_remaining;
 }
 
+string FGRunway::reverseIdent(const string& aRunwayIdent)
+{
+  // Helipads don't have a seperate number per end
+  if (aRunwayIdent.size() && (aRunwayIdent[0] == 'H' || aRunwayIdent[0] == 'h' || aRunwayIdent[0] == 'x')) {
+    return aRunwayIdent;
+  }
 
-// Return reverse rwy number
-// eg 01 -> 19
-// 03L -> 21R
-static string GetReverseRunwayNo(string& rwyno) {      
-    // cout << "Original rwyno = " << rwyNo << '\n';
+  std::string ident(aRunwayIdent);
     
-    // Helipads don't have a seperate number per end
-    if(rwyno.size() && (rwyno[0] == 'H' || rwyno[0] == 'h' || rwyno[0] == 'x')) {
-       return rwyno;
-    }
-    
-    // standardize input number
-    string tmp = rwyno.substr(1, 1);
-    if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
-       tmp = rwyno;
-       rwyno = "0" + tmp;
-        SG_LOG( SG_GENERAL, SG_INFO,
-                "Standardising rwy number from " << tmp << " to " << rwyno );
-    }
-    
-    char buf[4];
-    int rn = atoi(rwyno.substr(0,2).c_str());
-    rn += 18;
-    while(rn > 36) {
-       rn -= 36;
-    }
-    sprintf(buf, "%02i", rn);
-    if(rwyno.size() == 3) {
-       if(rwyno.substr(2,1) == "L") {
-           buf[2] = 'R';
-           buf[3] = '\0';
-       } else if (rwyno.substr(2,1) == "R") {
-           buf[2] = 'L';
-           buf[3] = '\0';
-       } else if (rwyno.substr(2,1) == "C") {
-           buf[2] = 'C';
-           buf[3] = '\0';
-       } else if (rwyno.substr(2,1) == "T") {
-           buf[2] = 'T';
-           buf[3] = '\0';
-       } else {
-           SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
-           << rwyno << " passed to GetReverseRunwayNo(...)");
-       }
-    }
-    return(buf);
-}
-
-
-// search for the specified apt id (wierd!)
-bool FGRunwayList::search( const string& aptid, FGRunway* r ) {
-    runway_map_iterator pos;
-
-    pos = runways.lower_bound(aptid);
-    if ( pos != runways.end() ) {
-        current = pos;
-        *r = pos->second;
-        return true;
+  char buf[4];
+  int rn = atoi(ident.substr(0,2).c_str());
+  rn += 18;
+  while(rn > 36) {
+         rn -= 36;
+  }
+  
+  sprintf(buf, "%02i", rn);
+  if(ident.size() == 3) {
+    if(ident.substr(2,1) == "L") {
+        buf[2] = 'R';
+        buf[3] = '\0';
+    } else if (ident.substr(2,1) == "R") {
+        buf[2] = 'L';
+        buf[3] = '\0';
+    } else if (ident.substr(2,1) == "C") {
+        buf[2] = 'C';
+        buf[3] = '\0';
+    } else if (ident.substr(2,1) == "T") {
+        buf[2] = 'T';
+        buf[3] = '\0';
     } else {
-        return false;
+        SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
+        << aRunwayIdent << " passed to FGRunway::reverseIdent");
     }
+  }
+  
+  return buf;
 }
 
-
-// search for the specified apt id and runway no
-bool FGRunwayList::search( const string& aptid, const string& rwyno,
-                           FGRunway *r )
+double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) const
 {
-    string revrwyno = "";
-    string runwayno = rwyno;
-    if ( runwayno.length() ) {
-        // standardize input number
-        string tmp = runwayno.substr(1, 1);
-        if (( tmp == "L" || tmp == "R" || tmp == "C" )
-            || (runwayno.size() == 1))
-        {
-            tmp = runwayno;
-            runwayno = "0" + tmp;
-            SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from "
-                    << tmp << " to " << runwayno );
-        }
-        revrwyno = GetReverseRunwayNo(runwayno);
-    }
-    runway_map_iterator pos;
-    for ( pos = runways.lower_bound( aptid );
-          pos != runways.upper_bound( aptid ); ++pos)
-    {
-        if ( pos->second._rwy_no == runwayno ) {
-            current = pos;
-            *r = pos->second;
-            return true;
-        } else if ( pos->second._rwy_no == revrwyno ) {
-            // Search again with the other-end runway number.
-            // Remember we have to munge the heading and rwy_no
-            // results if this one matches
-            current = pos;
-            *r = pos->second;
-            // NOTE - matching revrwyno implies that runwayno was
-            // actually correct.
-            r->_rwy_no = runwayno;
-            r->_heading += 180.0;
-            return true;
-        }
-    }
-
-    return false;
-}
-
-
-// (wierd!)
-FGRunway FGRunwayList::search( const string& aptid ) {
-    FGRunway a;
-    search( aptid, &a );
-    return a;
+  int surface = 1;
+  if (_surface_code == 12 || _surface_code == 5) // dry lakebed & gravel
+    surface = 2;
+  else if (_surface_code == 1 || _surface_code == 2) // asphalt & concrete
+    surface = 3;
+    
+  return _length * aLengthWt + _width * aWidthWt + surface * aSurfaceWt + 1e-20;
 }
 
-
-// Return the runway closest to a given heading
-bool FGRunwayList::search( const string& aptid, const int tgt_hdg,
-                           FGRunway *runway )
+bool FGRunway::isTaxiway() const
 {
-    string rwyNo = search(aptid, tgt_hdg);
-    return(rwyNo == "NN" ? false : search(aptid, rwyNo, runway));
-}
-
-
-// Return the runway number of the runway closest to a given heading
-string FGRunwayList::search( const string& aptid, const int hdg ) {
-    //SG_LOG(SG_GENERAL, SG_ALERT, "searching runway for " << aptid
-    //        << " with target heading " << hdg);
-
-    FGRunway r;
-    if (!search(aptid, &r)) {
-        SG_LOG(SG_GENERAL, SG_ALERT, "Failed to find "
-                << aptid << " in database.");
-        return "NN";
-    }
-
-    SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true);
-    double lenwgt = param->getDoubleValue("length-weight", 0.01);
-    double widwgt = param->getDoubleValue("width-weight", 0.01);
-    double surfwgt = param->getDoubleValue("surface-weight", 10);
-    double devwgt = param->getDoubleValue("deviation-weight", 1);
-
-    FGRunway best;
-    double max = 0.0;
-    bool reversed = false;
-
-    do {
-        if (r._id != aptid)
-            break;
-        if (r._type != "runway")
-            continue;
-
-        int surface = 1;
-        if (r._surface_code == 12 || r._surface_code == 5) // dry lakebed & gravel
-            surface = 2;
-        else if (r._surface_code == 1 || r._surface_code == 2) // asphalt & concrete
-            surface = 3;
-
-        double quality, bad, diff;
-        double good = lenwgt * r._length + widwgt * r._width + surfwgt * surface + 1e-20;
-
-        // this side
-        diff = hdg - r._heading;
-        while (diff < -180)
-            diff += 360;
-        while (diff >= 180)
-            diff -= 360;
-        bad = fabs(devwgt * diff) + 1e-20;
-
-        quality = good / bad;
-        //SG_LOG(SG_GENERAL, SG_ALERT, "  runway " << r._rwy_no <<  " -> " << quality);
-        if (quality > max) {
-            max = quality;
-            best = r;
-            reversed = false;
-        }
-
-        // other side
-        diff = hdg - r._heading - 180;
-        while (diff < -180)
-            diff += 360;
-        while (diff >= 180)
-            diff -= 360;
-        bad = fabs(devwgt * diff) + 1e-20;
-
-        quality = good / bad;
-        //SG_LOG(SG_GENERAL, SG_ALERT, "  runway " << GetReverseRunwayNo(r._rwy_no)
-        //        <<  " -> " << quality);
-        if (quality > max) {
-            max = quality;
-            best = r;
-            reversed = true;
-        }
-
-    } while (next(&r));
-
-    return reversed ? GetReverseRunwayNo(best._rwy_no) : best._rwy_no;
-}
-
-
-bool FGRunwayList::next( FGRunway* runway ) {
-    ++current;
-    if ( current != runways.end() ) {
-        *runway = current->second;
-        return true;
-    } else {
-        return false;
-    }
-}
-
-
-FGRunway FGRunwayList::next() {
-    FGRunway result;
-
-    ++current;
-    if ( current != runways.end() ) {
-        result = current->second;
-    }
-
-    return result;
-}
-
-
-// Destructor
-FGRunwayList::~FGRunwayList( void ) {
+  return (_rwy_no[0] == 'x');
 }
index 532c777cff8b2483cd8cd0c8156c9256dab32efe..34c884531c26a81d91e56bf239dc2ffc7c1bcbfb 100644 (file)
 #ifndef _FG_RUNWAYS_HXX
 #define _FG_RUNWAYS_HXX
 
-
-#ifndef __cplusplus                                                          
-# error This library requires C++
-#endif                                   
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #include <simgear/compiler.h>
 
 #include <string>
-#include <map>
+#include <vector>
 
-using std::string;
-using std::multimap;
-
-
-struct ltstr {
-    bool operator()(const string& s1, const string& s2) const {
-        return s1 < s2;
-    }
-};
-
-
-struct FGRunway {
-
-    string _id;
-    string _rwy_no;
-    string _type;                // runway / taxiway
+class FGRunway
+{
+public:
+  FGRunway();
+  
+  FGRunway(const std::string& id, const std::string& rwy_no,
+            const double longitude, const double latitude,
+            const double heading, const double length,
+            const double width,
+            const double displ_thresh1, const double displ_thresh2,
+            const double stopway1, const double stopway2,
+            const std::string& lighting_flags, const int surface_code,
+            const std::string& shoulder_code, const int marking_code,
+            const double smoothness, const bool dist_remaining);
+  
+  /**
+   * given a runway identifier (06, 18L, 31R) compute the identifier for the
+   * opposite heading runway (24, 36R, 13L) string.
+   */
+  static std::string reverseIdent(const std::string& aRunayIdent);
+  
+  /**
+   * score this runway according to the specified weights. Used by
+   * FGAirport::findBestRunwayForHeading
+   */
+  double score(double aLengthWt, double aWidthWt, double aSurfaceWt) const;
+
+  bool isTaxiway() const;
+  
+    std::string _id;
+    std::string _rwy_no;
+    std::string _type;                // runway / taxiway
 
     double _lon;
     double _lat;
@@ -66,60 +72,14 @@ struct FGRunway {
     double _stopway1;
     double _stopway2;
 
-    string _lighting_flags;
+    std::string _lighting_flags;
     int _surface_code;
-    string _shoulder_code;
+    std::string _shoulder_code;
     int _marking_code;
     double _smoothness;
     bool   _dist_remaining;
 };
 
-typedef multimap < string, FGRunway, ltstr > runway_map;
-typedef runway_map::iterator runway_map_iterator;
-typedef runway_map::const_iterator const_runway_map_iterator;
-
-class FGRunwayList {
-
-private:
-
-    runway_map runways;
-    runway_map_iterator current;
-
-public:
-
-    // Constructor (new)
-    FGRunwayList() {}
-
-    // Destructor
-    ~FGRunwayList();
-
-    // add an entry to the list
-    void add( const string& id, const string& rwy_no,
-              const double longitude, const double latitude,
-              const double heading, const double length, const double width,
-              const double displ_thresh1, const double displ_thresh2,
-              const double stopway1, const double stopway2,
-              const string& lighting_flags, const int surface_code,
-              const string& shoulder_code, const int marking_code,
-              const double smoothness, const bool dist_remaining );
-
-    // search for the specified apt id.
-    // Returns true if successful, otherwise returns false.
-    // On success, runway data is returned thru "runway" pointer.
-    // "runway" is not changed if "apt" is not found.
-    bool search( const string& aptid, FGRunway* runway );
-    bool search( const string& aptid, const string& rwyno, FGRunway* runway );
-
-    // DCL - search for runway closest to desired heading in degrees
-    bool search( const string& aptid, const int hdg, FGRunway* runway );
-
-    // Return the runway number of the runway closest to a given heading
-    string search( const string& aptid, const int tgt_hdg );
-
-    FGRunway search( const string& aptid );
-    bool next( FGRunway* runway );
-    FGRunway next();
-};
-
+typedef std::vector<FGRunway> FGRunwayVector;
 
 #endif // _FG_RUNWAYS_HXX
index 018b44cea9886f75b2de158248c9f80d5c8b06a4..c8a62a23359c74107092ec2ffb1bcb30c32c1b4c 100644 (file)
@@ -46,6 +46,7 @@
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <string>
 
@@ -103,9 +104,159 @@ FGAirportDynamics * FGAirport::getDynamics()
     return _dynamics;
 }
 
+unsigned int FGAirport::numRunways() const
+{
+  return mRunways.size();
+}
+
+FGRunway FGAirport::getRunwayByIndex(unsigned int aIndex) const
+{
+  assert(aIndex >= 0 && aIndex < mRunways.size());
+  return mRunways[aIndex];
+}
+
+bool FGAirport::hasRunwayWithIdent(const string& aIdent) const
+{
+  bool dummy;
+  return (getIteratorForRunwayIdent(aIdent, dummy) != mRunways.end());
+}
+
+FGRunway FGAirport::getRunwayByIdent(const string& aIdent) const
+{
+  bool reversed;
+  FGRunwayVector::const_iterator it = getIteratorForRunwayIdent(aIdent, reversed);
+  if (it == mRunways.end()) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "no such runway '" << aIdent << "' at airport " << _id);
+    throw sg_range_exception("unknown runway " + aIdent + " at airport:" + _id, "FGAirport::getRunwayByIdent");
+  }
+  
+  if (!reversed) {
+    return *it;
+  }
+
+  FGRunway result(*it);
+  result._heading += 180.0;
+  result._rwy_no = FGRunway::reverseIdent(it->_rwy_no);
+  return result;
+}
 
+FGRunwayVector::const_iterator
+FGAirport::getIteratorForRunwayIdent(const string& aIdent, bool& aReversed) const
+{
+  string ident(aIdent);
+  if ((aIdent.size() == 1) || !isdigit(aIdent[1])) {
+    ident = "0" + aIdent;
+  }
+
+  string reversedRunway = FGRunway::reverseIdent(ident);
+  FGRunwayVector::const_iterator it = mRunways.begin();
+  
+  for (; it != mRunways.end(); ++it) {
+    if (it->_rwy_no == ident) {
+      aReversed = false;
+      return it;
+    }
+    
+    if (it->_rwy_no == reversedRunway) {
+      aReversed = true;
+      return it;
+    }
+  }
 
+  return it; // end()
+}
+
+static double normaliseBearing(double aBearing)
+{
+  while (aBearing < -180.0) {
+    aBearing += 360.0;
+  }
+  
+  while (aBearing > 180.0) {
+    aBearing -= 180.0;
+  }
+  
+  return aBearing;
+}
 
+FGRunway FGAirport::findBestRunwayForHeading(double aHeading) const
+{
+  FGRunwayVector::const_iterator it = mRunways.begin();
+  FGRunway result;
+  double currentBestQuality = 0.0;
+  
+  SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true);
+  double lengthWeight = param->getDoubleValue("length-weight", 0.01);
+  double widthWeight = param->getDoubleValue("width-weight", 0.01);
+  double surfaceWeight = param->getDoubleValue("surface-weight", 10);
+  double deviationWeight = param->getDoubleValue("deviation-weight", 1);
+    
+  for (; it != mRunways.end(); ++it) {
+    double good = it->score(lengthWeight, widthWeight, surfaceWeight);
+    
+    // first side
+    double dev = normaliseBearing(aHeading - it->_heading);
+    double bad = fabs(deviationWeight * dev) + 1e-20;
+    double quality = good / bad;
+    
+    if (quality > currentBestQuality) {
+      currentBestQuality = quality;
+      result = *it;
+    }
+    
+    dev = normaliseBearing(aHeading - it->_heading - 180.0);
+    bad = fabs(deviationWeight * dev) + 1e-20;
+    quality = good / bad;
+    
+    if (quality > currentBestQuality) {
+      currentBestQuality = quality;
+      result = *it;
+      result._heading += 180.0;
+      result._rwy_no = FGRunway::reverseIdent(it->_rwy_no);
+    }
+  }
+
+  return result;
+}
+
+unsigned int FGAirport::numTaxiways() const
+{
+  return mTaxiways.size();
+}
+
+FGRunway FGAirport::getTaxiwayByIndex(unsigned int aIndex) const
+{
+  assert(aIndex >= 0 && aIndex < mTaxiways.size());
+  return mTaxiways[aIndex];
+}
+
+void FGAirport::addRunway(const FGRunway& aRunway)
+{
+  if (aRunway.isTaxiway()) {
+    mTaxiways.push_back(aRunway);
+  } else {
+    mRunways.push_back(aRunway);
+  }
+}
+
+FGRunway FGAirport::getActiveRunwayForUsage() const
+{
+  static FGEnvironmentMgr* envMgr = NULL;
+  if (!envMgr) {
+    envMgr = (FGEnvironmentMgr *) globals->get_subsystem("environment");
+  }
+  
+  FGEnvironment stationWeather(envMgr->getEnvironment(_location));
+  
+  double windSpeed = stationWeather.get_wind_speed_kt();
+  double hdg = stationWeather.get_wind_from_heading_deg();
+  if (windSpeed <= 0.0) {
+    hdg = 270; // This forces West-facing rwys to be used in no-wind situations
+    // which is consistent with Flightgear's initial setup.
+  }
+  
+  return findBestRunwayForHeading(hdg);
+}
 
 /******************************************************************************
  * FGAirportList
@@ -145,7 +296,7 @@ FGAirportList::~FGAirportList( void )
 
 
 // add an entry to the list
-void FGAirportList::add( const string &id, const SGGeod& location, const SGGeod& tower_location,
+FGAirport* FGAirportList::add( const string &id, const SGGeod& location, const SGGeod& tower_location,
                          const string &name, bool has_metar, bool is_airport, bool is_seaport,
                          bool is_heliport)
 {
@@ -158,6 +309,8 @@ void FGAirportList::add( const string &id, const SGGeod& location, const SGGeod&
     airports_array.push_back( a );
     SG_LOG( SG_GENERAL, SG_BULK, "Adding " << id << " pos = " << location.getLongitudeDeg()
             << ", " << location.getLatitudeDeg() << " elev = " << location.getElevationFt() );
+            
+    return a;
 }
 
 
index 78a53e750794bb1febfe90a76324550f4239141d..ca3ebcd4d8dcf572a8efb782c6f964dac41e6e07 100644 (file)
 #ifndef _FG_SIMPLE_HXX
 #define _FG_SIMPLE_HXX
 
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
 #include <simgear/math/point3d.hxx>
 
 #include <simgear/compiler.h>
 #include <set>
 #include <vector>
 
-#include "runwayprefs.hxx"
-#include "parking.hxx"
-#include "groundnetwork.hxx"
-#include "dynamics.hxx"
-
-
-using std::string;
-using std::map;
-using std::set;
-using std::vector;
-
-
+#include "Airports/runways.hxx"
 
+// forward decls
+class FGAirportDynamics;
 
 /***************************************************************************************
  *
  **************************************************************************************/
 class FGAirport {
 private:
-    string _id;
+    std::string _id;
     SGGeod _location;
     SGGeod _tower_location;
-    string _name;
+    std::string _name;
     bool _has_metar;
     bool _is_airport;
     bool _is_seaport;
@@ -77,12 +59,13 @@ private:
 public:
     FGAirport();
     // FGAirport(const FGAirport &other);
-    FGAirport(const string& id, const SGGeod& location, const SGGeod& tower, const string& name,
+    FGAirport(const std::string& id, const SGGeod& location, const SGGeod& tower, 
+            const std::string& name,
             bool has_metar, bool is_airport, bool is_seaport, bool is_heliport);
     ~FGAirport();
 
-    const string& getId() const { return _id; }
-    const string& getName() const { return _name; }
+    const std::string& getId() const { return _id; }
+    const std::string& getName() const { return _name; }
     double getLongitude() const { return _location.getLongitudeDeg(); }
     // Returns degrees
     double getLatitude()  const { return _location.getLatitudeDeg(); }
@@ -95,14 +78,35 @@ public:
 
     const SGGeod& getTowerLocation() const { return _tower_location; }
 
-    void setId(const string& id) { _id = id; }
+    void setId(const std::string& id) { _id = id; }
     void setMetar(bool value) { _has_metar = value; }
 
-    FGAirportDynamics *getDynamics();
+    FGRunway getActiveRunwayForUsage() const;
 
+    FGAirportDynamics *getDynamics();
+    
+    unsigned int numRunways() const;
+    FGRunway getRunwayByIndex(unsigned int aIndex) const;
+
+    bool hasRunwayWithIdent(const std::string& aIdent) const;
+    FGRunway getRunwayByIdent(const std::string& aIdent) const;
+    FGRunway findBestRunwayForHeading(double aHeading) const;
+    
+    unsigned int numTaxiways() const;
+    FGRunway getTaxiwayByIndex(unsigned int aIndex) const;
+    
+    void addRunway(const FGRunway& aRunway);
 private:
+    /**
+     * Helper to locate a runway by ident
+     */
+    FGRunwayVector::const_iterator getIteratorForRunwayIdent(const std::string& aIdent, bool& aReversed) const;
+
     FGAirport operator=(FGAirport &other);
     FGAirport(const FGAirport&);
+    
+    std::vector<FGRunway> mRunways;
+    std::vector<FGRunway> mTaxiways;
 };
 
 
@@ -114,11 +118,11 @@ public:
 };
 
 
-typedef map < string, FGAirport* > airport_map;
+typedef std::map < std::string, FGAirport* > airport_map;
 typedef airport_map::iterator airport_map_iterator;
 typedef airport_map::const_iterator const_airport_map_iterator;
 
-typedef vector < FGAirport * > airport_list;
+typedef std::vector < FGAirport * > airport_list;
 typedef airport_list::iterator airport_list_iterator;
 typedef airport_list::const_iterator const_airport_list_iterator;
 
@@ -138,13 +142,13 @@ public:
     ~FGAirportList();
 
     // add an entry to the list
-    void add( const string& id, const SGGeod& location, const SGGeod& tower,
-              const string& name, bool has_metar, bool is_airport,
+    FGAirport* add( const std::string& id, const SGGeod& location, const SGGeod& tower,
+              const std::string& name, bool has_metar, bool is_airport,
               bool is_seaport, bool is_heliport );
 
     // search for the specified id.
     // Returns NULL if unsucessfull.
-    FGAirport* search( const string& id );
+    FGAirport* search( const std::string& id );
 
     // Search for the next airport in ASCII sequence to the supplied id.
     // eg. id = "KDC" or "KDCA" would both return "KDCA".
@@ -152,7 +156,7 @@ public:
     // NOTE: Numbers come prior to A-Z in ASCII sequence so id = "LD" would return "LD57", not "LDDP"
     // Implementation assumes airport codes are unique.
     // Returns NULL if unsucessfull.
-    const FGAirport* findFirstById( const string& id, bool exact = false );
+    const FGAirport* findFirstById( const std::string& id, bool exact = false );
 
     // search for the airport closest to the specified position
     // (currently a linear inefficient search so it's probably not
@@ -179,23 +183,23 @@ public:
     /**
      * Mark the specified airport record as not having metar
      */
-    void no_metar( const string &id );
+    void no_metar( const std::string &id );
 
     /**
      * Mark the specified airport record as (yes) having metar
      */
-    void has_metar( const string &id );
+    void has_metar( const std::string &id );
 
 };
 
 // find basic airport location info from airport database
-const FGAirport *fgFindAirportID( const string& id);
+const FGAirport *fgFindAirportID( const std::string& id);
 
 // get airport elevation
-double fgGetAirportElev( const string& id );
+double fgGetAirportElev( const std::string& id );
 
 // get airport position
-Point3D fgGetAirportPos( const string& id );
+Point3D fgGetAirportPos( const std::string& id );
 
 #endif // _FG_SIMPLE_HXX
 
index f70ed6d779109c704464c6e0010d8ca3a0d19630..91fe234f8194159512ebadffea82381cadb10cc1 100644 (file)
@@ -177,10 +177,11 @@ void runway_instr::draw()
 
 bool runway_instr::get_active_runway(FGRunway& runway)
 {
-    FGEnvironment stationweather =
-            ((FGEnvironmentMgr *)globals->get_subsystem("environment"))->getEnvironment();
-    double hdg = stationweather.get_wind_from_heading_deg();
-    return globals->get_runways()->search(fgGetString("/sim/presets/airport-id"), int(hdg), &runway);
+  const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id"));
+  if (!apt) return false;
+  
+  runway = apt->getActiveRunwayForUsage();
+  return (!runway._rwy_no.empty());
 }
 
 
@@ -432,7 +433,7 @@ void runway_instr::setLineWidth()
     else
         alt_nm *= SG_METER_TO_NM;
 
-    //Calculate distance away from runway, C = v(A²+B²)
+    //Calculate distance away from runway, C = v(A≤+B≤)
     distance = sqrt(alt_nm * alt_nm + distance*distance);
     if (distance < scaleDist)
         glLineWidth(1.0 + ((lnScale - 1) * ((scaleDist - distance) / scaleDist)));
index a940df8c3d93be91ab020edc9fc0ca8dc01571d3..a7b860afa43aa4ac8433a640f0e4640f9021a5c8 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <stdio.h>     // sprintf
 #include <string.h>
+#include <iostream>
 
 #include <osg/CullFace>
 #include <osg/Depth>
index 5440ba253b87a4d194e0e5b10fe6551285062624..8806b674e10f04c4b2cc250a6e0d580c548f7faa 100644 (file)
@@ -285,6 +285,18 @@ FGEnvironmentMgr::getEnvironment (double lat, double lon, double alt) const
   return env;
 }
 
+FGEnvironment
+FGEnvironmentMgr::getEnvironment(const SGGeod& aPos) const
+{
+  // Always returns the same environment
+  // for now; we'll make it interesting
+  // later.
+  FGEnvironment env = *_environment;
+  env.set_elevation_ft(aPos.getElevationFt());
+  return env;
+
+}
+
 void
 FGEnvironmentMgr::_update_fdm () const
 {
index e45e353309adba6b5e15c08a76bf73e05f61022d..7e0bc68217a051c042148acf83165ea8358e78b5 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <simgear/compiler.h>
 #include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/math/SGMath.hxx>
 
 #ifdef SG_HAVE_STD_INCLUDES
 #  include <cmath>
@@ -70,6 +71,7 @@ public:
   virtual FGEnvironment getEnvironment (double lat, double lon,
                                        double alt) const;
 
+  virtual FGEnvironment getEnvironment(const SGGeod& aPos) const;
 private:
 
   void _update_fdm () const;
index 434b73c2ecb8b677267fcefe6ce118d7815c0213..286360cd25938b5125d8bb5e2ebdfb1ba95aa487 100644 (file)
@@ -170,13 +170,15 @@ void HUD::Runway::draw()
 
 bool HUD::Runway::get_active_runway(FGRunway& runway)
 {
-    FGEnvironment stationweather =
-            ((FGEnvironmentMgr *)globals->get_subsystem("environment"))->getEnvironment();
-    double hdg = stationweather.get_wind_from_heading_deg();
-    return globals->get_runways()->search(fgGetString("/sim/presets/airport-id"), int(hdg), &runway);
+  const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id"));
+  if (!apt) return false;
+  
+  runway = apt->getActiveRunwayForUsage();
+  return (!runway._rwy_no.empty());
 }
 
 
+
 void HUD::Runway::get_rwy_points(sgdVec3 *_points3d)
 {
     double alt = current_aircraft.fdm_state->get_Runway_altitude() * SG_FEET_TO_METER;
@@ -424,7 +426,7 @@ void HUD::Runway::setLineWidth()
 
     alt_nm *= SG_METER_TO_NM;
 
-    //Calculate distance away from runway, C = v(A²+B²)
+    //Calculate distance away from runway, C = v(A≤+B≤)
     distance = sqrt(alt_nm * alt_nm + distance*distance);
     if (distance < _scale_dist)
         glLineWidth(1.0 + ((_line_scale - 1) * ((_scale_dist - distance) / _scale_dist)));
index 5830bdc349e9dbafc147de7b8e6e1139ba180650..0be5c4acd185075a1fd1a2d91e00c990096a0eae 100644 (file)
@@ -514,23 +514,19 @@ void KLN89AptPage::UpdateAirport(const string& id) {
        
        // Runways
        _aptRwys.clear();
-       FGRunway r;
-       bool haveRwy = globals->get_runways()->search(id, &r);
-       while(haveRwy && r._id == id) {
-               // Insert the runway with longest at the start of the array
-               for(unsigned int i = 0; i <= _aptRwys.size(); ++i) {
-                       if(i == _aptRwys.size()) {
-                               _aptRwys.push_back(r);
-                               break;
-                       } else {
-                               if(r._length > _aptRwys[i]._length) {
-                                       _aptRwys.insert(_aptRwys.begin() + i, r);
-                                       break;
-                               }
-                       }
-               }
-               haveRwy = globals->get_runways()->next(&r);
-       }
+  const FGAirport* apt = fgFindAirportID(id);
+  assert(apt);
+  
+  // build local array, longest runway first
+  for (unsigned int r=0; r<apt->numRunways(); ++r) {
+    FGRunway rwy(apt->getRunwayByIndex(r));
+    if ((r > 0) && (rwy._length > _aptRwys.front()._length)) {
+      _aptRwys.insert(_aptRwys.begin(), rwy);
+    } else {
+      _aptRwys.push_back(rwy);
+    }
+  }
+  
        _nRwyPages = (_aptRwys.size() + 1) / 2; // 2 runways per page.
        if(_nFreqPages < 1) _nFreqPages = 1;
        if(_nRwyPages < 1) _nRwyPages = 1;
index 0ed7cdff51872c319082975b2f0f8c316045282d..24b04055e4910f76919a2b71ac34231f6ad65baf 100644 (file)
@@ -26,7 +26,9 @@
 #endif
 
 #include "kln89_page_fpl.hxx"
+
 #include <algorithm>
+#include <iostream>
 
 using namespace std;
 
index 02f8ca1a461f2169827b43e12c8233fcac17455a..ee000f234207b18548513f0930f1b8905561fc0a 100644 (file)
@@ -112,13 +112,30 @@ void GroundRadar::createTexture(const char* texture_name)
     FGTextureManager::addTexture(texture_name, getTexture());
 }
 
+void GroundRadar::addRunwayVertices(const FGRunway& aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices)
+{
+  double az1, az2, dist_m;
+  geo_inverse_wgs_84(aTowerLat, aTowerLon, aRunway._lat, aRunway._lon, &az1, &az2, &dist_m);
+
+  osg::Vec3 center = fromPolar(az1, dist_m * aScale) + osg::Vec3(256, 256, 0);
+  osg::Vec3 leftcenter = fromPolar(aRunway._heading, aRunway._length * SG_FEET_TO_METER * aScale / 2) + center;
+  osg::Vec3 lefttop = fromPolar(aRunway._heading - 90, aRunway._width * SG_FEET_TO_METER * aScale / 2) + leftcenter;
+  osg::Vec3 leftbottom = leftcenter * 2 - lefttop;
+  osg::Vec3 rightbottom = center * 2 - lefttop;
+  osg::Vec3 righttop = center * 2 - leftbottom;
+
+  aVertices->push_back(lefttop);
+  aVertices->push_back(leftbottom);
+  aVertices->push_back(rightbottom);
+  aVertices->push_back(righttop);
+}
+
 void GroundRadar::updateTexture()
 {
     osg::ref_ptr<osg::Vec3Array> rwy_vertices = new osg::Vec3Array;
     osg::ref_ptr<osg::Vec3Array> taxi_vertices = new osg::Vec3Array;
 
     const string airport_name = _airport_node->getStringValue();
-    FGRunwayList* runways = globals->get_runways();
 
     const FGAirport* airport = fgFindAirportID(airport_name);
     if (airport == 0)
@@ -128,26 +145,22 @@ void GroundRadar::updateTexture()
     const double tower_lat = tower_location.getLatitudeDeg();
     const double tower_lon = tower_location.getLongitudeDeg();
     double scale = SG_METER_TO_NM * 200 / _range_node->getDoubleValue();
+  
+    const FGAirport* apt = fgFindAirportID(airport_name);
+    assert(apt);
 
-    for (FGRunway runway = runways->search(airport_name); runway._id == airport_name; runway = runways->next())
+    for (unsigned int i=0; i<apt->numRunways(); ++i)
     {
-        double az1, az2, dist_m;
-        geo_inverse_wgs_84(tower_lat, tower_lon, runway._lat, runway._lon, &az1, &az2, &dist_m);
-
-        osg::Vec3 center = fromPolar(az1, dist_m * scale) + osg::Vec3(256, 256, 0);
-        osg::Vec3 leftcenter = fromPolar(runway._heading, runway._length * SG_FEET_TO_METER * scale / 2) + center;
-        osg::Vec3 lefttop = fromPolar(runway._heading - 90, runway._width * SG_FEET_TO_METER * scale / 2) + leftcenter;
-        osg::Vec3 leftbottom = leftcenter * 2 - lefttop;
-        osg::Vec3 rightbottom = center * 2 - lefttop;
-        osg::Vec3 righttop = center * 2 - leftbottom;
-
-        osg::Vec3Array* vertices = runway._rwy_no[0] == 'x' ? taxi_vertices.get() : rwy_vertices.get();
-        vertices->push_back(lefttop);
-        vertices->push_back(leftbottom);
-        vertices->push_back(rightbottom);
-        vertices->push_back(righttop);
+      FGRunway runway(apt->getRunwayByIndex(i));
+      addRunwayVertices(runway, tower_lat, tower_lon, scale, rwy_vertices.get());
     }
-
+    
+    for (unsigned int i=0; i<apt->numTaxiways(); ++i)
+    {
+      FGRunway runway(apt->getTaxiwayByIndex(i));
+      addRunwayVertices(runway, tower_lat, tower_lon, scale, taxi_vertices.get());
+    }
+    
     osg::Vec3Array* vertices = new osg::Vec3Array(*taxi_vertices.get());
     vertices->insert(vertices->end(), rwy_vertices->begin(), rwy_vertices->end());
     _geom->setVertexArray(vertices);
index 8839143faf32e8d679ae78237844af29e0ae565c..0836a526b893c9ad79d7335f16fbbc19d9816105 100644 (file)
@@ -25,6 +25,9 @@
 #include <simgear/props/props.hxx>
 #include "od_gauge.hxx"
 
+// forward decls
+class FGRunway;
+
 ////////////////////////////////////////////////////////////////////////
 // Built-in layer for the atc radar.
 ////////////////////////////////////////////////////////////////////////
@@ -39,7 +42,9 @@ public:
 
 protected:
     void createTexture(const char* texture_name);
-
+    
+    void addRunwayVertices(const FGRunway& aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices);
+    
     osg::ref_ptr<osg::Geometry> _geom;
     SGPropertyNode_ptr _airport_node;
     SGPropertyNode_ptr _range_node;
index fc34f0b792ed98c11b50348c13387b6a79142020..f423a70f5e08f40d3f7c1fca228b051ecb8eb72e 100755 (executable)
@@ -4288,19 +4288,15 @@ MK_VIII::Mode6Handler::test_runway (const FGRunway *_runway)
 bool
 MK_VIII::Mode6Handler::test_airport (const FGAirport *airport)
 {
-  FGRunway r;
-  if (globals->get_runways()->search(airport->getId(), &r))
-    do
-      {
-       if (test_runway(&r))
-         return true;
-
-       // reciprocal runway
-       r._heading = get_reciprocal_heading(r._heading);
-       if (test_runway(&r))
-         return true;
-      }
-    while (globals->get_runways()->next(&r) && r._id == airport->getId());
+  for (unsigned int r=0; r<airport->numRunways(); ++r) {
+    FGRunway rwy(airport->getRunwayByIndex(r));
+    
+    if (test_runway(&rwy)) return true;
+    
+    // reciprocal runway
+    rwy._heading = get_reciprocal_heading(rwy._heading);
+    if (test_runway(&rwy)) return true;
+  }
 
   return false;
 }
@@ -4525,46 +4521,46 @@ void
 MK_VIII::TCFHandler::select_runway (const FGAirport *airport,
                                    FGRunway *_runway)
 {
+/*
   FGRunway r;
   bool status = globals->get_runways()->search(airport->getId(), &r);
   assert(status);
 
+      }
+  while (globals->get_runways()->next(&r) && r._id == airport->getId());
+  */
+  
   double min_diff = 360;
-  do
+  
+  for (unsigned int r=0; r<airport->numRunways(); ++r) {
+    FGRunway rwy(airport->getRunwayByIndex(r));
+    double diff = get_azimuth_difference(&rwy);
+    if (diff < min_diff)
+         {
+      min_diff = diff;
+      *_runway = rwy;
+    }
+    
+    // reciprocal runway
+    rwy._heading = get_reciprocal_heading(rwy._heading);
+    diff = get_azimuth_difference(&rwy);
+    if (diff < min_diff)
     {
-      double diff;
-
-      diff = get_azimuth_difference(&r);
-      if (diff < min_diff)
-       {
-         min_diff = diff;
-         *_runway = r;
-       }
-
-      // reciprocal runway
-      r._heading = get_reciprocal_heading(r._heading);
-      diff = get_azimuth_difference(&r);
-      if (diff < min_diff)
-       {
-         min_diff = diff;
-         *_runway = r;
-       }
+      min_diff = diff;
+      *_runway = rwy;
     }
-  while (globals->get_runways()->next(&r) && r._id == airport->getId());
+  } // of airport runways iteration
 }
 
 bool
 MK_VIII::TCFHandler::test_airport (const FGAirport *airport)
 {
-  FGRunway r;
-  if (globals->get_runways()->search(airport->getId(), &r))
-    do
-      {
-       if (r._length >= mk->conf.runway_database)
-         return true;
-      }
-    while (globals->get_runways()->next(&r) && r._id == airport->getId());
-
+  for (unsigned int r=0; r<airport->numRunways(); ++r) {
+    if (airport->getRunwayByIndex(r)._length >= mk->conf.runway_database) {
+      return true;
+    }
+  }
+  
   return false;
 }
 
index 15e3caaa325f6e0a565b81691b595aa5cd8ca3d2..20b2f2447179922e6a349d79b3eeec3b809cfbf0 100644 (file)
@@ -67,6 +67,8 @@
 #include <Airports/apt_loader.hxx>
 #include <Airports/runways.hxx>
 #include <Airports/simple.hxx>
+#include <Airports/dynamics.hxx>
+
 #include <AIModel/AIManager.hxx>
 #include <ATCDCL/ATCmgr.hxx>
 #include <ATCDCL/AIMgr.hxx>
@@ -751,8 +753,6 @@ void fgInitTowerLocationListener() {
 
 // Set current_options lon/lat given an airport id and heading (degrees)
 static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
-    FGRunway r;
-
     if ( id.empty() )
         return false;
 
@@ -761,11 +761,9 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
             "Attempting to set starting position from airport code "
             << id << " heading " << tgt_hdg );
 
-    if ( ! globals->get_runways()->search( id, (int)tgt_hdg, &r ) ) {
-        SG_LOG( SG_GENERAL, SG_ALERT,
-                "Failed to find a good runway for " << id << '\n' );
-        return false;
-    }
+    const FGAirport* apt = fgFindAirportID(id);
+    if (!apt) return false;
+    FGRunway r = apt->findBestRunwayForHeading(tgt_hdg);
     fgSetString("/sim/atc/runway", r._rwy_no.c_str());
 
     double lat2, lon2, az2;
@@ -872,8 +870,6 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
 
 // Set current_options lon/lat given an airport id and runway number
 static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy, bool rwy_req ) {
-    FGRunway r;
-
     if ( id.empty() )
         return false;
 
@@ -882,12 +878,20 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy, bo
             "Attempting to set starting position for "
             << id << ":" << rwy );
 
-    if ( ! globals->get_runways()->search( id, rwy, &r ) ) {
-        SG_LOG( SG_GENERAL, rwy_req ? SG_ALERT : SG_INFO,
+    const FGAirport* apt = fgFindAirportID(id);
+    if (!apt) {
+      SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find airport:" << id);
+      return false;
+    }
+    
+    if (!apt->hasRunwayWithIdent(rwy)) {
+      SG_LOG( SG_GENERAL, rwy_req ? SG_ALERT : SG_INFO,
                 "Failed to find runway " << rwy <<
                 " at airport " << id << ". Using default runway." );
-        return false;
+      return false;
     }
+    
+    FGRunway r(apt->getRunwayByIdent(rwy));
     fgSetString("/sim/atc/runway", r._rwy_no.c_str());
 
     double lat2, lon2, az2;
@@ -1143,10 +1147,8 @@ fgInitNav ()
 
     FGAirportList *airports = new FGAirportList();
     globals->set_airports( airports );
-    FGRunwayList *runways = new FGRunwayList();
-    globals->set_runways( runways );
 
-    fgAirportDBLoad( airports, runways, aptdb.str(), p_metar.str() );
+    fgAirportDBLoad( airports, aptdb.str(), p_metar.str() );
 
     FGNavList *navlist = new FGNavList;
     FGNavList *loclist = new FGNavList;
@@ -1179,7 +1181,7 @@ fgInitNav ()
         double threshold
             = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg",
                            5.0 );
-        fgNavDBAlignLOCwithRunway( runways, loclist, threshold );
+        fgNavDBAlignLOCwithRunway( airports, loclist, threshold );
     }
 
     SG_LOG(SG_GENERAL, SG_INFO, "  Fixes");
index 30e3585feef3f9353e20bee5585c507d423ad6db..bf7ff48c4ab3a5ad9fad69455fb28d4f21a5afb4 100644 (file)
@@ -81,7 +81,6 @@ FGGlobals::FGGlobals() :
     current_panel( NULL ),
     soundmgr( NULL ),
     airports( NULL ),
-    runways( NULL ),
     ATC_mgr( NULL ),
     AI_mgr( NULL ),
     controls( NULL ),
@@ -135,7 +134,6 @@ FGGlobals::~FGGlobals()
     delete soundmgr;
     delete airports;
 
-    delete runways;
     delete ATC_mgr;
     delete AI_mgr;
     delete controls;
index 0c3de7f8aa6d3985ba42782e188e3cad6fc64045..efabd4e72b93fe4969f9f614f42d2cb129871849 100644 (file)
@@ -55,7 +55,6 @@ class SGSubsystemMgr;
 class SGSubsystem;
 
 class FGAirportList;
-class FGRunwayList;
 class FGAIMgr;
 class FGATCMgr;
 class FGAircraftModel;
@@ -142,9 +141,6 @@ private:
     // Simple Airport List
     FGAirportList *airports;
 
-    // Runway List
-    FGRunwayList *runways;
-
     // ATC manager
     FGATCMgr *ATC_mgr;
 
@@ -253,9 +249,6 @@ public:
     inline FGAirportList *get_airports() const { return airports; }
     inline void set_airports( FGAirportList *a ) {airports = a; }
 
-    inline FGRunwayList *get_runways() const { return runways; }
-    inline void set_runways( FGRunwayList *r ) {runways = r; }
-
     inline FGATCMgr *get_ATC_mgr() const { return ATC_mgr; }
     inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
 
index 712eb1a5f22a2f080bf2f532607fcca4e5c3553b..b38b3536a2ba51466a124a0c2e2f23d83e8176b3 100644 (file)
@@ -32,6 +32,8 @@
 #  include <signal.h>
 #endif
 
+#include <iostream>
+
 #include <plib/netSocket.h>
 
 #include <osg/Camera>
@@ -87,6 +89,8 @@ extern float init_volume;
 
 using namespace flightgear;
 
+using std::cerr;
+
 // This is a record containing a bit of global housekeeping information
 FGGeneral general;
 
index c16f3c690f97ac802cbb43eea8c1dd9d6bd1176b..08910ba21868102910368fde524814cd059e49ab 100644 (file)
@@ -35,6 +35,7 @@
 #include <string.h>            // strcmp()
 #include <algorithm>
 
+#include <iostream>
 #include <string>
 
 #include <plib/ul.h>
@@ -63,6 +64,9 @@
 
 using std::string;
 using std::sort;
+using std::cout;
+using std::cerr;
+using std::endl;
 
 #ifndef VERSION
 #define VERSION "CVS "__DATE__
index b835597762bee3ff2eb6bd48c0e7d821c913e956..c92a992b5e1091e6f6aa899679a4e10126937384 100644 (file)
@@ -31,6 +31,7 @@
 #include <config.h>
 #endif
 
+#include <iostream>
 #include <plib/netSocket.h>
 
 #include <simgear/misc/stdint.hxx>
@@ -43,6 +44,8 @@
 #include "multiplaymgr.hxx"
 #include "mpmessages.hxx"
 
+using std::cerr;
+
 #define MAX_PACKET_SIZE 1200
 #define MAX_TEXT_SIZE 128
 
index 089639f042500403c325292984aa0e6a3fd8c61a..a8d2fbdd71c9ad4acd8e5d388c9c82358546c6ac 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/sg_geodesy.hxx>
+#include <simgear/misc/strutils.hxx>
 
 #include <Airports/runways.hxx>
 #include <Airports/simple.hxx>
@@ -268,7 +269,7 @@ static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
 // it then "moves" the localizer and updates it's heading so it
 // *perfectly* aligns with the runway, but is still the same distance
 // from the runway threshold.
-void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist,
+void fgNavDBAlignLOCwithRunway( FGAirportList *airports, FGNavList *loclist,
                                 double threshold ) {
     nav_map_type navmap = loclist->get_navaids();
 
@@ -277,18 +278,19 @@ void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist,
         nav_list_type locs = freq->second;
         nav_list_const_iterator loc = locs.begin();
         while ( loc != locs.end() ) {
-            string name = (*loc)->get_name();
-            string::size_type pos1 = name.find(" ");
-            string id = name.substr(0, pos1);
-            name = name.substr(pos1+1);
-            string::size_type pos2 = name.find(" ");
-            string rwy = name.substr(0, pos2);
-
-            FGRunway r;
-            if ( runways->search(id, rwy, &r) ) {
-                update_loc_position( (*loc), &r, threshold );
-            }
-            ++loc;
+          vector<string> parts = simgear::strutils::split((*loc)->get_name());
+          if (parts.size() < 2) {
+            SG_LOG(SG_GENERAL, SG_ALERT, "can't parse navaid " << (*loc)->get_ident() 
+              << " name for airport/runway:" << (*loc)->get_name());
+            continue;
+          }
+          
+          FGAirport* airport = airports->search(parts[0]);
+          if (!airport) continue; // not found
+            
+          FGRunway r = airport->getRunwayByIdent(parts[1]);
+          update_loc_position( (*loc), &r, threshold );
+          ++loc;
         }
         ++freq;
     }
index 825fa1e621f7b9a3c8360ee8bc45a60bb31cc781..3c2321221261e57c58f0cb17a797f85493c9a5f4 100644 (file)
@@ -52,7 +52,7 @@ bool fgNavDBInit( FGAirportList *airports,
 // it then "moves" the localizer and updates it's heading so it
 // *perfectly* aligns with the runway, but is still the same distance
 // from the runway threshold.
-void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist,
+void fgNavDBAlignLOCwithRunway( FGAirportList *airport, FGNavList *loclist,
                                 double threshold );
 
 #endif // _FG_NAVDB_HXX
index 1177b21028347afbdb507d11284ce14528dd6386..639801d0de80cf208f772750ec4288aec034dcd3 100644 (file)
@@ -548,37 +548,32 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args)
 
     string id = apt->getId();
     string name = apt->getName();
-
+    
     // set runway hash
-    FGRunwayList *rwylst = globals->get_runways();
-    FGRunway rwy;
     naRef rwys = naNewHash(c);
-    if(rwylst->search(id, &rwy)) {
-        do {
-            if(rwy._id != id) break;
-            if(rwy._type[0] != 'r') continue;
-
-            naRef rwyid = naStr_fromdata(naNewString(c),
+    for (unsigned int r=0; r<apt->numRunways(); ++r) {
+      FGRunway rwy(apt->getRunwayByIndex(r));
+      
+      naRef rwyid = naStr_fromdata(naNewString(c),
                     const_cast<char *>(rwy._rwy_no.c_str()),
                     rwy._rwy_no.length());
 
-            naRef rwydata = naNewHash(c);
+      naRef rwydata = naNewHash(c);
 #define HASHSET(s,l,n) naHash_set(rwydata, naStr_fromdata(naNewString(c),s,l),n)
-            HASHSET("id", 2, rwyid);
-            HASHSET("lat", 3, naNum(rwy._lat));
-            HASHSET("lon", 3, naNum(rwy._lon));
-            HASHSET("heading", 7, naNum(rwy._heading));
-            HASHSET("length", 6, naNum(rwy._length * SG_FEET_TO_METER));
-            HASHSET("width", 5, naNum(rwy._width * SG_FEET_TO_METER));
-            HASHSET("threshold1", 10, naNum(rwy._displ_thresh1 * SG_FEET_TO_METER));
-            HASHSET("threshold2", 10, naNum(rwy._displ_thresh2 * SG_FEET_TO_METER));
-            HASHSET("stopway1", 8, naNum(rwy._stopway1 * SG_FEET_TO_METER));
-            HASHSET("stopway2", 8, naNum(rwy._stopway2 * SG_FEET_TO_METER));
+      HASHSET("id", 2, rwyid);
+      HASHSET("lat", 3, naNum(rwy._lat));
+      HASHSET("lon", 3, naNum(rwy._lon));
+      HASHSET("heading", 7, naNum(rwy._heading));
+      HASHSET("length", 6, naNum(rwy._length * SG_FEET_TO_METER));
+      HASHSET("width", 5, naNum(rwy._width * SG_FEET_TO_METER));
+      HASHSET("threshold1", 10, naNum(rwy._displ_thresh1 * SG_FEET_TO_METER));
+      HASHSET("threshold2", 10, naNum(rwy._displ_thresh2 * SG_FEET_TO_METER));
+      HASHSET("stopway1", 8, naNum(rwy._stopway1 * SG_FEET_TO_METER));
+      HASHSET("stopway2", 8, naNum(rwy._stopway2 * SG_FEET_TO_METER));
 #undef HASHSET
-            naHash_set(rwys, rwyid, rwydata);
-        } while(rwylst->next(&rwy));
+      naHash_set(rwys, rwyid, rwydata);
     }
-
+    
     // set airport hash
     naRef aptdata = naNewHash(c);
 #define HASHSET(s,l,n) naHash_set(aptdata, naStr_fromdata(naNewString(c),s,l),n)