From 3ba27cd481ad767906849f923b8216b8b8d410ed Mon Sep 17 00:00:00 2001 From: PSadrozinski Date: Sat, 8 Oct 2011 09:46:23 -0400 Subject: [PATCH] Added Airport boundary support. - needs testing on lots of airports. I'm uncomfortable with expanding concave polys by 20 meters. I really need to find a safe polygon expander. --- src/Airports/GenAirports850/airport.cxx | 39 +++- src/Airports/GenAirports850/airport.hxx | 6 + src/Airports/GenAirports850/closedpoly.cxx | 223 ++++++++++++--------- src/Airports/GenAirports850/closedpoly.hxx | 8 + src/Airports/GenAirports850/helipad.cxx | 19 +- src/Airports/GenAirports850/lights.cxx | 2 +- src/Airports/GenAirports850/parser.cxx | 52 ++++- src/Airports/GenAirports850/parser.hxx | 18 +- src/Airports/GenAirports850/runway.cxx | 23 ++- src/Airports/GenAirports850/runway.hxx | 2 +- 10 files changed, 267 insertions(+), 125 deletions(-) diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx index 9b72e682..31b370c9 100644 --- a/src/Airports/GenAirports850/airport.cxx +++ b/src/Airports/GenAirports850/airport.cxx @@ -35,14 +35,12 @@ Airport::Airport( int c, char* def) code = c; - SG_LOG(SG_GENERAL, SG_DEBUG, "sscanf " << def); numParams = sscanf(def, "%d %d %d %s %ls", &altitude, &x, &y, tmp, d); - SG_LOG(SG_GENERAL, SG_DEBUG, "done "); - SG_LOG(SG_GENERAL, SG_DEBUG, "got " << altitude << ", " << tmp << ", " << d); altitude *= SG_FEET_TO_METER; icao = tmp; description = d; + boundary = NULL; } // TODO: fix OSG - it was nice, but unnecesary... @@ -380,7 +378,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) { if ( runways[i]->IsPrecision() ) { - runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing ); + if (boundary) + { + runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, NULL, NULL ); + } + else + { + runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing ); + } } } @@ -397,7 +402,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) { for (i=0; iBuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing ); + if (boundary) + { + helipads[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, NULL, NULL ); + } + else + { + helipads[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing ); + } } } // Build the pavements @@ -406,8 +418,15 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) for ( i=0; iGetDescription()); - pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, &apt_base, &apt_clearing ); - // AddFeatures( pavements[i]->GetMarkings() ); + + if (boundary) + { + pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, NULL, NULL ); + } + else + { + pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, &apt_base, &apt_clearing ); + } } } else @@ -415,6 +434,12 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) SG_LOG(SG_GENERAL, SG_ALERT, "no pavements"); } + // build the base and clearing if there's a boundary + if (boundary) + { + boundary->BuildBtg( altitude, &apt_base, &apt_clearing ); + } + if ( apt_base.total_size() == 0 ) { SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated"); diff --git a/src/Airports/GenAirports850/airport.hxx b/src/Airports/GenAirports850/airport.hxx index dc3ec359..86371b09 100644 --- a/src/Airports/GenAirports850/airport.hxx +++ b/src/Airports/GenAirports850/airport.hxx @@ -57,6 +57,11 @@ public: } } + void SetBoundary( ClosedPoly* bndry ) + { + boundary = bndry; + } + void AddWindsock( Windsock* windsock ) { windsocks.push_back( windsock ); @@ -90,6 +95,7 @@ private: BeaconList beacons; SignList signs; HelipadList helipads; + ClosedPoly* boundary; }; typedef std::vector AirportList; diff --git a/src/Airports/GenAirports850/closedpoly.cxx b/src/Airports/GenAirports850/closedpoly.cxx index d3249602..da895200 100644 --- a/src/Airports/GenAirports850/closedpoly.cxx +++ b/src/Airports/GenAirports850/closedpoly.cxx @@ -14,12 +14,31 @@ #include "convex_hull.hxx" #include "closedpoly.hxx" +ClosedPoly::ClosedPoly( char* desc ) +{ + is_pavement = false; + + if ( desc ) + { + description = desc; + } + else + { + description = "none"; + } + + boundary = NULL; + cur_contour = NULL; + cur_feature = NULL; +} ClosedPoly::ClosedPoly( int st, float s, float th, char* desc ) { surface_type = st; smoothness = s; texture_heading = th; + is_pavement = true; + if ( desc ) { description = desc; @@ -43,31 +62,28 @@ void ClosedPoly::AddNode( BezNode* node ) } cur_contour->push_back( node ); - SG_LOG(SG_GENERAL, SG_DEBUG, "CLOSEDPOLY::ADDNODE : (" << node->GetLoc().x() << "," << node->GetLoc().y() << ")"); - - // TODO: Create ONE linear feature for each contour. - // Parse the polys in linear feature - // if recording a linear feature on the pavement, add this node - // to it as well - // TODO: just doing marking now, need lighting as well - if (!cur_feature) + // For pavement polys, add a linear feature for each contour + if (is_pavement) { - string feature_desc = description + ":"; - if (boundary) + if (!cur_feature) { - feature_desc += "hole"; - } - else - { - feature_desc += "boundary"; - } + string feature_desc = description + ":"; + if (boundary) + { + feature_desc += "hole"; + } + else + { + feature_desc += "boundary"; + } - SG_LOG(SG_GENERAL, SG_DEBUG, " Adding node (" << node->GetLoc().x() << "," << node->GetLoc().y() << ") to current linear feature " << cur_feature); - cur_feature = new LinearFeature(feature_desc, 1.0f ); - } - cur_feature->AddNode( node ); + SG_LOG(SG_GENERAL, SG_DEBUG, " Adding node (" << node->GetLoc().x() << "," << node->GetLoc().y() << ") to current linear feature " << cur_feature); + cur_feature = new LinearFeature(feature_desc, 1.0f ); + } + cur_feature->AddNode( node ); + } } void ClosedPoly::CreateConvexHull( void ) @@ -77,17 +93,20 @@ void ClosedPoly::CreateConvexHull( void ) Point3D p; int i; - if (boundary->size() > 2){ + if (boundary->size() > 2) + { for (i=0; isize(); i++) { - p = boundary->at(i)->GetLoc(); nodes.push_back( p ); } convexHull = convex_hull( nodes ); hull = convexHull.get_contour(0); - } else + } + else + { SG_LOG(SG_GENERAL, SG_ALERT, "Boundary size too small: " << boundary->size() << ". Ignoring..." ); + } } int ClosedPoly::CloseCurContour() @@ -281,9 +300,6 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst ) SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at (" << curLoc.x() << "," << curLoc.y() << ")"); } } - - // Add the first point again? - // dst->push_back( src->at(0)->GetLoc() ); } void ExpandPoint( Point3D *prev, Point3D *cur, Point3D *next, double expand_by, double *heading, double *offset ) @@ -459,7 +475,7 @@ int ClosedPoly::Finish() // error handling if (boundary == NULL) { - SG_LOG(SG_GENERAL, SG_DEBUG, "no boundary"); + SG_LOG(SG_GENERAL, SG_ALERT, "no boundary"); } SG_LOG(SG_GENERAL, SG_DEBUG, "Converting a poly with " << holes.size() << " holes"); @@ -485,7 +501,7 @@ int ClosedPoly::Finish() delete boundary; boundary = NULL; - // The convert the hole contours + // and the hole contours holes.clear(); } @@ -579,84 +595,109 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list string material; int j, k; - switch( surface_type ) + if (is_pavement) { - case 1: - material = "pa_tiedown"; - break; + switch( surface_type ) + { + case 1: + material = "pa_tiedown"; + break; - case 2: - material = "pc_tiedown"; - break; + case 2: + material = "pc_tiedown"; + break; - case 3: - material = "grass_rwy"; - break; -// TODO Differentiate more here: - case 4: - case 5: - case 12: - case 13: - case 14: - case 15: - material = "grass_rwy"; - break; + case 3: + material = "grass_rwy"; + break; + + // TODO Differentiate more here: + case 4: + case 5: + case 12: + case 13: + case 14: + case 15: + material = "grass_rwy"; + break; - default: - SG_LOG(SG_GENERAL, SG_ALERT, "ClosedPoly::BuildBtg: unknown surface type " << surface_type ); - exit(1); + default: + SG_LOG(SG_GENERAL, SG_ALERT, "ClosedPoly::BuildBtg: unknown surface type " << surface_type ); + exit(1); + } + + // verify the poly has been generated + if ( pre_tess.contours() ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours"); + + // do this before clipping and generating the base + pre_tess = remove_dups( pre_tess ); + pre_tess = reduce_degeneracy( pre_tess ); + + for (int c=0; cpush_back( sp ); + SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours()); + *accum = tgPolygonUnion( pre_tess, *accum ); + tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading ); + texparams->push_back( tp ); + + if ( apt_base ) + { + ExpandContour( hull, base, 20.0 ); + ExpandContour( hull, safe_base, 50.0 ); + + // add this to the airport clearing + *apt_clearing = tgPolygonUnion( safe_base, *apt_clearing); + + // and add the clearing to the base + *apt_base = tgPolygonUnion( base, *apt_base ); + } + } } + // clean up to save ram : we're done here... + return 1; +} + +int ClosedPoly::BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing ) +{ + TGPolygon base, safe_base; + // verify the poly has been generated if ( pre_tess.contours() ) { SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours"); - // do this before clipping and generating the base - pre_tess = remove_dups( pre_tess ); - pre_tess = reduce_degeneracy( pre_tess ); - - for (int c=0; cpush_back( sp ); - SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours()); - *accum = tgPolygonUnion( pre_tess, *accum ); - tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading ); - texparams->push_back( tp ); - - ExpandContour( hull, base, 20.0 ); - ExpandContour( hull, safe_base, 50.0 ); + hull = pre_tess.get_contour(0); + ExpandContour( hull, safe_base, 20.0 ); // add this to the airport clearing *apt_clearing = tgPolygonUnion( safe_base, *apt_clearing); // and add the clearing to the base - *apt_base = tgPolygonUnion( base, *apt_base ); + *apt_base = tgPolygonUnion( pre_tess, *apt_base ); } - - // clean up to save ram : we're done here... - - - return 1; } diff --git a/src/Airports/GenAirports850/closedpoly.hxx b/src/Airports/GenAirports850/closedpoly.hxx index 368ce0d8..08982fdf 100644 --- a/src/Airports/GenAirports850/closedpoly.hxx +++ b/src/Airports/GenAirports850/closedpoly.hxx @@ -18,13 +18,20 @@ using std::string; class ClosedPoly { public: + ClosedPoly( char* desc ); ClosedPoly( int st, float s, float th, char* desc ); inline string GetDescription() { return description; } void AddNode( BezNode* node ); int CloseCurContour(); int Finish(); + int BuildOsg( osg::Group* airport ); + + // Build BTG for airport base for airports with boundary + int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing ); + + // Build BTG for pavements for airports with no boundary int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing ); FeatureList* GetFeatures() @@ -40,6 +47,7 @@ private: osg::DrawArrays* CreateOsgPrimitive( point_list contour, osg::Vec3Array* vpave ); void ExpandContour( point_list& src, TGPolygon& dst, double dist ); + bool is_pavement; int surface_type; float smoothness; float texture_heading; diff --git a/src/Airports/GenAirports850/helipad.cxx b/src/Airports/GenAirports850/helipad.cxx index 28b094a7..77a31027 100644 --- a/src/Airports/GenAirports850/helipad.cxx +++ b/src/Airports/GenAirports850/helipad.cxx @@ -114,17 +114,20 @@ void Helipad::BuildBtg( float alt_m, // generate area around helipad - TGPolygon base, safe_base; - base = gen_runway_area_w_extend( 0.0, maxsize * 0.25 , 0.0, 0.0, maxsize * 0.25 ); + if (apt_base) + { + TGPolygon base, safe_base; + base = gen_runway_area_w_extend( 0.0, maxsize * 0.25 , 0.0, 0.0, maxsize * 0.25 ); - // also clear a safe area around the pad - safe_base = gen_runway_area_w_extend( 0.0, maxsize * 0.5, 0.0, 0.0, maxsize * 0.5 ); + // also clear a safe area around the pad + safe_base = gen_runway_area_w_extend( 0.0, maxsize * 0.5, 0.0, 0.0, maxsize * 0.5 ); - // add this to the airport clearing - *apt_clearing = tgPolygonUnion(safe_base, *apt_clearing); + // add this to the airport clearing + *apt_clearing = tgPolygonUnion(safe_base, *apt_clearing); - // and add the clearing to the base - *apt_base = tgPolygonUnion( base, *apt_base ); + // and add the clearing to the base + *apt_base = tgPolygonUnion( base, *apt_base ); + } // Now generate the helipad lights superpoly_list s = gen_helipad_lights(); diff --git a/src/Airports/GenAirports850/lights.cxx b/src/Airports/GenAirports850/lights.cxx index ff38c137..67c9f38e 100644 --- a/src/Airports/GenAirports850/lights.cxx +++ b/src/Airports/GenAirports850/lights.cxx @@ -2578,7 +2578,7 @@ superpoly_list Runway::gen_malsx( float alt_m, const string& kind, bool recip ) // top level runway light generator -void Runway::gen_runway_lights( float alt_m, superpoly_list *lights, TGPolygon *apt_base ) { +void Runway::gen_runway_lights( float alt_m, superpoly_list *lights ) { unsigned int i; diff --git a/src/Airports/GenAirports850/parser.cxx b/src/Airports/GenAirports850/parser.cxx index 66bb9261..5eac64e7 100644 --- a/src/Airports/GenAirports850/parser.cxx +++ b/src/Airports/GenAirports850/parser.cxx @@ -211,6 +211,30 @@ ClosedPoly* Parser::ParsePavement( char* line ) return poly; } +ClosedPoly* Parser::ParseBoundary( char* line ) +{ + ClosedPoly* poly; + char desc[256]; + char *d = NULL; + int numParams; + + numParams = sscanf(line, "%ls", desc); + + if (numParams == 1) + { + d = strstr(line,desc); + } + else + { + d = "none"; + } + + SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly for airport boundary : " << d); + poly = new ClosedPoly(d); + + return poly; +} + int Parser::SetState( int state ) { // if we are currently parsing pavement, the oly way we know we are done @@ -223,6 +247,14 @@ int Parser::SetState( int state ) cur_pavement = NULL; } + if ( cur_airport && cur_state == STATE_PARSE_BOUNDARY ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Closing and Adding boundary"); + cur_boundary->Finish(); + cur_airport->SetBoundary( cur_boundary ); + cur_boundary = NULL; + } + cur_state = state; } @@ -297,8 +329,7 @@ int Parser::ParseLine(char* line) case BOUNDRY_CODE: SetState( STATE_PARSE_BOUNDARY ); - SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airport boundary: " << line); -// ParseBoundry(line); + cur_boundary = ParseBoundary( line ); break; case NODE_CODE: @@ -317,6 +348,10 @@ int Parser::ParseLine(char* line) { cur_feat->AddNode( prev_node ); } + else if ( cur_state == STATE_PARSE_BOUNDARY ) + { + cur_boundary->AddNode( prev_node ); + } } prev_node = cur_node; @@ -340,6 +375,19 @@ int Parser::ParseLine(char* line) } cur_pavement->CloseCurContour(); } + else if ( cur_state == STATE_PARSE_BOUNDARY ) + { + if (cur_node != prev_node) + { + cur_boundary->AddNode( prev_node ); + cur_boundary->AddNode( cur_node ); + } + else + { + cur_boundary->AddNode( cur_node ); + } + cur_boundary->CloseCurContour(); + } else if ( cur_state == STATE_PARSE_FEATURE ) { if (cur_node != prev_node) diff --git a/src/Airports/GenAirports850/parser.hxx b/src/Airports/GenAirports850/parser.hxx index 199fcd44..0932b326 100644 --- a/src/Airports/GenAirports850/parser.hxx +++ b/src/Airports/GenAirports850/parser.hxx @@ -59,8 +59,16 @@ public: { filename = f; cur_airport = NULL; + cur_runway = NULL; + cur_waterrunway = NULL; + cur_helipad = NULL; cur_pavement = NULL; + cur_boundary = NULL; cur_feat = NULL; + cur_object = NULL; + cur_windsock = NULL; + cur_beacon = NULL; + cur_sign = NULL; prev_node = NULL; cur_state = STATE_NONE; } @@ -76,10 +84,12 @@ private: LinearFeature* ParseFeature( char* line ); ClosedPoly* ParsePavement( char* line ); osg::Geode* ParseRunway(char* line ); + ClosedPoly* ParseBoundary( char* line ); + int ParseLine( char* line ); -// int ParseBoundry(char* line, Node* airport); - + BezNode* prev_node; + int cur_state; string filename; // a polygon conists of an array of contours @@ -89,16 +99,14 @@ private: WaterRunway* cur_waterrunway; Helipad* cur_helipad; ClosedPoly* cur_pavement; + ClosedPoly* cur_boundary; LinearFeature* cur_feat; - BezNode* prev_node; LightingObj* cur_object; Windsock* cur_windsock; Beacon* cur_beacon; Sign* cur_sign; AirportList airports; - - int cur_state; }; #endif diff --git a/src/Airports/GenAirports850/runway.cxx b/src/Airports/GenAirports850/runway.cxx index ba08ab29..678084dd 100644 --- a/src/Airports/GenAirports850/runway.cxx +++ b/src/Airports/GenAirports850/runway.cxx @@ -170,7 +170,7 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te case 2: // concrete SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: asphalt or concrete" << rwy.surface); gen_rwy( alt_m, material, rwy_polys, texparams, accum ); - gen_runway_lights( alt_m, rwy_lights, apt_base ); + gen_runway_lights( alt_m, rwy_lights ); break; case 3: // Grass @@ -178,7 +178,7 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te case 5: // Gravel SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Turf, Dirt or Gravel" << rwy.surface ); gen_simple_rwy( alt_m, material, rwy_polys, texparams, accum ); - gen_runway_lights( alt_m, rwy_lights, apt_base ); + gen_runway_lights( alt_m, rwy_lights ); break; case 12: // dry lakebed @@ -202,15 +202,18 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te break; } - // generate area around runways - base = gen_runway_area_w_extend( 0.0, rwy.width * 0.25, -rwy.overrun[0], -rwy.overrun[1], rwy.width * 0.25); + if (apt_base) + { + // generate area around runways + base = gen_runway_area_w_extend( 0.0, rwy.width * 0.25, -rwy.overrun[0], -rwy.overrun[1], rwy.width * 0.25); - // also clear a safe area around the runway - safe_base = gen_runway_area_w_extend( 0.0, rwy.width, -rwy.overrun[0], -rwy.overrun[1], rwy.width ); + // also clear a safe area around the runway + safe_base = gen_runway_area_w_extend( 0.0, rwy.width, -rwy.overrun[0], -rwy.overrun[1], rwy.width ); - // add this to the airport clearing - *apt_clearing = tgPolygonUnion(safe_base, *apt_clearing); + // add this to the airport clearing + *apt_clearing = tgPolygonUnion(safe_base, *apt_clearing); - // and add the clearing to the base - *apt_base = tgPolygonUnion( base, *apt_base ); + // and add the clearing to the base + *apt_base = tgPolygonUnion( base, *apt_base ); + } } diff --git a/src/Airports/GenAirports850/runway.hxx b/src/Airports/GenAirports850/runway.hxx index 25086d92..26d2ee6b 100644 --- a/src/Airports/GenAirports850/runway.hxx +++ b/src/Airports/GenAirports850/runway.hxx @@ -130,7 +130,7 @@ private: texparams_list* texparams, TGPolygon* accum, int marking); - void gen_runway_lights( float alt_m, superpoly_list* lights, TGPolygon* apt_base ); + void gen_runway_lights( float alt_m, superpoly_list* lights ); Point3D gen_runway_light_vector( double angle, bool recip ); superpoly_list gen_runway_edge_lights( bool recip );