From ff352fad286e052a0f543ffc545118c705f0f70b Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Sun, 5 Feb 2012 10:13:15 -0500 Subject: [PATCH] remove_dups() cleanup function would miss 2D dups with different elevations. - created a new function that will take the higher elevated dup (as most are ar -9999.0 at initialization. Use the one with real elevation data) Fixes UMNB --- src/Airports/GenAirports850/airport.cxx | 14 ++- src/Lib/Geometry/point3d.hxx | 16 ++++ src/Lib/Geometry/poly_support.cxx | 121 +++++++++++++++++++++++- 3 files changed, 149 insertions(+), 2 deletions(-) diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx index a826006e..01ee99fa 100644 --- a/src/Airports/GenAirports850/airport.cxx +++ b/src/Airports/GenAirports850/airport.cxx @@ -669,6 +669,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) poly = remove_bad_contours( poly ); poly = remove_tiny_contours( poly ); poly = remove_spikes( poly ); + poly = remove_dups( poly ); poly = remove_bad_contours( poly ); rwy_polys[k].set_poly( poly ); @@ -685,6 +686,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) poly = remove_bad_contours( poly ); poly = remove_tiny_contours( poly ); poly = remove_spikes( poly ); + poly = remove_dups( poly ); poly = remove_bad_contours( poly ); pvmt_polys[k].set_poly( poly ); @@ -701,6 +703,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) poly = remove_bad_contours( poly ); poly = remove_tiny_contours( poly ); poly = remove_spikes( poly ); + poly = remove_dups( poly ); poly = remove_bad_contours( poly ); line_polys[k].set_poly( poly ); @@ -722,6 +725,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) base_poly = remove_bad_contours( base_poly ); base_poly = remove_tiny_contours( base_poly ); base_poly = remove_spikes( base_poly ); + base_poly = remove_dups( base_poly ); base_poly = remove_bad_contours( base_poly ); gettimeofday(&cleanup_end, NULL); @@ -737,7 +741,15 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) TGPolygon poly = rwy_polys[i].get_poly(); #if 0 - if ( i == 162 ) { + if ( i == 2 ) { + SG_LOG(SG_GENERAL, SG_INFO, "Problem poly before remove_dups: " << poly ); + + sglog().setLogLevels( SG_GENERAL, SG_BULK ); + poly = remove_dups( poly ); + sglog().setLogLevels( SG_GENERAL, SG_INFO ); + + SG_LOG(SG_GENERAL, SG_INFO, "Problem poly after remove_dups(): " << poly ); + tgChopNormalPolygon( "/home/pete", "Base", poly, false ); verbose_triangulation = true; diff --git a/src/Lib/Geometry/point3d.hxx b/src/Lib/Geometry/point3d.hxx index 6a654475..b7b29227 100644 --- a/src/Lib/Geometry/point3d.hxx +++ b/src/Lib/Geometry/point3d.hxx @@ -132,6 +132,9 @@ public: // Special functions double distance3D(const Point3D& a) const; // distance between double distance3Dsquared(const Point3D& a) const; // distance between ^ 2 + + bool IsEqual2D(const Point3D& a) const; // equality check in X,Y only + bool HasElevation() const; // does point have elevation data? }; @@ -377,6 +380,19 @@ inline SGVec2f Point3D::toSGVec2f(void) const return SGVec2f(x(), y()); } +inline bool Point3D::IsEqual2D(const Point3D& a) const +{ + return + fabs(a.n[PX] - n[PX]) < fgPoint3_Epsilon && + fabs(a.n[PY] - n[PY]) < fgPoint3_Epsilon; +} + +inline bool Point3D::HasElevation() const +{ + return fabs( n[PZ] + 9999.0 > fgPoint3_Epsilon ); +} + + // FRIENDS inline Point3D operator - (const Point3D& a) diff --git a/src/Lib/Geometry/poly_support.cxx b/src/Lib/Geometry/poly_support.cxx index 586e347a..faac9b92 100644 --- a/src/Lib/Geometry/poly_support.cxx +++ b/src/Lib/Geometry/poly_support.cxx @@ -761,7 +761,7 @@ void calc_points_inside( TGPolygon& p ) { delete ct; } - +#if 0 // remove duplicate nodes in a polygon should they exist. Returns the // fixed polygon TGPolygon remove_dups( const TGPolygon &poly ) { @@ -808,7 +808,124 @@ TGPolygon remove_dups( const TGPolygon &poly ) { return result; } +#endif +static point_list remove_contour_dups( const point_list& contour ) { + point_list result; + result.clear(); + + int iters = 0; + bool found; + unsigned int cur, next; + + for ( unsigned int i = 0; i < contour.size(); i++ ) + { + result.push_back( contour[i] ); + } + + SG_LOG(SG_GENERAL, SG_DEBUG, "remove contour dups : original contour has " << result.size() << " points" ); + + do + { + SG_LOG(SG_GENERAL, SG_DEBUG, "remove_contour_dups: start new iteration"); + found = false; + + // Step 1 - find a neighboring duplicate point + for ( unsigned int i = 0; i < result.size() && !found; i++ ) { + if (i == result.size()-1 ) { + cur = i; + next = 0; + SG_LOG(SG_GENERAL, SG_DEBUG, " cur is last point: " << cur << ": " << result[cur] << " next is first point: " << next << result[next] ); + } else { + cur = i; + next = i+1; + SG_LOG(SG_GENERAL, SG_DEBUG, " cur is: " << cur << ": " << result[cur] << " next is : " << next << result[next] ); + } + + if ( result[cur].IsEqual2D( result[next] ) ) { + // keep the point with higher Z + if ( result[cur].z() < result[next].z() ) { + SG_LOG(SG_GENERAL, SG_DEBUG, "remove_contour_dups: erasing " << result[cur] ); + result.erase( result.begin()+cur ); + } else { + SG_LOG(SG_GENERAL, SG_DEBUG, "remove_contour_dups: erasing " << result[next] ); + result.erase( result.begin()+next ); + } + found = true; + } + } + + iters++; + SG_LOG(SG_GENERAL, SG_DEBUG, "remove_contour_dups : after " << iters << "iterations, contour has " << result.size() << " points" ); + } while( found ); + + return result; +} + +TGPolygon remove_dups( const TGPolygon& poly ) +{ + TGPolygon result; + // cout << "remove dups: " << poly << endl; + for ( int i = 0; i < poly.contours(); ++i ) { + point_list contour = poly.get_contour(i); + contour = remove_contour_dups( contour ); + result.add_contour( contour, poly.get_hole_flag(i) ); + } + + return result; +} + + + + +#if 0 // fails to remove dupes with different Z +// remove duplicate nodes in a polygon should they exist. Returns the +// fixed polygon +TGPolygon remove_dups( const TGPolygon &poly ) { + TGPolygon result; + point_list contour, new_contour; + result.erase(); + + TGPolygon tmp = poly; + for ( int i = 0; i < tmp.contours(); ++i ) { + contour = poly.get_contour( i ); + // cout << "testing contour " << i << " size = " << contour.size() + // << " hole = " << poly.get_hole_flag( i ) << endl; + bool have_dups = true; + while ( have_dups && contour.size() ) { + have_dups = false; + new_contour.clear(); + Point3D last = contour[ contour.size() - 1 ]; + for ( int j = 0; j < (int)contour.size(); ++j ) { + // cout << " " << i << " " << j << endl; + Point3D cur = contour[j]; + if ( cur == last ) { + have_dups = true; + // cout << "skipping a duplicate point" << endl; + } else { + new_contour.push_back( cur ); + last = cur; + } + } + contour = new_contour; + } + + // cout << " final size = " << contour.size() << endl; + + if ( contour.size() ) { + int flag = poly.get_hole_flag( i ); + result.add_contour( contour, flag ); + } else { + // too small an area ... add a token point to the contour + // to keep other things happy, but this "bad" contour will + // get nuked later + result.add_node( i, poly.get_pt( i, 0 ) ); + } + } + + return result; +} +#endif static inline double snap (double value, double grid_size) @@ -1258,6 +1375,8 @@ static point_list remove_contour_spikes( const point_list& contour ) { result.push_back( contour[i] ); } + SG_LOG(SG_GENERAL, SG_DEBUG, "remove contour spikes : original contour has " << result.size() << " points" ); + do { SG_LOG(SG_GENERAL, SG_DEBUG, "remove_contour_spikes: start new iteration");