1
0
Fork 0

- Chased down a bug that caused threshold lighting to be omitted in some

situations

- Made the code a bit more robust and able to handle the handful of rare
  occasions when the least squares nurbs interpolator fails.

- Add airport surface bases for towers, windsocks, beacons, and vasi/papi
  lighting so they never are buried and never float.  (I'm considering the
  idea of doing this for the approach lighting too ...)
This commit is contained in:
curt 2004-11-11 15:05:13 +00:00
parent 696fa632b4
commit fb71b5876c
6 changed files with 121 additions and 42 deletions

View file

@ -132,8 +132,8 @@ TGAptSurface::TGAptSurface( const string& path,
#elif defined( _NURBS_LEAST_SQUARES )
// Minimum divs appears to need to be at least 5 before the
// leastsquares nurbs surface approximation stops crashing.
if ( xdivs < 5 ) { xdivs = 5; }
if ( ydivs < 5 ) { ydivs = 5; }
if ( xdivs < 6 ) { xdivs = 6; }
if ( ydivs < 6 ) { ydivs = 6; }
#else
# error "Need to define _NURBS_GLOBAL_INTER or _NURBS_LEAST_SQUARES"
#endif
@ -269,8 +269,11 @@ TGAptSurface::TGAptSurface( const string& path,
// sanity check: I'm finding that leastSquares() can produce nan
// surfaces. We test for this and fall back to globalInterp() if
// the least squares fails.
double result = query_solver( (min_deg.lon() + max_deg.lon()) / 2.0,
(min_deg.lat() + max_deg.lat()) / 2.0 );
Point3Dd p = apt_surf->pointAt( 0.5, 0.5 );
if ( p.z() <= 0.0 || p.z() >= 0.0 ) {
if ( (result > -9000.0) && (p.z() <= 0.0 || p.z() >= 0.0) ) {
// ok, a valid number
} else {
// no, sorry, a nan is not <= 0.0 or >= 0.0
@ -278,7 +281,7 @@ TGAptSurface::TGAptSurface( const string& path,
"leastSquares() nurbs interpolation failed!!!");
char command[256];
sprintf( command,
"least squares nurbs interpolation failed, using globalInterp() >> last_apt" );
"echo least squares nurbs interpolation failed, using globalInterp() >> last_apt" );
system( command );
// we could fall back to globalInterp() rather than aborting
@ -454,6 +457,13 @@ double TGAptSurface::query_solver( double lon_deg, double lat_deg ) {
}
u = (max_u + min_u) / 2.0;
if ( count > 100 ) {
// solver failed
cout << "binary solver failed..." << endl;
return -9999.0;
}
++count;
}
@ -487,6 +497,12 @@ double TGAptSurface::query_solver( double lon_deg, double lat_deg ) {
}
v = (max_v + min_v) / 2.0;
if ( count > 100 ) {
// solver failed
cout << "binary solver failed..." << endl;
return -9999.0;
}
++count;
}
@ -500,15 +516,7 @@ double TGAptSurface::query_solver( double lon_deg, double lat_deg ) {
// cout << " final query distance error = " << dist << endl;
return p.z();
}
gcount++;
if ( gcount % 100 == 0 ) {
cout << "query count = " << gcount << " dist = " << dx << ", "
<< dy << endl;
}
}
cout << "binary solver failed..." << endl;
return p.z();
}

View file

@ -603,16 +603,45 @@ void build_airport( string airport_id, float alt_m,
}
}
// write_polygon( accum, "accum" );
if ( apt_base.total_size() == 0 ) {
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");
return;
// Now generate small surface for each beacon
TGPolygon obj_base, obj_safe_base;
double obj_hdg = runways[0].heading;
for ( i = 0; i < (int)beacons.size(); ++i ) {
obj_base = gen_wgs84_area( beacons[i], 20.0, 0.0, 0.0, 20.0,
obj_hdg, alt_m, false );
obj_safe_base = gen_wgs84_area( beacons[i], 40.0, 0.0, 0.0, 40.0,
obj_hdg, alt_m, false );
apt_base = tgPolygonUnion( obj_base, apt_base );
apt_clearing = tgPolygonUnion( obj_safe_base, apt_clearing );
}
// Now generate small surface for each tower
for ( i = 0; i < (int)towers.size(); ++i ) {
obj_base = gen_wgs84_area( towers[i], 20.0, 0.0, 0.0, 20.0,
obj_hdg, alt_m, false );
obj_safe_base = gen_wgs84_area( towers[i], 40.0, 0.0, 0.0, 40.0,
obj_hdg, alt_m, false );
apt_base = tgPolygonUnion( obj_base, apt_base );
apt_clearing = tgPolygonUnion( obj_safe_base, apt_clearing );
}
// Now generate small surface for each windsock
for ( i = 0; i < (int)windsocks.size(); ++i ) {
obj_base = gen_wgs84_area( windsocks[i], 20.0, 0.0, 0.0, 20.0,
obj_hdg, alt_m, false );
obj_safe_base = gen_wgs84_area( windsocks[i], 40.0, 0.0, 0.0, 40.0,
obj_hdg, alt_m, false );
apt_base = tgPolygonUnion( obj_base, apt_base );
apt_clearing = tgPolygonUnion( obj_safe_base, apt_clearing );
}
// 5th pass: generate runway lights
superpoly_list rwy_lights; rwy_lights.clear();
for ( i = 0; i < (int)runways.size(); ++i ) {
gen_runway_lights( runways[i], alt_m, rwy_lights );
gen_runway_lights( runways[i], alt_m, rwy_lights, &apt_base );
}
// 6th pass: generate all taxiway lights
@ -620,11 +649,19 @@ void build_airport( string airport_id, float alt_m,
gen_taxiway_lights( taxiways[i], alt_m, rwy_lights );
}
// write_polygon( accum, "accum" );
// write_polygon( apt_base, "base" );
// write_polygon( apt_clearing, "clear" );
if ( apt_base.total_size() == 0 ) {
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");
return;
}
// generate convex hull (no longer)
// TGPolygon hull = convex_hull(apt_pts);
TGPolygon filled_base = tgPolygonStripHoles( apt_base );
// write_polygon( filled_base, "filled-base" );
// write_polygon( filled_base, "base" );
TGPolygon divided_base = tgPolygonSplitLongEdges( filled_base, 200.0 );
// write_polygon( divided_base, "divided-base" );
TGPolygon base_poly = tgPolygonDiff( divided_base, accum );

View file

@ -681,7 +681,7 @@ static TGSuperPoly gen_touchdown_zone_lights( const TGRunway& rwy_info,
// generate a simple 2 bar VASI for a 3 degree approach
static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
bool recip )
bool recip, TGPolygon *apt_base )
{
point_list lights; lights.clear();
point_list normals; normals.clear();
@ -768,14 +768,21 @@ static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
lights.push_back( pt1 );
normals.push_back( normal );
// grass base
Point3D base_pt = (ref + pt1) / 2.0;
TGPolygon obj_base = gen_wgs84_area( base_pt, 15.0, 0.0, 0.0, 15.0,
length_hdg, alt_m, false );
*apt_base = tgPolygonUnion( obj_base, *apt_base );
// upwind bar
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), length_hdg,
700 * SG_FEET_TO_METER, &lat, &lon, &r );
ref = Point3D( lon, lat, 0.0 );
normal = gen_runway_light_vector( rwy_info, 3.0, recip );
// unit1
pt1 = ref;
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), length_hdg,
700 * SG_FEET_TO_METER, &lat, &lon, &r );
pt1 = Point3D( lon, lat, 0.0 );
lights.push_back( pt1 );
normals.push_back( normal );
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
@ -808,6 +815,12 @@ static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
lights.push_back( pt1 );
normals.push_back( normal );
// grass base
base_pt = (ref + pt1) / 2.0;
obj_base = gen_wgs84_area( base_pt, 15.0, 0.0, 0.0, 15.0,
length_hdg, alt_m, false );
*apt_base = tgPolygonUnion( obj_base, *apt_base );
TGPolygon lights_poly; lights_poly.erase();
TGPolygon normals_poly; normals_poly.erase();
lights_poly.add_contour( lights, false );
@ -826,7 +839,7 @@ static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
// generate a simple PAPI for a 3 degree approach
static TGSuperPoly gen_papi( const TGRunway& rwy_info, float alt_m,
bool recip )
bool recip, TGPolygon *apt_base )
{
point_list lights; lights.clear();
point_list normals; normals.clear();
@ -908,6 +921,12 @@ static TGSuperPoly gen_papi( const TGRunway& rwy_info, float alt_m,
normal = gen_runway_light_vector( rwy_info, 2.5, recip );
normals.push_back( normal );
// grass base
Point3D base_pt = (ref + pt1) / 2.0;
TGPolygon obj_base = gen_wgs84_area( base_pt, 15.0, 0.0, 0.0, 30.0,
length_hdg, alt_m, false );
*apt_base = tgPolygonUnion( obj_base, *apt_base );
TGPolygon lights_poly; lights_poly.erase();
TGPolygon normals_poly; normals_poly.erase();
lights_poly.add_contour( lights, false );
@ -2563,7 +2582,7 @@ static superpoly_list gen_malsx( const TGRunway& rwy_info,
// top level runway light generator
void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
superpoly_list &lights ) {
superpoly_list &lights, TGPolygon *apt_base ) {
string lighting_flags = rwy_info.lighting_flags;
SG_LOG( SG_GENERAL, SG_DEBUG, "gen runway lights " << rwy_info.rwy_no << " "
@ -2632,17 +2651,17 @@ void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
// VASI/PAPI lighting
if ( vasi1 == 2 /* Has VASI */ ) {
TGSuperPoly s = gen_vasi( rwy_info, alt_m, false );
TGSuperPoly s = gen_vasi( rwy_info, alt_m, false, apt_base );
lights.push_back( s );
} else if ( vasi1 == 3 /* Has PAPI */ ) {
TGSuperPoly s = gen_papi( rwy_info, alt_m, false );
TGSuperPoly s = gen_papi( rwy_info, alt_m, false, apt_base );
lights.push_back( s );
}
if ( vasi2 == 2 /* Has VASI */ ) {
TGSuperPoly s = gen_vasi( rwy_info, alt_m, true );
TGSuperPoly s = gen_vasi( rwy_info, alt_m, true, apt_base );
lights.push_back( s );
} else if ( vasi2 == 3 /* Has PAPI */ ) {
TGSuperPoly s = gen_papi( rwy_info, alt_m, true );
TGSuperPoly s = gen_papi( rwy_info, alt_m, true, apt_base );
lights.push_back( s );
}
@ -2853,26 +2872,30 @@ void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
// Many aproach lighting systems define the threshold lighting
// needed, but for those that don't (i.e. REIL, ODALS, or Edge
// lights defined but no approach lights.)
// Make threshold lighting
// lights defined but no approach lights)
// make threshold lighting
cout << "rwylt1 = " << rwylt1 << " app1 = " << app1 << endl;
if ( rwylt1 >= 3 /* Has REIL lighting */
|| app1 == 6 /* ODALS Omni-directional approach light system */
|| ( rwylt1 >= 2 /* Has edge lighting */
&& app1 == 0 /* No approach lighting */ ) )
|| ( rwylt1 >= 2 && app1 <= 1 ) /* Has edge lighting, but no
approach lighting */ )
{
// forward direction
cout << "threshold lights for forward direction" << endl;
superpoly_list s = gen_runway_threshold_lights( rwy_info, rwylt1,
alt_m, false );
for ( i = 0; i < s.size(); ++i ) {
lights.push_back( s[i] );
}
}
cout << "rwylt2 = " << rwylt2 << " app2 = " << app2 << endl;
if ( rwylt2 >= 3 /* Has REIL lighting */
|| app2 == 6 /* ODALS Omni-directional approach light system */
|| ( rwylt2 >= 2 /* Has edge lighting */
&& app2 == 0 /* No approach lighting */ ) )
|| ( rwylt2 >= 2 && app2 <= 1 ) /* Has edge lighting, but no
approach lighting */ )
{
// reverse direction
cout << "threshold lights for reverse direction" << endl;
superpoly_list s = gen_runway_threshold_lights( rwy_info, rwylt1,
alt_m, true );
for ( i = 0; i < s.size(); ++i ) {

View file

@ -35,7 +35,7 @@
// generate runway lighting
void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
superpoly_list &lights );
superpoly_list &lights, TGPolygon *apt_base );
// generate taxiway lighting
void gen_taxiway_lights( const TGRunway& taxiway_info, float alt_m,

View file

@ -37,7 +37,7 @@
// given a runway center point, length, width, and heading, and
// altitude (meters) generate the lon and lat 4 corners using wgs84
// math.
static TGPolygon gen_wgs84_area( Point3D origin,
TGPolygon gen_wgs84_area( Point3D origin,
double length_m,
double displ1, double displ2,
double width_m,

View file

@ -71,6 +71,17 @@ typedef runway_list::iterator runway_list_iterator;
typedef runway_list::const_iterator const_runway_list_iterator;
// given a runway center point, length, width, and heading, and
// altitude (meters) generate the lon and lat 4 corners using wgs84
// math.
TGPolygon gen_wgs84_area( Point3D origin,
double length_m,
double displ1, double displ2,
double width_m,
double heading_deg,
double alt_m,
bool add_mid );
// generate an area for a runway with expantion specified as a scale
// factor (return result points in degrees)
TGPolygon gen_runway_area_w_scale( const TGRunway& runway,