1
0
Fork 0

Add support for generating taxiways.

Airport area is no longer the convex hull, but is instead just the area that
surrounds the runway and taxiways.
This commit is contained in:
curt 2001-06-22 19:26:09 +00:00
parent 2272a29287
commit 6c28c81180
4 changed files with 293 additions and 51 deletions

View file

@ -66,7 +66,8 @@
// except each point is the texture coordinate of the corresponding // except each point is the texture coordinate of the corresponding
// point in the original polygon. // point in the original polygon.
static FGPolygon rwy_section_tex_coords( const FGPolygon& in_poly, static FGPolygon rwy_section_tex_coords( const FGPolygon& in_poly,
const FGTexParams& tp ) const FGTexParams& tp,
const bool clip_result )
{ {
int i, j; int i, j;
FGPolygon result; FGPolygon result;
@ -131,15 +132,21 @@ static FGPolygon rwy_section_tex_coords( const FGPolygon& in_poly,
tx = (x - min.x()) / (max.x() - min.x()); tx = (x - min.x()) / (max.x() - min.x());
tx = ((int)(tx * 100)) / 100.0; tx = ((int)(tx * 100)) / 100.0;
cout << " (" << tx << ")" << endl; cout << " (" << tx << ")" << endl;
if ( tx < 0.0 ) { tx = 0.0; }
if ( tx > 1.0 ) { tx = 1.0; } if ( clip_result ) {
if ( tx < 0.0 ) { tx = 0.0; }
if ( tx > 1.0 ) { tx = 1.0; }
}
// ty = (y - min.y()) / (max.y() - min.y()); // ty = (y - min.y()) / (max.y() - min.y());
ty = (max.y() - y) / (max.y() - min.y()); ty = (max.y() - y) / (max.y() - min.y());
ty = ((int)(ty * 100)) / 100.0; ty = ((int)(ty * 100)) / 100.0;
cout << " (" << ty << ")" << endl; cout << " (" << ty << ")" << endl;
if ( ty < 0.0 ) { ty = 0.0; }
if ( ty > 1.0 ) { ty = 1.0; } if ( clip_result ) {
if ( ty < 0.0 ) { ty = 0.0; }
if ( ty > 1.0 ) { ty = 1.0; }
}
t = Point3D( tx, ty, 0 ); t = Point3D( tx, ty, 0 );
cout << " (" << tx << ", " << ty << ")" << endl; cout << " (" << tx << ", " << ty << ")" << endl;
@ -307,6 +314,24 @@ static FGPolygon split_long_edges( const FGPolygon &poly, double max_len ) {
} }
// Traverse a polygon and toss all the internal holes
static FGPolygon strip_out_holes( const FGPolygon &poly ) {
FGPolygon result; result.erase();
cout << "strip_out_holes()" << endl;
for ( int i = 0; i < poly.contours(); ++i ) {
// cout << "contour = " << i << endl;
point_list contour = poly.get_contour( i );
if ( ! poly.get_hole_flag(i) ) {
result.add_contour( contour, poly.get_hole_flag(i) );
}
}
return result;
}
// fix node elevations // fix node elevations
point_list calc_elevations( const string& root, const point_list& geod_nodes ) { point_list calc_elevations( const string& root, const point_list& geod_nodes ) {
bool done = false; bool done = false;
@ -495,6 +520,129 @@ static void gen_simple_rwy( const FGRunway& rwy_info, const string& material,
} }
// generate a taxiway. The routine modifies rwy_polys, texparams, and
// accum
static void gen_taxiway( const FGRunway& rwy_info, const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
FGPolygon *accum )
{
int j, k;
FGPolygon runway = gen_runway_w_mid( rwy_info );
// runway half "a"
FGPolygon runway_a;
runway_a.erase();
runway_a.add_node( 0, runway.get_pt(0, 0) );
runway_a.add_node( 0, runway.get_pt(0, 1) );
runway_a.add_node( 0, runway.get_pt(0, 2) );
runway_a.add_node( 0, runway.get_pt(0, 5) );
// runway half "b"
FGPolygon runway_b;
runway_b.erase();
runway_b.add_node( 0, runway.get_pt(0, 5) );
runway_b.add_node( 0, runway.get_pt(0, 2) );
runway_b.add_node( 0, runway.get_pt(0, 3) );
runway_b.add_node( 0, runway.get_pt(0, 4) );
Point3D p;
cout << "raw runway pts (a half)" << endl;
for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) {
p = runway_a.get_pt(0, j);
cout << " point = " << p << endl;
}
cout << "raw runway pts (b half)" << endl;
for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) {
p = runway_b.get_pt(0, j);
cout << " point = " << p << endl;
}
FGSuperPoly sp;
FGTexParams tp;
double xfactor = 1.0;
double yfactor = 1.0;
if ( fabs(rwy_info.width) > SG_EPSILON ) {
xfactor = 150.0 / rwy_info.width;
cout << "xfactor = " << xfactor << endl;
}
if ( fabs(rwy_info.length) > SG_EPSILON ) {
yfactor = 150.0 / rwy_info.length;
cout << "yfactor = " << yfactor << endl;
}
cout << "len = " << rwy_info.length << endl;
cout << "width = " << rwy_info.width << endl;
FGPolygon clipped_a = polygon_diff( runway_a, *accum );
FGPolygon split_a = split_long_edges( clipped_a, 400.0 );
sp.erase();
sp.set_poly( split_a );
sp.set_material( material );
sp.set_flag( 1 ); // mark as a taxiway
rwy_polys->push_back( sp );
cout << "clipped_a = " << clipped_a.contours() << endl;
*accum = polygon_union( runway_a, *accum );
tp = FGTexParams( Point3D( rwy_info.lon, rwy_info.lat, 0 ),
Point3D( (-250 / 2.0) * SG_FEET_TO_METER,
0.0,
0 ),
Point3D( (250 / 2.0) * SG_FEET_TO_METER,
(250 / 2.0) * SG_FEET_TO_METER,
0.0 ),
rwy_info.heading );
texparams->push_back( tp );
FGPolygon clipped_b = polygon_diff( runway_b, *accum );
FGPolygon split_b = split_long_edges( clipped_b, 400.0 );
sp.erase();
sp.set_poly( split_b );
sp.set_material( material );
rwy_polys->push_back( sp );
cout << "clipped_b = " << clipped_b.contours() << endl;
*accum = polygon_union( runway_b, *accum );
tp = FGTexParams( Point3D( rwy_info.lon, rwy_info.lat, 0 ),
Point3D( (-250 / 2.0) * SG_FEET_TO_METER,
0.0,
0 ),
Point3D( (250 / 2.0) * SG_FEET_TO_METER,
(250 / 2.0) * SG_FEET_TO_METER,
0.0 ),
rwy_info.heading + 180.0 );
texparams->push_back( tp );
#if 0
// after clip, but before removing T intersections
char tmpa[256], tmpb[256];
sprintf( tmpa, "a%d", i );
sprintf( tmpb, "b%d", i );
write_polygon( clipped_a, tmpa );
write_polygon( clipped_b, tmpb );
#endif
// print runway points
cout << "clipped runway pts (a)" << endl;
for ( j = 0; j < clipped_a.contours(); ++j ) {
for ( k = 0; k < clipped_a.contour_size( j ); ++k ) {
p = clipped_a.get_pt(j, k);
cout << " point = " << p << endl;
}
}
// print runway points
cout << "clipped runway pts (b)" << endl;
for ( j = 0; j < clipped_b.contours(); ++j ) {
for ( k = 0; k < clipped_b.contour_size( j ); ++k ) {
p = clipped_b.get_pt(j, k);
cout << " point = " << p << endl;
}
}
}
// generate a section of runway // generate a section of runway
static void gen_runway_section( const FGRunway& rwy_info, static void gen_runway_section( const FGRunway& rwy_info,
const FGPolygon& runway, const FGPolygon& runway,
@ -1491,34 +1639,46 @@ void build_runway( const FGRunway& rwy_info,
superpoly_list *rwy_polys, superpoly_list *rwy_polys,
texparams_list *texparams, texparams_list *texparams,
FGPolygon *accum, FGPolygon *accum,
point_list *apt_pts ) { FGPolygon *apt_base )
int j; {
cout << "surface flags = " << rwy_info.surface_flags << endl;
string surface_flag = rwy_info.surface_flags.substr(1, 1); string surface_flag = rwy_info.surface_flags.substr(1, 1);
cout << "surface flag = " << surface_flag << endl; cout << "surface flag = " << surface_flag << endl;
string material; string material;
if ( surface_flag == "A" ) { if ( surface_flag == "A" ) {
material = "pa_"; // asphalt if ( !rwy_info.really_taxiway ) {
material = "pa_"; // asphalt
} else {
material = "pa_taxiway";
}
} else if ( surface_flag == "C" ) { } else if ( surface_flag == "C" ) {
material = "pc_"; // concrete if ( !rwy_info.really_taxiway ) {
material = "pc_"; // concrete
} else {
material = "pc_taxiway";
}
} else if ( surface_flag == "D" ) { } else if ( surface_flag == "D" ) {
material = "dirt_rwy"; material = "dirt_rwy";
} else if ( surface_flag == "G" ) { } else if ( surface_flag == "G" ) {
material = "grass_rwy"; material = "grass_rwy";
} else if ( surface_flag == "T" ) { } else if ( surface_flag == "T" ) {
material = "grass_rwy"; material = "grass_rwy";
} else if ( surface_flag == "W" ) { } else if ( surface_flag == "W" ) {
// water ??? // water ???
} else { } else {
cout << "unknown runway type!" << endl; cout << "unknown runway type!" << endl;
exit(-1); exit(-1);
} }
string type_flag = rwy_info.surface_flags.substr(2, 1); string type_flag = rwy_info.surface_flags.substr(2, 1);
cout << "type flag = " << type_flag << endl; cout << "type flag = " << type_flag << endl;
if ( surface_flag == "D" || surface_flag == "G" || if ( rwy_info.really_taxiway ) {
gen_taxiway( rwy_info, material,
rwy_polys, texparams, accum );
} else if ( surface_flag == "D" || surface_flag == "G" ||
surface_flag == "T" ) surface_flag == "T" )
{ {
gen_simple_rwy( rwy_info, material, gen_simple_rwy( rwy_info, material,
@ -1549,18 +1709,14 @@ void build_runway( const FGRunway& rwy_info,
FGPolygon base = gen_runway_area( rwy_info, 1.05, 1.5 ); FGPolygon base = gen_runway_area( rwy_info, 1.05, 1.5 );
// add base to apt_pts (for convex hull of airport area) // add base to apt_base
for ( j = 0; j < base.contour_size( 0 ); ++j ) { *apt_base = polygon_union( base, *apt_base );
Point3D p = base.get_pt(0, j);
// cout << " point = " << p << endl;
apt_pts->push_back( p );
}
} }
// build 3d airport // build 3d airport
void build_airport( string airport_raw, string_list& runways_raw, void build_airport( string airport_raw, string_list& runways_raw,
const string& root ) string_list& taxiways_raw, const string& root )
{ {
int i, j, k; int i, j, k;
@ -1570,7 +1726,7 @@ void build_airport( string airport_raw, string_list& runways_raw,
// poly_list rwy_tris, rwy_txs; // poly_list rwy_tris, rwy_txs;
FGPolygon runway, runway_a, runway_b, clipped_a, clipped_b; FGPolygon runway, runway_a, runway_b, clipped_a, clipped_b;
FGPolygon split_a, split_b; FGPolygon split_a, split_b;
point_list apt_pts; FGPolygon apt_base;
Point3D p; Point3D p;
FGPolygon accum; FGPolygon accum;
@ -1627,6 +1783,8 @@ void build_airport( string airport_raw, string_list& runways_raw,
FGRunway rwy; FGRunway rwy;
rwy.really_taxiway = false;
cout << rwy_str << endl; cout << rwy_str << endl;
rwy.rwy_no = rwy_str.substr(2, 4); rwy.rwy_no = rwy_str.substr(2, 4);
@ -1645,9 +1803,71 @@ void build_airport( string airport_raw, string_list& runways_raw,
string rwy_width = rwy_str.substr(43, 4); string rwy_width = rwy_str.substr(43, 4);
rwy.width = atoi( rwy_width.c_str() ); rwy.width = atoi( rwy_width.c_str() );
rwy.surface_flags = rwy_str.substr(47, 4); rwy.surface_flags = rwy_str.substr(47, 5);
rwy.end1_flags = rwy_str.substr(52, 8);
rwy.end2_flags = rwy_str.substr(61, 8); rwy.end1_flags = rwy_str.substr(53, 4);
string rwy_disp_threshold1 = rwy_str.substr(58, 6);
rwy.disp_thresh1 = atoi( rwy_disp_threshold1.c_str() );
string rwy_stopway1 = rwy_str.substr(65, 6);
rwy.stopway1 = atoi( rwy_stopway1.c_str() );
rwy.end2_flags = rwy_str.substr(72, 4);
string rwy_disp_threshold2 = rwy_str.substr(77, 6);
rwy.disp_thresh2 = atoi( rwy_disp_threshold2.c_str() );
string rwy_stopway2 = rwy_str.substr(84, 6);
rwy.stopway2 = atoi( rwy_stopway2.c_str() );
cout << " no = " << rwy.rwy_no << endl;
cout << " lat = " << rwy_lat << " " << rwy.lat << endl;
cout << " lon = " << rwy_lon << " " << rwy.lon << endl;
cout << " hdg = " << rwy_hdg << " " << rwy.heading << endl;
cout << " len = " << rwy_len << " " << rwy.length << endl;
cout << " width = " << rwy_width << " " << rwy.width << endl;
cout << " sfc = " << rwy.surface_flags << endl;
cout << " end1 = " << rwy.end1_flags << endl;
cout << " dspth1= " << rwy_disp_threshold1 << " " << rwy.disp_thresh1 << endl;
cout << " stop1 = " << rwy_stopway1 << " " << rwy.stopway1 << endl;
cout << " end2 = " << rwy.end2_flags << endl;
cout << " dspth2= " << rwy_disp_threshold2 << " " << rwy.disp_thresh2 << endl;
cout << " stop2 = " << rwy_stopway2 << " " << rwy.stopway2 << endl;
runways.push_back( rwy );
}
// parse taxiways and generate the vertex list
runway_list taxiways;
taxiways.clear();
for ( i = 0; i < (int)taxiways_raw.size(); ++i ) {
rwy_str = taxiways_raw[i];
FGRunway taxi;
taxi.really_taxiway = true;
cout << rwy_str << endl;
taxi.rwy_no = rwy_str.substr(2, 4);
string rwy_lat = rwy_str.substr(6, 10);
taxi.lat = atof( rwy_lat.c_str() );
string rwy_lon = rwy_str.substr(17, 11);
taxi.lon = atof( rwy_lon.c_str() );
string rwy_hdg = rwy_str.substr(29, 7);
taxi.heading = atof( rwy_hdg.c_str() );
string rwy_len = rwy_str.substr(36, 7);
taxi.length = atoi( rwy_len.c_str() );
string rwy_width = rwy_str.substr(43, 5);
taxi.width = atoi( rwy_width.c_str() );
taxi.surface_flags = rwy_str.substr(48, 3);
/* /*
cout << " no = " << rwy_no << endl; cout << " no = " << rwy_no << endl;
@ -1661,7 +1881,7 @@ void build_airport( string airport_raw, string_list& runways_raw,
cout << " end2 = " << rwy_end2 << endl; cout << " end2 = " << rwy_end2 << endl;
*/ */
runways.push_back( rwy ); taxiways.push_back( taxi );
} }
FGSuperPoly sp; FGSuperPoly sp;
@ -1673,7 +1893,7 @@ void build_airport( string airport_raw, string_list& runways_raw,
string type_flag = runways[i].surface_flags.substr(2, 1); string type_flag = runways[i].surface_flags.substr(2, 1);
if ( type_flag == "P" ) { if ( type_flag == "P" ) {
build_runway( runways[i], build_runway( runways[i],
&rwy_polys, &texparams, &accum, &apt_pts ); &rwy_polys, &texparams, &accum, &apt_base );
} }
} }
@ -1682,28 +1902,34 @@ void build_airport( string airport_raw, string_list& runways_raw,
string type_flag = runways[i].surface_flags.substr(2, 1); string type_flag = runways[i].surface_flags.substr(2, 1);
if ( type_flag == "R" || type_flag == "V" ) { if ( type_flag == "R" || type_flag == "V" ) {
build_runway( runways[i], build_runway( runways[i],
&rwy_polys, &texparams, &accum, &apt_pts ); &rwy_polys, &texparams, &accum, &apt_base );
} }
} }
// Last pass: generate all remaining runways not covered in the first pass // 3rd pass: generate all remaining runways not covered in the first pass
for ( i = 0; i < (int)runways.size(); ++i ) { for ( i = 0; i < (int)runways.size(); ++i ) {
string type_flag = runways[i].surface_flags.substr(2, 1); string type_flag = runways[i].surface_flags.substr(2, 1);
if ( type_flag != "P" && type_flag != "R" && type_flag != "V" ) { if ( type_flag != "P" && type_flag != "R" && type_flag != "V" ) {
build_runway( runways[i], build_runway( runways[i],
&rwy_polys, &texparams, &accum, &apt_pts ); &rwy_polys, &texparams, &accum, &apt_base );
} }
} }
if ( apt_pts.size() == 0 ) { // 4th pass: generate all taxiways
for ( i = 0; i < (int)taxiways.size(); ++i ) {
build_runway( taxiways[i], &rwy_polys, &texparams, &accum, &apt_base );
}
if ( apt_base.total_size() == 0 ) {
cout << "no airport points generated" << endl; cout << "no airport points generated" << endl;
return; return;
} }
// generate convex hull // generate convex hull
FGPolygon hull = convex_hull(apt_pts); // FGPolygon hull = convex_hull(apt_pts);
FGPolygon divided_hull = split_long_edges( hull, 200.0 ); FGPolygon filled_base = strip_out_holes( apt_base );
FGPolygon base_poly = polygon_diff( divided_hull, accum ); FGPolygon divided_base = split_long_edges( filled_base, 200.0 );
FGPolygon base_poly = polygon_diff( divided_base, accum );
// write_polygon( base_poly, "base-raw" ); // write_polygon( base_poly, "base-raw" );
// Try to remove duplicated nodes and other degeneracies // Try to remove duplicated nodes and other degeneracies
@ -1836,8 +2062,13 @@ void build_airport( string airport_raw, string_list& runways_raw,
FGPolygon tri = polygon_tesselate_alt( poly ); FGPolygon tri = polygon_tesselate_alt( poly );
cout << "total size after = " << tri.total_size() << endl; cout << "total size after = " << tri.total_size() << endl;
// tc = rwy_calc_tex_coords( runways[i], 0.0, tri ); FGPolygon tc;
FGPolygon tc = rwy_section_tex_coords( tri, texparams[i] ); if ( rwy_polys[i].get_flag() ) {
cout << "no clip" << endl;
tc = rwy_section_tex_coords( tri, texparams[i], false );
} else {
tc = rwy_section_tex_coords( tri, texparams[i], true );
}
rwy_polys[i].set_tris( tri ); rwy_polys[i].set_tris( tri );
rwy_polys[i].set_texcoords( tc ); rwy_polys[i].set_texcoords( tc );
@ -1990,7 +2221,7 @@ void build_airport( string airport_raw, string_list& runways_raw,
string_list strip_materials; strip_materials.clear(); string_list strip_materials; strip_materials.clear();
string objpath = root + "/AirportObj"; string objpath = root + "/AirportObj";
string name = apt_code; string name = apt_code + ".btg";
SGBinObject obj; SGBinObject obj;
@ -2035,5 +2266,5 @@ void build_airport( string airport_raw, string_list& runways_raw,
string holepath = root + "/AirportArea"; string holepath = root + "/AirportArea";
// long int poly_index = poly_index_next(); // long int poly_index = poly_index_next();
// write_boundary( holepath, b, hull, poly_index ); // write_boundary( holepath, b, hull, poly_index );
split_polygon( holepath, HoleArea, divided_hull ); split_polygon( holepath, HoleArea, divided_base );
} }

View file

@ -37,7 +37,7 @@ extern int nudge;
// build 3d airport // build 3d airport
void build_airport( string airport, string_list& runways_raw, void build_airport( string airport, string_list& runways_raw,
const string& root ); string_list& taxiways_raw, const string& root );

View file

@ -57,10 +57,10 @@ int nudge = 10;
// reads the apt_full file and extracts and processes the individual // reads the apt_full file and extracts and processes the individual
// airport records // airport records
int main( int argc, char **argv ) { int main( int argc, char **argv ) {
string_list runways_list; string_list runways_list, taxiways_list;
string airport, last_airport; string airport, last_airport;
string line; string line;
char tmp[256]; char tmp[2048];
bool ready_to_go = true; bool ready_to_go = true;
sglog().setLogLevels( SG_ALL, SG_DEBUG ); sglog().setLogLevels( SG_ALL, SG_DEBUG );
@ -118,20 +118,20 @@ int main( int argc, char **argv ) {
poly_index_init( counter_file ); poly_index_init( counter_file );
sg_gzifstream in( input_file ); sg_gzifstream in( input_file );
if ( !in ) { if ( !in.is_open() ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << input_file ); SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << input_file );
exit(-1); exit(-1);
} }
// throw away the first line // throw away the first line
in.getline(tmp, 256); in.getline(tmp, 2048);
last_airport = ""; last_airport = "";
while ( ! in.eof() ) { while ( ! in.eof() ) {
in.getline(tmp, 256); in.getline(tmp, 2048);
line = tmp; line = tmp;
// cout << line << endl; cout << line << endl;
if ( line.length() == 0 ) { if ( line.length() == 0 ) {
// empty, skip // empty, skip
@ -158,17 +158,22 @@ int main( int argc, char **argv ) {
// process previous record // process previous record
// process_airport(last_airport, runways_list, argv[2]); // process_airport(last_airport, runways_list, argv[2]);
build_airport(last_airport, runways_list, work_dir); build_airport( last_airport, runways_list, taxiways_list,
work_dir );
} }
} }
// clear runway list for start of next airport // clear runway list for start of next airport
runways_list.clear(); runways_list.clear();
taxiways_list.clear();
last_airport = airport; last_airport = airport;
} else if ( line[0] == 'R' ) { } else if ( line[0] == 'R' ) {
// runway entry // runway entry
runways_list.push_back(line); runways_list.push_back(line);
} else if ( line[0] == 'T' ) {
// runway entry
taxiways_list.push_back(line);
} else if ( line == "[End]" ) { } else if ( line == "[End]" ) {
// end of file // end of file
break; break;
@ -191,7 +196,7 @@ int main( int argc, char **argv ) {
if ( ready_to_go ) { if ( ready_to_go ) {
// process previous record // process previous record
// process_airport(last_airport, runways_list, argv[2]); // process_airport(last_airport, runways_list, argv[2]);
build_airport(last_airport, runways_list, work_dir); build_airport(last_airport, runways_list, taxiways_list, work_dir);
} }
} }

View file

@ -42,7 +42,11 @@ struct FGRunway {
double heading; double heading;
double length; double length;
double width; double width;
double disp_thresh1;
double disp_thresh2;
double stopway1;
double stopway2;
string surface_flags; string surface_flags;
string end1_flags; string end1_flags;
string end2_flags; string end2_flags;
@ -53,6 +57,8 @@ struct FGRunway {
FGPolygon pre_td_zone; FGPolygon pre_td_zone;
FGPolygon td3_zone, td2_zone, td1a_zone, td1b_zone; FGPolygon td3_zone, td2_zone, td1a_zone, td1b_zone;
FGPolygon aim_point; FGPolygon aim_point;
bool really_taxiway;
}; };