1
0
Fork 0

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.
This commit is contained in:
PSadrozinski 2011-10-08 09:46:23 -04:00 committed by Christian Schmitt
parent 33c92f60f6
commit 3ba27cd481
10 changed files with 267 additions and 125 deletions

View file

@ -35,14 +35,12 @@ Airport::Airport( int c, char* def)
code = c; code = c;
SG_LOG(SG_GENERAL, SG_DEBUG, "sscanf " << def);
numParams = sscanf(def, "%d %d %d %s %ls", &altitude, &x, &y, tmp, d); 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; altitude *= SG_FEET_TO_METER;
icao = tmp; icao = tmp;
description = d; description = d;
boundary = NULL;
} }
// TODO: fix OSG - it was nice, but unnecesary... // TODO: fix OSG - it was nice, but unnecesary...
@ -379,10 +377,17 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for (i=0; i<runways.size(); i++ ) for (i=0; i<runways.size(); i++ )
{ {
if ( runways[i]->IsPrecision() ) if ( runways[i]->IsPrecision() )
{
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 ); runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing );
} }
} }
}
if (lightobjects.size()) if (lightobjects.size())
{ {
@ -396,18 +401,32 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
if (helipads.size()) if (helipads.size())
{ {
for (i=0; i<helipads.size(); i++ ) for (i=0; i<helipads.size(); i++ )
{
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 ); helipads[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing );
} }
} }
}
// Build the pavements // Build the pavements
if (pavements.size()) if (pavements.size())
{ {
for ( i=0; i<pavements.size(); i++ ) for ( i=0; i<pavements.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "Build Pavement Poly " << i << ": " << pavements[i]->GetDescription()); SG_LOG(SG_GENERAL, SG_ALERT, "Build Pavement Poly " << i << ": " << pavements[i]->GetDescription());
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 ); pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, &apt_base, &apt_clearing );
// AddFeatures( pavements[i]->GetMarkings() ); }
} }
} }
else else
@ -415,6 +434,12 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_ALERT, "no pavements"); 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 ) if ( apt_base.total_size() == 0 )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated"); SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");

View file

@ -57,6 +57,11 @@ public:
} }
} }
void SetBoundary( ClosedPoly* bndry )
{
boundary = bndry;
}
void AddWindsock( Windsock* windsock ) void AddWindsock( Windsock* windsock )
{ {
windsocks.push_back( windsock ); windsocks.push_back( windsock );
@ -90,6 +95,7 @@ private:
BeaconList beacons; BeaconList beacons;
SignList signs; SignList signs;
HelipadList helipads; HelipadList helipads;
ClosedPoly* boundary;
}; };
typedef std::vector <Airport *> AirportList; typedef std::vector <Airport *> AirportList;

View file

@ -14,12 +14,31 @@
#include "convex_hull.hxx" #include "convex_hull.hxx"
#include "closedpoly.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 ) ClosedPoly::ClosedPoly( int st, float s, float th, char* desc )
{ {
surface_type = st; surface_type = st;
smoothness = s; smoothness = s;
texture_heading = th; texture_heading = th;
is_pavement = true;
if ( desc ) if ( desc )
{ {
description = desc; description = desc;
@ -43,15 +62,11 @@ void ClosedPoly::AddNode( BezNode* node )
} }
cur_contour->push_back( node ); cur_contour->push_back( node );
SG_LOG(SG_GENERAL, SG_DEBUG, "CLOSEDPOLY::ADDNODE : (" << node->GetLoc().x() << "," << node->GetLoc().y() << ")"); SG_LOG(SG_GENERAL, SG_DEBUG, "CLOSEDPOLY::ADDNODE : (" << node->GetLoc().x() << "," << node->GetLoc().y() << ")");
// For pavement polys, add a linear feature for each contour
// TODO: Create ONE linear feature for each contour. if (is_pavement)
// 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) if (!cur_feature)
{ {
string feature_desc = description + ":"; string feature_desc = description + ":";
@ -68,6 +83,7 @@ void ClosedPoly::AddNode( BezNode* node )
cur_feature = new LinearFeature(feature_desc, 1.0f ); cur_feature = new LinearFeature(feature_desc, 1.0f );
} }
cur_feature->AddNode( node ); cur_feature->AddNode( node );
}
} }
void ClosedPoly::CreateConvexHull( void ) void ClosedPoly::CreateConvexHull( void )
@ -77,17 +93,20 @@ void ClosedPoly::CreateConvexHull( void )
Point3D p; Point3D p;
int i; int i;
if (boundary->size() > 2){ if (boundary->size() > 2)
{
for (i=0; i<boundary->size(); i++) for (i=0; i<boundary->size(); i++)
{ {
p = boundary->at(i)->GetLoc(); p = boundary->at(i)->GetLoc();
nodes.push_back( p ); nodes.push_back( p );
} }
convexHull = convex_hull( nodes ); convexHull = convex_hull( nodes );
hull = convexHull.get_contour(0); hull = convexHull.get_contour(0);
} else }
else
{
SG_LOG(SG_GENERAL, SG_ALERT, "Boundary size too small: " << boundary->size() << ". Ignoring..." ); SG_LOG(SG_GENERAL, SG_ALERT, "Boundary size too small: " << boundary->size() << ". Ignoring..." );
}
} }
int ClosedPoly::CloseCurContour() 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() << ")"); 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 ) void ExpandPoint( Point3D *prev, Point3D *cur, Point3D *next, double expand_by, double *heading, double *offset )
@ -459,7 +475,7 @@ int ClosedPoly::Finish()
// error handling // error handling
if (boundary == NULL) 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"); SG_LOG(SG_GENERAL, SG_DEBUG, "Converting a poly with " << holes.size() << " holes");
@ -485,7 +501,7 @@ int ClosedPoly::Finish()
delete boundary; delete boundary;
boundary = NULL; boundary = NULL;
// The convert the hole contours // and the hole contours
holes.clear(); holes.clear();
} }
@ -579,6 +595,8 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
string material; string material;
int j, k; int j, k;
if (is_pavement)
{
switch( surface_type ) switch( surface_type )
{ {
case 1: case 1:
@ -592,7 +610,8 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
case 3: case 3:
material = "grass_rwy"; material = "grass_rwy";
break; break;
// TODO Differentiate more here:
// TODO Differentiate more here:
case 4: case 4:
case 5: case 5:
case 12: case 12:
@ -645,6 +664,8 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading ); tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading );
texparams->push_back( tp ); texparams->push_back( tp );
if ( apt_base )
{
ExpandContour( hull, base, 20.0 ); ExpandContour( hull, base, 20.0 );
ExpandContour( hull, safe_base, 50.0 ); ExpandContour( hull, safe_base, 50.0 );
@ -654,9 +675,29 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( base, *apt_base ); *apt_base = tgPolygonUnion( base, *apt_base );
} }
}
}
// clean up to save ram : we're done here... // clean up to save ram : we're done here...
return 1; 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");
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( pre_tess, *apt_base );
}
}

View file

@ -18,13 +18,20 @@ using std::string;
class ClosedPoly class ClosedPoly
{ {
public: public:
ClosedPoly( char* desc );
ClosedPoly( int st, float s, float th, char* desc ); ClosedPoly( int st, float s, float th, char* desc );
inline string GetDescription() { return description; } inline string GetDescription() { return description; }
void AddNode( BezNode* node ); void AddNode( BezNode* node );
int CloseCurContour(); int CloseCurContour();
int Finish(); int Finish();
int BuildOsg( osg::Group* airport ); 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 ); int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing );
FeatureList* GetFeatures() FeatureList* GetFeatures()
@ -40,6 +47,7 @@ private:
osg::DrawArrays* CreateOsgPrimitive( point_list contour, osg::Vec3Array* vpave ); osg::DrawArrays* CreateOsgPrimitive( point_list contour, osg::Vec3Array* vpave );
void ExpandContour( point_list& src, TGPolygon& dst, double dist ); void ExpandContour( point_list& src, TGPolygon& dst, double dist );
bool is_pavement;
int surface_type; int surface_type;
float smoothness; float smoothness;
float texture_heading; float texture_heading;

View file

@ -114,6 +114,8 @@ void Helipad::BuildBtg( float alt_m,
// generate area around helipad // generate area around helipad
if (apt_base)
{
TGPolygon base, safe_base; TGPolygon base, safe_base;
base = gen_runway_area_w_extend( 0.0, maxsize * 0.25 , 0.0, 0.0, maxsize * 0.25 ); base = gen_runway_area_w_extend( 0.0, maxsize * 0.25 , 0.0, 0.0, maxsize * 0.25 );
@ -125,6 +127,7 @@ void Helipad::BuildBtg( float alt_m,
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( base, *apt_base ); *apt_base = tgPolygonUnion( base, *apt_base );
}
// Now generate the helipad lights // Now generate the helipad lights
superpoly_list s = gen_helipad_lights(); superpoly_list s = gen_helipad_lights();

View file

@ -2578,7 +2578,7 @@ superpoly_list Runway::gen_malsx( float alt_m, const string& kind, bool recip )
// top level runway light generator // 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; unsigned int i;

View file

@ -211,6 +211,30 @@ ClosedPoly* Parser::ParsePavement( char* line )
return poly; 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 ) int Parser::SetState( int state )
{ {
// if we are currently parsing pavement, the oly way we know we are done // 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; 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; cur_state = state;
} }
@ -297,8 +329,7 @@ int Parser::ParseLine(char* line)
case BOUNDRY_CODE: case BOUNDRY_CODE:
SetState( STATE_PARSE_BOUNDARY ); SetState( STATE_PARSE_BOUNDARY );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airport boundary: " << line); cur_boundary = ParseBoundary( line );
// ParseBoundry(line);
break; break;
case NODE_CODE: case NODE_CODE:
@ -317,6 +348,10 @@ int Parser::ParseLine(char* line)
{ {
cur_feat->AddNode( prev_node ); cur_feat->AddNode( prev_node );
} }
else if ( cur_state == STATE_PARSE_BOUNDARY )
{
cur_boundary->AddNode( prev_node );
}
} }
prev_node = cur_node; prev_node = cur_node;
@ -340,6 +375,19 @@ int Parser::ParseLine(char* line)
} }
cur_pavement->CloseCurContour(); 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 ) else if ( cur_state == STATE_PARSE_FEATURE )
{ {
if (cur_node != prev_node) if (cur_node != prev_node)

View file

@ -59,8 +59,16 @@ public:
{ {
filename = f; filename = f;
cur_airport = NULL; cur_airport = NULL;
cur_runway = NULL;
cur_waterrunway = NULL;
cur_helipad = NULL;
cur_pavement = NULL; cur_pavement = NULL;
cur_boundary = NULL;
cur_feat = NULL; cur_feat = NULL;
cur_object = NULL;
cur_windsock = NULL;
cur_beacon = NULL;
cur_sign = NULL;
prev_node = NULL; prev_node = NULL;
cur_state = STATE_NONE; cur_state = STATE_NONE;
} }
@ -76,10 +84,12 @@ private:
LinearFeature* ParseFeature( char* line ); LinearFeature* ParseFeature( char* line );
ClosedPoly* ParsePavement( char* line ); ClosedPoly* ParsePavement( char* line );
osg::Geode* ParseRunway(char* line ); osg::Geode* ParseRunway(char* line );
ClosedPoly* ParseBoundary( char* line );
int ParseLine( char* line ); int ParseLine( char* line );
// int ParseBoundry(char* line, Node* airport); BezNode* prev_node;
int cur_state;
string filename; string filename;
// a polygon conists of an array of contours // a polygon conists of an array of contours
@ -89,16 +99,14 @@ private:
WaterRunway* cur_waterrunway; WaterRunway* cur_waterrunway;
Helipad* cur_helipad; Helipad* cur_helipad;
ClosedPoly* cur_pavement; ClosedPoly* cur_pavement;
ClosedPoly* cur_boundary;
LinearFeature* cur_feat; LinearFeature* cur_feat;
BezNode* prev_node;
LightingObj* cur_object; LightingObj* cur_object;
Windsock* cur_windsock; Windsock* cur_windsock;
Beacon* cur_beacon; Beacon* cur_beacon;
Sign* cur_sign; Sign* cur_sign;
AirportList airports; AirportList airports;
int cur_state;
}; };
#endif #endif

View file

@ -170,7 +170,7 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
case 2: // concrete case 2: // concrete
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: asphalt or concrete" << rwy.surface); SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: asphalt or concrete" << rwy.surface);
gen_rwy( alt_m, material, rwy_polys, texparams, accum ); 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; break;
case 3: // Grass case 3: // Grass
@ -178,7 +178,7 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
case 5: // Gravel case 5: // Gravel
SG_LOG( SG_GENERAL, SG_ALERT, "Build Runway: Turf, Dirt or Gravel" << rwy.surface ); 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_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; break;
case 12: // dry lakebed case 12: // dry lakebed
@ -202,6 +202,8 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
break; break;
} }
if (apt_base)
{
// generate area around runways // 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); base = gen_runway_area_w_extend( 0.0, rwy.width * 0.25, -rwy.overrun[0], -rwy.overrun[1], rwy.width * 0.25);
@ -213,4 +215,5 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( base, *apt_base ); *apt_base = tgPolygonUnion( base, *apt_base );
}
} }

View file

@ -130,7 +130,7 @@ private:
texparams_list* texparams, texparams_list* texparams,
TGPolygon* accum, int marking); 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 ); Point3D gen_runway_light_vector( double angle, bool recip );
superpoly_list gen_runway_edge_lights( bool recip ); superpoly_list gen_runway_edge_lights( bool recip );