- Build runway shoulders at the same time as runway segments
- hook up --dump-rwy=x to shapefile generation for debugging runway and shoulder polys using qgis
This commit is contained in:
parent
a83bf32c2c
commit
a7e6f7fa1b
6 changed files with 401 additions and 219 deletions
|
@ -255,6 +255,96 @@ static TGPolygon rwy_section_tex_coords( const TGPolygon& in_poly, const TGTexPa
|
|||
return result;
|
||||
}
|
||||
|
||||
static TGPolygon shoulder_tex_coords( const TGPolygon& in_poly, const TGTexParams& tp )
|
||||
{
|
||||
int i, j;
|
||||
TGPolygon result;
|
||||
result.erase();
|
||||
|
||||
Point3D ref = tp.get_ref();
|
||||
double width = tp.get_width();
|
||||
double length = tp.get_length();
|
||||
double heading = tp.get_heading();
|
||||
double minu = tp.get_minu();
|
||||
double maxu = tp.get_maxu();
|
||||
double minv = tp.get_minv();
|
||||
double maxv = tp.get_maxv();
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "section ref = " << ref );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " width = " << width );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " length = " << length );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " heading = " << heading );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " minv = " << minv );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " maxv = " << maxv );
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, " heading = " << heading );
|
||||
|
||||
Point3D p, t;
|
||||
double x, y, tx, ty;
|
||||
|
||||
for ( i = 0; i < in_poly.contours(); ++i )
|
||||
{
|
||||
for ( j = 0; j < in_poly.contour_size( i ); ++j )
|
||||
{
|
||||
p = in_poly.get_pt( i, j );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "tex coords for contour " << i << "point " << j << ": " << p );
|
||||
|
||||
//
|
||||
// 1. Calculate distance and bearing from the center of
|
||||
// the feature
|
||||
//
|
||||
|
||||
// given alt, lat1, lon1, lat2, lon2, calculate starting
|
||||
// and ending az1, az2 and distance (s). Lat, lon, and
|
||||
// azimuth are in degrees. distance in meters
|
||||
double az1, az2, dist;
|
||||
geo_inverse_wgs_84( 0, ref.y(), ref.x(), p.y(), p.x(),
|
||||
&az1, &az2, &dist );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "basic course from ref = " << az2);
|
||||
|
||||
//
|
||||
// 2. Rotate this back into a coordinate system where Y
|
||||
// runs the length of the runway and X runs crossways.
|
||||
//
|
||||
|
||||
double course = az2 - heading;
|
||||
while ( course < -360 ) { course += 360; }
|
||||
while ( course > 360 ) { course -= 360; }
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG,
|
||||
" course = " << course << " dist = " << dist );
|
||||
|
||||
//
|
||||
// 3. Convert from polar to cartesian coordinates
|
||||
//
|
||||
|
||||
x = sin( course * SGD_DEGREES_TO_RADIANS ) * dist;
|
||||
y = cos( course * SGD_DEGREES_TO_RADIANS ) * dist;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " x = " << x << " y = " << y);
|
||||
|
||||
//
|
||||
// 4. Map x, y point into texture coordinates
|
||||
//
|
||||
double tmp;
|
||||
|
||||
tmp = x / width;
|
||||
tx = tmp * (maxu - minu) + minu;
|
||||
|
||||
if ( tx < 0.00 ) { tx = 0.0; }
|
||||
if ( tx > 1.00 ) { tx = 1.0; }
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ")");
|
||||
|
||||
ty = (y/length) + minv;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << ty << ")");
|
||||
|
||||
t = Point3D( tx, ty, 0 );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ", " << ty << ")");
|
||||
|
||||
result.add_node( i, t );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: add to linear feature class
|
||||
static TGPolygon linear_feature_tex_coords( const TGPolygon& in_poly, const TGTexParams& tp )
|
||||
{
|
||||
|
@ -546,13 +636,21 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
|
||||
if ( runways[i]->IsPrecision() )
|
||||
{
|
||||
if ( (dbg_rwy_poly > 0) && (i == (unsigned int)dbg_rwy_poly-1) ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Problem runway poly (" << i << ")");
|
||||
|
||||
make_shapefiles = true;
|
||||
} else {
|
||||
make_shapefiles = false;
|
||||
}
|
||||
|
||||
if (boundary)
|
||||
{
|
||||
runways[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, NULL, NULL );
|
||||
runways[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, NULL, NULL, make_shapefiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
runways[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, &apt_base, &apt_clearing );
|
||||
runways[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, &apt_base, &apt_clearing, make_shapefiles );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,7 +731,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
SG_LOG( SG_GENERAL, SG_ALERT, "Finished building Pavements for " << icao << " at " << ctime(&log_time) );
|
||||
|
||||
// Build runway shoulders here
|
||||
#if 0
|
||||
for ( unsigned int i=0; i<runways.size(); i++ )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Build Runway shoulder " << i + 1 << " of " << runways.size());
|
||||
|
@ -641,14 +738,21 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
if ( runways[i]->GetsShoulder() )
|
||||
{
|
||||
slivers.clear();
|
||||
runways[i]->BuildShoulder( &rwy_polys, &rwy_tps, &accum, slivers, &apt_base, &apt_clearing );
|
||||
|
||||
if (boundary)
|
||||
{
|
||||
runways[i]->BuildShoulder( &rwy_polys, &rwy_tps, &accum, slivers, NULL, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
runways[i]->BuildShoulder( &rwy_polys, &rwy_tps, &accum, slivers, &apt_base, &apt_clearing );
|
||||
}
|
||||
|
||||
// Now try to merge any slivers we found
|
||||
merge_slivers( rwy_polys, slivers );
|
||||
merge_slivers( pvmt_polys, slivers );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// build the base and clearing if there's a boundary
|
||||
if (boundary)
|
||||
|
@ -850,7 +954,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size());
|
||||
|
||||
TGPolygon tc;
|
||||
tc = rwy_section_tex_coords( tri, rwy_tps[i], true );
|
||||
if (rwy_polys[i].get_flag() == "shoulder")
|
||||
{
|
||||
tc = shoulder_tex_coords( tri, rwy_tps[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
tc = rwy_section_tex_coords( tri, rwy_tps[i], true );
|
||||
}
|
||||
|
||||
rwy_polys[i].set_tris( tri );
|
||||
rwy_polys[i].set_texcoords( tc );
|
||||
|
|
|
@ -553,8 +553,6 @@ Point3D midpoint( Point3D p0, Point3D p1 )
|
|||
return Point3D( (p0.x() + p1.x()) / 2, (p0.y() + p1.y()) / 2, (p0.z() + p1.z()) / 2 );
|
||||
}
|
||||
|
||||
#define DEBUG_LF (0)
|
||||
|
||||
int LinearFeature::Finish( bool closed, unsigned int idx )
|
||||
{
|
||||
TGPolygon poly;
|
||||
|
@ -573,16 +571,6 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
|
|||
double light_delta = 0;
|
||||
double pt_x = 0, pt_y = 0;
|
||||
|
||||
#if DEBUG_LF
|
||||
void* ds_id;
|
||||
void* l_id;
|
||||
|
||||
// Create a datasource for each linear feature
|
||||
char ds_name[128];
|
||||
sprintf(ds_name, "./lf_debug/%04d_%s", idx, description.c_str());
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
#endif
|
||||
|
||||
// create the inner and outer boundaries to generate polys
|
||||
// this generates 2 point lists for the contours, and remembers
|
||||
// the start stop points for markings and lights
|
||||
|
@ -710,13 +698,6 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
|
|||
exit(1);
|
||||
}
|
||||
|
||||
#if DEBUG_LF
|
||||
// Create a new layer in the datasource for each Mark
|
||||
char layer_name[128];
|
||||
sprintf( layer_name, "%04d_%s", i, material.c_str() );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
#endif
|
||||
|
||||
last_end_v = 0.0f;
|
||||
for (unsigned int j = marks[i]->start_idx; j <= marks[i]->end_idx; j++)
|
||||
{
|
||||
|
@ -755,12 +736,6 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
|
|||
poly.add_node( 0, cur_inner );
|
||||
poly = snap( poly, gSnap );
|
||||
|
||||
#if DEBUG_LF
|
||||
char feature_name[128];
|
||||
sprintf( feature_name, "%04d", j);
|
||||
tgShapefileCreateFeature( ds_id, l_id, poly, feature_name );
|
||||
#endif
|
||||
|
||||
sp.erase();
|
||||
sp.set_poly( poly );
|
||||
sp.set_material( material );
|
||||
|
@ -779,11 +754,6 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
|
|||
}
|
||||
}
|
||||
|
||||
#if DEBUG_LF
|
||||
// Close the datasource
|
||||
tgShapefileCloseDatasource( ds_id );
|
||||
#endif
|
||||
|
||||
// now generate the supoerpoly list for lights with constant distance between lights (depending on feature type)
|
||||
for (unsigned int i=0; i<lights.size(); i++)
|
||||
{
|
||||
|
@ -916,7 +886,7 @@ int LinearFeature::BuildBtg(float alt_m, superpoly_list* line_polys, texparams_l
|
|||
|
||||
if ( make_shapefiles ) {
|
||||
char ds_name[128];
|
||||
sprintf(ds_name, "./lf_debug/problem");
|
||||
sprintf(ds_name, "./lf_debug");
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ TGPolygon WaterRunway::GetNodes()
|
|||
}
|
||||
|
||||
|
||||
int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, ClipPolyType* accum, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing )
|
||||
int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, ClipPolyType* accum, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles )
|
||||
{
|
||||
TGPolygon base, safe_base;
|
||||
|
||||
|
@ -128,7 +128,7 @@ int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, supe
|
|||
case 1: // asphalt:
|
||||
case 2: // concrete
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Build Runway: asphalt or concrete" << rwy.surface);
|
||||
gen_rwy( rwy_polys, texparams, accum, slivers );
|
||||
gen_rwy( rwy_polys, texparams, accum, slivers, make_shapefiles );
|
||||
gen_runway_lights( rwy_lights );
|
||||
break;
|
||||
|
||||
|
@ -163,8 +163,6 @@ int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, supe
|
|||
|
||||
if (apt_base)
|
||||
{
|
||||
// If we have shoulders, we need to grow even further...
|
||||
|
||||
// generate area around runways
|
||||
base = gen_runway_area_w_extend( 20.0, -rwy.overrun[0], -rwy.overrun[1], 20.0 );
|
||||
base = snap( base, gSnap );
|
||||
|
|
|
@ -41,9 +41,7 @@ public:
|
|||
|
||||
bool GetsShoulder()
|
||||
{
|
||||
if (rwy.surface < 3 || rwy.shoulder > 0)
|
||||
return true;
|
||||
else return false;
|
||||
return (rwy.surface < 3) ? true : false;
|
||||
}
|
||||
|
||||
int BuildBtg( superpoly_list* rwy_polys,
|
||||
|
@ -52,7 +50,8 @@ public:
|
|||
ClipPolyType* accum,
|
||||
poly_list& slivers,
|
||||
TGPolygon* apt_base,
|
||||
TGPolygon* apt_clearing );
|
||||
TGPolygon* apt_clearing,
|
||||
bool make_shapefiles );
|
||||
|
||||
void BuildShoulder( superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
|
@ -91,6 +90,11 @@ private:
|
|||
TGRunway rwy;
|
||||
std::string material_prefix;
|
||||
|
||||
// storage for Shoulders - The superpolys are generated during rwy construction,
|
||||
// but not clipped until shoulder construction.
|
||||
superpoly_list shoulder_polys;
|
||||
texparams_list shoulder_tps;
|
||||
|
||||
// Build Helpers:
|
||||
// generate an area for a runway and include midpoints
|
||||
TGPolygon gen_runway_w_mid( double length_extend_m, double width_extend_m )
|
||||
|
@ -110,7 +114,8 @@ private:
|
|||
superpoly_list* rwy_polys,
|
||||
texparams_list* texparams,
|
||||
ClipPolyType* accum,
|
||||
poly_list& slivers );
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles );
|
||||
|
||||
// generate a section of runway
|
||||
void gen_runway_section( const TGPolygon& runway,
|
||||
|
@ -121,15 +126,28 @@ private:
|
|||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
superpoly_list *shoulder_polys,
|
||||
texparams_list *shoulder_tps,
|
||||
ClipPolyType *accum,
|
||||
poly_list& slivers );
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles );
|
||||
|
||||
// generate a section of shoulder
|
||||
void gen_shoulder_section( Point3D p0, Point3D p1,
|
||||
Point3D t0, Point3D t1,
|
||||
int side,
|
||||
double heading,
|
||||
double width,
|
||||
std::string surface,
|
||||
TGSuperPoly& sp, TGTexParams& tp );
|
||||
|
||||
void gen_simple_rwy( superpoly_list *rwy_polys, texparams_list *texparams, ClipPolyType *accum, poly_list& slivers );
|
||||
|
||||
void gen_rwy( superpoly_list* rwy_polys,
|
||||
texparams_list* texparams,
|
||||
ClipPolyType* accum,
|
||||
poly_list& slivers );
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles );
|
||||
|
||||
void gen_runway_lights( superpoly_list* lights );
|
||||
|
||||
|
|
|
@ -88,6 +88,63 @@ static const struct sections nprec[] = {
|
|||
};
|
||||
|
||||
|
||||
void Runway::gen_shoulder_section( Point3D p0, Point3D p1, Point3D t0, Point3D t1, int side, double heading, double width, std::string surface, TGSuperPoly& sp, TGTexParams& tp )
|
||||
{
|
||||
Point3D s0, s1, s2, s3;
|
||||
TGPolygon poly;
|
||||
|
||||
double wid_hdg = 0.0f;
|
||||
double az2 = 0.0f;
|
||||
double dist = 0.0f;
|
||||
double pt_x = 0.0f;
|
||||
double pt_y = 0.0f;
|
||||
|
||||
// calc heading from p1 to p0
|
||||
geo_inverse_wgs_84( p0.y(), p0.x(), p1.y(), p1.x(), &wid_hdg, &az2, &dist);
|
||||
|
||||
// s0 is width away from t1 in wid_hdg direction
|
||||
geo_direct_wgs_84( t1.y(), t1.x(), wid_hdg, width, &pt_y, &pt_x, &az2 );
|
||||
s0 = Point3D( pt_x, pt_y, 0.0f );
|
||||
|
||||
// s1 is width away from t0 in wid_hdg direction
|
||||
geo_direct_wgs_84( t0.y(), t0.x(), wid_hdg, width, &pt_y, &pt_x, &az2 );
|
||||
s1 = Point3D( pt_x, pt_y, 0.0f );
|
||||
|
||||
// s2 is nudge away from t0 in -wid_hdg direction
|
||||
geo_direct_wgs_84( t0.y(), t0.x(), wid_hdg, -0.01, &pt_y, &pt_x, &az2 );
|
||||
s2 = Point3D( pt_x, pt_y, 0.0f );
|
||||
|
||||
// s3 is nudge away from t1 in -wid_hdg direction
|
||||
geo_direct_wgs_84( t1.y(), t1.x(), wid_hdg, -0.01, &pt_y, &pt_x, &az2 );
|
||||
s3 = Point3D( pt_x, pt_y, 0.0f );
|
||||
|
||||
// Generate a poly
|
||||
poly.erase();
|
||||
poly.add_node( 0, s0 );
|
||||
poly.add_node( 0, s1 );
|
||||
poly.add_node( 0, s2 );
|
||||
poly.add_node( 0, s3 );
|
||||
poly = snap( poly, gSnap );
|
||||
|
||||
sp.erase();
|
||||
sp.set_poly( poly );
|
||||
sp.set_material( surface );
|
||||
sp.set_flag( "shoulder" );
|
||||
|
||||
if (side == 0) {
|
||||
tp = TGTexParams( poly.get_pt(0,2), width, dist, heading );
|
||||
tp.set_minu(0);
|
||||
tp.set_maxu(1);
|
||||
} else {
|
||||
tp = TGTexParams( poly.get_pt(0,1), width, dist, heading );
|
||||
tp.set_minu(1);
|
||||
tp.set_maxu(0);
|
||||
}
|
||||
|
||||
tp.set_minv(0);
|
||||
tp.set_maxv(1);
|
||||
}
|
||||
|
||||
// generate a section of texture
|
||||
void Runway::gen_runway_section( const TGPolygon& runway,
|
||||
double startl_pct, double endl_pct,
|
||||
|
@ -97,12 +154,22 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
const string& material,
|
||||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
superpoly_list *shoulder_polys,
|
||||
texparams_list *shoulder_tps,
|
||||
ClipPolyType *accum,
|
||||
poly_list& slivers )
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles )
|
||||
{
|
||||
int j, k;
|
||||
double width = rwy.width;
|
||||
double length = rwy.length;
|
||||
double lshoulder_width = 0.0f;
|
||||
double rshoulder_width = 0.0f;
|
||||
std::string shoulder_surface = "";
|
||||
|
||||
void* ds_id = NULL; // If we are going to build shapefiles
|
||||
void* l_id = NULL; // datasource and layer IDs
|
||||
static int poly_id = 0; // for naming
|
||||
|
||||
Point3D a0 = runway.get_pt(0, 1);
|
||||
Point3D a1 = runway.get_pt(0, 2);
|
||||
|
@ -115,11 +182,48 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
if ( endl_pct < 1.0 ) {
|
||||
endl_pct += nudge * SG_EPSILON;
|
||||
}
|
||||
|
||||
if ( endl_pct > 1.0 ) {
|
||||
endl_pct = 1.0;
|
||||
}
|
||||
|
||||
if ( make_shapefiles ) {
|
||||
char ds_name[128];
|
||||
sprintf(ds_name, "./rwy_debug");
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
}
|
||||
|
||||
// calculate if we are going to be creating shoulder polys
|
||||
if ( (rwy.shoulder > 0) && (rwy.surface < 3) ){
|
||||
if (rwy.shoulder == 1){
|
||||
shoulder_surface = "pa_shoulder";
|
||||
} else if (rwy.shoulder == 2){
|
||||
shoulder_surface = "pc_shoulder";
|
||||
}
|
||||
|
||||
if ( startw_pct == 0.0f ) {
|
||||
lshoulder_width = 11.0;
|
||||
}
|
||||
if ( endw_pct == 1.0f ) {
|
||||
rshoulder_width = 11.0;
|
||||
}
|
||||
} else {
|
||||
// We add a fake shoulder if the runway has an asphalt or concrete surface
|
||||
if ( (rwy.surface == 1) || (rwy.surface == 2) ) {
|
||||
if (rwy.surface == 1) {
|
||||
shoulder_surface = "pa_shoulder_f";
|
||||
} else if (rwy.surface == 2){
|
||||
shoulder_surface = "pc_shoulder_f";
|
||||
}
|
||||
|
||||
if ( startw_pct == 0.0f ) {
|
||||
lshoulder_width = 1.0;
|
||||
}
|
||||
if ( endw_pct == 1.0f ) {
|
||||
rshoulder_width = 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
|
||||
|
@ -170,6 +274,29 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
Point3D p1 = Point3D( t2.x() + dwx * endw_pct,
|
||||
t2.y() + dwy * endw_pct, 0);
|
||||
|
||||
// check for left shoulder
|
||||
if ( lshoulder_width > 0.0f ) {
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
gen_shoulder_section( p0, p1, t0, t1, 0, heading, lshoulder_width, shoulder_surface, sp, tp );
|
||||
shoulder_polys->push_back( sp );
|
||||
shoulder_tps->push_back( tp );
|
||||
|
||||
/* If debugging this runway, write the shoulder poly */
|
||||
if (ds_id) {
|
||||
poly_id++;
|
||||
|
||||
char layer_name[128];
|
||||
sprintf( layer_name, "lshoulder_%d", poly_id );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
char feature_name[128];
|
||||
sprintf( feature_name, "lshoulder_%d", poly_id);
|
||||
tgShapefileCreateFeature( ds_id, l_id, sp.get_poly(), feature_name );
|
||||
}
|
||||
}
|
||||
|
||||
dwx = t1.x() - t3.x();
|
||||
dwy = t1.y() - t3.y();
|
||||
|
||||
|
@ -179,6 +306,29 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
Point3D p3 = Point3D( t3.x() + dwx * endw_pct,
|
||||
t3.y() + dwy * endw_pct, 0);
|
||||
|
||||
// check for right shoulder
|
||||
if ( rshoulder_width > 0.0f ) {
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
gen_shoulder_section( p1, p0, t2, t3, 1, heading, rshoulder_width, shoulder_surface, sp, tp );
|
||||
shoulder_polys->push_back( sp );
|
||||
shoulder_tps->push_back( tp );
|
||||
|
||||
/* If debugging this runway, write the shoulder poly */
|
||||
if (ds_id) {
|
||||
poly_id++;
|
||||
|
||||
char layer_name[128];
|
||||
sprintf( layer_name, "rshoulder_%d", poly_id );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
char feature_name[128];
|
||||
sprintf( feature_name, "rshoulder_%d", poly_id);
|
||||
tgShapefileCreateFeature( ds_id, l_id, sp.get_poly(), feature_name );
|
||||
}
|
||||
}
|
||||
|
||||
TGPolygon section;
|
||||
section.erase();
|
||||
|
||||
|
@ -188,6 +338,18 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
section.add_node( 0, p3 );
|
||||
section = snap( section, gSnap );
|
||||
|
||||
/* If debugging this runway, write the shoulder poly */
|
||||
if (ds_id) {
|
||||
char layer_name[128];
|
||||
sprintf( layer_name, "poly_%d", poly_id );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
char feature_name[128];
|
||||
sprintf( feature_name, "section_%d", poly_id);
|
||||
tgShapefileCreateFeature( ds_id, l_id, section, feature_name );
|
||||
}
|
||||
|
||||
|
||||
// print runway points
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "pre clipped runway pts " << material_prefix << material);
|
||||
for ( j = 0; j < section.contours(); ++j ) {
|
||||
|
@ -212,6 +374,7 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
sp.set_poly( split );
|
||||
sp.set_material( material_prefix + material );
|
||||
rwy_polys->push_back( sp );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "section = " << clipped.contours());
|
||||
|
||||
*accum = tgPolygonUnionClipper( section, *accum );
|
||||
|
@ -246,6 +409,10 @@ void Runway::gen_runway_section( const TGPolygon& runway,
|
|||
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
|
||||
}
|
||||
}
|
||||
|
||||
if (ds_id) {
|
||||
tgShapefileCloseDatasource( ds_id );
|
||||
}
|
||||
}
|
||||
|
||||
void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
||||
|
@ -253,7 +420,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
|||
superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
ClipPolyType *accum,
|
||||
poly_list& slivers )
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles )
|
||||
{
|
||||
if (rwname != "XX") { /* Do not create a designation block if the runway name is set to none */
|
||||
string letter = "";
|
||||
|
@ -277,7 +445,10 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
letter,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
|
||||
|
||||
|
@ -304,14 +475,20 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
tex1,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
gen_runway_section( poly,
|
||||
start_pct, end_pct,
|
||||
0.5, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
tex2,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
|
||||
} else if (rwname.length() == 1) {
|
||||
sprintf( tex1, "%c%c", rwname[0], 'c');
|
||||
|
@ -322,7 +499,10 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
tex1,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +514,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
|
|||
void Runway::gen_rwy( superpoly_list *rwy_polys,
|
||||
texparams_list *texparams,
|
||||
ClipPolyType *accum,
|
||||
poly_list& slivers )
|
||||
poly_list& slivers,
|
||||
bool make_shapefiles )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Building runway = " << rwy.rwnum[0] << " / " << rwy.rwnum[1]);
|
||||
|
||||
|
@ -429,7 +610,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, tex_pct, 1.0,
|
||||
heading,
|
||||
"dspl_thresh",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
|
||||
// main chunks
|
||||
for ( int i = 0; i < count; ++i ) {
|
||||
|
@ -441,7 +625,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
"dspl_thresh",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
|
||||
// final arrows
|
||||
|
@ -453,7 +640,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
"dspl_arrows",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
|
||||
if (rwy.marking[rwhalf] == 0) {
|
||||
|
@ -466,7 +656,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
"no_threshold",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
} else {
|
||||
// Thresholds for all others
|
||||
start1_pct = end1_pct;
|
||||
|
@ -477,13 +670,17 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
"threshold",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
|
||||
// Runway designation block
|
||||
gen_rw_designation( runway_half, heading,
|
||||
rwname, start1_pct, end1_pct,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams, accum, slivers,
|
||||
make_shapefiles );
|
||||
|
||||
// Generate remaining markings depending on type of runway
|
||||
if (rwy.marking[rwhalf] > 1) {
|
||||
|
@ -521,7 +718,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
rw_marking_list[i].tex,
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +747,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0,
|
||||
heading,
|
||||
"rest",
|
||||
rwy_polys, texparams, accum, slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
|
||||
start1_pct = 0.0;
|
||||
|
@ -574,10 +777,10 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
|
|||
0.0, 1.0, 0.0, 1.0, //last number is lengthwise
|
||||
heading,
|
||||
"stopway",
|
||||
rwy_polys,
|
||||
texparams,
|
||||
accum,
|
||||
slivers );
|
||||
rwy_polys, texparams,
|
||||
&shoulder_polys, &shoulder_tps,
|
||||
accum, slivers,
|
||||
make_shapefiles );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,157 +794,36 @@ void Runway::BuildShoulder( superpoly_list *rwy_polys,
|
|||
TGPolygon* apt_clearing )
|
||||
{
|
||||
TGPolygon base, safe_base;
|
||||
TGPolygon shoulder;
|
||||
|
||||
string shoulder_surface = "";
|
||||
double shoulder_width = 0.0f;
|
||||
for (unsigned int i=0; i<shoulder_polys.size(); i++) {
|
||||
shoulder = shoulder_polys[i].get_poly();
|
||||
|
||||
if (rwy.shoulder > 0){
|
||||
// Add a shoulder to the runway
|
||||
shoulder_width = 11.0f;
|
||||
// Clip the new polygon against what ever has already been created.
|
||||
TGPolygon clipped = tgPolygonDiffClipper( shoulder, *accum );
|
||||
tgPolygonFindSlivers( clipped, slivers );
|
||||
|
||||
if (rwy.shoulder == 1){
|
||||
shoulder_surface = "pa_shoulder";
|
||||
} else if (rwy.shoulder == 2){
|
||||
shoulder_surface = "pc_shoulder";
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown shoulder surface code = " << rwy.shoulder );
|
||||
// Split long edges to create an object that can better flow with
|
||||
// the surface terrain
|
||||
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
|
||||
shoulder_polys[i].set_poly( split );
|
||||
|
||||
rwy_polys->push_back( shoulder_polys[i] );
|
||||
texparams->push_back( shoulder_tps[i] );
|
||||
|
||||
*accum = tgPolygonUnionClipper( shoulder, *accum );
|
||||
|
||||
if (apt_base)
|
||||
{
|
||||
// also clear a safe area around the runway
|
||||
base = tgPolygonExpand( shoulder, 20.0);
|
||||
safe_base = tgPolygonExpand( shoulder, 50.0);
|
||||
|
||||
// add this to the airport clearing
|
||||
*apt_clearing = tgPolygonUnionClipper( safe_base, *apt_clearing );
|
||||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnionClipper( base, *apt_base );
|
||||
}
|
||||
} else {
|
||||
// We add a fake shoulder if the runway has an asphalt or concrete surface
|
||||
shoulder_width = 1.0;
|
||||
if (rwy.surface == 1){
|
||||
shoulder_surface = "pa_shoulder_f";
|
||||
} else if (rwy.surface == 2){
|
||||
shoulder_surface = "pc_shoulder_f";
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder width = " << shoulder_width );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder surface is: " << shoulder_surface );
|
||||
|
||||
if (shoulder_width > 0.0f) {
|
||||
// we need to break these shoulders up into managable pieces, as we're asked to triangulate
|
||||
// 3-4 km long by 1m wide strips - jrs-can't handle it.
|
||||
double max_dist = (double)shoulder_width * 25.0f;
|
||||
if (max_dist > 100.0f) {
|
||||
max_dist = 100.0f;
|
||||
}
|
||||
int numSegs = (rwy.length / max_dist) + 1;
|
||||
double dist = rwy.length / numSegs;
|
||||
|
||||
TGPolygon poly;
|
||||
TGSuperPoly sp;
|
||||
TGTexParams tp;
|
||||
|
||||
double lat = 0.0f;
|
||||
double lon = 0.0f;
|
||||
double r = 0.0f;
|
||||
Point3D inner_start, inner_end;
|
||||
Point3D outer_start, outer_end;
|
||||
Point3D curInnerLoc, nextInnerLoc;
|
||||
Point3D curOuterLoc, nextOuterLoc;
|
||||
|
||||
// Create two paralell lines from start position to end position, and interpolate in between
|
||||
// many airports line the taxiway directly to the corner of the runway. This can create problems,
|
||||
// so extend the shoulders 0.5 meters past each end of the runway
|
||||
for (int i=0; i<2; i++) {
|
||||
double rev_hdg = rwy.heading - 180.0;
|
||||
if ( rev_hdg < 0 ) { rev_hdg += 360.0; }
|
||||
|
||||
if (i == 0) {
|
||||
// left side
|
||||
double left_hdg = rwy.heading - 90.0;
|
||||
if ( left_hdg < 0 ) { left_hdg += 360.0; }
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy.lat[0], rwy.lon[0], left_hdg, rwy.width*.5, &lat, &lon, &r );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rev_hdg, 0.5f, &lat, &lon, &r );
|
||||
|
||||
inner_start = Point3D( lon, lat, 0.0f );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rwy.heading, rwy.length+1.0f, &lat, &lon, &r );
|
||||
inner_end = Point3D( lon, lat, 0.0f );
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy.lat[0], rwy.lon[0], left_hdg, rwy.width*.5 + shoulder_width, &lat, &lon, &r );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rev_hdg, 0.5f, &lat, &lon, &r );
|
||||
|
||||
outer_start = Point3D( lon, lat, 0.0f );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rwy.heading, rwy.length+1.0f, &lat, &lon, &r );
|
||||
outer_end = Point3D( lon, lat, 0.0f );
|
||||
} else {
|
||||
// right side
|
||||
double right_hdg = rwy.heading + 90.0;
|
||||
if ( right_hdg > 360 ) { right_hdg -= 360.0; }
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy.lat[0], rwy.lon[0], right_hdg, rwy.width*.5, &lat, &lon, &r );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rev_hdg, 0.5f, &lat, &lon, &r );
|
||||
|
||||
inner_start = Point3D( lon, lat, 0.0f );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rwy.heading, rwy.length+1.0f, &lat, &lon, &r );
|
||||
inner_end = Point3D( lon, lat, 0.0f );
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy.lat[0], rwy.lon[0], right_hdg, rwy.width*.5 + shoulder_width, &lat, &lon, &r );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rev_hdg, 0.5f, &lat, &lon, &r );
|
||||
|
||||
outer_start = Point3D( lon, lat, 0.0f );
|
||||
geo_direct_wgs_84 ( 0, lat, lon, rwy.heading, rwy.length+1.0f, &lat, &lon, &r );
|
||||
outer_end = Point3D( lon, lat, 0.0f );
|
||||
}
|
||||
|
||||
curInnerLoc = inner_start;
|
||||
curOuterLoc = outer_start;
|
||||
|
||||
for (int p=0; p<numSegs; p++)
|
||||
{
|
||||
// calculate next locations
|
||||
nextInnerLoc = CalculateLinearLocation( inner_start, inner_end, (1.0f/numSegs) * (p+1) );
|
||||
nextOuterLoc = CalculateLinearLocation( outer_start, outer_end, (1.0f/numSegs) * (p+1) );
|
||||
|
||||
// Generate a poly
|
||||
poly.erase();
|
||||
if (i == 0 ) {
|
||||
poly.add_node( 0, curInnerLoc );
|
||||
poly.add_node( 0, nextInnerLoc );
|
||||
poly.add_node( 0, nextOuterLoc );
|
||||
poly.add_node( 0, curOuterLoc );
|
||||
} else {
|
||||
poly.add_node( 0, curOuterLoc );
|
||||
poly.add_node( 0, nextOuterLoc );
|
||||
poly.add_node( 0, nextInnerLoc );
|
||||
poly.add_node( 0, curInnerLoc );
|
||||
}
|
||||
|
||||
TGPolygon clipped = tgPolygonDiffClipper( poly, *accum );
|
||||
tgPolygonFindSlivers( clipped, slivers );
|
||||
|
||||
sp.erase();
|
||||
sp.set_poly( clipped );
|
||||
sp.set_material( shoulder_surface );
|
||||
rwy_polys->push_back( sp );
|
||||
|
||||
*accum = tgPolygonUnionClipper( poly, *accum );
|
||||
|
||||
tp = TGTexParams( poly.get_pt(0,0), shoulder_width, dist, rwy.heading );
|
||||
tp.set_maxv(dist);
|
||||
// reverse u direction for right side
|
||||
if ( i == 1 ) {
|
||||
tp.set_maxu(0);
|
||||
tp.set_minu(1);
|
||||
}
|
||||
texparams->push_back( tp );
|
||||
|
||||
// Add to base / safe base
|
||||
base = tgPolygonExpand( poly, 20.0f );
|
||||
safe_base = tgPolygonExpand( poly, 50.0f );
|
||||
|
||||
// add this to the airport clearing
|
||||
*apt_clearing = tgPolygonUnionClipper(safe_base, *apt_clearing);
|
||||
|
||||
// and add the clearing to the base
|
||||
*apt_base = tgPolygonUnionClipper( base, *apt_base );
|
||||
|
||||
// now set cur locations for the next iteration
|
||||
curInnerLoc = nextInnerLoc;
|
||||
curOuterLoc = nextOuterLoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,9 @@ void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
|
|||
heading,
|
||||
"",
|
||||
rwy_polys, texparams,
|
||||
accum, slivers );
|
||||
NULL, NULL,
|
||||
accum, slivers,
|
||||
false );
|
||||
}
|
||||
|
||||
// Generate runway
|
||||
|
@ -101,7 +103,8 @@ void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
|
|||
heading,
|
||||
"",
|
||||
rwy_polys, texparams,
|
||||
accum, slivers );
|
||||
|
||||
NULL, NULL,
|
||||
accum, slivers,
|
||||
false );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue