From b14614987774dc161c7d89565211b966881dc22f Mon Sep 17 00:00:00 2001
From: Christian Schmitt <chris@ilovelinux.de>
Date: Wed, 5 Oct 2011 10:56:34 +0200
Subject: [PATCH] Port airport light objects support

---
 src/Airports/GenAirports850/CMakeLists.txt |   1 +
 src/Airports/GenAirports850/airport.cxx    |   8 ++
 src/Airports/GenAirports850/airport.hxx    |   7 +
 src/Airports/GenAirports850/object.cxx     | 107 ++++++++++++++
 src/Airports/GenAirports850/object.hxx     |  32 +++++
 src/Airports/GenAirports850/parser.cxx     |   2 +
 src/Airports/GenAirports850/parser.hxx     |   1 +
 src/Airports/GenAirports850/runway.cxx     | 155 ---------------------
 8 files changed, 158 insertions(+), 155 deletions(-)
 create mode 100644 src/Airports/GenAirports850/object.cxx
 create mode 100644 src/Airports/GenAirports850/object.hxx

diff --git a/src/Airports/GenAirports850/CMakeLists.txt b/src/Airports/GenAirports850/CMakeLists.txt
index f0e909d9..8f0e6b9c 100644
--- a/src/Airports/GenAirports850/CMakeLists.txt
+++ b/src/Airports/GenAirports850/CMakeLists.txt
@@ -9,6 +9,7 @@ add_executable(genapts850
 	lights.cxx
 	linearfeature.hxx linearfeature.cxx
 	main.cxx
+	object.hxx object.cxx
 	parser.hxx parser.cxx
 	point2d.cxx point2d.hxx 
 	poly_extra.cxx poly_extra.hxx 
diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx
index 7fb1cb9f..0e65617e 100644
--- a/src/Airports/GenAirports850/airport.cxx
+++ b/src/Airports/GenAirports850/airport.cxx
@@ -383,6 +383,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
 	    }
     }
 
+    if (lightobjects.size())
+    {
+        for ( i=0; i<lightobjects.size(); i++ )
+        {
+            lightobjects[i]->BuildBtg( altitude, &rwy_lights );
+        }
+    }
+
     // Build the pavements
     if (pavements.size())
     {
diff --git a/src/Airports/GenAirports850/airport.hxx b/src/Airports/GenAirports850/airport.hxx
index a8375808..157b0195 100644
--- a/src/Airports/GenAirports850/airport.hxx
+++ b/src/Airports/GenAirports850/airport.hxx
@@ -5,6 +5,7 @@
 #include <stdlib.h>
 
 #include "runway.hxx"
+#include "object.hxx"
 #include "closedpoly.hxx"
 #include "linearfeature.hxx"
 
@@ -20,6 +21,11 @@ public:
         runways.push_back( runway );
     }
 
+    void AddObj( LightingObj* lightobj )
+    {
+        lightobjects.push_back( lightobj );
+    }
+
     void AddPavement( ClosedPoly* pavement )
     {
         pavements.push_back( pavement );
@@ -51,6 +57,7 @@ private:
     PavementList    pavements;
     FeatureList     features;
     RunwayList      runways;
+    LightingObjList lightobjects;
 };
 
 typedef std::vector <Airport *> AirportList;
diff --git a/src/Airports/GenAirports850/object.cxx b/src/Airports/GenAirports850/object.cxx
new file mode 100644
index 00000000..268bf81e
--- /dev/null
+++ b/src/Airports/GenAirports850/object.cxx
@@ -0,0 +1,107 @@
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/debug/logstream.hxx>
+#include "object.hxx"
+
+LightingObj::LightingObj( char* definition )
+{
+    sscanf(definition, "%lf %lf %d %lf %lf %s", &lat, &lon, &type, &heading, &glideslope, &assoc_rw);
+
+    SG_LOG(SG_GENERAL, SG_DEBUG, "Read lighting object: (" << lon << "," << lat << ") heading: " << heading << " type: " << type  );
+}
+
+void LightingObj::BuildBtg( int alt_m, superpoly_list* lights )
+{
+    point_list lightobj; lightobj.clear();
+    point_list normals; normals.clear();
+
+    
+
+    Point3D ref;
+    double lon2, lat2, r;
+    double left_hdg = heading - 90.0;
+
+    ref.setlat( lat );
+    ref.setlon( lon );
+
+    if ( left_hdg < 0 ) { left_hdg += 360.0; }
+
+    if ( glideslope < 0.5 ) {
+        glideslope = 3.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 ( lat, lon, heading,
+                        100, &lat2, &lon2, &r);
+
+    Point3D end1, end2;
+
+    end1.setlat( lat2 );
+    end1.setlon( lon2 );
+
+    end2.setlat( lat);
+    end2.setlon( 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( 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
+    SG_LOG(SG_GENERAL, SG_DEBUG, "Generating PAPI = " << assoc_rw);
+
+    // unit1
+    Point3D pt1 = ref;
+    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, &lat2, &lon2, &r );
+    pt1 = Point3D( lon2, lat2, 0.0 );
+    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, &lat2, &lon2, &r );
+    pt1 = Point3D( lon2, lat2, 0.0 );
+    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, &lat2, &lon2, &r );
+    pt1 = Point3D( lon2, lat2, 0.0 );
+    lightobj.push_back( pt1 );
+    normals.push_back( normal );
+
+    TGPolygon lights_poly; lights_poly.erase();
+    TGPolygon normals_poly; normals_poly.erase();
+    lights_poly.add_contour( lightobj, false );
+    normals_poly.add_contour( normals, false );
+
+    TGSuperPoly result;
+    result.set_poly( lights_poly );
+    result.set_normals( normals_poly );
+    result.set_material( "RWY_VASI_LIGHTS" );
+
+    lights->push_back( result);
+}
diff --git a/src/Airports/GenAirports850/object.hxx b/src/Airports/GenAirports850/object.hxx
new file mode 100644
index 00000000..51006e21
--- /dev/null
+++ b/src/Airports/GenAirports850/object.hxx
@@ -0,0 +1,32 @@
+#ifndef _OBJECT_H_
+#define _OBJECT_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Polygon/polygon.hxx>
+#include <Polygon/superpoly.hxx>
+#include <Geometry/point3d.hxx>
+
+#include "texparams.hxx"
+
+using std::string;
+
+class LightingObj
+{
+public:
+    LightingObj(char* def);
+
+    double lat;
+    double lon;
+    int type;
+    double heading;
+    double glideslope;
+    char assoc_rw;
+
+
+void BuildBtg( int alt_m, superpoly_list* lights );
+
+};
+typedef std::vector <LightingObj *> LightingObjList;
+#endif
\ No newline at end of file
diff --git a/src/Airports/GenAirports850/parser.cxx b/src/Airports/GenAirports850/parser.cxx
index 62411b41..d6a09e42 100644
--- a/src/Airports/GenAirports850/parser.cxx
+++ b/src/Airports/GenAirports850/parser.cxx
@@ -402,6 +402,8 @@ int Parser::ParseLine(char* line)
             case LIGHTING_OBJECT:
                 SetState( STATE_PARSE_SIMPLE );
                 SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing lighting object: " << line);
+                cur_object = new LightingObj(line);
+                cur_airport->AddObj( cur_object );
                 break;
             case COMM_FREQ1_CODE:
                 SetState( STATE_PARSE_SIMPLE );
diff --git a/src/Airports/GenAirports850/parser.hxx b/src/Airports/GenAirports850/parser.hxx
index a8f9328c..11e8b4e4 100644
--- a/src/Airports/GenAirports850/parser.hxx
+++ b/src/Airports/GenAirports850/parser.hxx
@@ -89,6 +89,7 @@ private:
     ClosedPoly*     cur_pavement;
     LinearFeature*  cur_feat;
     BezNode*        prev_node;
+    LightingObj*    cur_object;
 
     AirportList     airports;
 
diff --git a/src/Airports/GenAirports850/runway.cxx b/src/Airports/GenAirports850/runway.cxx
index dd2c0121..2736daa9 100644
--- a/src/Airports/GenAirports850/runway.cxx
+++ b/src/Airports/GenAirports850/runway.cxx
@@ -214,161 +214,6 @@ TGPolygon Runway::gen_runway_w_mid( double alt_m, double length_extend_m, double
     return result_list;
 }
 
