From 27dd0a41d8201d3e72b5b51f52d8abe4ab4cbc78 Mon Sep 17 00:00:00 2001
From: Ralf Gerlich <ralf.gerlich@custom-scenery.org>
Date: Thu, 8 Nov 2007 22:27:02 +0100
Subject: [PATCH] Fixed the genapts apt.dat parser:

- The VASI GS angle is properly parsed
- Don't assume given column numbers but properly split the lines at whitespaces
- actually make use of the order of taxiways as specified in the apt.dat
- make the min/max lat/lon work (patch provided by Torsten Dreyer on terragear-devel [1])

[1] http://mail.flightgear.org/pipermail/terragear-devel/2007-January/001389.html
---
 src/Airports/GenAirports/build.cxx | 56 ++++++++++++++++-----------
 src/Airports/GenAirports/main.cxx  | 62 +++++++++++++++++++++++-------
 2 files changed, 81 insertions(+), 37 deletions(-)

diff --git a/src/Airports/GenAirports/build.cxx b/src/Airports/GenAirports/build.cxx
index bb873314..d705ccda 100644
--- a/src/Airports/GenAirports/build.cxx
+++ b/src/Airports/GenAirports/build.cxx
@@ -426,10 +426,14 @@ void build_airport( string airport_id, float alt_m,
         rwy.smoothness = atof( token[13].c_str() );
         rwy.dist_remaining = (atoi( token[14].c_str() ) == 1 );
 
-        string vasi_angles = token[15];
-        vector<string> vasis = simgear::strutils::split( vasi_angles, "." );
-        rwy.gs_angle1 = atof( vasis[0].c_str() ) * 0.01;
-        rwy.gs_angle2 = atof( vasis[1].c_str() ) * 0.01;
+	if (token.size()>15) {
+		string vasi_angles = token[15];
+		vector<string> vasis = simgear::strutils::split( vasi_angles, "." );
+		rwy.gs_angle1 = atof( vasis[0].c_str() ) * 0.01;
+		rwy.gs_angle2 = atof( vasis[1].c_str() ) * 0.01;
+	} else {
+		rwy.gs_angle1 = rwy.gs_angle2 = 3.0;
+	}
 
 	SG_LOG( SG_GENERAL, SG_DEBUG, "  no    = " << rwy.rwy_no);
 	SG_LOG( SG_GENERAL, SG_DEBUG, "  lat   = " << rwy.lat);
@@ -463,18 +467,14 @@ void build_airport( string airport_id, float alt_m,
     point_list beacons; beacons.clear();
     for ( i = 0; i < (int)beacons_raw.size(); ++i ) {
 	string beacon_str = beacons_raw[i];
+        vector<string> token = simgear::strutils::split( beacon_str );
 
 	Point3D beacon;
 
 	SG_LOG(SG_GENERAL, SG_INFO, beacon_str);
 
-	string beacon_lat = beacon_str.substr(2, 10);
-	beacon.setlat( atof( beacon_lat.c_str() ) );
-
-	string beacon_lon = beacon_str.substr(13, 11);
-	beacon.setlon( atof( beacon_lon.c_str() ) );
-
-	string beacon_type = beacon_str.substr(25, 1);
+	beacon.setlat( atof( token[1].c_str() ) );
+	beacon.setlon( atof( token[2].c_str() ) );
 
 	SG_LOG( SG_GENERAL, SG_DEBUG, "  beacon   = " << beacon );
 
@@ -484,18 +484,19 @@ void build_airport( string airport_id, float alt_m,
     point_list towers; towers.clear();
     for ( i = 0; i < (int)towers_raw.size(); ++i ) {
 	string tower_str = towers_raw[i];
+        vector<string> token = simgear::strutils::split( tower_str );
 
 	Point3D tower;
 
 	SG_LOG(SG_GENERAL, SG_INFO, tower_str);
 
-	string tower_lat = tower_str.substr(2, 10);
-	tower.setlat( atof( tower_lat.c_str() ) );
+	tower.setlat( atof( token[1].c_str() ) );
+	tower.setlon( atof( token[2].c_str() ) );
 
-	string tower_lon = tower_str.substr(13, 11);
-	tower.setlon( atof( tower_lon.c_str() ) );
-
-	string tower_type = tower_str.substr(25, 1);
+	if (!atoi(token[4].c_str())) {
+		// Ralf Gerlich: Skip towers that shall not be drawn
+		continue;
+	}
 
 	SG_LOG( SG_GENERAL, SG_DEBUG, "  tower   = " << tower );
 
@@ -506,18 +507,16 @@ void build_airport( string airport_id, float alt_m,
     int_list windsock_types; windsock_types.clear();
     for ( i = 0; i < (int)windsocks_raw.size(); ++i ) {
 	string windsock_str = windsocks_raw[i];
+        vector<string> token = simgear::strutils::split( windsock_str );
 
 	Point3D windsock;
 
 	SG_LOG(SG_GENERAL, SG_INFO, windsock_str);
 
-	string windsock_lat = windsock_str.substr(2, 10);
-	windsock.setlat( atof( windsock_lat.c_str() ) );
+	windsock.setlat( atof( token[1].c_str() ) );
+	windsock.setlon( atof( token[2].c_str() ) );
 
-	string windsock_lon = windsock_str.substr(13, 11);
-	windsock.setlon( atof( windsock_lon.c_str() ) );
-
-	string windsock_type = windsock_str.substr(25, 1);
+	string windsock_type = token[3];
 
 	SG_LOG( SG_GENERAL, SG_DEBUG, "  windsock   = " << windsock );
 
@@ -578,6 +577,7 @@ void build_airport( string airport_id, float alt_m,
 
     // 4th pass: generate all taxiways
 
+#if 0
     // we want to generate in order of largest size first so this will
     // look a little weird, but that's all I'm doing, otherwise a
     // simple list traversal would work fine.
@@ -607,6 +607,16 @@ void build_airport( string airport_id, float alt_m,
             done = true;
         }
     }
+#else
+    /* Ralf Gerlich: Generate Taxiways in specified order from bottom to top */
+    for ( size_t i=0; i<taxiways.size(); ++i ) {
+            SG_LOG( SG_GENERAL, SG_DEBUG, "generating " << i );
+            build_runway( taxiways[i], alt_m,
+                          &rwy_polys, &texparams, &accum,
+                          &apt_base, &apt_clearing );
+            taxiways[i].generated = true;
+    }
+#endif
 
     // Now generate small surface for each beacon
     TGPolygon obj_base, obj_safe_base;
diff --git a/src/Airports/GenAirports/main.cxx b/src/Airports/GenAirports/main.cxx
index a4fca964..38b86f72 100644
--- a/src/Airports/GenAirports/main.cxx
+++ b/src/Airports/GenAirports/main.cxx
@@ -18,7 +18,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 //
-// $Id: main.cxx,v 1.37 2005-12-19 15:53:21 curt Exp $
+// $Id: main.cxx,v 1.37 2005/12/19 15:53:21 curt Exp $
 //
 
 
@@ -61,6 +61,7 @@ SG_USING_STD(vector);
 
 int nudge = 10;
 
+static int is_in_range( string_list & runway_list, float min_lat, float max_lat, float min_lon, float max_lon );
 
 // Display usage
 static void usage( int argc, char **argv ) {
@@ -319,13 +320,15 @@ int main( int argc, char **argv ) {
                                 // skip building heliports and
                                 // seaplane bases
                             } else {
-                                build_airport( last_apt_id,
-                                               elev * SG_FEET_TO_METER,
-                                               runways_list,
-                                               beacon_list,
-                                               tower_list,
-                                               windsock_list,
-                                               work_dir, elev_src );
+                                if( is_in_range( runways_list, min_lat, max_lat, min_lon, max_lon ) ) {
+                                    build_airport( last_apt_id,
+                                                   elev * SG_FEET_TO_METER,
+                                                   runways_list,
+                                                   beacon_list,
+                                                   tower_list,
+                                                   windsock_list,
+                                                   work_dir, elev_src );
+                                }
                             }
                         } catch (sg_exception &e) {
                             SG_LOG( SG_GENERAL, SG_ALERT,
@@ -417,12 +420,14 @@ int main( int argc, char **argv ) {
                     // skip building heliports and
                     // seaplane bases
                 } else {
-                    build_airport( last_apt_id, elev * SG_FEET_TO_METER,
-                                   runways_list,
-                                   beacon_list,
-                                   tower_list,
-                                   windsock_list,
-                                   work_dir, elev_src );
+                    if( is_in_range( runways_list, min_lat, max_lat, min_lon, max_lon ) ) {
+                        build_airport( last_apt_id, elev * SG_FEET_TO_METER,
+                                       runways_list,
+                                       beacon_list,
+                                       tower_list,
+                                       windsock_list,
+                                       work_dir, elev_src );
+                    }
                 }
             } catch (sg_exception &e) {
                 SG_LOG( SG_GENERAL, SG_ALERT,
@@ -441,3 +446,32 @@ int main( int argc, char **argv ) {
 
     return 0;
 }
+
+static int is_in_range( string_list & runways_raw, float min_lat, float max_lat, float min_lon, float max_lon )
+{
+    int i;
+    int rwy_count = 0;
+    double apt_lon = 0.0, apt_lat = 0.0;
+
+    for ( i = 0; i < (int)runways_raw.size(); ++i ) {
+        ++rwy_count;
+
+	string rwy_str = runways_raw[i];
+        vector<string> token = simgear::strutils::split( rwy_str );
+
+        apt_lat += atof( token[1].c_str() );
+        apt_lon += atof( token[2].c_str() );
+    }
+
+    if( rwy_count > 0 ) {
+      apt_lat /= rwy_count;
+      apt_lon /= rwy_count;
+    }
+
+    if( apt_lat >= min_lat && apt_lat <= max_lat &&
+        apt_lon >= min_lon && apt_lon <= max_lon ) {
+        return 1;
+    }
+
+    return 0;
+}