Towards better airport surface simplification and smoothing. There were
several bugs in the previous try. These changes should correct them.
This commit is contained in:
parent
c75fa83c15
commit
c8ded2eda1
1 changed files with 150 additions and 36 deletions
|
@ -57,9 +57,9 @@ static void calc_elevations( const string &root, const string_list elev_src,
|
||||||
}
|
}
|
||||||
|
|
||||||
// set all elevations to -9999
|
// set all elevations to -9999
|
||||||
for ( i = 0; i < Pts.rows(); ++i ) {
|
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( j = 0; j < Pts.cols(); ++j ) {
|
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||||
Point3Df p = Pts(i,j);
|
Point3Df p = Pts(j,i);
|
||||||
p.z() = -9999.0;
|
p.z() = -9999.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,9 @@ static void calc_elevations( const string &root, const string_list elev_src,
|
||||||
// find first node with -9999 elevation
|
// find first node with -9999 elevation
|
||||||
Point3Df first;
|
Point3Df first;
|
||||||
bool found_one = false;
|
bool found_one = false;
|
||||||
for ( i = 0; i < Pts.rows(); ++i ) {
|
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( j = 0; j < Pts.cols(); ++j ) {
|
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||||
Point3Df p = Pts(i,j);
|
Point3Df p = Pts(j,i);
|
||||||
if ( p.z() < -9000.0 && !found_one ) {
|
if ( p.z() < -9000.0 && !found_one ) {
|
||||||
first = p;
|
first = p;
|
||||||
found_one = true;
|
found_one = true;
|
||||||
|
@ -107,17 +107,19 @@ static void calc_elevations( const string &root, const string_list elev_src,
|
||||||
// this array file
|
// this array file
|
||||||
double elev;
|
double elev;
|
||||||
done = true;
|
done = true;
|
||||||
for ( i = 0; i < Pts.rows(); ++i ) {
|
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( j = 0; j < Pts.cols(); ++j ) {
|
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||||
Point3Df p = Pts(i,j);
|
Point3Df p = Pts(j,i);
|
||||||
if ( p.z() < -9000.0 ) {
|
if ( p.z() < -9000.0 ) {
|
||||||
done = false;
|
done = false;
|
||||||
elev = array.altitude_from_grid( p.x() * 3600.0,
|
elev = array.altitude_from_grid( p.x() * 3600.0,
|
||||||
p.y() * 3600.0 );
|
p.y() * 3600.0 );
|
||||||
if ( elev > -9000 ) {
|
if ( elev > -9000 ) {
|
||||||
p.z() = elev;
|
p.z() = elev;
|
||||||
Pts(i,j) = p;
|
Pts(j,i) = p;
|
||||||
// cout << "interpolating for " << p << endl;
|
// cout << "interpolating for " << p << endl;
|
||||||
|
// cout << p.x() << " " << p.y() << " " << p.z()
|
||||||
|
// << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,9 +136,9 @@ static void calc_elevations( const string &root, const string_list elev_src,
|
||||||
// find the average height of the queried points
|
// find the average height of the queried points
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for ( i = 0; i < Pts.rows(); ++i ) {
|
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( j = 0; j < Pts.cols(); ++j ) {
|
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||||
Point3Df p = Pts(i,j);
|
Point3Df p = Pts(j,i);
|
||||||
total += p.z();
|
total += p.z();
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -146,17 +148,21 @@ static void calc_elevations( const string &root, const string_list elev_src,
|
||||||
|
|
||||||
// now go through the elevations and clamp them all to within
|
// now go through the elevations and clamp them all to within
|
||||||
// +/-10m (33') of the average.
|
// +/-10m (33') of the average.
|
||||||
const double dz = 10.0;
|
const double dz = 100.0;
|
||||||
for ( i = 0; i < Pts.rows(); ++i ) {
|
for ( i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( j = 0; j < Pts.cols(); ++j ) {
|
for ( j = 0; j < Pts.rows(); ++j ) {
|
||||||
Point3Df p = Pts(i,j);
|
Point3Df p = Pts(j,i);
|
||||||
if ( p.z() < average - dz ) {
|
if ( p.z() < average - dz ) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||||
|
<< " to " << average - dz );
|
||||||
p.z() = average - dz;
|
p.z() = average - dz;
|
||||||
Pts(i,j) = p;
|
Pts(j,i) = p;
|
||||||
}
|
}
|
||||||
if ( p.z() > average + dz ) {
|
if ( p.z() > average + dz ) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||||
|
<< " to " << average + dz );
|
||||||
p.z() = average + dz;
|
p.z() = average + dz;
|
||||||
Pts(i,j) = p;
|
Pts(j,i) = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,10 +207,10 @@ TGAptSurface::TGAptSurface( const string& path,
|
||||||
|
|
||||||
// Build the extra res input grid
|
// Build the extra res input grid
|
||||||
int mult = 10;
|
int mult = 10;
|
||||||
Matrix_Point3Df dPts((xdivs+2) * mult + 1, (ydivs+2) * mult + 1);
|
Matrix_Point3Df dPts( (ydivs+2) * mult + 1, (xdivs+2) * mult + 1 );
|
||||||
for ( int i = 0; i < dPts.rows(); ++i ) {
|
for ( int i = 0; i < dPts.cols(); ++i ) {
|
||||||
for ( int j = 0; j < dPts.cols(); ++j ) {
|
for ( int j = 0; j < dPts.rows(); ++j ) {
|
||||||
dPts(i,j) = Point3Df( min_deg.lon() + (i-mult)*(dlon/(double)mult),
|
dPts(j,i) = Point3Df( min_deg.lon() + (i-mult)*(dlon/(double)mult),
|
||||||
min_deg.lat() + (j-mult)*(dlat/(double)mult),
|
min_deg.lat() + (j-mult)*(dlat/(double)mult),
|
||||||
-9999 );
|
-9999 );
|
||||||
}
|
}
|
||||||
|
@ -214,34 +220,73 @@ TGAptSurface::TGAptSurface( const string& path,
|
||||||
calc_elevations( path, elev_src, dPts );
|
calc_elevations( path, elev_src, dPts );
|
||||||
|
|
||||||
// Build the normal res input grid from the double res version
|
// Build the normal res input grid from the double res version
|
||||||
Matrix_Point3Df Pts(xdivs + 1, ydivs + 1);
|
Matrix_Point3Df Pts(ydivs + 1, xdivs + 1);
|
||||||
for ( int i = 0; i < xdivs + 1; ++i ) {
|
for ( int i = 0; i < Pts.cols(); ++i ) {
|
||||||
for ( int j = 0; j < ydivs + 1; ++j ) {
|
for ( int j = 0; j < Pts.rows(); ++j ) {
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, i << "," << j);
|
SG_LOG(SG_GENERAL, SG_DEBUG, i << "," << j);
|
||||||
double accum = 0.0;
|
double accum = 0.0;
|
||||||
for ( int ii = 0; ii < mult; ++ii ) {
|
for ( int ii = 0; ii < mult; ++ii ) {
|
||||||
for ( int jj = 0; jj < mult; ++jj ) {
|
for ( int jj = 0; jj < mult; ++jj ) {
|
||||||
double value = dPts(mult*(i+1) - (mult/2) + ii,
|
double value = dPts(mult*(j+1) - (mult/2) + jj,
|
||||||
mult*(j+1) - (mult/2) + jj).z();
|
mult*(i+1) - (mult/2) + ii).z();
|
||||||
SG_LOG( SG_GENERAL, SG_DEBUG, "value = " << value );
|
SG_LOG( SG_GENERAL, SG_DEBUG, "value = " << value );
|
||||||
accum += dPts(mult*(i+1) - (mult/2) + ii,
|
accum += dPts(mult*(j+1) - (mult/2) + jj,
|
||||||
mult*(j+1) - (mult/2) + jj).z();
|
mult*(i+1) - (mult/2) + ii).z();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SG_LOG( SG_GENERAL, SG_DEBUG,
|
SG_LOG( SG_GENERAL, SG_DEBUG,
|
||||||
" average = " << accum / (mult*mult) );
|
" average = " << accum / (mult*mult) );
|
||||||
Pts(i,j) = Point3Df( min_deg.lon() + i * dlon,
|
Pts(j,i) = Point3Df( min_deg.lon() + i * dlon,
|
||||||
min_deg.lat() + j * dlat,
|
min_deg.lat() + j * dlat,
|
||||||
accum / (mult*mult) );
|
accum / (mult*mult) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Add some "slope" sanity to the resulting surface grid points
|
||||||
|
for ( i = 0; i < Pts.cols() - 1; ++i ) {
|
||||||
|
for ( j = 0; j < Pts.rows() - 1; ++j ) {
|
||||||
|
Point3Df p = Pts(j,i);
|
||||||
|
Point3Df p1 = Pts(j,i+1);
|
||||||
|
geo_inverse_wgs_84( 0.0,
|
||||||
|
|
||||||
|
if ( p.z() < average - dz ) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||||
|
<< " to " << average - dz );
|
||||||
|
p.z() = average - dz;
|
||||||
|
Pts(j,i) = p;
|
||||||
|
}
|
||||||
|
if ( p.z() > average + dz ) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " clamping " << p.z()
|
||||||
|
<< " to " << average + dz );
|
||||||
|
p.z() = average + dz;
|
||||||
|
Pts(j,i) = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create the nurbs surface
|
// Create the nurbs surface
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "ready to create nurbs surface");
|
SG_LOG(SG_GENERAL, SG_DEBUG, "ready to create nurbs surface");
|
||||||
apt_surf = new PlNurbsSurfacef;
|
apt_surf = new PlNurbsSurfacef;
|
||||||
apt_surf->globalInterp( Pts, 3, 3);
|
apt_surf->globalInterp( Pts, 3, 3);
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, " successful.");
|
SG_LOG(SG_GENERAL, SG_DEBUG, " successful.");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// For debugging only: output an array of surface points suitable
|
||||||
|
// for plotting with gnuplot. This is useful for comparing the
|
||||||
|
// approximated and smoothed surface to the original rough
|
||||||
|
// surface.
|
||||||
|
cout << "DEBUGGING TEST" << endl;
|
||||||
|
for ( int i = 0; i < (xdivs+2) * mult + 1; ++i ) {
|
||||||
|
for ( int j = 0; j < (ydivs+2) * mult + 1; ++j ) {
|
||||||
|
double x = min_deg.lon() + (i-mult)*(dlon/(double)mult);
|
||||||
|
double y = min_deg.lat() + (j-mult)*(dlat/(double)mult);
|
||||||
|
cout << x << " " << y << " " << query(x,y) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,6 +297,8 @@ TGAptSurface::~TGAptSurface() {
|
||||||
|
|
||||||
// Query the elevation of a point, return -9999 if out of range
|
// Query the elevation of a point, return -9999 if out of range
|
||||||
double TGAptSurface::query( double lon_deg, double lat_deg ) {
|
double TGAptSurface::query( double lon_deg, double lat_deg ) {
|
||||||
|
const double eps = 0.00001;
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if ( lon_deg < min_deg.lon() || lon_deg > max_deg.lon() ||
|
if ( lon_deg < min_deg.lon() || lon_deg > max_deg.lon() ||
|
||||||
lat_deg < min_deg.lat() || lat_deg > max_deg.lat() )
|
lat_deg < min_deg.lat() || lat_deg > max_deg.lat() )
|
||||||
|
@ -260,12 +307,79 @@ double TGAptSurface::query( double lon_deg, double lat_deg ) {
|
||||||
return -9999.0;
|
return -9999.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert lon,lat to nurbs space
|
double lat_range = max_deg.lat() - min_deg.lat();
|
||||||
double x = (lon_deg - min_deg.lon()) / (max_deg.lon() - min_deg.lon());
|
double lon_range = max_deg.lon() - min_deg.lon();
|
||||||
double y = (lat_deg - min_deg.lat()) / (max_deg.lat() - min_deg.lat());
|
|
||||||
|
|
||||||
Point3Df p = apt_surf->pointAt( x, y );
|
// convert lon,lat to nurbs space
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, " querying for " << x << ", " << y << " = " << p.z());
|
double u = (lat_deg - min_deg.lat()) / lat_range;
|
||||||
|
double v = (lon_deg - min_deg.lon()) / lon_range;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
Point3Df p;
|
||||||
|
while ( count < 20 ) {
|
||||||
|
if ( u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0 ) {
|
||||||
|
// oops, something goofed in the solver
|
||||||
|
}
|
||||||
|
|
||||||
|
p = apt_surf->pointAt( u, v );
|
||||||
|
// cout << " querying for " << u << ", " << v << " = " << p.z()
|
||||||
|
// << endl;
|
||||||
|
// cout << " found " << p.x() << ", " << p.y() << " = " << p.z()
|
||||||
|
// << endl;
|
||||||
|
double dx = lon_deg - p.x();
|
||||||
|
double dy = lat_deg - p.y();
|
||||||
|
// cout << " dx = " << dx << " dy = " << dy << endl;
|
||||||
|
|
||||||
|
if ( (fabs(dx) < eps) && (fabs(dy) < eps) ) {
|
||||||
|
return p.z();
|
||||||
|
} else {
|
||||||
|
u = u + (dy/lat_range);
|
||||||
|
v = v + (dx/lon_range);
|
||||||
|
if ( u < 0.0 ) { u = 0.0; }
|
||||||
|
if ( u > 1.0 ) { u = 1.0; }
|
||||||
|
if ( v < 0.0 ) { v = 0.0; }
|
||||||
|
if ( v > 1.0 ) { v = 1.0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// failed to converge with fast approach, try a binary paritition
|
||||||
|
// scheme
|
||||||
|
double min_u = 0.0;
|
||||||
|
double max_u = 1.0;
|
||||||
|
double min_v = 0.0;
|
||||||
|
double max_v = 1.0;
|
||||||
|
count = 0;
|
||||||
|
while ( count < 30 ) {
|
||||||
|
u = (max_u + min_u) / 2.0;
|
||||||
|
v = (max_v + min_v) / 2.0;
|
||||||
|
p = apt_surf->pointAt( u, v );
|
||||||
|
// cout << " binary querying for " << u << ", " << v << " = "
|
||||||
|
// << p.z() << endl;
|
||||||
|
// cout << " found " << p.x() << ", " << p.y() << " = " << p.z()
|
||||||
|
// << endl;
|
||||||
|
double dx = lon_deg - p.x();
|
||||||
|
double dy = lat_deg - p.y();
|
||||||
|
// cout << " dx = " << dx << " dy = " << dy << endl;
|
||||||
|
|
||||||
|
if ( (fabs(dx) < eps) && (fabs(dy) < eps) ) {
|
||||||
|
return p.z();
|
||||||
|
} else {
|
||||||
|
if ( dy >= eps ) {
|
||||||
|
min_u = u;
|
||||||
|
} else if ( dy <= eps ) {
|
||||||
|
max_u = u;
|
||||||
|
}
|
||||||
|
if ( dx >= eps ) {
|
||||||
|
min_v = v;
|
||||||
|
} else if ( dx <= eps ) {
|
||||||
|
max_v = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
return p.z();
|
return p.z();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue