]> git.mxchange.org Git - flightgear.git/blobdiff - src/Airports/apt_loader.cxx
GUI ‘restore defaults’ support.
[flightgear.git] / src / Airports / apt_loader.cxx
index a3aa490d3c4815485a68aff6e09f6d21f72c91bf..f2f3b712076fcbc9e013fbd560671165d5cbf5a0 100644 (file)
@@ -43,7 +43,7 @@
 
 #include <string>
 
-#include "simple.hxx"
+#include "airport.hxx"
 #include "runways.hxx"
 #include "pavement.hxx"
 #include <Navaids/NavDataCache.hxx>
@@ -90,7 +90,7 @@ public:
 
     if ( !in.is_open() ) {
         SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << aptdb_file );
-        exit(-1);
+        throw sg_io_exception("cannot open APT file", aptdb_file);
     }
 
     string line;
@@ -105,10 +105,10 @@ public:
       line = tmp; // string copy, ack
       line_num++;
 
-      if ( !line.size() || isspace(tmp[0])) {
+      if ( line.empty() || isspace(tmp[0]) || tmp[0] == '#' ) {
         continue;
       }
-      
+
       if (line.size() >= 3) {
           char *p = (char *)memchr(tmp, ' ', 3);
           if ( p )
@@ -116,16 +116,16 @@ public:
       }
 
       line_id = atoi(tmp);
-      if ( tmp[0] == 'I' ) {
-        // First line, indicates IBM (i.e. DOS line endings I
-        // believe.)
+      if ( tmp[0] == 'I' || tmp[0] == 'A' ) {
+        // First line, indicates IBM ("I") or Macintosh ("A")
+        // line endings.
 
         // move past this line and read and discard the next line
         // which is the version and copyright information
         in.getline(tmp, 2048);
-        // vector<string> vers_token = simgear::strutils::split( tmp );
-        if ( strlen(tmp) > 4 ) {
-           char *p = (char *)memchr(tmp, ' ', 4);
+
+        if ( strlen(tmp) > 5 ) {
+           char *p = (char *)memchr(tmp, ' ', 5);
            if ( p )
               *p = 0;
         }
@@ -179,12 +179,14 @@ public:
         pavement = false;
       } else if ( line_id == 130 ) {
         pavement = false;
+      } else if ( line_id >= 1000 ) {
+          // airport traffic flow (ignore)
       } else if ( line_id == 99 ) {
           SG_LOG( SG_GENERAL, SG_DEBUG, "End of file reached" );
       } else {
           SG_LOG( SG_GENERAL, SG_ALERT, 
-                  "Unknown line(#" << line_num << ") in file: " << line );
-          exit( -1 );
+                  "Unknown line(#" << line_num << ") in apt.dat file: " << line );
+          throw sg_format_exception("malformed line in apt.dat:", line);
       }
     }
 
@@ -285,15 +287,23 @@ private:
     double heading = atof( token[4].c_str() );
     double length = atoi( token[5].c_str() );
     double width = atoi( token[8].c_str() );
+    length *= SG_FEET_TO_METER;
+    width *= SG_FEET_TO_METER;
+
+    // adjust lat / lon to the start of the runway/taxiway, not the middle
+    SGGeod pos_1 = SGGeodesy::direct( SGGeod::fromDegFt(lon, lat, last_apt_elev), heading, -length/2 );
 
     last_rwy_heading = heading;
 
     int surface_code = atoi( token[10].c_str() );
-    SGGeod pos(SGGeod::fromDegFt(lon, lat, last_apt_elev));
-    
-    if (rwy_no[0] == 'x') {
-      cache->insertRunway(FGPositioned::TAXIWAY,rwy_no, pos, currentAirportID,
-                          heading, length, width, 0, 0, surface_code);
+
+    if (rwy_no[0] == 'x') {  // Taxiway
+      cache->insertRunway(FGPositioned::TAXIWAY, rwy_no, pos_1, currentAirportID,
+                          heading, length, width, 0.0, 0.0, surface_code);
+    } else if (rwy_no[0] == 'H') {  // Helipad
+      SGGeod pos(SGGeod::fromDegFt(lon, lat, last_apt_elev));
+      cache->insertRunway(FGPositioned::HELIPAD, rwy_no, pos, currentAirportID,
+                          heading, length, width, 0.0, 0.0, surface_code);
     } else {
       // (pair of) runways
       string rwy_displ_threshold = token[6];
@@ -301,22 +311,29 @@ private:
           = simgear::strutils::split( rwy_displ_threshold, "." );
       double displ_thresh1 = atof( displ[0].c_str() );
       double displ_thresh2 = atof( displ[1].c_str() );
+      displ_thresh1 *= SG_FEET_TO_METER;
+      displ_thresh2 *= SG_FEET_TO_METER;
 
       string rwy_stopway = token[7];
       vector<string> stop
           = simgear::strutils::split( rwy_stopway, "." );
       double stopway1 = atof( stop[0].c_str() );
       double stopway2 = atof( stop[1].c_str() );
+      stopway1 *= SG_FEET_TO_METER;
+      stopway2 *= SG_FEET_TO_METER;
+
+      SGGeod pos_2 = SGGeodesy::direct( pos_1, heading, length );
 
-      PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no, pos,
+      PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no, pos_1,
                                              currentAirportID, heading, length,
                                              width, displ_thresh1, stopway1,
                                              surface_code);
       
       PositionedID reciprocal = cache->insertRunway(FGPositioned::RUNWAY,
-                                              FGRunway::reverseIdent(rwy_no), pos,
-                                             currentAirportID, heading + 180.0, length,
-                                             width, displ_thresh2, stopway2,
+                                             FGRunway::reverseIdent(rwy_no), pos_2,
+                                             currentAirportID,
+                                             SGMiscd::normalizePeriodic(0, 360, heading + 180.0),
+                                             length, width, displ_thresh2, stopway2,
                                              surface_code);
 
       cache->setRunwayReciprocal(rwy, reciprocal);
@@ -325,7 +342,7 @@ private:
 
   void parseRunwayLine850(const vector<string>& token)
   {
-    double width = atof( token[1].c_str() ) * SG_METER_TO_FEET;
+    double width = atof( token[1].c_str() );
     int surface_code = atoi( token[2].c_str() );
 
     double lat_1 = atof( token[9].c_str() );
@@ -342,17 +359,14 @@ private:
     rwy_lon_accum += lon_2;
     rwy_count++;
 
-    double length, heading_1, heading_2, dummy;
+    double length, heading_1, heading_2;
     SGGeodesy::inverse( pos_1, pos_2, heading_1, heading_2, length );
-    SGGeod pos;
-    SGGeodesy::direct( pos_1, heading_1, length / 2.0, pos, dummy );
-    length *= SG_METER_TO_FEET;
 
     last_rwy_heading = heading_1;
 
     const string& rwy_no_1(token[8]);
     const string& rwy_no_2(token[17]);
-    if ( rwy_no_1.size() == 0 || rwy_no_2.size() == 0 )
+    if ( rwy_no_1.empty() || rwy_no_2.empty() )
         return;
 
     double displ_thresh1 = atof( token[11].c_str() );
@@ -361,13 +375,13 @@ private:
     double stopway1 = atof( token[12].c_str() );
     double stopway2 = atof( token[21].c_str() );
 
-    PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no_1, pos,
+    PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no_1, pos_1,
                                            currentAirportID, heading_1, length,
                                            width, displ_thresh1, stopway1,
                                            surface_code);
     
     PositionedID reciprocal = cache->insertRunway(FGPositioned::RUNWAY,
-                                                  rwy_no_2, pos,
+                                                  rwy_no_2, pos_2,
                                                   currentAirportID, heading_2, length,
                                                   width, displ_thresh2, stopway2,
                                                   surface_code);
@@ -377,7 +391,7 @@ private:
 
   void parseWaterRunwayLine850(const vector<string>& token)
   {
-    double width = atof( token[1].c_str() ) * SG_METER_TO_FEET;
+    double width = atof( token[1].c_str() );
 
     double lat_1 = atof( token[4].c_str() );
     double lon_1 = atof( token[5].c_str() );
@@ -393,22 +407,20 @@ private:
     rwy_lon_accum += lon_2;
     rwy_count++;
 
-    double length, heading_1, heading_2, dummy;
+    double length, heading_1, heading_2;
     SGGeodesy::inverse( pos_1, pos_2, heading_1, heading_2, length );
-    SGGeod pos;
-    SGGeodesy::direct( pos_1, heading_1, length / 2.0, pos, dummy );
 
     last_rwy_heading = heading_1;
 
     const string& rwy_no_1(token[3]);
     const string& rwy_no_2(token[6]);
 
-    PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no_1, pos,
+    PositionedID rwy = cache->insertRunway(FGPositioned::RUNWAY, rwy_no_1, pos_1,
                                            currentAirportID, heading_1, length,
                                            width, 0.0, 0.0, 13);
     
     PositionedID reciprocal = cache->insertRunway(FGPositioned::RUNWAY,
-                                                  rwy_no_2, pos,
+                                                  rwy_no_2, pos_2,
                                                   currentAirportID, heading_2, length,
                                                   width, 0.0, 0.0, 13);
     
@@ -417,8 +429,8 @@ private:
 
   void parseHelipadLine850(const vector<string>& token)
   {
-    double length = atof( token[5].c_str() ) * SG_METER_TO_FEET;
-    double width = atof( token[6].c_str() ) * SG_METER_TO_FEET;
+    double length = atof( token[5].c_str() );
+    double width = atof( token[6].c_str() );
 
     double lat = atof( token[2].c_str() );
     double lon = atof( token[3].c_str() );
@@ -434,7 +446,7 @@ private:
     const string& rwy_no(token[1]);
     int surface_code = atoi( token[7].c_str() );
 
-    cache->insertRunway(FGPositioned::RUNWAY, rwy_no, pos,
+    cache->insertRunway(FGPositioned::HELIPAD, rwy_no, pos,
                         currentAirportID, heading, length,
                         width, 0.0, 0.0, surface_code);
   }