1
0
Fork 0

Read and create airport light objects like PAPIs and calculate their light vectors.

This commit is contained in:
Christian Schmitt 2011-09-23 09:46:45 +02:00
parent 785c4afcda
commit 2eb8428a59
6 changed files with 113 additions and 116 deletions

View file

@ -289,7 +289,8 @@ void build_airport( string airport_id, float alt_m,
string_list& runways_raw,
string_list& beacons_raw,
string_list& towers_raw,
string_list& windsocks_raw,
string_list& windsocks_raw,
string_list& lights_raw,
const string& root,
const string_list& elev_src )
{
@ -316,7 +317,6 @@ void build_airport( string airport_id, float alt_m,
// parse runways and generate the vertex list
runway_list runways; runways.clear();
runway_list taxiways; taxiways.clear();
for ( i = 0; i < (int)runways_raw.size(); ++i ) {
++rwy_count;
@ -395,16 +395,6 @@ void build_airport( string airport_id, float alt_m,
rwy.reil1 = atoi( token[16].c_str() );
rwy.reil2 = atoi( token[25].c_str() );
if (token.size()>15) {
string vasi_angles = token[15];
vector<string> vasis = simgear::strutils::split( vasi_angles, "." );
rwy.gs_angle1 = atof( vasis[0].c_str() ) * 0.01;
rwy.gs_angle2 = atof( vasis[1].c_str() ) * 0.01;
} else {
rwy.gs_angle1 = rwy.gs_angle2 = 3.0;
}
SG_LOG( SG_GENERAL, SG_DEBUG, " no1/2 = " << rwy.rwy_no1 << " " << rwy.rwy_no2);
SG_LOG( SG_GENERAL, SG_DEBUG, " lat = " << rwy.lat);
SG_LOG( SG_GENERAL, SG_DEBUG, " lon = " << rwy.lon);
@ -422,7 +412,6 @@ void build_airport( string airport_id, float alt_m,
runways.push_back( rwy );
}
SG_LOG(SG_GENERAL, SG_INFO, "Runway count = " << runways.size() );
SG_LOG(SG_GENERAL, SG_INFO, "Taxiway count = " << taxiways.size() );
SGBucket b( apt_lon / (double)rwy_count, apt_lat / (double)rwy_count );
SG_LOG(SG_GENERAL, SG_INFO, b.gen_base_path() << "/" << b.gen_index_str());
@ -492,6 +481,26 @@ void build_airport( string airport_id, float alt_m,
}
// parse all light objects (PAPI/VASI) etc.
light_list lightobj; lightobj.clear();
for ( i = 0; i < (int)lights_raw.size(); ++i ) {
string light_str = lights_raw[i];
vector<string> token = simgear::strutils::split( light_str );
TGLightobj light;
light.lat = atof( token[1].c_str() );
light.lon = atof( token[2].c_str() );
light.type = atoi( token[3].c_str() );
light.heading = atof( token[4].c_str() );
light.glideslope = atof( token[5].c_str() );
light.rwy_name = token[6];
lightobj.push_back( light );
}
//TODO: Clean up
// First pass: generate the precision runways since these have
// precidence
for ( i = 0; i < (int)runways.size(); ++i ) {
@ -536,17 +545,6 @@ void build_airport( string airport_id, float alt_m,
}
}
// 4th pass: generate all taxiways
/* Ralf Gerlich: Generate Taxiways in specified order from bottom to top */
for ( i=0; i<taxiways.size(); ++i ) {
SG_LOG( SG_GENERAL, SG_DEBUG, "generating " << i );
build_runway( taxiways[i], alt_m,
&rwy_polys, &texparams, &accum,
&apt_base, &apt_clearing );
taxiways[i].generated = true;
}
// Now generate small surface for each beacon
TGPolygon obj_base, obj_safe_base;
double obj_hdg = runways[0].heading;
@ -588,11 +586,16 @@ void build_airport( string airport_id, float alt_m,
gen_runway_lights( runways[i], alt_m, rwy_lights, &apt_base );
}
// 6th pass: generate all taxiway lights
for ( i = 0; i < (int)taxiways.size(); ++i ) {
gen_taxiway_lights( taxiways[i], alt_m, rwy_lights );
//generate runway light objects
for ( i = 0; i < (int)lightobj.size(); ++i ) {
gen_airport_lightobj( lightobj[i], alt_m, rwy_lights );
}
// 6th pass: generate all taxiway lights
//for ( i = 0; i < (int)taxiways.size(); ++i ) {
// gen_taxiway_lights( taxiways[i], alt_m, rwy_lights );
//}
// write_polygon( accum, "accum" );
// write_polygon( apt_base, "base" );
// write_polygon( apt_clearing, "clear" );

View file

@ -38,7 +38,8 @@ void build_airport( string airport_id, float alt_m,
string_list& runways_raw,
string_list& beacons_raw,
string_list& towers_raw,
string_list& windsocks_raw,
string_list& windsocks_raw,
string_list& lights_raw,
const string& root,
const string_list& elev_src );

View file

@ -683,9 +683,9 @@ static TGSuperPoly gen_touchdown_zone_lights( const TGRunway& rwy_info,
return result;
}
/*
// generate a simple 2 bar VASI
static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
static TGSuperPoly gen_vasi( const TGLightobj& rwy_light, float alt_m,
bool recip, TGPolygon *apt_base )
{
point_list lights; lights.clear();
@ -847,110 +847,103 @@ static TGSuperPoly gen_vasi( const TGRunway& rwy_info, float alt_m,
result.set_flag( flag );
return result;
}
*/
// generate a simple PAPI
static TGSuperPoly gen_papi( const TGRunway& rwy_info, float alt_m,
bool recip, TGPolygon *apt_base )
// Generate the airports light objects (PAPI/VASI)
void gen_airport_lightobj( const TGLightobj& rwy_light, float alt_m, superpoly_list &lights )
{
point_list lights; lights.clear();
point_list lightobj; lightobj.clear();
point_list normals; normals.clear();
int i;
string flag;
double gs_angle = 3.0;
cout << "gen papi " << rwy_info.rwy_no1 << endl;
cout << "gen papi " << rwy_light.rwy_name << endl;
Point3D normal;
// using TGPolygon is a bit innefficient, but that's what the
// routine returns.
TGPolygon poly_corners
= gen_runway_area_w_extend( rwy_info, 0.0, 0.0,
rwy_info.disp_thresh1,
rwy_info.disp_thresh2,
0.0 );
point_list corner;
for ( i = 0; i < poly_corners.contour_size( 0 ); ++i ) {
corner.push_back( poly_corners.get_pt( 0, i ) );
}
// determine the start point.
Point3D ref;
double length_hdg, left_hdg;
double lon, lat, r;
if ( recip ) {
ref = corner[0];
length_hdg = rwy_info.heading + 180.0;
if ( length_hdg > 360.0 ) { length_hdg -= 360.0; }
flag = rwy_info.rwy_no1 + "-i";
gs_angle = rwy_info.gs_angle1;
} else {
ref = corner[2];
length_hdg = rwy_info.heading;
flag = rwy_info.rwy_no1;
gs_angle = rwy_info.gs_angle2;
}
double gs_angle = rwy_light.glideslope;
double left_hdg = rwy_light.heading - 90.0;
ref.setlat( rwy_light.lat );
ref.setlon( rwy_light.lon );
left_hdg = length_hdg - 90.0;
if ( left_hdg < 0 ) { left_hdg += 360.0; }
cout << "length hdg = " << length_hdg
<< " left heading = " << left_hdg << endl;
if ( gs_angle < 0.5 ) {
gs_angle = 3.0;
}
// offset 950' upwind
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), length_hdg,
950 * SG_FEET_TO_METER, &lat, &lon, &r );
ref = Point3D( lon, lat, 0.0 );
// offset 50' left
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), left_hdg,
50 * SG_FEET_TO_METER, &lat, &lon, &r );
ref = Point3D( lon, lat, 0.0 );
// Calculate the normal once for all object parts.
// SG takes care of the angle.
// calculate a second point in the object heading direction
geo_direct_wgs_84 ( rwy_light.lat, rwy_light.lon, rwy_light.heading,
100, &lat, &lon, &r);
Point3D end1, end2;
end1.setlat( lat );
end1.setlon( lon );
end2.setlat( rwy_light.lat);
end2.setlon( rwy_light.lon);
Point3D cart1 = sgGeodToCart( end1 * SG_DEGREES_TO_RADIANS );
Point3D cart2 = sgGeodToCart( end2 * SG_DEGREES_TO_RADIANS );
Point3D up = cart1;
double length = up.distance3D( Point3D(0.0) );
up = up / length;
Point3D obj_vec = cart2 - cart1;
// angle up specified amount
length = obj_vec.distance3D( Point3D(0.0) );
double up_length = length * tan( rwy_light.glideslope * SG_DEGREES_TO_RADIANS);
Point3D light_vec = obj_vec + (up * up_length);
length = light_vec.distance3D( Point3D(0.0) );
Point3D normal = light_vec / length;
SG_LOG(SG_GENERAL, SG_DEBUG, "obj_normal = " << normal);
// We know our normal, now create the lights
// unit1
Point3D pt1 = ref;
lights.push_back( pt1 );
normal = gen_runway_light_vector( rwy_info, gs_angle + 0.5, recip );
lightobj.push_back( pt1 );
normals.push_back( normal );
// unit2
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
30 * SG_FEET_TO_METER, &lat, &lon, &r );
pt1 = Point3D( lon, lat, 0.0 );
lights.push_back( pt1 );
normal = gen_runway_light_vector( rwy_info, gs_angle + 0.167, recip );
lightobj.push_back( pt1 );
normals.push_back( normal );
// unit3
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
30 * SG_FEET_TO_METER, &lat, &lon, &r );
pt1 = Point3D( lon, lat, 0.0 );
lights.push_back( pt1 );
normal = gen_runway_light_vector( rwy_info, gs_angle - 0.167, recip );
lightobj.push_back( pt1 );
normals.push_back( normal );
// unit4
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
30 * SG_FEET_TO_METER, &lat, &lon, &r );
pt1 = Point3D( lon, lat, 0.0 );
lights.push_back( pt1 );
normal = gen_runway_light_vector( rwy_info, gs_angle - 0.5, recip );
lightobj.push_back( pt1 );
normals.push_back( normal );
// grass base
/* // grass base
Point3D base_pt = (ref + pt1) / 2.0;
TGPolygon obj_base = gen_wgs84_area( base_pt, 15.0, 0.0, 0.0, 30.0,
length_hdg, alt_m, false );
*apt_base = tgPolygonUnion( obj_base, *apt_base );
*apt_base = tgPolygonUnion( obj_base, *apt_base );*/
TGPolygon lights_poly; lights_poly.erase();
TGPolygon normals_poly; normals_poly.erase();
lights_poly.add_contour( lights, false );
lights_poly.add_contour( lightobj, false );
normals_poly.add_contour( normals, false );
TGSuperPoly result;
@ -958,9 +951,7 @@ static TGSuperPoly gen_papi( const TGRunway& rwy_info, float alt_m,
result.set_normals( normals_poly );
result.set_material( "RWY_VASI_LIGHTS" );
result.set_flag( flag );
return result;
lights.push_back( result);
}
@ -2667,23 +2658,8 @@ void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
TGSuperPoly s = gen_reil( rwy_info, alt_m, true );
lights.push_back( s );
}
#if 0
// VASI/PAPI lighting
if ( vasi1 == 2 /* Has VASI */ ) {
TGSuperPoly s = gen_vasi( rwy_info, alt_m, false, apt_base );
lights.push_back( s );
} else if ( vasi1 == 3 /* Has PAPI */ ) {
TGSuperPoly s = gen_papi( rwy_info, alt_m, false, apt_base );
lights.push_back( s );
}
if ( vasi2 == 2 /* Has VASI */ ) {
TGSuperPoly s = gen_vasi( rwy_info, alt_m, true, apt_base );
lights.push_back( s );
} else if ( vasi2 == 3 /* Has PAPI */ ) {
TGSuperPoly s = gen_papi( rwy_info, alt_m, true, apt_base );
lights.push_back( s );
}
#endif
// Approach lighting
////////////////////////////////////////////////////////////

View file

@ -41,4 +41,7 @@ void gen_runway_lights( const TGRunway& rwy_info, float alt_m,
void gen_taxiway_lights( const TGRunway& taxiway_info, float alt_m,
superpoly_list &lights );
// generate light objects
void gen_airport_lightobj( const TGLightobj& rwy_light, float alt_m, superpoly_list &lights );
#endif // _RWY_LIGHTS_HXX

View file

@ -251,6 +251,7 @@ int main( int argc, char **argv ) {
string_list beacon_list;
string_list tower_list;
string_list windsock_list;
string_list light_list;
vector<string> token;
string last_apt_id = "";
@ -335,6 +336,7 @@ int main( int argc, char **argv ) {
beacon_list,
tower_list,
windsock_list,
light_list,
work_dir, elev_src );
}
}
@ -367,6 +369,7 @@ int main( int argc, char **argv ) {
beacon_list.clear();
tower_list.clear();
windsock_list.clear();
light_list.clear();
} else if ( token[0] == "100" ) {
// runway entry
runways_list.push_back(line);
@ -380,7 +383,8 @@ int main( int argc, char **argv ) {
// windsock entry
windsock_list.push_back(line);
} else if ( token[0] == "21" ) {
// light object
// PAPI / VASI list
light_list.push_back(line);
} else if ( token[0] == "15" ) {
// ignore custom startup locations
} else if ( token[0] == "50" || token[0] == "51" || token[0] == "52"
@ -439,6 +443,7 @@ int main( int argc, char **argv ) {
beacon_list,
tower_list,
windsock_list,
light_list,
work_dir, elev_src );
}
}

View file

@ -64,9 +64,6 @@ struct TGRunway {
bool dist_remaining;
double gs_angle1;
double gs_angle2;
TGPolygon threshold;
TGPolygon tens, tens_margin, ones, ones_margin;
TGPolygon letter, letter_margin_left, letter_margin_right;
@ -75,12 +72,24 @@ struct TGRunway {
TGPolygon aim_point;
bool generated;
};
typedef std::vector < TGRunway > runway_list;
typedef runway_list::iterator runway_list_iterator;
typedef runway_list::const_iterator const_runway_list_iterator;
struct TGLightobj {
double lon;
double lat;
int type;
double heading;
double glideslope;
std::string rwy_name;
};
typedef std::vector < TGLightobj > light_list;
typedef light_list::iterator light_list_iterator;
typedef light_list::const_iterator const_light_list_iterator;
// given a runway center point, length, width, and heading, and
// altitude (meters) generate the lon and lat 4 corners using wgs84