-#if 0
-void Runway::gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
-{
-    Point3D mp, end[2];
-    int i;
-
-    // create the runway in two halves, as markings may be different in each direction
-    end[0] = GetStart();
-    mp = GetMidpoint();
-    end[1] = GetEnd();
-
-    for (i=0; i<2; i++)
-    {
-        gen_simple_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
-    }
-}
-#endif
-
-/*void gen_simple_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
-{
-    int j, k;
-
-    TGPolygon runway = gen_runway_w_mid( alt_m, 0.0, 0.0 );
-
-    // runway half "a"
-    TGPolygon 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"
-    TGPolygon 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;
-    SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (a half)");
-    for ( j = 0; j < runway_a.contour_size( 0 ); ++j ) 
-    {
-    	p = runway_a.get_pt(0, j);
-    	SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
-    }
-    SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway pts (b half)");
-    for ( j = 0; j < runway_b.contour_size( 0 ); ++j ) 
-    {
-    	p = runway_b.get_pt(0, j);
-    	SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
-    }
-	
-    // do this before clipping and generating the base
-    runway_a = remove_dups( runway_a );
-    runway_a = reduce_degeneracy( runway_a );
-
-    runway_b = remove_dups( runway_b );
-    runway_b = reduce_degeneracy( runway_b );
-
-    TGSuperPoly sp;
-    TGTexParams tp;
-
-    TGPolygon clipped_a = tgPolygonDiff( runway_a, *accum );
-    TGPolygon split_a = tgPolygonSplitLongEdges( clipped_a, 400.0 );
-    sp.erase();
-    sp.set_poly( split_a );
-    sp.set_material( material );
-    rwy_polys->push_back( sp );
-    SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_a = " << clipped_a.contours());
-    *accum = tgPolygonUnion( runway_a, *accum );
-    tp = TGTexParams( runway_a.get_pt(0,0), rwy.width, rwy.length/2.0, rwy.heading );
-    texparams->push_back( tp );
-
-    TGPolygon clipped_b = tgPolygonDiff( runway_b, *accum );
-    TGPolygon split_b = tgPolygonSplitLongEdges( clipped_b, 400.0 );
-    sp.erase();
-    sp.set_poly( split_b );
-    sp.set_material( material );
-    rwy_polys->push_back( sp );
-    SG_LOG(SG_GENERAL, SG_DEBUG, "clipped_b = " << clipped_b.contours());
-    *accum = tgPolygonUnion( runway_b, *accum );
-    tp = TGTexParams( runway_b.get_pt(0,2), rwy.width, rwy.length/2.0, rwy.heading+180.0 );
-    texparams->push_back( tp );
-
-    // print runway points
-    SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (a)");
-    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);
-    	    SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
-    	}
-    }
-
-    // print runway points
-    SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts (b)");
-    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);
-    	    SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
-    	}
-    }
-
-#if 0    
-    gen_runway_stopway( rwy_info, runway_a, runway_b,
-    	    		material,
-    	    		rwy_polys, texparams, accum );
-#endif
-}*/
-
-#if 0
-void Runway::gen_marked_rwy( double alt_m, const string& material, superpoly_list *rwy_polys, texparams_list *texparams, TGPolygon *accum )
-{
-    Point3D mp, end[2];
-    int i;
-
-    // create the runway in two halves, as markings may be different in each direction
-    end[0] = GetStart();
-    mp = GetMidpoint();
-    end[1] = GetEnd();
-
-    for (i=0; i<2; i++)
-    {
-        // first, create half 'a'
-        switch( marking[i] )
-        {
-            case 0:
-            case 1: // Visual
-                SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Visual marking");
-                gen_visual_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
-                break;
-
-            case 2: // non-precision
-                SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Non Precision marking");
-                gen_non_precision_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
-                break;
-
-            case 3: // precision
-                SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has Precision marking");
-                //gen_precision_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
-                gen_simple_half( alt_m, mp, end[i], material, rwy_polys, texparams, accum );
-                break;
-
-            default: // unknown
-                SG_LOG( SG_GENERAL, SG_ALERT, "Half " << i << ": has unknown marking");
-                break;
-        }
-    }
-}
-#endif
 
 int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing )
 {