From 79d86a25ac647985a127d8b44674c4413b8e0e2b Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Wed, 20 Sep 2000 21:44:59 +0000
Subject: [PATCH] Many changes to support airport modeling approach.

---
 src/Airports/GenAirports/Makefile.am |   8 +-
 src/Airports/GenAirports/build.cxx   | 196 +++++++++++++++++++++------
 src/Airports/GenAirports/process.pl  |   6 +-
 3 files changed, 162 insertions(+), 48 deletions(-)

diff --git a/src/Airports/GenAirports/Makefile.am b/src/Airports/GenAirports/Makefile.am
index 4013c234..1c6330a9 100644
--- a/src/Airports/GenAirports/Makefile.am
+++ b/src/Airports/GenAirports/Makefile.am
@@ -44,7 +44,7 @@ genapts_LDADD = \
 	$(base_LIBS)
 
 INCLUDES += \
-	-I$(top_builddir) \
-	-I$(top_builddir)/src \
-	-I$(top_builddir)/src/Lib \
-	-I$(top_builddir)/src/Construct
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/Lib \
+	-I$(top_srcdir)/src/Construct
diff --git a/src/Airports/GenAirports/build.cxx b/src/Airports/GenAirports/build.cxx
index 39bcfcff..d0c58074 100644
--- a/src/Airports/GenAirports/build.cxx
+++ b/src/Airports/GenAirports/build.cxx
@@ -155,18 +155,13 @@ static FGPolygon rwy_section_tex_coords( const FGPolygon& in_poly,
 }
 
 
