1
0
Fork 0

command line option --airport working. Tested with full apt.dat

This commit is contained in:
PSadrozinski 2011-10-08 14:18:16 -04:00 committed by Christian Schmitt
parent 3ba27cd481
commit 1663620e35
6 changed files with 280 additions and 92 deletions

View file

@ -29,18 +29,54 @@
Airport::Airport( int c, char* def)
{
int numParams;
char d[100];
char tmp[16];
char* tok;
int x, y;
code = c;
numParams = sscanf(def, "%d %d %d %s %ls", &altitude, &x, &y, tmp, d);
// we need to tokenize airports, since we can't scanf two strings next to each other...
numParams = 0;
bool done = false;
while (!done)
{
// trim leading whitespace
while(isspace(*def)) def++;
tok = strtok(def, " \t\r\n");
if (tok)
{
def += strlen(tok)+1;
switch( numParams )
{
case 0:
altitude = atoi(tok);
break;
case 1:
x = atoi(tok);
break;
case 2:
y = atoi(tok);
break;
case 3:
icao = tok;
description = def;
done = true;
break;
}
}
numParams++;
}
altitude *= SG_FEET_TO_METER;
icao = tmp;
description = d;
boundary = NULL;
SG_LOG( SG_GENERAL, SG_DEBUG, "Created airport with icao " << icao << " and description " << description );
}
// TODO: fix OSG - it was nice, but unnecesary...

View file

@ -77,6 +77,11 @@ public:
signs.push_back( sign );
}
string GetIcao( )
{
return icao;
}
void BuildOsg( osg::Group* airport );
void BuildBtg( const string& root, const string_list& elev_src );

View file

@ -302,14 +302,14 @@ Point3D LinearFeature::OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *
// check the turn direction
SGVec3d cp = cross( dir1, dir2 );
SG_LOG(SG_GENERAL, SG_ALERT, "\tcross product of dir1: " << dir1 << " and dir2: " << dir2 << " is " << cp );
SG_LOG(SG_GENERAL, SG_DEBUG, "\tcross product of dir1: " << dir1 << " and dir2: " << dir2 << " is " << cp );
// calculate the angle between cur->prev and cur->next
theta = SGMiscd::rad2deg(CalculateTheta(*prev, *cur, *next));
if ( abs(theta - 180.0) < 0.1 )
{
SG_LOG(SG_GENERAL, SG_ALERT, "\nLinearFeature: (theta close to 180) " << description << ": theta is " << theta );
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (theta close to 180) " << description << ": theta is " << theta );
// find the direction to the next point
geo_inverse_wgs_84( cur->y(), cur->x(), next->y(), next->x(), &next_dir, &az2, &dist);
@ -325,7 +325,7 @@ Point3D LinearFeature::OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *
}
else if ( abs(theta) < 0.1 )
{
SG_LOG(SG_GENERAL, SG_ALERT, "\nLinearFeature: (theta close to 0) " << description << ": theta is " << theta );
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (theta close to 0) " << description << ": theta is " << theta );
// find the direction to the next point
geo_inverse_wgs_84( cur->y(), cur->x(), next->y(), next->x(), &next_dir, &az2, &dist);
@ -341,7 +341,7 @@ Point3D LinearFeature::OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *
}
else
{
SG_LOG(SG_GENERAL, SG_ALERT, "\nLinearFeature: (theta NOT close to 180) " << description << ": theta is " << theta );
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (theta NOT close to 180) " << description << ": theta is " << theta );
// find the offset angle
geo_inverse_wgs_84( avg.y(), avg.x(), 0.0f, 0.0f, &offset_dir, &az2, &dist);
@ -363,12 +363,12 @@ Point3D LinearFeature::OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *
dist = (offset_by)/sin(SGMiscd::deg2rad(next_dir-offset_dir));
}
SG_LOG(SG_GENERAL, SG_ALERT, "\theading is " << offset_dir << " distance is " << dist );
SG_LOG(SG_GENERAL, SG_DEBUG, "\theading is " << offset_dir << " distance is " << dist );
// calculate the point from cur
geo_direct_wgs_84( cur->y(), cur->x(), offset_dir, dist, &pt_y, &pt_x, &az2 );
SG_LOG(SG_GENERAL, SG_ALERT, "\tpoint is (" << pt_x << "," << pt_y << ")" );
SG_LOG(SG_GENERAL, SG_DEBUG, "\tpoint is (" << pt_x << "," << pt_y << ")" );
return Point3D(pt_x, pt_y, 0.0f);
}

