From 4fb0ca1e2b01743c87f4aa4b74e0336c9a766ab6 Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 8 Oct 2002 22:25:01 +0000 Subject: [PATCH] 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. --- src/Airports/GenAirports/build.cxx | 4 +- src/Airports/GenAirports/build.hxx | 2 +- src/Airports/GenAirports/lights.cxx | 280 +++++++++++++++++++++++++--- src/Airports/GenAirports/lights.hxx | 2 +- src/Airports/GenAirports/main.cxx | 25 ++- 5 files changed, 276 insertions(+), 37 deletions(-) diff --git a/src/Airports/GenAirports/build.cxx b/src/Airports/GenAirports/build.cxx index 4a7bf973..27836a17 100644 --- a/src/Airports/GenAirports/build.cxx +++ b/src/Airports/GenAirports/build.cxx @@ -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) diff --git a/src/Airports/GenAirports/build.hxx b/src/Airports/GenAirports/build.hxx index 4642e18d..0c959d88 100644 --- a/src/Airports/GenAirports/build.hxx +++ b/src/Airports/GenAirports/build.hxx @@ -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 ); diff --git a/src/Airports/GenAirports/lights.cxx b/src/Airports/GenAirports/lights.cxx index 637d8463..25c54178 100644 --- a/src/Airports/GenAirports/lights.cxx +++ b/src/Airports/GenAirports/lights.cxx @@ -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 ); } diff --git a/src/Airports/GenAirports/lights.hxx b/src/Airports/GenAirports/lights.hxx index 9aaadf5a..19c6bdf0 100644 --- a/src/Airports/GenAirports/lights.hxx +++ b/src/Airports/GenAirports/lights.hxx @@ -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 ); diff --git a/src/Airports/GenAirports/main.cxx b/src/Airports/GenAirports/main.cxx index 02dfd930..3fbcebf3 100644 --- a/src/Airports/GenAirports/main.cxx +++ b/src/Airports/GenAirports/main.cxx @@ -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); } }