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:
parent
33c92f60f6
commit
3ba27cd481
10 changed files with 267 additions and 125 deletions
|
@ -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...
|
||||
|
@ -379,10 +377,17 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
for (i=0; i<runways.size(); i++ )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lightobjects.size())
|
||||
{
|
||||
|
@ -396,18 +401,32 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
if (helipads.size())
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Build the pavements
|
||||
if (pavements.size())
|
||||
{
|
||||
for ( i=0; i<pavements.size(); i++ )
|
||||
{
|
||||
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 );
|
||||
// AddFeatures( pavements[i]->GetMarkings() );
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
|
|
|
@ -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 <Airport *> AirportList;
|
||||
|
|
|
@ -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,15 +62,11 @@ 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
|
||||
// For pavement polys, add a linear feature for each contour
|
||||
if (is_pavement)
|
||||
{
|
||||
if (!cur_feature)
|
||||
{
|
||||
string feature_desc = description + ":";
|
||||
|
@ -68,6 +83,7 @@ void ClosedPoly::AddNode( BezNode* node )
|
|||
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; i<boundary->size(); 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,6 +595,8 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
|
|||
string material;
|
||||
int j, k;
|
||||
|
||||
if (is_pavement)
|
||||
{
|
||||
switch( surface_type )
|
||||
{
|
||||
case 1:
|
||||
|
@ -592,7 +610,8 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
|
|||
case 3:
|
||||
material = "grass_rwy";
|
||||
break;
|
||||
// TODO Differentiate more here:
|
||||
|
||||
// TODO Differentiate more here:
|
||||
case 4:
|
||||
case 5:
|
||||
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 );
|
||||
texparams->push_back( tp );
|
||||
|
||||
if ( apt_base )
|
||||
{
|
||||
ExpandContour( hull, base, 20.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
|
||||
*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");
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -114,6 +114,8 @@ void Helipad::BuildBtg( float alt_m,
|
|||
|
||||
|
||||
// generate area around helipad
|
||||
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 );
|
||||
|
||||
|
@ -125,6 +127,7 @@ void Helipad::BuildBtg( float alt_m,
|
|||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnion( base, *apt_base );
|
||||
}
|
||||
|
||||
// Now generate the helipad lights
|
||||
superpoly_list s = gen_helipad_lights();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,6 +202,8 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
|
|||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -213,4 +215,5 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
|
|||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnion( base, *apt_base );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue