Fix helipad generation and simplify the routine.
Add edge lights to the corners
This commit is contained in:
parent
4808d2a2e5
commit
356cdd17d4
2 changed files with 68 additions and 234 deletions
|
@ -14,7 +14,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/constants.h>
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
|
||||||
|
@ -41,197 +40,37 @@ Helipad::Helipad(char* definition)
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width );
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width );
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a section of texture
|
superpoly_list Helipad::gen_helipad_lights(double maxsize){
|
||||||
void Helipad::gen_helipad( const TGPolygon& runway,
|
|
||||||
double startl_pct, double endl_pct,
|
|
||||||
double startw_pct, double endw_pct,
|
|
||||||
double minu, double maxu, double minv, double maxv,
|
|
||||||
double heading,
|
|
||||||
const string& prefix,
|
|
||||||
const string& material,
|
|
||||||
superpoly_list *rwy_polys,
|
|
||||||
texparams_list *texparams,
|
|
||||||
ClipPolyType *accum,
|
|
||||||
poly_list& slivers )
|
|
||||||
{
|
|
||||||
int j, k;
|
|
||||||
double width = heli.width;
|
|
||||||
double length = heli.length;
|
|
||||||
|
|
||||||
Point3D a0 = runway.get_pt(0, 1);
|
point_list g_lights; g_lights.clear();
|
||||||
Point3D a1 = runway.get_pt(0, 2);
|
point_list g_normals; g_normals.clear();
|
||||||
Point3D a2 = runway.get_pt(0, 0);
|
|
||||||
Point3D a3 = runway.get_pt(0, 3);
|
|
||||||
|
|
||||||
if ( startl_pct > 0.0 ) {
|
//vector calculation
|
||||||
startl_pct -= nudge * SG_EPSILON;
|
Point3D vec = sgGeodToCart( GetLoc() * SG_DEGREES_TO_RADIANS );
|
||||||
}
|
|
||||||
if ( endl_pct < 1.0 ) {
|
|
||||||
endl_pct += nudge * SG_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( startl_pct < 0.0 ) {
|
|
||||||
startl_pct = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( endl_pct > 1.0 ) {
|
|
||||||
endl_pct = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// partial "w" percentages could introduce "T" intersections which
|
|
||||||
// we compensate for later, but could still cause problems now
|
|
||||||
// with our polygon clipping code. This attempts to compensate
|
|
||||||
// for that by nudging the areas a bit bigger so we don't end up
|
|
||||||
// with polygon slivers.
|
|
||||||
if ( startw_pct > 0.0 || endw_pct < 1.0 ) {
|
|
||||||
if ( startw_pct > 0.0 ) {
|
|
||||||
startw_pct -= nudge * SG_EPSILON;
|
|
||||||
}
|
|
||||||
if ( endw_pct < 1.0 ) {
|
|
||||||
endw_pct += nudge * SG_EPSILON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "start len % = " << startl_pct
|
|
||||||
<< " end len % = " << endl_pct);
|
|
||||||
|
|
||||||
double dlx, dly;
|
|
||||||
|
|
||||||
dlx = a1.x() - a0.x();
|
|
||||||
dly = a1.y() - a0.y();
|
|
||||||
|
|
||||||
Point3D t0 = Point3D( a0.x() + dlx * startl_pct,
|
|
||||||
a0.y() + dly * startl_pct, 0);
|
|
||||||
Point3D t1 = Point3D( a0.x() + dlx * endl_pct,
|
|
||||||
a0.y() + dly * endl_pct, 0);
|
|
||||||
|
|
||||||
dlx = a3.x() - a2.x();
|
|
||||||
dly = a3.y() - a2.y();
|
|
||||||
|
|
||||||
Point3D t2 = Point3D( a2.x() + dlx * startl_pct,
|
|
||||||
a2.y() + dly * startl_pct, 0);
|
|
||||||
|
|
||||||
Point3D t3 = Point3D( a2.x() + dlx * endl_pct,
|
|
||||||
a2.y() + dly * endl_pct, 0);
|
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "start wid % = " << startw_pct
|
|
||||||
<< " end wid % = " << endw_pct);
|
|
||||||
|
|
||||||
double dwx, dwy;
|
|
||||||
|
|
||||||
dwx = t0.x() - t2.x();
|
|
||||||
dwy = t0.y() - t2.y();
|
|
||||||
|
|
||||||
Point3D p0 = Point3D( t2.x() + dwx * startw_pct,
|
|
||||||
t2.y() + dwy * startw_pct, 0);
|
|
||||||
|
|
||||||
Point3D p1 = Point3D( t2.x() + dwx * endw_pct,
|
|
||||||
t2.y() + dwy * endw_pct, 0);
|
|
||||||
|
|
||||||
dwx = t1.x() - t3.x();
|
|
||||||
dwy = t1.y() - t3.y();
|
|
||||||
|
|
||||||
Point3D p2 = Point3D( t3.x() + dwx * startw_pct,
|
|
||||||
t3.y() + dwy * startw_pct, 0);
|
|
||||||
|
|
||||||
Point3D p3 = Point3D( t3.x() + dwx * endw_pct,
|
|
||||||
t3.y() + dwy * endw_pct, 0);
|
|
||||||
|
|
||||||
TGPolygon section;
|
|
||||||
section.erase();
|
|
||||||
|
|
||||||
section.add_node( 0, p2 );
|
|
||||||
section.add_node( 0, p0 );
|
|
||||||
section.add_node( 0, p1 );
|
|
||||||
section.add_node( 0, p3 );
|
|
||||||
section = snap( section, gSnap );
|
|
||||||
|
|
||||||
// print runway points
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "pre clipped runway pts " << prefix << material);
|
|
||||||
for ( j = 0; j < section.contours(); ++j ) {
|
|
||||||
for ( k = 0; k < section.contour_size( j ); ++k ) {
|
|
||||||
Point3D p = section.get_pt(j, k);
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clip the new polygon against what ever has already been created.
|
|
||||||
TGPolygon clipped = tgPolygonDiffClipper( section, *accum );
|
|
||||||
tgPolygonFindSlivers( clipped, slivers );
|
|
||||||
|
|
||||||
// Split long edges to create an object that can better flow with
|
|
||||||
// the surface terrain
|
|
||||||
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
|
|
||||||
|
|
||||||
// Create the final output and push on to the runway super_polygon
|
|
||||||
// list
|
|
||||||
TGSuperPoly sp;
|
|
||||||
sp.erase();
|
|
||||||
sp.set_poly( split );
|
|
||||||
sp.set_material( prefix + material );
|
|
||||||
rwy_polys->push_back( sp );
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "section = " << clipped.contours());
|
|
||||||
|
|
||||||
*accum = tgPolygonUnionClipper( section, *accum );
|
|
||||||
|
|
||||||
// Store away what we need to know for texture coordinate
|
|
||||||
// calculation. (CLO 10/20/02: why can't we calculate texture
|
|
||||||
// coordinates here? Oh, becuase later we need to massage the
|
|
||||||
// polygons to avoid "T" intersections and clean up other
|
|
||||||
// potential artifacts and we may add or remove points and need to
|
|
||||||
// do new texture coordinate calcs later.
|
|
||||||
|
|
||||||
double len = length / 2.0;
|
|
||||||
double sect_len = len * ( endl_pct - startl_pct );
|
|
||||||
|
|
||||||
double sect_wid = width * ( endw_pct - startw_pct );
|
|
||||||
|
|
||||||
TGTexParams tp;
|
|
||||||
tp = TGTexParams( p0,
|
|
||||||
sect_wid,
|
|
||||||
sect_len,
|
|
||||||
heading );
|
|
||||||
tp.set_minu( minu );
|
|
||||||
tp.set_maxu( maxu );
|
|
||||||
tp.set_minv( minv );
|
|
||||||
tp.set_maxv( maxv );
|
|
||||||
texparams->push_back( tp );
|
|
||||||
|
|
||||||
// print runway points
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts " << prefix + material);
|
|
||||||
for ( j = 0; j < clipped.contours(); ++j ) {
|
|
||||||
for ( k = 0; k < clipped.contour_size( j ); ++k ) {
|
|
||||||
Point3D p = clipped.get_pt(j, k);
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
superpoly_list Helipad::gen_helipad_lights(void){
|
|
||||||
|
|
||||||
point_list c_lights; c_lights.clear();
|
|
||||||
point_list c_normals; c_normals.clear();
|
|
||||||
double lat2 = 0, lon2 = 0, az2;
|
|
||||||
|
|
||||||
// Create a circle of lights approx. where the white circle is
|
|
||||||
for (int deg=0; deg<360; deg+=10){
|
|
||||||
geo_direct_wgs_84(0, heli.lat, heli.lon, deg ,
|
|
||||||
heli.width * 0.46 , &lat2, &lon2, &az2 );
|
|
||||||
|
|
||||||
c_lights.push_back( Point3D( lon2, lat2, 0.0 ) );
|
|
||||||
|
|
||||||
Point3D tmp = Point3D( lon2, lat2, 0.0 );
|
|
||||||
Point3D vec = sgGeodToCart( tmp * SG_DEGREES_TO_RADIANS );
|
|
||||||
double length = vec.distance3D( Point3D(0.0) );
|
double length = vec.distance3D( Point3D(0.0) );
|
||||||
vec = vec / length;
|
vec = vec / length;
|
||||||
c_normals.push_back( vec );
|
|
||||||
|
// Create green edge lights
|
||||||
|
TGPolygon area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
for ( int i = 0; i < area.contour_size( 0 ); ++i ) {
|
||||||
|
g_lights.push_back( area.get_pt( 0, i ) );
|
||||||
|
g_normals.push_back( vec );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a circle of lights approx. where the white texture circle is
|
||||||
|
double lat = heli.lat, lon = heli.lon, az;
|
||||||
|
for (int deg = 0; deg < 360; deg += 10){
|
||||||
|
geo_direct_wgs_84(0, heli.lat, heli.lon, deg ,
|
||||||
|
maxsize * 0.46 , &lat, &lon, &az );
|
||||||
|
|
||||||
|
g_lights.push_back( Point3D( lon, lat, 0.0 ) );
|
||||||
|
g_normals.push_back( vec );
|
||||||
}
|
}
|
||||||
|
|
||||||
TGPolygon lights_poly; lights_poly.erase();
|
TGPolygon lights_poly; lights_poly.erase();
|
||||||
TGPolygon normals_poly; normals_poly.erase();
|
TGPolygon normals_poly; normals_poly.erase();
|
||||||
lights_poly.add_contour( c_lights, false );
|
lights_poly.add_contour( g_lights, false );
|
||||||
normals_poly.add_contour( c_normals, false );
|
normals_poly.add_contour( g_normals, false );
|
||||||
|
|
||||||
TGSuperPoly green;
|
TGSuperPoly green;
|
||||||
green.set_poly( lights_poly );
|
green.set_poly( lights_poly );
|
||||||
|
@ -253,47 +92,61 @@ void Helipad::BuildBtg( superpoly_list *rwy_polys,
|
||||||
TGPolygon* apt_base,
|
TGPolygon* apt_base,
|
||||||
TGPolygon* apt_clearing )
|
TGPolygon* apt_clearing )
|
||||||
{
|
{
|
||||||
SG_LOG( SG_GENERAL, SG_INFO, "Building helipad = " << heli.designator );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Generate the basic helipad outlines
|
// Generate the basic helipad outlines
|
||||||
//
|
//
|
||||||
Point3D helicenter = Point3D( heli.lon, heli.lat, 0.0);
|
|
||||||
|
|
||||||
|
|
||||||
TGPolygon helipad = gen_wgs84_area( helicenter, heli.length, 0, 0, heli.width, heli.heading, false);
|
|
||||||
|
|
||||||
double start1_pct = 0.0;
|
|
||||||
double end1_pct = 0.0;
|
|
||||||
double maxsize = heli.width - heli.length;
|
double maxsize = heli.width - heli.length;
|
||||||
|
|
||||||
if (maxsize <= 0)
|
if (maxsize <= 0)
|
||||||
maxsize = heli.width;
|
maxsize = heli.width;
|
||||||
else if (maxsize > 0)
|
else
|
||||||
maxsize = heli.length;
|
maxsize = heli.length;
|
||||||
|
|
||||||
double percent = (maxsize / heli.length) /2;
|
TGPolygon helipad = gen_wgs84_area( GetLoc(), maxsize, 0, 0, maxsize, heli.heading, false);
|
||||||
|
helipad = snap( helipad, gSnap );
|
||||||
|
|
||||||
start1_pct = 0.5 - percent;
|
string material;
|
||||||
end1_pct = 0.5 + percent;
|
if (heli.surface == 1)
|
||||||
gen_helipad( helipad,
|
material = "pa_";
|
||||||
start1_pct, end1_pct,
|
else
|
||||||
0.0, 1.0,
|
material = "pc_";
|
||||||
0.0, 1.0, 0.0, 1.0,
|
|
||||||
heli.heading,
|
// Clip the new polygon against what ever has already been created.
|
||||||
"pc_", "heli",
|
TGPolygon clipped = tgPolygonDiffClipper( helipad, *accum );
|
||||||
rwy_polys, texparams, accum, slivers );
|
tgPolygonFindSlivers( clipped, slivers );
|
||||||
|
|
||||||
|
// Split long edges to create an object that can better flow with
|
||||||
|
// the surface terrain
|
||||||
|
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
|
||||||
|
|
||||||
|
// Create the final output and push on to the runway super_polygon
|
||||||
|
// list
|
||||||
|
TGSuperPoly sp;
|
||||||
|
sp.erase();
|
||||||
|
sp.set_poly( split );
|
||||||
|
sp.set_material( material + "heli" );
|
||||||
|
rwy_polys->push_back( sp );
|
||||||
|
|
||||||
|
*accum = tgPolygonUnionClipper( helipad, *accum );
|
||||||
|
|
||||||
|
TGTexParams tp;
|
||||||
|
tp = TGTexParams( helipad.get_pt(0,0), maxsize, maxsize, heli.heading );
|
||||||
|
tp.set_minu( 1 );
|
||||||
|
tp.set_maxu( 0 );
|
||||||
|
tp.set_minv( 1 );
|
||||||
|
tp.set_maxv( 0 );
|
||||||
|
texparams->push_back( tp );
|
||||||
|
|
||||||
|
|
||||||
// generate area around helipad
|
// generate area around helipad
|
||||||
if (apt_base)
|
if (apt_base)
|
||||||
{
|
{
|
||||||
TGPolygon base, safe_base;
|
TGPolygon base, safe_base;
|
||||||
base = gen_runway_area_w_extend( 0.0, maxsize * 0.25 , 0.0, 0.0, maxsize * 0.25 );
|
base = gen_runway_area_w_extend( 0.0, heli.length * 0.25 , 0.0, 0.0, heli.width * 0.25 );
|
||||||
base = snap( base, gSnap );
|
base = snap( base, gSnap );
|
||||||
|
|
||||||
// also clear a safe area around the pad
|
// also clear a safe area around the pad
|
||||||
safe_base = gen_runway_area_w_extend( 0.0, maxsize * 0.5, 0.0, 0.0, maxsize * 0.5 );
|
safe_base = gen_runway_area_w_extend( 0.0, heli.length * 0.5, 0.0, 0.0, heli.width * 0.5 );
|
||||||
safe_base = snap( safe_base, gSnap );
|
safe_base = snap( safe_base, gSnap );
|
||||||
|
|
||||||
// add this to the airport clearing
|
// add this to the airport clearing
|
||||||
|
@ -306,7 +159,7 @@ void Helipad::BuildBtg( superpoly_list *rwy_polys,
|
||||||
if (heli.edge_lights)
|
if (heli.edge_lights)
|
||||||
{
|
{
|
||||||
// Now generate the helipad lights
|
// Now generate the helipad lights
|
||||||
superpoly_list s = gen_helipad_lights();
|
superpoly_list s = gen_helipad_lights(maxsize);
|
||||||
for ( unsigned int i = 0; i < s.size(); ++i ) {
|
for ( unsigned int i = 0; i < s.size(); ++i ) {
|
||||||
rwy_lights->push_back( s[i] );
|
rwy_lights->push_back( s[i] );
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
#ifndef _HELIPAD_HXX
|
#ifndef _HELIPAD_HXX
|
||||||
#define _HELIPAD_HXX
|
#define _HELIPAD_HXX
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <Polygon/polygon.hxx>
|
#include <Polygon/polygon.hxx>
|
||||||
#include <Polygon/superpoly.hxx>
|
#include <Polygon/superpoly.hxx>
|
||||||
#include <Polygon/texparams.hxx>
|
#include <Polygon/texparams.hxx>
|
||||||
|
@ -36,47 +33,31 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct TGRunway {
|
struct TGRunway {
|
||||||
// data for whole runway
|
// data for helipad
|
||||||
int surface;
|
|
||||||
int shoulder;
|
|
||||||
int edge_lights;
|
|
||||||
|
|
||||||
double width;
|
|
||||||
double length;
|
|
||||||
double heading;
|
|
||||||
double smoothness;
|
|
||||||
|
|
||||||
// data for each end
|
|
||||||
char designator[16];
|
char designator[16];
|
||||||
double lat;
|
double lat;
|
||||||
double lon;
|
double lon;
|
||||||
|
double heading;
|
||||||
|
double length;
|
||||||
|
double width;
|
||||||
|
int surface;
|
||||||
int marking;
|
int marking;
|
||||||
|
int shoulder;
|
||||||
|
double smoothness;
|
||||||
|
int edge_lights;
|
||||||
};
|
};
|
||||||
|
|
||||||
TGRunway heli;
|
TGRunway heli;
|
||||||
|
|
||||||
|
|
||||||
void gen_helipad( const TGPolygon& runway,
|
|
||||||
double startl_pct, double endl_pct,
|
|
||||||
double startw_pct, double endw_pct,
|
|
||||||
double minu, double maxu, double minv, double maxv,
|
|
||||||
double heading,
|
|
||||||
const string& prefix,
|
|
||||||
const string& material,
|
|
||||||
superpoly_list *rwy_polys,
|
|
||||||
texparams_list *texparams,
|
|
||||||
ClipPolyType *accum,
|
|
||||||
poly_list& slivers );
|
|
||||||
|
|
||||||
// generate an area for a runway with expansion specified in meters
|
// generate an area for a runway with expansion specified in meters
|
||||||
// (return result points in degrees)
|
// (return result points in degrees)
|
||||||
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
|
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
|
||||||
{
|
{
|
||||||
return ( gen_wgs84_area(Point3D(heli.lon, heli.lat, 0.0f), heli.length + 2.0*length_extend, displ1, displ2, heli.width + 2.0*width_extend, heli.heading, false) );
|
return ( gen_wgs84_area( GetLoc(), heli.length + 2.0*length_extend, displ1, displ2, heli.width + 2.0*width_extend, heli.heading, false) );
|
||||||
}
|
}
|
||||||
|
|
||||||
superpoly_list gen_helipad_lights(void);
|
superpoly_list gen_helipad_lights(double maxsize);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue