diff --git a/src/Airports/GenAirports/apt_surface.cxx b/src/Airports/GenAirports/apt_surface.cxx index 086b1547..442cbfff 100644 --- a/src/Airports/GenAirports/apt_surface.cxx +++ b/src/Airports/GenAirports/apt_surface.cxx @@ -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(); } diff --git a/src/Airports/GenAirports/build.cxx b/src/Airports/GenAirports/build.cxx index 9ff354dd..fef21c1a 100644 --- a/src/Airports/GenAirports/build.cxx +++ b/src/Airports/GenAirports/build.cxx @@ -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 ); diff --git a/src/Airports/GenAirports/lights.cxx b/src/Airports/GenAirports/lights.cxx index 42d6ea47..1ca36a15 100644 --- a/src/Airports/GenAirports/lights.cxx +++ b/src/Airports/GenAirports/lights.cxx @@ -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 ) { diff --git a/src/Airports/GenAirports/lights.hxx b/src/Airports/GenAirports/lights.hxx index 373a1e88..56617cdd 100644 --- a/src/Airports/GenAirports/lights.hxx +++ b/src/Airports/GenAirports/lights.hxx @@ -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, diff --git a/src/Airports/GenAirports/runway.cxx b/src/Airports/GenAirports/runway.cxx index 64c557f2..b4a87e63 100644 --- a/src/Airports/GenAirports/runway.cxx +++ b/src/Airports/GenAirports/runway.cxx @@ -37,13 +37,13 @@ // 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, - double length_m, - double displ1, double displ2, - double width_m, - double heading_deg, - double alt_m, - bool add_mid ) +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 ) { TGPolygon result_list; double length_hdg = heading_deg; diff --git a/src/Airports/GenAirports/runway.hxx b/src/Airports/GenAirports/runway.hxx index 011e46a7..9bfc15ad 100644 --- a/src/Airports/GenAirports/runway.hxx +++ b/src/Airports/GenAirports/runway.hxx @@ -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,