-// Divide segment if there are other existing points on it, return the
-// new polygon
-void add_intermediate_nodes( int contour, const Point3D& start, 
-			     const Point3D& end, const FGTriNodes& tmp_nodes,
-			     FGPolygon *result )
+// Find a point in the given node list that lies between start and
+// end, return true if something found, false if nothing found.
+bool find_intermediate_node( const Point3D& start, const Point3D& end,
+			     const point_list& nodes, Point3D *result )
 {
-    bool found_extra = false;
-    int extra_index = 0;
-    int counter;
+    bool found_node = false;
     double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min;
-    const_point_list_iterator current, last;
-    point_list nodes = tmp_nodes.get_node_list();
 
     Point3D p0 = start;
     Point3D p1 = end;
@@ -199,33 +194,30 @@ void add_intermediate_nodes( int contour, const Point3D& start,
 
 	// cout << "m = " << m << " b = " << b << endl;
 
-	current = nodes.begin();
-	last = nodes.end();
-	counter = 0;
-	for ( ; current != last; ++current ) {
-	    // cout << counter << endl;
+	for ( int i = 0; i < (int)nodes.size(); ++i ) {
+	    // cout << i << endl;
+	    Point3D current = nodes[i];
 
-	    if ( (current->x() > (p_min.x() + FG_EPSILON)) 
-		 && (current->x() < (p_max.x() - FG_EPSILON)) ) {
+	    if ( (current.x() > (p_min.x() + FG_EPSILON)) 
+		 && (current.x() < (p_max.x() - FG_EPSILON)) ) {
 
 		// printf( "found a potential candidate %.7f %.7f %.7f\n",
-		//         current->x(), current->y(), current->z() );
+		//         current.x(), current.y(), current.z() );
 
-		y_err = fabs(current->y() - (m * current->x() + b));
+		y_err = fabs(current.y() - (m * current.x() + b));
 		// cout << "y_err = " << y_err << endl;
 
 		if ( y_err < tgAirportEpsilon ) {
 		    // cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
-		    // cout << p_min << " < " << *current << " < "
+		    // cout << p_min << " < " << current << " < "
 		    //      << p_max << endl;
-		    found_extra = true;
+		    found_node = true;
 		    if ( y_err < y_err_min ) {
-			extra_index = counter;
+			*result = current;
 			y_err_min = y_err;
 		    }
 		}
 	    }
-	    ++counter;
 	}
     } else {
 	// cout << "use x = m1 * y + b1" << endl;
@@ -251,17 +243,16 @@ void add_intermediate_nodes( int contour, const Point3D& start,
 	// cout << "  should = 0 = "
 	//      << fabs(p_max.x() - (m1 * p_max.y() + b1)) << endl;
 
-	current = nodes.begin();
-	last = nodes.end();
-	counter = 0;
-	for ( ; current != last; ++current ) {
-	    if ( (current->y() > (p_min.y() + FG_EPSILON)) 
-		 && (current->y() < (p_max.y() - FG_EPSILON)) ) {
+	for ( int i = 0; i < (int)nodes.size(); ++i ) {
+	    Point3D current = nodes[i];
+
+	    if ( (current.y() > (p_min.y() + FG_EPSILON)) 
+		 && (current.y() < (p_max.y() - FG_EPSILON)) ) {
 		
 		// printf( "found a potential candidate %.7f %.7f %.7f\n",
-		//         current->x(), current->y(), current->z() );
+		//         current.x(), current.y(), current.z() );
 
-		x_err = fabs(current->x() - (m1 * current->y() + b1));
+		x_err = fabs(current.x() - (m1 * current.y() + b1));
 		// cout << "x_err = " << x_err << endl;
 
 		// if ( temp ) {
@@ -270,29 +261,117 @@ void add_intermediate_nodes( int contour, const Point3D& start,
 
 		if ( x_err < tgAirportEpsilon ) {
 		    // cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
-		    // cout << p_min << " < " << *current << " < "
+		    // cout << p_min << " < " << current << " < "
 		    //      << p_max << endl;
-		    found_extra = true;
+		    found_node = true;
 		    if ( x_err < x_err_min ) {
-			extra_index = counter;
+			*result = current;
 			x_err_min = x_err;
 		    }
 		}
 	    }
-	    ++counter;
 	}
     }
 
+    return found_node;
+}
+
+
+// Attempt to reduce degeneracies where a subsequent point of a
+// polygon lies *on* a previous line segment.  These artifacts are
+// occasionally introduced by the gpc polygon clipper.
+static point_list reduce_contour_degeneracy( const point_list& contour ) {
+    point_list result = contour;
+
+    Point3D p0, p1, bad_node;
+    bool done = false;
+
+    while ( !done ) {
+	// traverse the contour until we find the first bad node or
+	// hit the end of the contour
+	cout << "   ... not done ... " << endl;
+	bool bad = false;
+
+	int i = 0;
+	while ( i < (int)result.size() - 1 && !bad ) {
+	    p0 = result[i];
+	    p1 = result[i+1];
+	
+	    bad = find_intermediate_node( p0, p1, result, &bad_node );
+	    ++i;
+	}
+	if ( !bad ) {
+	    // do the end/start connecting segment
+	    p0 = result[result.size() - 1];
+	    p1 = result[0];
+
+	    bad = find_intermediate_node( p0, p1, result, &bad_node );
+	}
+
+	if ( bad ) {
+	    // remove bad node from contour
+	    point_list tmp; tmp.clear();
+	    for ( int j = 0; j < (int)result.size(); ++j ) {
+		if ( result[j] == bad_node ) {
+		    // skip
+		} else {
+		    tmp.push_back( result[j] );
+		}
+	    }
+	    result = tmp;
+	} else { 
+	    done = true;
+	}
+    }
+
+    return result;
+}
+
+// Search each segment of each contour for degenerate points (i.e. out
+// of order points that lie coincident on other segments
+
+static FGPolygon reduce_degeneracy( const FGPolygon& poly ) {
+    FGPolygon result;
+
+    for ( int i = 0; i < poly.contours(); ++i ) {
+	point_list contour = poly.get_contour(i);
+	contour = reduce_contour_degeneracy( contour );
+	result.add_contour( contour, poly.get_hole_flag(i) );
+
+	// maintain original hole flag setting
+	// result.set_hole_flag( i, poly.get_hole_flag( i ) );
+    }
+
+    return result;
+}
+
+
+// Divide segment if there are other existing points on it, return the
+// new polygon
+void add_intermediate_nodes( int contour, const Point3D& start, 
+			     const Point3D& end, const FGTriNodes& tmp_nodes,
+			     FGPolygon *result )
+{
+    point_list nodes = tmp_nodes.get_node_list();
+
+    // cout << "  add_intermediate_nodes()" << endl;
+    printf("   %.7f %.7f %.7f <=> %.7f %.7f %.7f\n",
+	   start.x(), start.y(), start.z(), end.x(), end.y(), end.z() );
+
+    
+    Point3D new_pt;
+    bool found_extra = find_intermediate_node( start, end, nodes, &new_pt );
+
     if ( found_extra ) {
 	// recurse with two sub segments
 	// cout << "dividing " << p0 << " " << nodes[extra_index]
 	//      << " " << p1 << endl;
-	add_intermediate_nodes( contour, p0, nodes[extra_index], tmp_nodes, 
+	add_intermediate_nodes( contour, start, new_pt, tmp_nodes, 
 				result );
 
-	result->add_node( contour, nodes[extra_index] );
+	result->add_node( contour, new_pt );
 
-	add_intermediate_nodes( contour, nodes[extra_index], p1, tmp_nodes,
+	add_intermediate_nodes( contour, new_pt, end, tmp_nodes,
 				result );
     } else {
 	// this segment does not need to be divided
@@ -689,14 +768,19 @@ static void gen_runway_section( const FGRunway& rwy_info,
 	endl_pct = 1.0;
     }
 
+    if ( startl_pct > 0.0 ) {
+	startl_pct -= nudge * FG_EPSILON;
+    }
+    if ( endl_pct < 1.0 ) {
+	endl_pct += nudge * FG_EPSILON;
+    }
+
     // partial "w" percentages could introduce "T" intersections which
     // we compensate for later, but could still cause problems now
     // with our polygon clipping code.  This attempts to compensate
     // for that by nudging the areas a bit bigger so we don't end up
     // with polygon slivers.
     if ( startw_pct > 0.0 || endw_pct < 1.0 ) {
-	startl_pct -= nudge * FG_EPSILON;
-	endl_pct += nudge * FG_EPSILON;
 	if ( startw_pct > 0.0 ) {
 	    startw_pct -= nudge * FG_EPSILON;
 	}
@@ -888,6 +972,7 @@ static void gen_precision_rwy( const FGRunway& rwy_info,
     runway_a.add_node( 0, runway.get_pt(0, 2) );
     runway_a.add_node( 0, runway.get_pt(0, 5) );
 
+
     // runway half "b"
     FGPolygon runway_b;
     runway_b.erase();
@@ -1915,8 +2000,37 @@ void build_airport( string airport_raw, string_list& runways_raw,
 	     << " " << rwy_polys[k].get_material() << endl;
 	FGPolygon poly = rwy_polys[k].get_poly();
 	cout << "total size before = " << poly.total_size() << endl;
+	for ( int i = 0; i < poly.contours(); ++i ) {
+	    for ( int j = 0; j < poly.contour_size(i); ++j ) {
+		Point3D tmp = poly.get_pt(i, j);
+		printf("  %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() );
+	    }
+	}
+
+	poly = remove_dups( poly );
+	cout << "total size after remove_dups() = "
+	     << poly.total_size() << endl;
+
+	for ( int i = 0; i < poly.contours(); ++i ) {
+	    for ( int j = 0; j < poly.contour_size(i); ++j ) {
+		Point3D tmp = poly.get_pt(i, j);
+		printf("    %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() );
+	    }
+	}
+
+	poly = reduce_degeneracy( poly );
+	cout << "total size after reduce_degeneracy() = "
+	     << poly.total_size() << endl;
+
+	for ( int i = 0; i < poly.contours(); ++i ) {
+	    for ( int j = 0; j < poly.contour_size(i); ++j ) {
+		Point3D tmp = poly.get_pt(i, j);
+		printf("    %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() );
+	    }
+	}
+
 	poly = add_nodes_to_poly( poly, tmp_nodes );
-	cout << "total size after = " << poly.total_size() << endl;
+	cout << "total size after add nodes = " << poly.total_size() << endl;
 
 #if 0
 	char tmp[256];
diff --git a/src/Airports/GenAirports/process.pl b/src/Airports/GenAirports/process.pl
index 508fcd39..713f1893 100755
--- a/src/Airports/GenAirports/process.pl
+++ b/src/Airports/GenAirports/process.pl
@@ -23,10 +23,10 @@
 
 # Edit the following values to set up your preferences:
 
-$workdir = "/fgfs01/curt/Work";
+$workdir = "/stage/fgfs01/curt/Work";
 $inputfile = "./default.apt";
 $binary = "./genapts";
-$startid = "BNF";
+$startid = "EGLL";
 
 # end of user configurable section
 
@@ -38,7 +38,7 @@ while ( ! $done ) {
 
     # update the nudge value
     $nudge += 5;
-    if ( $nudge > 25 ) {
+    if ( $nudge > 40 ) {
 	$nudge = 5;
     }