From 16ff1e89cc6aec3fa0fcf8f8a5d722f8c91964f4 Mon Sep 17 00:00:00 2001 From: Christian Schmitt Date: Fri, 14 Oct 2011 17:50:56 +0200 Subject: [PATCH] Add runway shoulders support. This was harder than expected as the shoulders were often partially covered by runway polygons. This was caused by inaccuracies introduced by the calculation of dimensions from the runway center. Now we create shoulders if set in apt.dat. If no shoulders are set, a 1m broad stripe is added to concrete and asphalt runways to make the blending runway-airport surface more visually appealing. --- src/Airports/GenAirports850/airport.cxx | 9 +++ src/Airports/GenAirports850/runway.hxx | 12 +++- src/Airports/GenAirports850/rwy_gen.cxx | 76 +++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx index d4d779bf..3853479c 100644 --- a/src/Airports/GenAirports850/airport.cxx +++ b/src/Airports/GenAirports850/airport.cxx @@ -438,6 +438,15 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) SG_LOG(SG_GENERAL, SG_DEBUG, "no pavements"); } + // Build runway shoulders here + for (i=0; iGetsShoulder() ) + { + runways[i]->BuildShoulder( altitude, &rwy_polys, &rwy_tps, &accum ); + } + } + // build the base and clearing if there's a boundary if (boundary) { diff --git a/src/Airports/GenAirports850/runway.hxx b/src/Airports/GenAirports850/runway.hxx index 309d338d..77688c59 100644 --- a/src/Airports/GenAirports850/runway.hxx +++ b/src/Airports/GenAirports850/runway.hxx @@ -39,7 +39,18 @@ public: return ( Point3D( (rwy.lon[0]+rwy.lon[1])/2.0f, (rwy.lat[0]+rwy.lat[1])/2.0f, 0.0f) ); } + bool GetsShoulder() + { + if (rwy.surface < 3 || rwy.shoulder > 0) + return true; + else return false; + } + int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, ClipPolyType* accum, TGPolygon* apt_base, TGPolygon* apt_clearing ); + void BuildShoulder( float alt_m, + superpoly_list *rwy_polys, + texparams_list *texparams, + ClipPolyType *accum ); private: struct TGRunway { @@ -84,7 +95,6 @@ private: return ( gen_wgs84_area( Point3D(GetStart()), Point3D(GetEnd()), rwy.length + 2.0*length_extend, displ1, displ2, rwy.width + 2.0*width_extend, rwy.heading, alt_m, false) ); } - void gen_rw_designation( const std::string& material, TGPolygon poly, double heading, string rwname, double &start_pct, double &end_pct, diff --git a/src/Airports/GenAirports850/rwy_gen.cxx b/src/Airports/GenAirports850/rwy_gen.cxx index f47a6f42..5de61b73 100644 --- a/src/Airports/GenAirports850/rwy_gen.cxx +++ b/src/Airports/GenAirports850/rwy_gen.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include "runway.hxx" #include @@ -332,3 +333,78 @@ for ( int rwhalf=0; rwhalf<2; ++rwhalf ){ } } + +void Runway::BuildShoulder( float alt_m, + superpoly_list *rwy_polys, + texparams_list *texparams, + ClipPolyType *accum ) +{ + string shoulder_surface = ""; + double shoulder_width; + if (rwy.shoulder > 0){ // Add a shoulder to the runway + shoulder_width = rwy.width * 0.15; + if (shoulder_width > 8.0){ + shoulder_width = 8.0; + } + if (rwy.shoulder == 1){ + shoulder_surface = "pa_shoulder"; + } else if (rwy.shoulder == 2){ + shoulder_surface = "pc_shoulder"; + } else SG_LOG(SG_GENERAL, SG_ALERT, "Unknown shoulder surface code = " << rwy.shoulder ); + + } else if (rwy.shoulder == 0){ // We add a fake shoulder if the runway has an asphalt or concrete surface + shoulder_width = 1; + if (rwy.surface == 1){ + shoulder_surface = "pa_shoulder_f"; + } else if (rwy.surface == 2){ + shoulder_surface = "pc_shoulder_f"; + } + } + SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder width = " << shoulder_width ); + SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder surface is: " << shoulder_surface ); + + double lat, lon,r; + // Create both shoulder sides + for (int i=0; i<2; ++i){ + double step; + double lat, lon,r; + + if (i == 0){ + step= (rwy.width + shoulder_width)*0.5; + } else if (i == 1) { + step= -(rwy.width + shoulder_width)*0.5; + } + double left_hdg = rwy.heading - 90.0; + if ( left_hdg < 0 ) { left_hdg += 360.0; } + + geo_direct_wgs_84 ( alt_m, rwy.lat[0], rwy.lon[0], left_hdg, + step, &lat, &lon, &r ); + + Point3D shoulder1 = Point3D( lon, lat, 0.0f ); + + geo_direct_wgs_84 ( alt_m, rwy.lat[1], rwy.lon[1], left_hdg, + step, &lat, &lon, &r ); + + Point3D shoulder2 = Point3D( lon, lat, 0.0f ); + + TGPolygon shoulder = gen_wgs84_area( shoulder1, shoulder2, 0.0, 0.0, 0.0, shoulder_width, rwy.heading, alt_m, false); + + TGSuperPoly sp; + TGTexParams tp; + TGPolygon clipped = tgPolygonDiff( shoulder, *accum ); + TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 ); + + sp.erase(); + sp.set_poly( split ); + sp.set_material( shoulder_surface ); + rwy_polys->push_back( sp ); + + *accum = tgPolygonUnion( shoulder, *accum ); + tp = TGTexParams( shoulder.get_pt(0,0), shoulder_width , rwy.length + 2, rwy.heading ); + if (i == 1){ + tp.set_maxu(0); + tp.set_minu(1); + } + texparams->push_back( tp ); + } +}