View file

@ -58,17 +58,19 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sgstream.hxx>
//#include <simgear/misc/strutils.hxx>
#include <Polygon/index.hxx>
#include <Geometry/util.hxx>
#include "beznode.hxx"
#include "closedpoly.hxx"
#include "linearfeature.hxx"
#include "parser.hxx"
using namespace std;
// TODO : Modularize this function
// IDEAS
// 1) Start / Stop MarkStyle
@ -105,6 +107,42 @@ void setup_default_elevation_sources(string_list& elev_src) {
elev_src.push_back( "SRTM-30" );
}
// Display help and usage
static void help( int argc, char **argv, const string_list& elev_src ) {
cout << "genapts generates airports for use in generating scenery for the FlightGear flight simulator. \n";
cout << "Airport, runway, and taxiway vector data and attributes are input, and generated 3D airports \n";
cout << "are output for further processing by the TerraGear scenery creation tools. \n";
cout << "\n\n";
cout << "The standard input file is runways.dat.gz which is found in $FG_ROOT/Airports. \n";
cout << "This file is periodically generated for the FlightGear project by Robin Peel, who \n";
cout << "maintains an airport database for both the X-Plane and FlightGear simulators. \n";
cout << "The format of this file is documented on the FlightGear web site. \n";
cout << "Any other input file corresponding to this format may be used as input to genapts. \n";
cout << "Input files may be gzipped or left as plain text as required. \n";
cout << "\n\n";
cout << "Processing all the world's airports takes a *long* time. To cut down processing time \n";
cout << "when only some airports are required, you may refine the input selection either by airport \n";
cout << "or by area. By airport, either one airport can be specified using --airport=abcd, where abcd is \n";
cout << "a valid airport code eg. --airport-id=KORD, or a starting airport can be specified using --start-id=abcd \n";
cout << "where once again abcd is a valid airport code. In this case, all airports in the file subsequent to the \n";
cout << "start-id are done. This is convienient when re-starting after a previous error. \n";
cout << "\nAn input area may be specified by lat and lon extent using min and max lat and lon. \n";
cout << "Alternatively, you may specify a chunk (10 x 10 degrees) or tile (1 x 1 degree) using a string \n";
cout << "such as eg. w080n40, e000s27. \n";
cout << "\nAn input file containing only a subset of the world's \n";
cout << "airports may of course be used.\n";
cout << "\n\n";
cout << "It is necessary to generate the elevation data for the area of interest PRIOR TO GENERATING THE AIRPORTS. \n";
cout << "Failure to do this will result in airports being generated with an elevation of zero. \n";
cout << "The following subdirectories of the work-dir will be searched for elevation files:\n\n";
string_list::const_iterator elev_src_it;
for (elev_src_it = elev_src.begin(); elev_src_it != elev_src.end(); elev_src_it++) {
cout << *elev_src_it << "\n";
}
cout << "\n";
usage( argc, argv );
}
// TODO: where do these belong
int nudge = 10;
@ -116,7 +154,6 @@ int main(int argc, char **argv)
float max_lon = 180;
float min_lat = -90;
float max_lat = 90;
bool ready_to_go = true;
bool view_osg = false;
string_list elev_src;
@ -154,7 +191,6 @@ int main(int argc, char **argv)
else if ( arg.find("--start-id=") == 0 )
{
start_id = arg.substr(11);
ready_to_go = false;
}
else if ( arg.find("--nudge=") == 0 )
{
@ -176,7 +212,6 @@ int main(int argc, char **argv)
{
max_lat = atof( arg.substr(10).c_str() );
}
#if 0
else if ( arg.find("--chunk=") == 0 )
{
tg::Rectangle rectangle = tg::parseChunk(arg.substr(8).c_str(), 10.0);
@ -193,11 +228,9 @@ int main(int argc, char **argv)
max_lon = rectangle.getMax().x();
max_lat = rectangle.getMax().y();
}
#endif
else if ( arg.find("--airport=") == 0 )
{
airport_id = arg.substr(10).c_str();
ready_to_go = false;
}
else if ( arg == "--clear-dem-path" )
{
@ -220,13 +253,11 @@ int main(int argc, char **argv)
{
slope_max = atof( arg.substr(12).c_str() );
}
#if 0
else if ( (arg.find("--help") == 0) || (arg.find("-h") == 0) )
{
help( argc, argv, elev_src );
exit(-1);
}
#endif
else
{
usage( argc, argv );
@ -290,48 +321,40 @@ int main(int argc, char **argv)
SG_LOG(SG_GENERAL, SG_INFO, "Creating parser");
// Create the parser...
Parser* parser = new Parser(input_file);
Parser* parser = new Parser(input_file, work_dir, elev_src);
SG_LOG(SG_GENERAL, SG_INFO, "Parse katl");
parser->Parse((char*)"edfe");
if (view_osg)
// just one airport
if ( airport_id != "" )
{
// just view in OSG
osg::Group* airportNode;
// just find and add the one airport
parser->AddAirport( airport_id );
SG_LOG(SG_GENERAL, SG_INFO, "View OSG");
airportNode = parser->CreateOsgGroup();
SG_LOG(SG_GENERAL, SG_INFO, "Finished Adding airport - now parse");
// and start the parser
parser->Parse();
}
#if 0
else if ( start_id != "" )
{
// scroll forward in datafile
parser->FindAirport( start_id );
// construct the viewer.
osgViewer::Viewer viewer;
// add remaining airports within boundary
parser->AddAirports( min_lat, min_lon, max_lat, max_lon );
// add the thread model handler
viewer.addEventHandler(new osgViewer::ThreadingHandler);
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
// add model to viewer.
viewer.setSceneData( airportNode );
viewer.setUpViewAcrossAllScreens();
// create the windows and run the threads.
viewer.realize();
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
osgUtil::Optimizer optimzer;
optimzer.optimize(airportNode);
viewer.run();
// parse all the airports that were found
parser->Parse();
}
else
{
// write a .btg file....
SG_LOG(SG_GENERAL, SG_INFO, "Write BTG");
parser->WriteBtg(work_dir, elev_src);
// find all airports within given boundary
parser->AddAirports( min_lat, min_lon, max_lat, max_lon );
// and parser them
parser->Parse();
}
#endif
SG_LOG(SG_GENERAL, SG_INFO, "Done");

View file

@ -3,35 +3,140 @@
#include "parser.hxx"
#if 0
int Parser::ParseBoundry(char* line)
{
return 0;
}
#endif
int Parser::Parse( char* icao )
bool Parser::IsAirportDefinition( char* line, string icao )
{
string line;
char tmp[2048];
char* tok;
int code;
Airport* airport = NULL;
bool match = false;
// Get the number code
tok = strtok(line, " \t\r\n");
sg_gzifstream in( filename );
if (tok)
{
line += strlen(tok)+1;
code = atoi(tok);
switch(code)
{
case LAND_AIRPORT_CODE:
case SEA_AIRPORT_CODE:
airport = new Airport( code, line );
if ( airport->GetIcao() == icao )
{
match = true;
}
break;
case HELIPORT_CODE:
case LAND_RUNWAY_CODE:
case WATER_RUNWAY_CODE:
case HELIPAD_CODE:
case PAVEMENT_CODE:
case LINEAR_FEATURE_CODE:
case BOUNDRY_CODE:
case NODE_CODE:
case BEZIER_NODE_CODE:
case CLOSE_NODE_CODE:
case CLOSE_BEZIER_NODE_CODE:
case TERM_NODE_CODE:
case TERM_BEZIER_NODE_CODE:
case AIRPORT_VIEWPOINT_CODE:
case AIRPLANE_STARTUP_LOCATION_CODE:
case LIGHT_BEACON_CODE:
case WINDSOCK_CODE:
case TAXIWAY_SIGN:
case LIGHTING_OBJECT:
case COMM_FREQ1_CODE:
case COMM_FREQ2_CODE:
case COMM_FREQ3_CODE:
case COMM_FREQ4_CODE:
case COMM_FREQ5_CODE:
case COMM_FREQ6_CODE:
case COMM_FREQ7_CODE:
case END_OF_FILE :
break;
}
}
return match;
}
void Parser::AddAirport( string icao )
{
char line[2048];
long cur_pos;
bool found = false;
ifstream in( filename.c_str() );
if ( !in.is_open() )
{
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << filename );
exit(-1);
}
while ( !in.eof() )
SG_LOG( SG_GENERAL, SG_ALERT, "Adding airport " << icao << " to parse list");
while ( !in.eof() && !found )
{
in.getline(tmp, 2048);
line = tmp;
// remember the position of this line
cur_pos = in.tellg();
// Parse the line
ParseLine(tmp);
// get a line
in.getline(line, 2048);
// this is and airport definition - remember it
if ( IsAirportDefinition( line, icao ) )
{
SG_LOG( SG_GENERAL, SG_ALERT, "Found airport " << line << " at " << cur_pos );
parse_positions.push_back( cur_pos );
found = true;
}
}
}
void Parser::Parse()
{
char tmp[2048];
bool done = false;
int i;
ifstream in( filename.c_str() );
if ( !in.is_open() )
{
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << filename );
exit(-1);
}
return 1;
// for each position in parse_positions, parse an airport
for (i=0; i<parse_positions.size(); i++)
{
SetState(STATE_NONE);
in.clear();
SG_LOG( SG_GENERAL, SG_ALERT, "seeking to " << parse_positions[i] );
in.seekg(parse_positions[i], ios::beg);
while ( !in.eof() && (cur_state != STATE_DONE ) )
{
in.getline(tmp, 2048);
// Parse the line
ParseLine(tmp);
}
// write the airport BTG
if (cur_airport)
{
cur_airport->BuildBtg( work_dir, elevation );
delete cur_airport;
cur_airport = NULL;
}
}
}
BezNode* Parser::ParseNode( int type, char* line, BezNode* prevNode )
@ -183,7 +288,7 @@ LinearFeature* Parser::ParseFeature( char* line )
feature = new LinearFeature(NULL, 0.0f);
}
SG_LOG(SG_GENERAL, SG_ALERT, "Creating Linear Feature with desription \"" << line << "\"");
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Linear Feature with desription \"" << line << "\"");
return feature;
}
@ -226,7 +331,7 @@ ClosedPoly* Parser::ParseBoundary( char* line )
}
else
{
d = "none";
d = (char *)"none";
}
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly for airport boundary : " << d);
@ -278,10 +383,16 @@ int Parser::ParseLine(char* line)
{
case LAND_AIRPORT_CODE:
case SEA_AIRPORT_CODE:
SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing land airport: " << line);
cur_airport = new Airport( code, line );
airports.push_back( cur_airport );
if (cur_state == STATE_NONE)
{
SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing land airport: " << line);
cur_airport = new Airport( code, line );
}
else
{
SetState( STATE_DONE );
}
break;
case HELIPORT_CODE:
SetState( STATE_PARSE_SIMPLE );
@ -504,19 +615,10 @@ int Parser::ParseLine(char* line)
}
}
return 0;
}
void Parser::WriteBtg( const string& root, const string_list& elev_src )
{
int i;
for (i=0; i<airports.size(); i++)
{
airports[i]->BuildBtg( root, elev_src );
}
return cur_state;
}
#if 0
osg::Group* Parser::CreateOsgGroup( void )
{
osg::Group* airportNode = new osg::Group();
@ -530,4 +632,5 @@ osg::Group* Parser::CreateOsgGroup( void )
return airportNode;
}
#endif

View file

@ -1,6 +1,9 @@
#ifndef _PARSER_H_
#define _PARSER_H_
#include <iostream>
#include <fstream>
#include "beznode.hxx"
#include "closedpoly.hxx"
#include "linearfeature.hxx"
@ -52,12 +55,20 @@
#define END_OF_FILE (99)
using namespace std;
typedef std::vector <long> ParseList;
class Parser
{
public:
Parser(string& f)
Parser(string& datafile, const string& root, const string_list& elev_src)
{
filename = f;
filename = datafile;
work_dir = root;
elevation = elev_src;
cur_airport = NULL;
cur_runway = NULL;
cur_waterrunway = NULL;
@ -73,11 +84,18 @@ public:
cur_state = STATE_NONE;
}
int Parse( char* icao );
void WriteBtg( const string& root, const string_list& elev_src );
osg::Group* CreateOsgGroup( void );
// int Parse( char* icao );
void FindAirport( string icao );
void AddAirport( string icao );
void AddAirports( float min_lat, float min_lon, float max_lat, float max_lon );
void Parse( void );
// osg::Group* CreateOsgGroup( void );
private:
bool IsAirportDefinition( char* line, string icao );
int SetState( int state );
BezNode* ParseNode( int type, char* line, BezNode* prevNode );
@ -91,6 +109,8 @@ private:
BezNode* prev_node;
int cur_state;
string filename;
string_list elevation;
string work_dir;
// a polygon conists of an array of contours
// (first is outside boundry, remaining are holes)
@ -106,7 +126,8 @@ private:
Beacon* cur_beacon;
Sign* cur_sign;
AirportList airports;
// List of positions in database file to parse
ParseList parse_positions;
};
#endif