Beginning work on generating/placing VASI lights.
Ooops, I noticed my light infrastructure is insufficient, I need to add support for creating multiple groups of lights with different types.
This commit is contained in:
parent
9b63deeb03
commit
4fb0ca1e2b
5 changed files with 276 additions and 37 deletions
|
@ -347,7 +347,7 @@ void build_runway( const FGRunway& rwy_info,
|
|||
|
||||
|
||||
// build 3d airport
|
||||
void build_airport( string airport_raw, string_list& runways_raw,
|
||||
void build_airport( string airport_raw, float alt_m, string_list& runways_raw,
|
||||
string_list& taxiways_raw, const string& root )
|
||||
{
|
||||
int i, j, k;
|
||||
|
@ -567,7 +567,7 @@ void build_airport( string airport_raw, string_list& runways_raw,
|
|||
point_list rwy_lights; rwy_lights.clear();
|
||||
point_list rwy_light_normals; rwy_light_normals.clear();
|
||||
for ( i = 0; i < (int)runways.size(); ++i ) {
|
||||
gen_runway_lights( runways[i], &rwy_lights, &rwy_light_normals );
|
||||
gen_runway_lights( runways[i], alt_m, &rwy_lights, &rwy_light_normals );
|
||||
}
|
||||
|
||||
// generate convex hull (no longer)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
|
||||
// build 3d airport
|
||||
void build_airport( string airport, string_list& runways_raw,
|
||||
void build_airport( string airport, float alt_m, string_list& runways_raw,
|
||||
string_list& taxiways_raw, const string& root );
|
||||
|
||||
|
||||
|
|
|
@ -27,21 +27,75 @@
|
|||
#include "lights.hxx"
|
||||
|
||||
|
||||
// calculate the runway light direction vector. I don't want to think
|
||||
// about matrix transformations tonight, so instead I can take the
|
||||
// center of one runway end - the center of the other end to get the
|
||||
// direction of the runway. Combine this with an appropriate portion
|
||||
// of the local 'up' vector gives the light direction vector for the
|
||||
// runway.
|
||||
Point3D gen_runway_light_vector( const FGRunway& rwy_info ) {
|
||||
// calculate the runway light direction vector. We take the center of
|
||||
// one runway end - the center of the other end to get the direction
|
||||
// of the runway. Combine this with an appropriate portion of the
|
||||
// local 'up' vector based on the provide 'angle' gives the light
|
||||
// direction vector for the runway.
|
||||
static Point3D gen_runway_light_vector( const FGRunway& rwy_info,
|
||||
double angle, bool recip ) {
|
||||
double length;
|
||||
|
||||
// Generate the 4 corners of the runway
|
||||
FGPolygon poly_corners = gen_runway_area_w_expand( rwy_info, 0.0, 0.0 );
|
||||
point_list corner;
|
||||
for ( int i = 0; i < poly_corners.contour_size( 0 ); ++i ) {
|
||||
corner.push_back( poly_corners.get_pt( 0, i ) );
|
||||
}
|
||||
Point3D end1 = (corner[0] + corner[1]) / 2.0;
|
||||
Point3D end2 = (corner[2] + corner[3]) / 2.0;
|
||||
|
||||
Point3D end1, end2;
|
||||
if ( !recip ) {
|
||||
end1 = (corner[0] + corner[1]) / 2.0;
|
||||
end2 = (corner[2] + corner[3]) / 2.0;
|
||||
} else {
|
||||
end2 = (corner[0] + corner[1]) / 2.0;
|
||||
end1 = (corner[2] + corner[3]) / 2.0;
|
||||
}
|
||||
Point3D cart1 = sgGeodToCart( end1 * SG_DEGREES_TO_RADIANS );
|
||||
Point3D cart2 = sgGeodToCart( end2 * SG_DEGREES_TO_RADIANS );
|
||||
cout << "cart1 = " << cart1 << " cart2 = " << cart2 << endl;
|
||||
|
||||
Point3D up = cart1;
|
||||
length = up.distance3D( Point3D(0.0) );
|
||||
up = up / length;
|
||||
|
||||
Point3D rwy_vec = cart2 - cart1;
|
||||
cout << "rwy_vec = " << rwy_vec << endl;
|
||||
|
||||
// angle up specified amount
|
||||
length = rwy_vec.distance3D( Point3D(0.0) );
|
||||
double up_length = length * tan(angle * SG_DEGREES_TO_RADIANS);
|
||||
Point3D light_vec = rwy_vec + (up * up_length);
|
||||
|
||||
length = light_vec.distance3D( Point3D(0.0) );
|
||||
light_vec = light_vec / length;
|
||||
|
||||
return light_vec;
|
||||
}
|
||||
|
||||
|
||||
// calculate the runway length vector. We take the center of one
|
||||
// runway end - the center of the other end to get the direction of
|
||||
// the runway.
|
||||
static Point3D gen_runway_length_vector( const FGRunway& rwy_info, bool recip )
|
||||
{
|
||||
double length;
|
||||
|
||||
// Generate the 4 corners of the runway
|
||||
FGPolygon poly_corners = gen_runway_area_w_expand( rwy_info, 0.0, 0.0 );
|
||||
point_list corner;
|
||||
for ( int i = 0; i < poly_corners.contour_size( 0 ); ++i ) {
|
||||
corner.push_back( poly_corners.get_pt( 0, i ) );
|
||||
}
|
||||
|
||||
Point3D end1, end2;
|
||||
if ( recip ) {
|
||||
end2 = (corner[0] + corner[1]) / 2.0;
|
||||
end1 = (corner[2] + corner[3]) / 2.0;
|
||||
} else {
|
||||
end1 = (corner[0] + corner[1]) / 2.0;
|
||||
end2 = (corner[2] + corner[3]) / 2.0;
|
||||
}
|
||||
Point3D cart1 = sgGeodToCart( end1 * SG_DEGREES_TO_RADIANS );
|
||||
Point3D cart2 = sgGeodToCart( end2 * SG_DEGREES_TO_RADIANS );
|
||||
cout << "cart1 = " << cart1 << " cart2 = " << cart2 << endl;
|
||||
|
@ -49,24 +103,59 @@ Point3D gen_runway_light_vector( const FGRunway& rwy_info ) {
|
|||
Point3D rwy_vec = cart2 - cart1;
|
||||
cout << "rwy_vec = " << rwy_vec << endl;
|
||||
|
||||
// FIXME
|
||||
// need to angle up (i.e. 3 degrees)
|
||||
length = rwy_vec.distance3D( Point3D(0.0) );
|
||||
rwy_vec = rwy_vec / length;
|
||||
|
||||
double length = rwy_vec.distance3D( Point3D(0.0) );
|
||||
return rwy_vec / length;
|
||||
return rwy_vec;
|
||||
}
|
||||
|
||||
|
||||
// calculate a vector orthogonal to the runway direction in the
|
||||
// surface plane. As you approach the runway, positive will be left.
|
||||
static Point3D gen_runway_left_vector( const FGRunway& rwy_info, bool recip )
|
||||
{
|
||||
double length;
|
||||
|
||||
// Generate the 4 corners of the runway
|
||||
FGPolygon poly_corners = gen_runway_area_w_expand( rwy_info, 0.0, 0.0 );
|
||||
point_list corner;
|
||||
for ( int i = 0; i < poly_corners.contour_size( 0 ); ++i ) {
|
||||
corner.push_back( poly_corners.get_pt( 0, i ) );
|
||||
}
|
||||
|
||||
Point3D end1, end2;
|
||||
if ( recip ) {
|
||||
end1 = corner[2];
|
||||
end2 = corner[3];
|
||||
} else {
|
||||
end1 = corner[0];
|
||||
end2 = corner[1];
|
||||
}
|
||||
Point3D cart1 = sgGeodToCart( end1 * SG_DEGREES_TO_RADIANS );
|
||||
Point3D cart2 = sgGeodToCart( end2 * SG_DEGREES_TO_RADIANS );
|
||||
cout << "cart1 = " << cart1 << " cart2 = " << cart2 << endl;
|
||||
|
||||
Point3D left_vec = cart2 - cart1;
|
||||
cout << "left_vec = " << left_vec << endl;
|
||||
|
||||
length = left_vec.distance3D( Point3D(0.0) );
|
||||
left_vec = left_vec / length;
|
||||
|
||||
return left_vec;
|
||||
}
|
||||
|
||||
|
||||
// generate runway edge lighting
|
||||
// 60 meters spacing or the next number down that divides evenly.
|
||||
void gen_runway_edge_lights( const FGRunway& rwy_info,
|
||||
point_list *lights, point_list *normals ) {
|
||||
static void gen_runway_edge_lights( const FGRunway& rwy_info,
|
||||
point_list *lights, point_list *normals,
|
||||
bool recip ) {
|
||||
int i;
|
||||
|
||||
double len = rwy_info.length * SG_FEET_TO_METER;
|
||||
int divs = (int)(len / 60.0) + 1;
|
||||
|
||||
Point3D normal = gen_runway_light_vector( rwy_info );
|
||||
Point3D normal = gen_runway_light_vector( rwy_info, 3.0, recip );
|
||||
|
||||
// using FGPolygon is a bit innefficient, but that's what the
|
||||
// routine returns.
|
||||
|
@ -77,11 +166,21 @@ void gen_runway_edge_lights( const FGRunway& rwy_info,
|
|||
corner.push_back( poly_corners.get_pt( 0, i ) );
|
||||
}
|
||||
|
||||
Point3D inc1 = (corner[3] - corner[0]) / divs;
|
||||
Point3D inc2 = (corner[2] - corner[1]) / divs;
|
||||
Point3D inc1, inc2;
|
||||
Point3D pt1, pt2;
|
||||
|
||||
if ( recip ) {
|
||||
inc1 = (corner[0] - corner[3]) / divs;
|
||||
inc2 = (corner[1] - corner[2]) / divs;
|
||||
pt1 = corner[3];
|
||||
pt2 = corner[2];
|
||||
} else {
|
||||
inc1 = (corner[3] - corner[0]) / divs;
|
||||
inc2 = (corner[2] - corner[1]) / divs;
|
||||
pt1 = corner[0];
|
||||
pt2 = corner[1];
|
||||
}
|
||||
|
||||
Point3D pt1 = corner[0];
|
||||
Point3D pt2 = corner[1];
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
lights->push_back( pt2 );
|
||||
|
@ -98,8 +197,141 @@ void gen_runway_edge_lights( const FGRunway& rwy_info,
|
|||
}
|
||||
|
||||
|
||||
void gen_runway_lights( const FGRunway& rwy_info,
|
||||
point_list *lights, point_list *normals ) {
|
||||
// Make edge lighting
|
||||
gen_runway_edge_lights( rwy_info, lights, normals );
|
||||
// generate a simple 2 bar VASI
|
||||
static void gen_vasi( const FGRunway& rwy_info, float alt_m,
|
||||
point_list *lights, point_list *normals,
|
||||
bool recip ) {
|
||||
int i;
|
||||
|
||||
cout << "gen vasi " << rwy_info.rwy_no << endl;
|
||||
|
||||
Point3D normal;
|
||||
|
||||
// using FGPolygon is a bit innefficient, but that's what the
|
||||
// routine returns.
|
||||
FGPolygon poly_corners = gen_runway_area_w_expand( rwy_info, 0.0, 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 = 360.0 - rwy_info.heading;
|
||||
} else {
|
||||
ref = corner[2];
|
||||
length_hdg = rwy_info.heading;
|
||||
}
|
||||
left_hdg = length_hdg - 90.0;
|
||||
if ( left_hdg < 0 ) { left_hdg += 360.0; }
|
||||
|
||||
// offset 600' upwind
|
||||
geo_direct_wgs_84 ( alt_m, ref.lat(), ref.lon(), length_hdg,
|
||||
600 * 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 );
|
||||
|
||||
// downwind bar
|
||||
normal = gen_runway_light_vector( rwy_info, 2.5, recip );
|
||||
|
||||
// unit1
|
||||
Point3D pt1 = ref;
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
|
||||
// unit2
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
16 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
|
||||
// unit3
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
16 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
|
||||
// upwind bar
|
||||
normal = gen_runway_light_vector( rwy_info, 3.0, recip );
|
||||
|
||||
// unit1
|
||||
pt1 = ref;
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), length_hdg,
|
||||
700 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
|
||||
// unit2
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
16 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
|
||||
// unit3
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
16 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
geo_direct_wgs_84 ( alt_m, pt1.lat(), pt1.lon(), left_hdg,
|
||||
1 * SG_FEET_TO_METER, &lat, &lon, &r );
|
||||
pt1 = Point3D( lon, lat, 0.0 );
|
||||
lights->push_back( pt1 );
|
||||
normals->push_back( normal );
|
||||
}
|
||||
|
||||
|
||||
void gen_runway_lights( const FGRunway& rwy_info, float alt_m,
|
||||
point_list *lights, point_list *normals ) {
|
||||
|
||||
cout << "gen runway lights " << rwy_info.rwy_no << " " << rwy_info.end1_flags << " " << rwy_info.end2_flags << endl;;
|
||||
|
||||
// Approach lighting
|
||||
if ( rwy_info.end1_flags.substr(2,1) == "V" ) {
|
||||
gen_vasi( rwy_info, alt_m, lights, normals, false );
|
||||
}
|
||||
if ( rwy_info.end2_flags.substr(2,1) == "V" ) {
|
||||
gen_vasi( rwy_info, alt_m, lights, normals, true );
|
||||
}
|
||||
|
||||
// Make edge lighting
|
||||
gen_runway_edge_lights( rwy_info, lights, normals, false );
|
||||
gen_runway_edge_lights( rwy_info, lights, normals, true );
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
|
||||
// generate runway lighting
|
||||
void gen_runway_lights( const FGRunway& rwy_info,
|
||||
void gen_runway_lights( const FGRunway& rwy_info, float alt_m,
|
||||
point_list *lights, point_list *normals );
|
||||
|
||||
|
||||
|
|
|
@ -175,10 +175,11 @@ int main( int argc, char **argv ) {
|
|||
if ( !last_airport.empty() ) {
|
||||
char ctmp, id[32];
|
||||
float lat, lon;
|
||||
sscanf( last_airport.c_str(), "%c %s %f %f",
|
||||
&ctmp, id, &lat, &lon);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Airport lat/lon = "
|
||||
<< lat << ',' << lon);
|
||||
int alt_ft;
|
||||
sscanf( last_airport.c_str(), "%c %s %f %f %d",
|
||||
&ctmp, id, &lat, &lon, &alt_ft);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Airport lat/lon/alt = "
|
||||
<< lat << ',' << lon << "," << alt_ft);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Id portion = " << id);
|
||||
|
||||
if (lon >= min_lon && lon <= max_lon &&
|
||||
|
@ -197,8 +198,8 @@ int main( int argc, char **argv ) {
|
|||
// process previous record
|
||||
// process_airport(last_airport, runways_list, argv[2]);
|
||||
try {
|
||||
build_airport( last_airport, runways_list, taxiways_list,
|
||||
work_dir );
|
||||
build_airport( last_airport, alt_ft * SG_FEET_TO_METER,
|
||||
runways_list, taxiways_list, work_dir );
|
||||
} catch (sg_exception &e) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to build airport "
|
||||
<< id);
|
||||
|
@ -234,8 +235,13 @@ int main( int argc, char **argv ) {
|
|||
|
||||
if ( last_airport.length() ) {
|
||||
char ctmp, id[32];
|
||||
sscanf( last_airport.c_str(), "%c %s", &ctmp, id );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Id portion = " << id);
|
||||
float lat, lon;
|
||||
int alt_ft;
|
||||
sscanf( last_airport.c_str(), "%c %s %f %f %d",
|
||||
&ctmp, id, &lat, &lon, &alt_ft);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Airport lat/lon/alt = "
|
||||
<< lat << ',' << lon << "," << alt_ft);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Id portion = " << id);
|
||||
|
||||
if ( start_id.length() && start_id == id ) {
|
||||
ready_to_go = true;
|
||||
|
@ -244,7 +250,8 @@ int main( int argc, char **argv ) {
|
|||
if ( ready_to_go ) {
|
||||
// process previous record
|
||||
// process_airport(last_airport, runways_list, argv[2]);
|
||||
build_airport(last_airport, runways_list, taxiways_list, work_dir);
|
||||
build_airport(last_airport, alt_ft * SG_FEET_TO_METER,
|
||||
runways_list, taxiways_list, work_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue