Read and create airport light objects like PAPIs and calculate their light vectors.
This commit is contained in:
parent
785c4afcda
commit
2eb8428a59
6 changed files with 113 additions and 116 deletions
|
@ -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" );
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue