1
0
Fork 0

genapts port complete - time to debug

This commit is contained in:
Peter Sadrozinski 2012-10-25 17:04:37 -04:00 committed by Christian Schmitt
parent 820c9a6b5d
commit 608057596b
27 changed files with 4034 additions and 2284 deletions

File diff suppressed because it is too large Load diff

View file

@ -110,7 +110,7 @@ public:
tm = cleanup_time;
}
void merge_slivers( superpoly_list& polys, poly_list& slivers );
void merge_slivers( tgpolygon_list& polys, tgcontour_list& slivers );
void BuildBtg( const string& root, const string_list& elev_src );
void SetDebugPolys( int rwy, int taxi, int pvmt, int feat, int base );

View file

@ -18,149 +18,123 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <Geometry/poly_support.hxx>
#include "apt_math.hxx"
#include "global.hxx"
#include <stdlib.h>
using std::string;
TGPolygon gen_wgs84_area( SGGeod origin,
tgContour gen_wgs84_area( SGGeod origin,
double length_m,
double displ1, double displ2,
double width_m,
double heading_deg,
bool add_mid )
{
TGPolygon result_list;
tgContour result;
double length_hdg = heading_deg;
double left_hdg = length_hdg - 90.0;
if ( left_hdg < 0 ) { left_hdg += 360.0; }
double left_hdg = SGMiscd::normalizePeriodic(0, 360, length_hdg - 90.0);
// move to the +l end/center of the runway
SGGeod ref = SGGeodesy::direct( origin, length_hdg, length_m / 2.0 - displ2 );
// move to the l,-w corner (then we add points in a clockwise direction)
SGGeod p = SGGeodesy::direct( ref, left_hdg, -width_m / 2.0) ;
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, -width_m / 2.0) );
// move to the l,w corner
p = SGGeodesy::direct( ref, left_hdg, width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, width_m / 2.0 ) );
if ( add_mid ) {
// move to the 0,w point (then we add points in a clockwise direction)
p = SGGeodesy::direct( origin, left_hdg, width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( origin, left_hdg, width_m / 2.0 ) );
}
// move to the -l end/center of the runway
ref = SGGeodesy::direct( origin, length_hdg, displ1 - length_m/2.0);
// move to the -l,w corner (then we add points in a clockwise direction)
p = SGGeodesy::direct( ref, left_hdg, width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, width_m / 2.0 ) );
// move to the -l,-w corner
p = SGGeodesy::direct( ref, left_hdg, -width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, -width_m / 2.0 ) );
if ( add_mid ) {
// move to the 0,-w point (then we add points in a clockwise direction)
p = SGGeodesy::direct( origin, left_hdg, -width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( origin, left_hdg, -width_m / 2.0 ) );
}
return result_list;
result.SetHole( false );
return result;
}
TGPolygon gen_wgs84_area( SGGeod end1, SGGeod end2,
tgContour gen_wgs84_area( SGGeod end1, SGGeod end2,
double length_m,
double displ1, double displ2,
double width_m,
double heading_deg,
bool add_mid )
{
TGPolygon result_list;
double left_hdg = heading_deg - 90.0;
if ( left_hdg < 0 ) { left_hdg += 360.0; }
tgContour result;
double left_hdg = SGMiscd::normalizePeriodic( 0, 360, heading_deg - 90.0 );
double course1, course2, distance;
SGGeodesy::inverse(end1, end2, course1, course2, distance);
// Calc the center
SGGeod center = SGGeodesy::direct(end1, course1, distance/2 );
// move from end2 to the displaced threshold
SGGeod ref = SGGeodesy::direct( end2, heading_deg, length_m / 2.0 - displ2);
// move to the l,-w corner
SGGeod p = SGGeodesy::direct(ref, left_hdg, -width_m / 2.0);
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct(ref, left_hdg, -width_m / 2.0) );
// move to the l,w corner
p = SGGeodesy::direct(ref, left_hdg, width_m / 2.0);
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct(ref, left_hdg, width_m / 2.0) );
if ( add_mid ) {
// move to the 0,w point
p = SGGeodesy::direct( center, left_hdg, width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( center, left_hdg, width_m / 2.0 ) );
}
// move to the end1 center to the displ. threshold
ref = SGGeodesy::direct( end1, heading_deg, displ1 - length_m / 2.0 );
// move to the -l,w corner
p = SGGeodesy::direct( ref, left_hdg, width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, width_m / 2.0 ) );
// move to the -l,-w corner
p = SGGeodesy::direct( ref, left_hdg, -width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( ref, left_hdg, -width_m / 2.0 ) );
if ( add_mid ) {
// move to the 0,-w point
p = SGGeodesy::direct( center, left_hdg, -width_m / 2.0 );
result_list.add_node( 0, Point3D::fromSGGeod(p) );
result.AddNode( SGGeodesy::direct( center, left_hdg, -width_m / 2.0 ) );
}
return result_list;
return result;
}
TGPolygon gen_wgs84_rect( double lat, double lon, double heading, double length, double width )
tgContour gen_wgs84_rect( double lat, double lon, double heading, double length, double width )
{
TGPolygon result_list;
double ptlat = 0.0f;
double ptlon = 0.0f;
double r = 0.0f;
Point3D p;
tgContour result;
SGGeod ref = SGGeod::fromDeg(lon, lat);
SGGeod p;
// starting point is in the middle of the rectangle width, at the beginning - stretch to heading
// Point 1 is -90deg, 1/2 width away
double left_hdg = heading -90;
if ( left_hdg < 0 ) { left_hdg += 360.0; }
geo_direct_wgs_84 ( 0.0, lat, lon, left_hdg, width / 2.0, &ptlat, &ptlon, &r );
p = Point3D( ptlon, ptlat, 0.0 );
result_list.add_node( 0, p );
double left_hdg = SGMiscd::normalizePeriodic(0, 360, heading -90 );
p = SGGeodesy::direct( ref, left_hdg, width / 2.0 );
result.AddNode( p );
// Point 2 is heading, length away from point 1
geo_direct_wgs_84 ( 0.0, ptlat, ptlon, heading, length, &ptlat, &ptlon, &r );
p = Point3D( ptlon, ptlat, 0.0 );
result_list.add_node( 0, p );
p = SGGeodesy::direct( p, heading, length );
result.AddNode( p );
// Point 3 is -90deg, -width away from point 2
geo_direct_wgs_84 ( 0.0, ptlat, ptlon, left_hdg, -width, &ptlat, &ptlon, &r );
p = Point3D( ptlon, ptlat, 0.0 );
result_list.add_node( 0, p );
p = SGGeodesy::direct( p, left_hdg, -width );
result.AddNode( p );
// last point is heading, -length from point 3
geo_direct_wgs_84 ( 0.0, ptlat, ptlon, heading, -length, &ptlat, &ptlon, &r );
p = Point3D( ptlon, ptlat, 0.0 );
result_list.add_node( 0, p );
p = SGGeodesy::direct( p, heading, -length );
result.AddNode( p );
return result_list;
result.SetHole( false );
return result;
}

View file

@ -12,7 +12,7 @@
using std::string;
TGPolygon gen_wgs84_area( SGGeod origin,
tgContour gen_wgs84_area( SGGeod origin,
double length_m,
double displ1,
double displ2,
@ -20,28 +20,14 @@ TGPolygon gen_wgs84_area( SGGeod origin,
double heading_deg,
bool add_mid );
// This function uses the 2 runway end points for calculation, which
// yields a higher precision
TGPolygon gen_wgs84_area( SGGeod end1, SGGeod end2,
tgContour gen_wgs84_area( SGGeod end1, SGGeod end2,
double length_m,
double displ1, double displ2,
double width_m,
double heading_deg,
bool add_mid );
TGPolygon gen_wgs84_rect( double lat, double lon, double heading, double length, double width );
tgContour gen_wgs84_rect( double lat, double lon, double heading, double length, double width );
void gen_tex_section( 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, double width, double length,
const string& prefix,
const string& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
ClipPolyType *accum,
poly_list& slivers );
#endif

View file

@ -135,7 +135,7 @@ void ClosedPoly::CloseCurContour()
}
}
void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
void ClosedPoly::ConvertContour( BezContour* src, tgContour& dst )
{
BezNode* curNode;
BezNode* nextNode;
@ -152,7 +152,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating a contour with " << src->size() << " nodes");
// clear anything in this point list
dst->empty();
dst.Erase();
// iterate through each bezier node in the contour
for (unsigned int i = 0; i <= src->size()-1; i++)
@ -273,7 +273,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
// add the pavement vertex
// convert from lat/lon to geo
// (maybe later) - check some simgear objects...
dst->push_back( Point3D::fromSGGeod(curLoc) );
dst.AddNode( curLoc );
if (p==0)
{
@ -298,7 +298,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
nextLoc = CalculateLinearLocation( curNode->GetLoc(), nextNode->GetLoc(), (1.0f/num_segs) * (p+1) );
// add the feature vertex
dst->push_back( Point3D::fromSGGeod(curLoc) );
dst.AddNode( curLoc );
if (p==0)
{
@ -318,7 +318,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
nextLoc = nextNode->GetLoc();
// just add the one vertex - dist is small
dst->push_back( Point3D::fromSGGeod(curLoc) );
dst.AddNode( curLoc );
SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at " << curLoc );
@ -331,7 +331,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
// finish the poly - convert to TGPolygon, and tesselate
void ClosedPoly::Finish()
{
point_list dst_contour;
tgContour dst_contour;
// error handling
if (boundary == NULL)
@ -340,25 +340,27 @@ void ClosedPoly::Finish()
}
SG_LOG(SG_GENERAL, SG_DEBUG, "Converting a poly with " << holes.size() << " holes");
if (boundary != NULL)
{
// create the boundary
ConvertContour( boundary, &dst_contour );
ConvertContour( boundary, dst_contour );
dst_contour.SetHole( false );
// and add it to the geometry
pre_tess.add_contour( dst_contour, 0 );
pre_tess.AddContour( dst_contour );
// Then convert the hole contours
for (unsigned int i=0; i<holes.size(); i++)
{
dst_contour.clear();
ConvertContour( holes[i], &dst_contour );
pre_tess.add_contour( dst_contour, 1 );
ConvertContour( holes[i], dst_contour );
dst_contour.SetHole( true );
pre_tess.AddContour( dst_contour );
}
pre_tess = snap( pre_tess, gSnap );
pre_tess = remove_dups( pre_tess );
pre_tess = tgPolygon::Snap( pre_tess, gSnap );
pre_tess = tgPolygon::RemoveDups( pre_tess );
}
// save memory by deleting unneeded resources
@ -377,170 +379,111 @@ void ClosedPoly::Finish()
delete holes[i]->at(j);
}
}
holes.clear();
}
int ClosedPoly::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles )
std::string ClosedPoly::GetMaterial( int surface )
{
TGPolygon base, safe_base;
std::string material;
switch( surface ) {
case 1:
material = "pa_tiedown";
break;
string material;
void* ds_id = NULL; // If we are going to build shapefiles
void* l_id = NULL; // datasource and layer IDs
case 2:
material = "pc_tiedown";
break;
if ( make_shapefiles ) {
char ds_name[128];
sprintf(ds_name, "./cp_debug");
ds_id = tgShapefileOpenDatasource( ds_name );
case 3:
material = "grass_rwy";
break;
// TODO Differentiate more here:
case 4:
case 5:
case 12:
case 13:
case 14:
case 15:
material = "grass_rwy";
break;
default:
SG_LOG(SG_GENERAL, SG_ALERT, "ClosedPoly::BuildBtg: unknown surface type " << surface_type );
exit(1);
}
if (is_pavement)
return material;
}
int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, bool make_shapefiles )
{
if (is_pavement && pre_tess.Contours() )
{
switch( surface_type )
{
case 1:
material = "pa_tiedown";
break;
tgPolygon base, safe_base;
case 2:
material = "pc_tiedown";
break;
BuildBtg( rwy_polys, slivers, make_shapefiles );
case 3:
material = "grass_rwy";
break;
// TODO Differentiate more here:
case 4:
case 5:
case 12:
case 13:
case 14:
case 15:
material = "grass_rwy";
break;
base = tgPolygon::Expand( pre_tess, 20.0 );
safe_base = tgPolygon::Expand( pre_tess, 50.0);
default:
SG_LOG(SG_GENERAL, SG_ALERT, "ClosedPoly::BuildBtg: unknown surface type " << surface_type );
exit(1);
}
// add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing);
// verify the poly has been generated
if ( pre_tess.contours() )
{
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours" << " and " << pre_tess.total_size() << " points" );
// do this before clipping and generating the base
// pre_tess = tgPolygonSimplify( pre_tess );
// pre_tess = reduce_degeneracy( pre_tess );
TGSuperPoly sp;
TGTexParams tp;
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "original" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "original" );
tgShapefileCreateFeature( ds_id, l_id, pre_tess, feature_name );
}
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( pre_tess );
tgPolygonFindSlivers( clipped, slivers );
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours());
sp.erase();
sp.set_poly( clipped );
sp.set_material( material );
//sp.set_flag("taxi");
rwy_polys->push_back( sp );
tgPolygonAddToClipperAccumulator( pre_tess, false );
/* If debugging this poly, write the poly, and clipped poly and the accum buffer into their own layers */
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "clipped" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "clipped" );
tgShapefileCreateFeature( ds_id, l_id, clipped, feature_name );
}
SG_LOG(SG_GENERAL, SG_DEBUG, "tp construct");
tp = TGTexParams( pre_tess.get_pt(0,0).toSGGeod(), 5.0, 5.0, texture_heading );
texparams->push_back( tp );
if ( apt_base )
{
base = tgPolygonExpand( pre_tess, 20.0);
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "exp_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_base" );
tgShapefileCreateFeature( ds_id, l_id, base, feature_name );
}
safe_base = tgPolygonExpand( pre_tess, 50.0);
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
SG_LOG(SG_GENERAL, SG_INFO, "expanded safe poly: " << safe_base);
sprintf( layer_name, "exp_safe_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_safe_base" );
tgShapefileCreateFeature( ds_id, l_id, safe_base, feature_name );
}
// 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 );
}
if ( make_shapefiles )
{
tgShapefileCloseDatasource( ds_id );
}
}
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
}
// clean up to save ram : we're done here...
return 1;
}
int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, bool make_shapefiles )
{
if ( is_pavement && pre_tess.Contours() )
{
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.Contours() << " contours" << " and " << pre_tess.TotalNodes() << " points" );
tgPolygon clipped = tgPolygon::DiffWithAccumulator( pre_tess );
tgPolygon::RemoveSlivers( clipped, slivers );
clipped.SetMaterial( GetMaterial( surface_type ) );
clipped.SetTexParams( clipped.GetNode(0,0), 5.0, 5.0, texture_heading );
clipped.SetTexLimits( 0.0, 0.0, 1.0, 1.0 );
clipped.SetTexMethod( TG_TEX_BY_TPS_NOCLIP );
rwy_polys.push_back( clipped );
tgPolygon::AddToAccumulator( pre_tess );
}
// clean up to save ram : we're done here...
return 1;
}
// Just used for user defined border - add a little bit, as some modelers made the border exactly on the edges
// - resulting in no base, which we can't handle
int ClosedPoly::BuildBtg( TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles )
int ClosedPoly::BuildBtg( tgPolygon& apt_base, tgPolygon& apt_clearing, bool make_shapefiles )
{
TGPolygon base, safe_base;
tgPolygon base, safe_base;
// verify the poly has been generated
if ( pre_tess.contours() )
// verify the poly has been generated, and the contour isn't a pavement
if ( !is_pavement && pre_tess.Contours() )
{
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours");
base = tgPolygonExpand( pre_tess, 2.0);
safe_base = tgPolygonExpand( pre_tess, 5.0);
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.Contours() << " contours");
base = tgPolygon::Expand( pre_tess, 2.0);
safe_base = tgPolygon::Expand( pre_tess, 5.0);
// add this to the airport clearing
*apt_clearing = tgPolygonUnionClipper( safe_base, *apt_clearing);
apt_clearing = tgPolygon::Union( safe_base, apt_clearing);
// and add the clearing to the base
*apt_base = tgPolygonUnionClipper( base, *apt_base );
apt_base = tgPolygon::Union( base, apt_base );
}
return 1;
}
}

View file

@ -25,10 +25,20 @@ public:
void Finish();
// Build BTG for airport base for airports with boundary
int BuildBtg( TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles );
int BuildBtg( tgPolygon& apt_base,
tgPolygon& apt_clearing,
bool make_shapefiles );
// Build BTG for pavements for airports with no boundary
int BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles );
int BuildBtg( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles );
int BuildBtg( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing,
bool make_shapefiles );
FeatureList* GetFeatures()
{
@ -38,13 +48,15 @@ public:
private:
// convert the BezierPoly to a normal Poly (adding nodes for the curves)
void CreateConvexHull( void );
void ConvertContour( BezContour* src, point_list *dst );
void ConvertContour( BezContour* src, tgContour& dst );
void ExpandContour( point_list& src, TGPolygon& dst, double dist );
std::string GetMaterial( int surface );
bool is_pavement;
int surface_type;
float smoothness;
float texture_heading;
double texture_heading;
string description;
// outer boundary definition as bezier nodes
@ -60,7 +72,7 @@ private:
point_list hull;
// Converted polygon after parsing complete
TGPolygon pre_tess;
tgPolygon pre_tess;
// pavement definitions have multiple linear features (markings and lights for each contour)
LinearFeature* cur_feature;

View file

@ -40,7 +40,8 @@ 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 );
}
superpoly_list Helipad::gen_helipad_lights(double maxsize){
tglightcontour_list Helipad::gen_helipad_lights(double maxsize){
tglightcontour_list result;
point_list y_lights; y_lights.clear();
point_list y_normals; y_normals.clear();
@ -50,71 +51,58 @@ superpoly_list Helipad::gen_helipad_lights(double maxsize){
// Create yellow edge lights, 5m spacing
int divs = (int)(maxsize / 5.0);
TGPolygon area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
tgContour area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
Point3D pt, inc;
tgLightContour yellow;
yellow.SetType( "RWY_YELLOW_LIGHTS" );
for ( unsigned int i = 0; i < area.GetSize(); ++i ) {
pt = Point3D::fromSGGeod( area.GetNode( i ) );
inc = (Point3D::fromSGGeod( area.GetNode( i==3 ? 0 : i+1) ) - Point3D::fromSGGeod( area.GetNode(i) ) ) / divs;
for ( int i = 0; i < area.contour_size( 0 ); ++i ) {
pt = area.get_pt( 0, i );
inc = (area.get_pt(0, i==3 ? 0 : i+1) - area.get_pt(0,i)) / divs;
for ( int j = 0; j < divs; ++j) {
y_lights.push_back( pt);
y_normals.push_back(Point3D::fromSGVec3(vec));
yellow.AddLight( pt.toSGGeod(), vec );
pt += inc;
}
}
// Create a circle of yellow lights where the white texture circle is
for (int deg = 0; deg < 360; deg += 45){
y_lights.push_back( Point3D::fromSGGeod( SGGeodesy::direct(GetLoc(), deg, maxsize * 0.46)) );
y_normals.push_back( Point3D::fromSGVec3(vec) );
yellow.AddLight( SGGeodesy::direct(GetLoc(), deg, maxsize * 0.46), vec );
}
TGPolygon lights_poly; lights_poly.erase();
TGPolygon normals_poly; normals_poly.erase();
lights_poly.add_contour( y_lights, false );
normals_poly.add_contour( y_normals, false );
TGSuperPoly yellow;
yellow.set_poly( lights_poly );
yellow.set_normals( normals_poly );
yellow.set_material( "RWY_YELLOW_LIGHTS" );
superpoly_list result; result.clear();
result.push_back( yellow );
return result;
}
void Helipad::WriteGeom( TGPolygon polygon, string material,
superpoly_list *rwy_polys,
poly_list& slivers )
tgPolygon Helipad::WriteGeom( const tgContour& area, string material,
tgpolygon_list& rwy_polys,
tgcontour_list& slivers )
{
// Clip the new polygon against what ever has already been created.
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( polygon );
tgPolygonFindSlivers( clipped, slivers );
tgPolygon clipped = tgContour::DiffWithAccumulator( area );
tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with
// the surface terrain
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
tgPolygon split = tgPolygon::SplitLongEdges( 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 );
rwy_polys->push_back( sp );
split.SetMaterial( material );
rwy_polys.push_back( split );
tgPolygonAddToClipperAccumulator( polygon, false );
tgContour::AddToAccumulator( area );
return split;
}
void Helipad::BuildBtg( superpoly_list *rwy_polys,
texparams_list *texparams,
superpoly_list *rwy_lights,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing )
void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing )
{
//
// Generate the basic helipad outlines
@ -133,67 +121,61 @@ void Helipad::BuildBtg( superpoly_list *rwy_polys,
area_side = true;
}
TGPolygon helipad = gen_wgs84_area( GetLoc(), maxsize, 0, 0, maxsize, heli.heading, false);
helipad = snap( helipad, gSnap );
tgContour helipad = gen_wgs84_area( GetLoc(), maxsize, 0, 0, maxsize, heli.heading, false);
helipad = tgContour::Snap( helipad, gSnap );
string material, shoulder_mat;
if (heli.surface == 1)
material = "pa_";
else
material = "pc_";
// write out
WriteGeom( helipad, material + "heli", rwy_polys, slivers);
TGTexParams tp;
tp = TGTexParams( helipad.get_pt(0,0).toSGGeod(), maxsize, maxsize, heli.heading );
tp.set_minu( 1 );
tp.set_maxu( 0 );
tp.set_minv( 1 );
tp.set_maxv( 0 );
texparams->push_back( tp );
// write out
tgPolygon result = WriteGeom( helipad, material + "heli", rwy_polys, slivers);
result.SetTexParams( helipad.GetNode(0), maxsize, maxsize, heli.heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( result );
int i = 0;
double heading = 0, areahight = 0;
TGPolygon heli_area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
heli_area = snap( heli_area, gSnap );
TGPolygon area_poly; area_poly.erase();
point_list area; area.clear();
tgContour heli_area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
heli_area = tgContour::Snap( heli_area, gSnap );
tgcontour_list area_contours;
tgContour area;
if (area_top || area_side) {
if (area_top) {
areahight = (heli.length - maxsize) /2;
heading = heli.heading;
heading = SGMiscd::normalizePeriodic( 0, 360, heli.heading-90 );
i = 0;
} else {
areahight = (heli.width - maxsize) /2;
heading = heli.heading - 90;
if ( heading < 0.0 ) { heading += 360.0; }
heading = SGMiscd::normalizePeriodic( 0, 360, heli.heading-90 );
i = 1;
}
for (;i<4; ++i) {
area.push_back( heli_area.get_pt( 0,i ) );
area.push_back( heli_area.get_pt( 0,i == 3? 0 : i+1 ) );
area.push_back( helipad.get_pt( 0,i == 3? 0 : i+1) );
area.push_back( helipad.get_pt( 0,i ) );
area_poly.add_contour( area, false );
area.clear();
area.Erase();
area.AddNode( heli_area.GetNode( i ) );
area.AddNode( heli_area.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( helipad.GetNode( i == 3 ? 0 : i+1) );
area.AddNode( helipad.GetNode( i ) );
area.SetHole( false );
area_contours.push_back( area );
i++;
}
TGPolygon area_geom;
tgPolygon result;
for (i = 0; i < 2; ++i) {
area_geom.add_contour(area_poly.get_contour(i), false);
WriteGeom( area_geom, material + "tiedown", rwy_polys, slivers);
tp = TGTexParams( area_poly.get_pt(i,0).toSGGeod(), maxsize, areahight, heading );
tp.set_minu( 1 );
tp.set_maxu( 0 );
tp.set_minv( 1 );
tp.set_maxv( 0 );
texparams->push_back( tp );
area_geom.erase();
heading += 180;
if ( heading > 360.0 ) { heading -= 360.0; }
result = WriteGeom( area_contours[i], material + "tiedown", rwy_polys, slivers);
result.SetTexParams( area_contours[i].GetNode(0), maxsize, areahight, heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( result );
heading = SGMiscd::normalizePeriodic(0, 360, heading + 180 );
}
}
@ -208,7 +190,6 @@ void Helipad::BuildBtg( superpoly_list *rwy_polys,
areahight = 1; // fake shoulder size in m
}
TGSuperPoly sp;
double shoulder_width = heli.length;
heading = heli.heading;
@ -216,100 +197,234 @@ void Helipad::BuildBtg( superpoly_list *rwy_polys,
shoulder_width = heli.width;
}
TGPolygon shoulder = gen_runway_area_w_extend(0.0, areahight, 0.0, 0.0, areahight);
shoulder = snap( shoulder, gSnap );
tgContour shoulder = gen_runway_area_w_extend(0.0, areahight, 0.0, 0.0, areahight);
shoulder = tgContour::Snap( shoulder, gSnap );
for (i = 0; i < 4; ++i) {
heading -= 90;
if ( heading < 0.0 ) { heading += 360.0; }
area_poly.erase();
area.clear();
heading = SGMiscd::normalizePeriodic(0,360,heading-90);
area.Erase();
area.AddNode( shoulder.GetNode( i ) );
area.AddNode( shoulder.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( heli_area.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( heli_area.GetNode( i ) );
area.SetHole(false);
area.push_back( shoulder.get_pt( 0,i ) );
area.push_back( shoulder.get_pt( 0,i == 3? 0 : i+1 ) );
area.push_back( heli_area.get_pt( 0,i == 3? 0 : i+1 ) );
area.push_back( heli_area.get_pt( 0,i ) );
area_poly.add_contour( area, false );
sp.erase();
sp.set_poly( area_poly );
sp.set_material( shoulder_mat );
sp.set_flag( "heli-shoulder" );
shoulder_polys.push_back( sp );
tp = TGTexParams( area_poly.get_pt(0,1).toSGGeod(), areahight, shoulder_width, heading );
tp.set_minu( 1 );
tp.set_maxu( 0 );
tp.set_minv( 1 );
tp.set_maxv( 0 );
shoulder_tps.push_back( tp );
}
// generate area around helipad
if (apt_base)
{
TGPolygon base, safe_base;
base = gen_runway_area_w_extend( 0.0, heli.length * 0.25 , 0.0, 0.0, heli.width * 0.25 );
base = snap( base, gSnap );
// also clear a safe area around the pad
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 );
// 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 );
result.Erase();
result.AddContour( area );
result.SetMaterial( shoulder_mat );
result.SetTexParams( area.GetNode(1), areahight, shoulder_width, heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
shoulder_polys.push_back( result );
}
if (heli.edge_lights)
{
// Now generate the helipad lights
superpoly_list s = gen_helipad_lights(maxsize);
tglightcontour_list s = gen_helipad_lights(maxsize);
for ( unsigned int i = 0; i < s.size(); ++i ) {
rwy_lights->push_back( s[i] );
rwy_lights.push_back( s[i] );
}
}
// generate area around helipad
tgContour base, safe_base;
base = gen_runway_area_w_extend( 0.0, heli.length * 0.25 , 0.0, 0.0, heli.width * 0.25 );
base = tgContour::Snap( base, gSnap );
// also clear a safe area around the pad
safe_base = gen_runway_area_w_extend( 0.0, heli.length * 0.5, 0.0, 0.0, heli.width * 0.5 );
safe_base = tgContour::Snap( safe_base, gSnap );
// add this to the airport clearing
apt_clearing = tgPolygon::Union(safe_base, apt_clearing);
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
}
void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights,
tgcontour_list& slivers )
{
//
// Generate the basic helipad outlines
//
double maxsize = heli.width - heli.length;
bool area_top = false;
bool area_side = false;
if (maxsize == 0) {
maxsize = heli.width;
} else if (maxsize < 0) {
maxsize = heli.width;
area_top = true;
} else {
maxsize = heli.length;
area_side = true;
}
tgContour helipad = gen_wgs84_area( GetLoc(), maxsize, 0, 0, maxsize, heli.heading, false);
helipad = tgContour::Snap( helipad, gSnap );
string material, shoulder_mat;
if (heli.surface == 1)
material = "pa_";
else
material = "pc_";
// write out
tgPolygon result = WriteGeom( helipad, material + "heli", rwy_polys, slivers);
result.SetTexParams( helipad.GetNode(0), maxsize, maxsize, heli.heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( result );
int i = 0;
double heading = 0, areahight = 0;
tgContour heli_area = gen_runway_area_w_extend(0.0, 0.0, 0.0, 0.0, 0.0);
heli_area = tgContour::Snap( heli_area, gSnap );
tgcontour_list area_contours;
tgContour area;
if (area_top || area_side) {
if (area_top) {
areahight = (heli.length - maxsize) /2;
heading = SGMiscd::normalizePeriodic( 0, 360, heli.heading-90 );
i = 0;
} else {
areahight = (heli.width - maxsize) /2;
heading = SGMiscd::normalizePeriodic( 0, 360, heli.heading-90 );
i = 1;
}
for (;i<4; ++i) {
area.Erase();
area.AddNode( heli_area.GetNode( i ) );
area.AddNode( heli_area.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( helipad.GetNode( i == 3 ? 0 : i+1) );
area.AddNode( helipad.GetNode( i ) );
area.SetHole( false );
area_contours.push_back( area );
i++;
}
tgPolygon result;
for (i = 0; i < 2; ++i) {
result = WriteGeom( area_contours[i], material + "tiedown", rwy_polys, slivers);
result.SetTexParams( area_contours[i].GetNode(0), maxsize, areahight, heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( result );
heading = SGMiscd::normalizePeriodic(0, 360, heading + 180 );
}
}
if (heli.shoulder == 1) {
shoulder_mat = "pa_shoulder";
areahight = 6; // shoulder size in m
} else if (heli.shoulder == 2) {
shoulder_mat = "pc_shoulder";
areahight = 6; // shoulder size in m
} else {
shoulder_mat = material + "shoulder_f";
areahight = 1; // fake shoulder size in m
}
double shoulder_width = heli.length;
heading = heli.heading;
if (area_side) {
shoulder_width = heli.width;
}
tgContour shoulder = gen_runway_area_w_extend(0.0, areahight, 0.0, 0.0, areahight);
shoulder = tgContour::Snap( shoulder, gSnap );
for (i = 0; i < 4; ++i) {
heading = SGMiscd::normalizePeriodic(0,360,heading-90);
area.Erase();
area.AddNode( shoulder.GetNode( i ) );
area.AddNode( shoulder.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( heli_area.GetNode( i == 3 ? 0 : i+1 ) );
area.AddNode( heli_area.GetNode( i ) );
area.SetHole(false);
result.Erase();
result.AddContour( area );
result.SetMaterial( shoulder_mat );
result.SetTexParams( area.GetNode(1), areahight, shoulder_width, heading );
result.SetTexLimits( 1,1,0,0 );
result.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
shoulder_polys.push_back( result );
}
if (heli.edge_lights)
{
// Now generate the helipad lights
tglightcontour_list s = gen_helipad_lights(maxsize);
for ( unsigned int i = 0; i < s.size(); ++i ) {
rwy_lights.push_back( s[i] );
}
}
}
void Helipad::BuildShoulder( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing )
void Helipad::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing )
{
TGPolygon base, safe_base;
TGPolygon shoulder;
tgPolygon base, safe_base;
tgPolygon shoulder;
for (unsigned int i=0; i<shoulder_polys.size(); i++) {
shoulder = shoulder_polys[i].get_poly();
shoulder = shoulder_polys[i];
// Clip the new polygon against what ever has already been created.
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( shoulder );
tgPolygonFindSlivers( clipped, slivers );
tgPolygon clipped = tgPolygon::DiffWithAccumulator( shoulder );
tgPolygon::RemoveSlivers( clipped, slivers );
// 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 );
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 );
shoulder_polys[i] = split;
rwy_polys->push_back( shoulder_polys[i] );
texparams->push_back( shoulder_tps[i] );
rwy_polys.push_back( shoulder_polys[i] );
tgPolygonAddToClipperAccumulator( shoulder, false );
tgPolygon::AddToAccumulator( shoulder );
if (apt_base)
{
// also clear a safe area around the runway
base = tgPolygonExpand( shoulder, 20.0);
safe_base = tgPolygonExpand( shoulder, 50.0);
// also clear a safe area around the runway
base = tgPolygon::Expand( shoulder, 20.0);
safe_base = tgPolygon::Expand( shoulder, 50.0);
// add this to the airport clearing
*apt_clearing = tgPolygonUnionClipper( safe_base, *apt_clearing );
// add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing );
// and add the clearing to the base
*apt_base = tgPolygonUnionClipper( base, *apt_base );
}
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
}
}
void Helipad::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers )
{
tgPolygon shoulder;
for (unsigned int i=0; i<shoulder_polys.size(); i++) {
shoulder = shoulder_polys[i];
// Clip the new polygon against what ever has already been created.
tgPolygon clipped = tgPolygon::DiffWithAccumulator( shoulder );
tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with
// the surface terrain
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 );
shoulder_polys[i] = split;
rwy_polys.push_back( shoulder_polys[i] );
tgPolygon::AddToAccumulator( shoulder );
}
}

View file

@ -24,7 +24,16 @@ class Helipad
{
public:
Helipad(char* def);
void BuildBtg( superpoly_list* heli_polys, texparams_list* texparams, superpoly_list* heli_lights, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing );
void BuildBtg( tgpolygon_list& heli_polys,
tglightcontour_list& heli_lights,
tgcontour_list& slivers );
void BuildBtg( tgpolygon_list& heli_polys,
tglightcontour_list& heli_lights,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing );
SGGeod GetLoc()
{
@ -36,11 +45,13 @@ public:
return (heli.surface < 3) ? true : false;
}
void BuildShoulder( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing );
private:
struct TGRunway {
@ -63,21 +74,21 @@ private:
// generate an area for a runway with expansion specified in meters
// (return result points in degrees)
TGPolygon gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
tgContour gen_runway_area_w_extend( double alt_m, double length_extend, double displ1, double displ2, double width_extend )
{
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(double maxsize);
tglightcontour_list gen_helipad_lights(double maxsize);
// storage for Shoulders - The superpolys are generated during
// helipad construction, but not clipped until shoulder construction.
superpoly_list shoulder_polys;
texparams_list shoulder_tps;
tgpolygon_list shoulder_polys;
void WriteGeom( TGPolygon polygon, string material,
superpoly_list *rwy_polys,
poly_list& slivers );
tgPolygon WriteGeom( const tgContour& area,
string material,
tgpolygon_list& rwy_polys,
tgcontour_list& slivers );
};

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,6 @@
#include <Geometry/poly_support.hxx>
#include <Geometry/util.hxx>
// for debugging clipping errors
#include <Polygon/chop.hxx>
#include "global.hxx"
#include "beznode.hxx"
#include "linearfeature.hxx"
@ -410,8 +407,7 @@ SGGeod LinearFeature::OffsetPointMiddle( const SGGeod& gPrev, const SGGeod& gCur
// straight line blows up math - offset 90 degree and dist is as given
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseNext-90.0);
distOffset = offset_by;
}
else {
} else {
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature: (normal case) " << description << ": theta is " << theta );
// calculate correct distance for the offset point
@ -477,10 +473,7 @@ SGGeod midpoint( const SGGeod& p0, const SGGeod& p1 )
int LinearFeature::Finish( bool closed, unsigned int idx )
{
TGPolygon poly, poly2;
TGPolygon normals_poly, normals_poly2;
TGSuperPoly sp;
TGTexParams tp;
tgPolygon poly;
SGGeod prev_inner, prev_outer;
SGGeod cur_inner, cur_outer;
double heading;
@ -650,22 +643,18 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
SGGeod cur_mp = midpoint( cur_outer, cur_inner );
SGGeodesy::inverse( prev_mp, cur_mp, heading, az2, dist );
poly.erase();
poly.add_node( 0, Point3D::fromSGGeod( prev_inner ) );
poly.add_node( 0, Point3D::fromSGGeod( prev_outer ) );
poly.add_node( 0, Point3D::fromSGGeod( cur_outer ) );
poly.add_node( 0, Point3D::fromSGGeod( cur_inner ) );
poly = snap( poly, gSnap );
poly.Erase();
poly.AddNode( 0, prev_inner );
poly.AddNode( 0, prev_outer );
poly.AddNode( 0, cur_outer );
poly.AddNode( 0, cur_inner );
poly = tgPolygon::Snap( poly, gSnap );
sp.erase();
sp.set_poly( poly );
sp.set_material( material );
sp.set_flag("lf");
marking_polys.push_back(sp);
tp = TGTexParams( prev_inner, width, 1.0f, heading );
tp.set_minv(last_end_v);
marking_tps.push_back(tp);
poly.SetMaterial( material );
poly.SetTexParams( prev_inner, width, 1.0f, heading );
poly.SetTexLimits( 0, last_end_v, 1, 1 );
poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, -1.0, 0.0, 1.0, 0.0 );
marking_polys.push_back(poly);
last_end_v = (double)1.0f - (fmod( (double)(dist - last_end_v), (double)1.0f ));
} else {
@ -678,6 +667,10 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
}
// now generate the superpoly list for lights with constant distance between lights (depending on feature type)
tglightcontour_list light_contours;
tgLightContour cur_light_contour;
tgLightContour alt_light_contour;
for (unsigned int i=0; i<lights.size(); i++)
{
markStarted = false;
@ -689,43 +682,38 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
switch( lights[i]->type )
{
case LF_BIDIR_GREEN:
material = "RWY_GREEN_TAXIWAY_LIGHTS";
cur_light_contour.SetType( "RWY_GREEN_TAXIWAY_LIGHTS" );
light_delta = 10.0f;
break;
case LF_OMNIDIR_BLUE:
material = "RWY_BLUE_TAXIWAY_LIGHTS";
cur_light_contour.SetType( "RWY_BLUE_TAXIWAY_LIGHTS" );
light_delta = 10.0f;
break;
case LF_UNIDIR_CLOSE_AMBER:
material = "RWY_YELLOW_LIGHTS";
cur_light_contour.SetType( "RWY_YELLOW_LIGHTS" );
light_delta = 2.0f;
break;
case LF_UNIDIR_CLOSE_AMBER_PULSE:
material = "RWY_YELLOW_PULSE_LIGHTS";
cur_light_contour.SetType( "RWY_YELLOW_PULSE_LIGHTS" );
light_delta = 2.0f;
break;
case LF_BIDIR_GREEN_AMBER:
material = "RWY_GREEN_TAXIWAY_LIGHTS";
cur_light_contour.SetType( "RWY_GREEN_TAXIWAY_LIGHTS" );
alt_light_contour.SetType( "RWY_YELLOW_LIGHTS" );
light_delta = 10.0f;
alternate = true;
break;
case LF_OMNIDIR_RED:
material = "RWY_RED_LIGHTS";
cur_light_contour.SetType( "RWY_RED_LIGHTS" );
light_delta = 10.0f;
break;
}
poly.erase();
poly2.erase();
normals_poly.erase();
normals_poly2.erase();
sp.erase();
for (unsigned int j = lights[i]->start_idx; j <= lights[i]->end_idx; j++)
{
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::Finish: calculating offsets for light " << i << " whose start idx is " << lights[i]->start_idx << " and end idx is " << lights[i]->end_idx << " cur idx is " << j );
@ -781,23 +769,19 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
if (!alternate)
{
poly.add_node(0, Point3D::fromSGGeod(tmp));
normals_poly.add_node(0, Point3D::fromSGVec3(vec) );
cur_light_contour.AddLight( tmp, vec );
}
else
{
if (switch_poly)
{
poly.add_node(0, Point3D::fromSGGeod(tmp));
normals_poly.add_node(0, Point3D::fromSGVec3(vec) );
switch_poly = !switch_poly;
cur_light_contour.AddLight( tmp, vec );
}
else
{
poly2.add_node(0, Point3D::fromSGGeod(tmp));
normals_poly2.add_node(0, Point3D::fromSGVec3(vec) );
switch_poly = !switch_poly;
alt_light_contour.AddLight( tmp, vec );
}
switch_poly = !switch_poly;
}
// update current light distance
@ -814,26 +798,19 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
}
// if there were lights generated - create the superpoly
if (poly.total_size())
if (cur_light_contour.ContourSize())
{
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::Finish: Adding superpoly with " << poly.total_size() << " lights" );
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::Finish: Adding light contour with " << cur_light_contour.ContourSize() << " lights" );
cur_light_contour.SetFlag("");
lighting_polys.push_back(cur_light_contour);
}
sp.set_poly( poly );
sp.set_normals( normals_poly );
sp.set_material( material );
sp.set_flag("");
lighting_polys.push_back(sp);
// create the superpoly for the alternating light color
if (poly2.total_size())
{
sp.erase();
sp.set_poly( poly2 );
sp.set_normals( normals_poly2 );
sp.set_material( "RWY_YELLOW_LIGHTS" );
sp.set_flag("");
lighting_polys.push_back(sp);
}
// create the superpoly for the alternating light color
if (alt_light_contour.ContourSize())
{
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::Finish: Adding light contour with " << cur_light_contour.ContourSize() << " lights" );
alt_light_contour.SetFlag("");
lighting_polys.push_back(cur_light_contour);
}
else
{
@ -844,53 +821,26 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
return 1;
}
int LinearFeature::BuildBtg(superpoly_list* line_polys, texparams_list* line_tps, superpoly_list* lights, bool make_shapefiles )
int LinearFeature::BuildBtg(tgpolygon_list& line_polys, tglightcontour_list& lights, bool make_shapefiles )
{
TGPolygon poly, tmp;
void* ds_id = NULL; // If we are going to build shapefiles
void* l_id = NULL; // datasource and layer IDs
SGGeod min, max, minp, maxp;
if ( make_shapefiles ) {
char ds_name[128];
sprintf(ds_name, "./lf_debug");
ds_id = tgShapefileOpenDatasource( ds_name );
}
tgPolygon poly;
SGGeod min, max, minp, maxp;
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::BuildBtg: " << description);
for ( unsigned int i = 0; i < marking_polys.size(); i++)
{
poly = tgPolygonDiffClipperWithAccumulator( marking_polys[i].get_poly() );
// Clipping and triangulation need to copy texparams, and material info...
marking_polys[i] = tgPolygon::DiffWithAccumulator( marking_polys[i] );
line_polys.push_back( marking_polys[i] );
marking_polys[i].set_poly( poly );
line_polys->push_back( marking_polys[i] );
/* If debugging this lf, write the polys into their own layers */
if (ds_id) {
char layer_name[128];
sprintf( layer_name, "poly_%d", i );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
char feature_name[128];
sprintf( feature_name, "poly_%d", i);
tgShapefileCreateFeature( ds_id, l_id, poly, feature_name );
}
tgPolygonAddToClipperAccumulator(poly, false);
line_tps->push_back( marking_tps[i] );
}
if (ds_id) {
tgShapefileCloseDatasource( ds_id );
tgPolygon::AddToAccumulator( marking_polys[i] );
}
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: add " << lighting_polys.size() << " light defs");
for ( unsigned i = 0; i < lighting_polys.size(); i++)
{
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: adding light " << i );
lights->push_back( lighting_polys[i] );
lights.push_back( lighting_polys[i] );
}
return 1;
}
}

View file

@ -97,17 +97,15 @@ public:
}
int Finish( bool closed, unsigned int idx );
int BuildBtg( superpoly_list* line_polys, texparams_list* line_tps, superpoly_list* lights, bool debug );
// int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, ClipPolyType* line_accum, superpoly_list* lights );
int BuildBtg( tgpolygon_list& line_polys, tglightcontour_list& lights, bool debug );
private:
SGGeod OffsetPointFirst( const SGGeod& cur, const SGGeod& next, double offset_by );
SGGeod OffsetPointMiddle( const SGGeod& prev, const SGGeod& cur, const SGGeod& next, double offset_by );
SGGeod OffsetPointLast( const SGGeod& prev, const SGGeod& cur, double offset_by );
double offset;
double width;
double offset;
double width;
MarkingList marks;
Marking* cur_mark;
@ -119,17 +117,15 @@ private:
// text description
string description;
// contour definition (each beznode has marking type)
BezContour contour;
// contour definition after bezier interpolation
point_list points;
superpoly_list marking_polys;
texparams_list marking_tps;
superpoly_list lighting_polys;
tgpolygon_list marking_polys;
tglightcontour_list lighting_polys;
};
typedef std::vector <LinearFeature *> FeatureList;

View file

@ -120,6 +120,9 @@ int nudge = 10;
double slope_max = 0.02;
double gSnap = 0.00000001; // approx 1 mm
//TODO : new polygon chop API
extern bool tgPolygon_index_init( const std::string& path );
// For creating a buffered stream to write to the socket
Net::StreamSocket ss;
Net::SocketStreamBuf ssb( ss );
@ -328,13 +331,13 @@ int main(int argc, char **argv)
SGPath sgp( airportareadir );
sgp.append( "dummy" );
sgp.create_dir( 0755 );
string command = argv[0];
string lastaptfile = work_dir+"/last_apt";
// initialize persistant polygon counter
string counter_file = airportareadir+"/poly_counter";
poly_index_init( counter_file );
tgPolygon_index_init( counter_file );
// Initialize shapefile support (for debugging)
tgShapefileInit();

View file

@ -9,23 +9,20 @@ LightingObj::LightingObj( char* definition )
SG_LOG(SG_GENERAL, SG_DEBUG, "Read lighting object: (" << lon << "," << lat << ") heading: " << heading << " type: " << type );
}
void LightingObj::BuildBtg( superpoly_list* lights )
void LightingObj::BuildBtg( tglightcontour_list& lights )
{
point_list lightobj; lightobj.clear();
point_list normals; normals.clear();
tgLightContour light_contour;
light_contour.SetType( "RWY_VASI_LIGHTS" );
double left_hdg = heading - 90.0;
if ( left_hdg < 0 ) { left_hdg += 360.0; }
SGGeod ref = SGGeod::fromDeg(lon, lat);
double left_hdg = SGMiscd::normalizePeriodic(0, 360, heading - 90.0 );
SGGeod ref = SGGeod::fromDeg(lon, lat);
// Calculate the light normal with the help of a second point
// in the object heading direction.
// SimGear takes care of the glideslope angle calculation from the normal
SGVec3d cart1 = SGVec3d::fromGeod(SGGeodesy::direct( ref, heading, 10));
SGVec3d cart2 = SGVec3d::fromGeod(ref);
Point3D normal = Point3D::fromSGVec3(normalize(cart2 - cart1));
SGVec3d normal = normalize(cart2 - cart1);
// We know our normal, now create the lights
SGGeod pt1;
@ -42,15 +39,13 @@ void LightingObj::BuildBtg( superpoly_list* lights )
// unit1
pt1 = SGGeodesy::direct( pt1, left_hdg, -5 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
// unit2+3
for (int i = 0; i < 2; ++i)
{
pt1 = SGGeodesy::direct( pt1, left_hdg, 5 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
}
// Go to upwind bar
@ -58,15 +53,13 @@ void LightingObj::BuildBtg( superpoly_list* lights )
// unit4
pt1 = SGGeodesy::direct( pt1, left_hdg, -5 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
// unit5+6
for (int i = 0; i < 2; ++i)
{
pt1 = SGGeodesy::direct( pt1, left_hdg,5 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
}
}
else if (type == 2)
@ -75,15 +68,13 @@ void LightingObj::BuildBtg( superpoly_list* lights )
// unit1
pt1 = SGGeodesy::direct( ref, left_hdg, -12 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
// unit2-4
for (int i = 0; i < 3; ++i)
{
pt1 = SGGeodesy::direct( pt1, left_hdg, 8 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
}
}
else if (type == 3)
@ -92,15 +83,13 @@ void LightingObj::BuildBtg( superpoly_list* lights )
// unit1
pt1 = SGGeodesy::direct( ref, left_hdg, 12 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
// unit2-4
for (int i = 0; i < 3; ++i)
{
pt1 = SGGeodesy::direct( pt1, left_hdg, -8 );
lightobj.push_back( Point3D::fromSGGeod(pt1) );
normals.push_back( normal );
light_contour.AddLight( pt1, normal );
}
}
else if (type == 4)
@ -113,8 +102,7 @@ void LightingObj::BuildBtg( superpoly_list* lights )
SG_LOG(SG_GENERAL, SG_DEBUG, "Generating tri-colour VASI = " << assoc_rw);
// only one light here
lightobj.push_back( Point3D::fromSGGeod(ref) );
normals.push_back( normal );
light_contour.AddLight( ref, normal );
}
else
{
@ -122,15 +110,5 @@ void LightingObj::BuildBtg( superpoly_list* lights )
return;
}
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);
lights.push_back( light_contour);
}

View file

@ -23,7 +23,7 @@ public:
char assoc_rw;
void BuildBtg( superpoly_list* lights );
void BuildBtg( tglightcontour_list& lights );
};
typedef std::vector <LightingObj *> LightingObjList;

View file

@ -455,16 +455,19 @@ int Parser::ParseLine(char* line)
case PAVEMENT_CODE:
SetState( STATE_PARSE_PAVEMENT );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing pavement: " << line);
cur_pavement = ParsePavement( line );
break;
case LINEAR_FEATURE_CODE:
SetState( STATE_PARSE_FEATURE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Linear Feature: " << line);
cur_feat = ParseFeature( line );
break;
case BOUNDRY_CODE:
SetState( STATE_PARSE_BOUNDARY );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing Boundary: " << line);
cur_boundary = ParseBoundary( line );
break;

View file

@ -60,10 +60,9 @@ WaterRunway::WaterRunway(char* definition)
SG_LOG(SG_GENERAL, SG_DEBUG, "Read water runway: (" << lon[0] << "," << lat[0] << ") to (" << lon[1] << "," << lat[1] << ") width: " << width << " buoys = " << buoys );
}
point_list WaterRunway::GetNodes()
tgContour WaterRunway::GetNodes()
{
point_list buoys_nodes;
buoys_nodes.clear();
tgContour buoys_nodes;
if (buoys){
double heading, az2, length;
@ -72,15 +71,17 @@ point_list WaterRunway::GetNodes()
// create a polygon for the outline and use it to calculate the point list
int divs = (int)(length / 100.0);
TGPolygon area = gen_wgs84_area(GetStart(), GetEnd(),
tgContour area = gen_wgs84_area(GetStart(), GetEnd(),
0, 0, 0, width, heading, false);
Point3D pt, inc;
Point3D pt, inc;
for ( int i = 0; i < area.contour_size( 0 ); ++i ) {
pt = area.get_pt( 0, i );
inc = (area.get_pt(0, i==3 ? 0 : i+1) - area.get_pt(0,i)) / divs;
for ( unsigned int i = 0; i < area.GetSize(); ++i ) {
pt = Point3D::fromSGGeod( area.GetNode(i) );
inc = ( Point3D::fromSGGeod( area.GetNode(i==3 ? 0 : i+1) ) -
Point3D::fromSGGeod( area.GetNode(i)) ) / divs;
for ( int j = 0; j < divs; ++j) {
buoys_nodes.push_back( pt);
buoys_nodes.AddNode( pt.toSGGeod() );
pt += inc;
}
}
@ -88,31 +89,56 @@ point_list WaterRunway::GetNodes()
return buoys_nodes;
}
int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles )
point_list WaterRunway::TempGetAsPointList()
{
TGPolygon base, safe_base;
point_list buoys_nodes;
if (buoys){
double heading, az2, length;
// calculate runway heading and length
SGGeodesy::inverse(GetStart(), GetEnd(), heading, az2, length);
// create a polygon for the outline and use it to calculate the point list
int divs = (int)(length / 100.0);
tgContour area = gen_wgs84_area(GetStart(), GetEnd(),
0, 0, 0, width, heading, false);
Point3D pt, inc;
for ( unsigned int i = 0; i < area.GetSize(); ++i ) {
pt = Point3D::fromSGGeod( area.GetNode( i ) );
inc = ( Point3D::fromSGGeod( area.GetNode(i==3 ? 0 : i+1) ) -
Point3D::fromSGGeod( area.GetNode(i)) ) / divs;
for ( int j = 0; j < divs; ++j) {
buoys_nodes.push_back( pt );
pt += inc;
}
}
}
return buoys_nodes;
}
int Runway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, bool make_shapefiles )
{
if ( rwy.surface == 1 /* Asphalt */ )
{
material_prefix = "pa_";
}
}
else if ( rwy.surface == 2 /* Concrete */ )
{
material_prefix = "pc_";
}
}
else if ( rwy.surface == 3 /* Turf/Grass */ )
{
material_prefix = "grass_rwy";
}
}
else if ( rwy.surface == 4 /* Dirt */ || rwy.surface == 5 /* Gravel */ )
{
material_prefix = "dirt_rwy";
}
}
else if ( rwy.surface == 12 /* Dry Lakebed */ )
{
material_prefix = "lakebed_taxiway";
}
}
else if ( rwy.surface == 13 /* Water runway (buoys) */ )
{
// water
@ -125,10 +151,10 @@ int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, supe
{
//Transparent texture
}
else
else
{
SG_LOG(SG_GENERAL, SG_WARN, "surface_code = " << rwy.surface);
throw sg_exception("unknown runway type!");
throw sg_exception("unknown runway type!");
}
// first, check the surface type - anything but concrete and asphalt are easy
@ -137,16 +163,16 @@ 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, slivers, make_shapefiles );
gen_rwy( rwy_polys, slivers, make_shapefiles );
gen_runway_lights( rwy_lights );
break;
case 3: // Grass
case 4: // Dirt
case 5: // Gravel
case 12: // dry lakebed
SG_LOG( SG_GENERAL, SG_DEBUG, "Build Runway: Grass, Dirt, Gravel or Dry Lakebed " << rwy.surface );
gen_simple_rwy( rwy_polys, texparams, slivers );
gen_simple_rwy( rwy_polys, slivers );
gen_runway_lights( rwy_lights );
break;
@ -165,24 +191,30 @@ int Runway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, supe
default: // unknown
SG_LOG( SG_GENERAL, SG_DEBUG, "Build Runway: unknown: " << rwy.surface);
break;
}
if (apt_base)
{
// generate area around runways
base = gen_runway_area_w_extend( 20.0, -rwy.overrun[0], -rwy.overrun[1], 20.0 );
base = snap( base, gSnap );
// also clear a safe area around the runway
safe_base = gen_runway_area_w_extend( 180.0, -rwy.overrun[0], -rwy.overrun[1], 50.0 );
safe_base = snap( safe_base, gSnap );
// 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 );
}
return 0;
}
int Runway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, bool make_shapefiles )
{
tgContour base, safe_base;
BuildBtg( rwy_polys, rwy_lights, slivers, make_shapefiles );
// generate area around runways
base = gen_runway_area_w_extend( 20.0, -rwy.overrun[0], -rwy.overrun[1], 20.0 );
base = tgContour::Snap( base, gSnap );
// also clear a safe area around the runway
safe_base = gen_runway_area_w_extend( 180.0, -rwy.overrun[0], -rwy.overrun[1], 50.0 );
safe_base = tgContour::Snap( safe_base, gSnap );
// add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing );
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
return 0;
}

View file

@ -39,19 +39,25 @@ public:
return (rwy.surface < 3) ? true : false;
}
int BuildBtg( superpoly_list* rwy_polys,
texparams_list* texparams,
superpoly_list* rwy_lights,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing,
int BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights,
tgcontour_list& slivers,
bool make_shapefiles );
void BuildShoulder( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing );
int BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing,
bool make_shapefiles );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing );
private:
struct TGRunway {
@ -85,61 +91,66 @@ private:
// storage for Shoulders - The superpolys are generated during rwy construction,
// but not clipped until shoulder construction.
superpoly_list shoulder_polys;
texparams_list shoulder_tps;
tgpolygon_list shoulder_polys;
// Build Helpers:
// generate an area for a runway and include midpoints
TGPolygon gen_runway_w_mid( double length_extend_m, double width_extend_m )
tgContour gen_runway_w_mid( double length_extend_m, double width_extend_m )
{
return ( gen_wgs84_area( GetStart(), GetEnd(), 2.0*length_extend_m, 0.0, 0.0, rwy.width + 2.0 * width_extend_m, rwy.heading, true) );
}
// generate an area for a runway with expansion specified in meters
// (return result points in degrees)
TGPolygon gen_runway_area_w_extend( double length_extend, double displ1, double displ2, double width_extend )
tgContour gen_runway_area_w_extend( double length_extend, double displ1, double displ2, double width_extend )
{
return ( gen_wgs84_area( GetStart(), GetEnd(), 2.0*length_extend, displ1, displ2, rwy.width + 2.0*width_extend, rwy.heading, false) );
}
void gen_rw_designation( TGPolygon poly, double heading, string rwname,
void gen_rw_designation( tgPolygon poly, double heading, string rwname,
double &start_pct, double &end_pct,
superpoly_list* rwy_polys,
texparams_list* texparams,
poly_list& slivers,
tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles );
// generate a section of runway
void gen_runway_section( const TGPolygon& runway,
// generate a section of runway with shoulders
void gen_runway_section( 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& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
superpoly_list *shoulder_polys,
texparams_list *shoulder_tps,
poly_list& slivers,
tgpolygon_list& rwy_polys,
tgpolygon_list& shoulder_polys,
tgcontour_list& slivers,
bool make_shapefiles );
// generate a section of runway without shoulders
void gen_runway_section( 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& material,
tgpolygon_list& rwy_polys,
tgcontour_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 );
tgPolygon gen_shoulder_section( SGGeod& p0, SGGeod& p1,
SGGeod& t0, SGGeod& t1,
int side,
double heading,
double width,
std::string surface );
void gen_simple_rwy( superpoly_list *rwy_polys, texparams_list *texparams, poly_list& slivers );
void gen_simple_rwy( tgpolygon_list& rwy_polys, tgcontour_list& slivers );
void gen_rwy( superpoly_list* rwy_polys,
texparams_list* texparams,
poly_list& slivers,
void gen_rwy( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles );
void gen_runway_lights( superpoly_list* lights );
void gen_runway_lights( tglightcontour_list& lights );
int get_thresh0(bool recip)
{
@ -156,17 +167,17 @@ private:
return (rwy.threshold[get_thresh0(recip)] > 60.0) ? true : false;
}
Point3D gen_runway_light_vector( float angle, bool recip );
superpoly_list gen_runway_edge_lights( bool recip );
superpoly_list gen_runway_threshold_lights( const int kind, bool recip );
superpoly_list gen_runway_center_line_lights( bool recip );
TGSuperPoly gen_touchdown_zone_lights( bool recip );
TGSuperPoly gen_reil( const int kind, bool recip );
superpoly_list gen_calvert( const string &kind, bool recip );
superpoly_list gen_alsf( const string &kind, bool recip );
TGSuperPoly gen_odals( const int kind, bool recip );
superpoly_list gen_ssalx( const string& kind, bool recip );
superpoly_list gen_malsx( const string& kind, bool recip );
SGVec3d gen_runway_light_vector( float angle, bool recip );
tglightcontour_list gen_runway_edge_lights( bool recip );
tglightcontour_list gen_runway_threshold_lights( const int kind, bool recip );
tglightcontour_list gen_runway_center_line_lights( bool recip );
tgLightContour gen_touchdown_zone_lights( bool recip );
tgLightContour gen_reil( const int kind, bool recip );
tglightcontour_list gen_calvert( const string &kind, bool recip );
tglightcontour_list gen_alsf( const string &kind, bool recip );
tgLightContour gen_odals( const int kind, bool recip );
tglightcontour_list gen_ssalx( const string& kind, bool recip );
tglightcontour_list gen_malsx( const string& kind, bool recip );
};
typedef std::vector <Runway *> RunwayList;
@ -177,7 +188,8 @@ class WaterRunway
public:
WaterRunway(char* def);
point_list GetNodes();
tgContour GetNodes();
point_list TempGetAsPointList();
SGGeod GetStart(void)
{

View file

@ -88,92 +88,77 @@ 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 )
tgPolygon Runway::gen_shoulder_section( SGGeod& p0, SGGeod& p1, SGGeod& t0, SGGeod& t1, int side, double heading, double width, std::string surface )
{
Point3D s0, s1, s2, s3;
TGPolygon poly;
SGGeod 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);
// calc heading and distance from p0 to p1
SGGeodesy::inverse( p0, p1, 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 );
s0 = SGGeodesy::direct( t1, wid_hdg, width );
// 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 );
s1 = SGGeodesy::direct( t0, wid_hdg, width );
// 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 );
s2 = SGGeodesy::direct( t0, wid_hdg, -0.01 );
// 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 );
s3 = SGGeodesy::direct( t1, wid_hdg, -0.01 );
// 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" );
poly.AddNode( 0, s0 );
poly.AddNode( 0, s1 );
poly.AddNode( 0, s2 );
poly.AddNode( 0, s3 );
poly = tgPolygon::Snap( poly, gSnap );
poly.SetMaterial( surface );
if (side == 0) {
tp = TGTexParams( poly.get_pt(0,2).toSGGeod(), width, dist, heading );
tp.set_minu(0);
tp.set_maxu(1);
poly.SetTexParams( poly.GetNode(0,2), width, dist, heading );
poly.SetTexLimits( 0,0,1,1 );
} else {
tp = TGTexParams( poly.get_pt(0,1).toSGGeod(), width, dist, heading );
tp.set_minu(1);
tp.set_maxu(0);
poly.SetTexParams( poly.GetNode(0,1), width, dist, heading );
poly.SetTexLimits( 1,0,0,1 );
}
poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, 0.0, 0.0, 1.0, 0.0 );
tp.set_minv(0);
tp.set_maxv(1);
return poly;
}
// generate a section of texture
void Runway::gen_runway_section( const TGPolygon& runway,
// generate a section of texture with shoulders
void Runway::gen_runway_section( 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& material,
superpoly_list *rwy_polys,
texparams_list *texparams,
superpoly_list *shoulder_polys,
texparams_list *shoulder_tps,
poly_list& slivers,
tgpolygon_list& rwy_polys,
tgpolygon_list& shoulder_polys,
tgcontour_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
static int runway_idx = 0;
static int section_idx = 0;
static int clipped_idx = 0;
char layer[64];
Point3D a0 = runway.get_pt(0, 1);
Point3D a1 = runway.get_pt(0, 2);
Point3D a2 = runway.get_pt(0, 0);
Point3D a3 = runway.get_pt(0, 3);
SGVec2d a0 = SGVec2d( runway.GetNode(0, 1).getLongitudeDeg(), runway.GetNode(0, 1).getLatitudeDeg() );
SGVec2d a1 = SGVec2d( runway.GetNode(0, 2).getLongitudeDeg(), runway.GetNode(0, 2).getLatitudeDeg() );
SGVec2d a2 = SGVec2d( runway.GetNode(0, 0).getLongitudeDeg(), runway.GetNode(0, 0).getLatitudeDeg() );
SGVec2d a3 = SGVec2d( runway.GetNode(0, 3).getLongitudeDeg(), runway.GetNode(0, 3).getLatitudeDeg() );
if ( startl_pct > 0.0 ) {
startl_pct -= nudge * SG_EPSILON;
@ -185,12 +170,6 @@ void Runway::gen_runway_section( const TGPolygon& runway,
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){
@ -237,146 +216,98 @@ void Runway::gen_runway_section( const TGPolygon& runway,
}
}
SG_LOG(SG_GENERAL, SG_DEBUG, "start len % = " << startl_pct
<< " end len % = " << endl_pct);
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);
SGVec2d t0 = SGVec2d( a0.x() + dlx * startl_pct,
a0.y() + dly * startl_pct );
SGVec2d t1 = SGVec2d( a0.x() + dlx * endl_pct,
a0.y() + dly * endl_pct );
dlx = a3.x() - a2.x();
dly = a3.y() - a2.y();
Point3D t2 = Point3D( a2.x() + dlx * startl_pct,
a2.y() + dly * startl_pct, 0);
SGVec2d t2 = SGVec2d( a2.x() + dlx * startl_pct,
a2.y() + dly * startl_pct );
Point3D t3 = Point3D( a2.x() + dlx * endl_pct,
a2.y() + dly * endl_pct, 0);
SGVec2d t3 = SGVec2d( a2.x() + dlx * endl_pct,
a2.y() + dly * endl_pct );
SG_LOG(SG_GENERAL, SG_DEBUG, "start wid % = " << startw_pct
<< " end wid % = " << endw_pct);
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);
SGVec2d p0 = SGVec2d( t2.x() + dwx * startw_pct,
t2.y() + dwy * startw_pct );
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 );
}
}
SGVec2d p1 = SGVec2d( t2.x() + dwx * endw_pct,
t2.y() + dwy * endw_pct );
dwx = t1.x() - t3.x();
dwy = t1.y() - t3.y();
Point3D p2 = Point3D( t3.x() + dwx * startw_pct,
t3.y() + dwy * startw_pct, 0);
SGVec2d p2 = SGVec2d( t3.x() + dwx * startw_pct,
t3.y() + dwy * startw_pct );
Point3D p3 = Point3D( t3.x() + dwx * endw_pct,
t3.y() + dwy * endw_pct, 0);
SGVec2d p3 = SGVec2d( t3.x() + dwx * endw_pct,
t3.y() + dwy * endw_pct );
// convert vectors back to GEOD
SGGeod pg0 = SGGeod::fromDeg( p0.x(), p0.y() );
SGGeod pg1 = SGGeod::fromDeg( p1.x(), p1.y() );
SGGeod pg2 = SGGeod::fromDeg( p2.x(), p2.y() );
SGGeod pg3 = SGGeod::fromDeg( p3.x(), p3.y() );
SGGeod tg0 = SGGeod::fromDeg( t0.x(), t0.y() );
SGGeod tg1 = SGGeod::fromDeg( t1.x(), t1.y() );
SGGeod tg2 = SGGeod::fromDeg( t2.x(), t2.y() );
SGGeod tg3 = SGGeod::fromDeg( t3.x(), t3.y() );
// check for left shoulder
if ( lshoulder_width > 0.0f ) {
tgPolygon sp;
sp = gen_shoulder_section( pg0, pg1, tg0, tg1, 0, heading, lshoulder_width, shoulder_surface );
shoulder_polys.push_back( sp );
}
// check for right shoulder
if ( rshoulder_width > 0.0f ) {
TGSuperPoly sp;
TGTexParams tp;
tgPolygon sp;
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 );
}
sp = gen_shoulder_section( pg1, pg0, tg2, tg3, 1, heading, rshoulder_width, shoulder_surface );
shoulder_polys.push_back( sp );
}
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 );
/* 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 );
}
tgPolygon section;
section.AddNode( 0, pg2 );
section.AddNode( 0, pg0 );
section.AddNode( 0, pg1 );
section.AddNode( 0, pg3 );
section = tgPolygon::Snap( section, gSnap );
// print runway points
SG_LOG(SG_GENERAL, SG_DEBUG, "pre clipped runway pts " << material_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);
}
}
SG_LOG(SG_GENERAL, SG_DEBUG, section );
// Clip the new polygon against what ever has already been created.
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( section );
tgPolygonFindSlivers( clipped, slivers );
tgPolygon clipped = tgPolygon::DiffWithAccumulator( section );
tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with
// the surface terrain
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
tgPolygon split = tgPolygon::SplitLongEdges( 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_prefix + material );
rwy_polys->push_back( sp );
SG_LOG(SG_GENERAL, SG_DEBUG, "section = " << clipped.contours());
tgPolygonAddToClipperAccumulator( section, false );
tgPolygon::AddToAccumulator( section );
// Store away what we need to know for texture coordinate
// calculation. (CLO 10/20/02: why can't we calculate texture
@ -389,36 +320,157 @@ void Runway::gen_runway_section( const TGPolygon& runway,
double sect_len = len * ( endl_pct - startl_pct );
double sect_wid = width * ( endw_pct - startw_pct );
TGTexParams tp;
tp = TGTexParams( p0.toSGGeod(),
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 );
split.SetMaterial( material_prefix + material );
split.SetTexParams( pg0, sect_wid, sect_len, heading );
split.SetTexLimits( minu, minv, maxu, maxv );
split.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
// print runway points
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped runway pts " << material_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);
// Create the final output and push on to the runway super_polygon
// list
rwy_polys.push_back( split );
}
// generate a section of texture without shoulders
void Runway::gen_runway_section( 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& material,
tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles )
{
double width = rwy.width;
double length = rwy.length;
SGVec2d a0 = SGVec2d( runway.GetNode(0, 1).getLongitudeDeg(), runway.GetNode(0, 1).getLatitudeDeg() );
SGVec2d a1 = SGVec2d( runway.GetNode(0, 1).getLongitudeDeg(), runway.GetNode(0, 2).getLatitudeDeg() );
SGVec2d a2 = SGVec2d( runway.GetNode(0, 1).getLongitudeDeg(), runway.GetNode(0, 0).getLatitudeDeg() );
SGVec2d a3 = SGVec2d( runway.GetNode(0, 1).getLongitudeDeg(), runway.GetNode(0, 3).getLatitudeDeg() );
if ( startl_pct > 0.0 ) {
startl_pct -= nudge * SG_EPSILON;
}
if ( endl_pct < 1.0 ) {
endl_pct += nudge * SG_EPSILON;
}
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;
}
}
if (ds_id) {
tgShapefileCloseDatasource( ds_id );
}
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();
SGVec2d t0 = SGVec2d( a0.x() + dlx * startl_pct,
a0.y() + dly * startl_pct );
SGVec2d t1 = SGVec2d( a0.x() + dlx * endl_pct,
a0.y() + dly * endl_pct );
dlx = a3.x() - a2.x();
dly = a3.y() - a2.y();
SGVec2d t2 = SGVec2d( a2.x() + dlx * startl_pct,
a2.y() + dly * startl_pct );
SGVec2d t3 = SGVec2d( a2.x() + dlx * endl_pct,
a2.y() + dly * endl_pct );
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();
SGVec2d p0 = SGVec2d( t2.x() + dwx * startw_pct,
t2.y() + dwy * startw_pct );
SGVec2d p1 = SGVec2d( t2.x() + dwx * endw_pct,
t2.y() + dwy * endw_pct );
dwx = t1.x() - t3.x();
dwy = t1.y() - t3.y();
SGVec2d p2 = SGVec2d( t3.x() + dwx * startw_pct,
t3.y() + dwy * startw_pct );
SGVec2d p3 = SGVec2d( t3.x() + dwx * endw_pct,
t3.y() + dwy * endw_pct );
// convert vectors back to GEOD
SGGeod pg0 = SGGeod::fromDeg( p0.x(), p0.y() );
SGGeod pg1 = SGGeod::fromDeg( p1.x(), p1.y() );
SGGeod pg2 = SGGeod::fromDeg( p2.x(), p2.y() );
SGGeod pg3 = SGGeod::fromDeg( p3.x(), p3.y() );
tgPolygon section;
section.AddNode( 0, pg2 );
section.AddNode( 0, pg0 );
section.AddNode( 0, pg1 );
section.AddNode( 0, pg3 );
section = tgPolygon::Snap( section, gSnap );
// print runway points
SG_LOG(SG_GENERAL, SG_DEBUG, "pre clipped runway pts " << material_prefix << material);
SG_LOG(SG_GENERAL, SG_DEBUG, section );
// Clip the new polygon against what ever has already been created.
tgPolygon clipped = tgPolygon::DiffWithAccumulator( section );
tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with
// the surface terrain
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 );
tgPolygon::AddToAccumulator( section );
// 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 );
split.SetMaterial( material_prefix + material );
split.SetTexParams( pg0, sect_wid, sect_len, heading );
split.SetTexLimits( minu, minv, maxu, maxv );
split.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
// Create the final output and push on to the runway super_polygon
// list
rwy_polys.push_back( split );
}
void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
void Runway::gen_rw_designation( tgPolygon poly, double heading, string rwname,
double &start_pct, double &end_pct,
superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles )
{
if (rwname != "XX") { /* Do not create a designation block if the runway name is set to none */
@ -443,8 +495,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
0.0, 1.0, 0.0, 1.0,
heading,
letter,
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -473,8 +525,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
0.0, 1.0, 0.0, 1.0,
heading,
tex1,
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
gen_runway_section( poly,
@ -483,8 +535,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
0.0, 1.0, 0.0, 1.0,
heading,
tex2,
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
@ -497,8 +549,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
0.0, 1.0, 0.0, 1.0,
heading,
tex1,
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -509,9 +561,8 @@ void Runway::gen_rw_designation( TGPolygon poly, double heading, string rwname,
// rwy_polys, texparams, and accum. For specific details and
// dimensions of precision runway markings, please refer to FAA
// document AC 150/5340-1H
void Runway::gen_rwy( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
void Runway::gen_rwy( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
bool make_shapefiles )
{
SG_LOG( SG_GENERAL, SG_DEBUG, "Building runway = " << rwy.rwnum[0] << " / " << rwy.rwnum[1]);
@ -519,35 +570,35 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
//
// Generate the basic runway outlines
//
TGPolygon runway = gen_runway_w_mid( 0, 0 );
tgContour runway = gen_runway_w_mid( 0, 0 );
tgPolygon runway_half;
TGPolygon runway_half;
for ( int rwhalf=0; rwhalf<2; ++rwhalf ){
if (rwhalf == 0) {
//Create the first half of the runway (first entry in apt.dat)
runway_half.erase();
runway_half.add_node( 0, runway.get_pt(0, 3) );
runway_half.add_node( 0, runway.get_pt(0, 4) );
runway_half.add_node( 0, runway.get_pt(0, 5) );
runway_half.add_node( 0, runway.get_pt(0, 2) );
runway_half.Erase();
runway_half.AddNode( 0, runway.GetNode(3) );
runway_half.AddNode( 0, runway.GetNode(4) );
runway_half.AddNode( 0, runway.GetNode(5) );
runway_half.AddNode( 0, runway.GetNode(2) );
}
else if (rwhalf == 1) {
//Create the second runway half from apt.dat
runway_half.erase();
runway_half.add_node( 0, runway.get_pt(0, 0) );
runway_half.add_node( 0, runway.get_pt(0, 1) );
runway_half.add_node( 0, runway.get_pt(0, 2) );
runway_half.add_node( 0, runway.get_pt(0, 5) );
runway_half.Erase();
runway_half.AddNode( 0, runway.GetNode(0) );
runway_half.AddNode( 0, runway.GetNode(1) );
runway_half.AddNode( 0, runway.GetNode(2) );
runway_half.AddNode( 0, runway.GetNode(5) );
}
Point3D p;
SGGeod p;
SG_LOG(SG_GENERAL, SG_DEBUG, "raw runway half pts (run " << rwhalf << ")");
for ( int i = 0; i < runway_half.contour_size( 0 ); ++i ) {
p = runway_half.get_pt( 0, i );
for ( unsigned int i = 0; i < runway_half.ContourSize( 0 ); ++i ) {
p = runway_half.GetNode( 0, i );
SG_LOG(SG_GENERAL, SG_DEBUG, " point = " << p);
}
@ -576,7 +627,7 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
// Displaced threshold if it exists
//
if (rwhalf == 0) {
heading = rwy.heading + 180.0;
heading = SGMiscd::normalizePeriodic( 0,360, rwy.heading + 180.0 );
rwname = rwy.rwnum[0];
}
else if (rwhalf == 1) {
@ -614,8 +665,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, tex_pct, 1.0,
heading,
"dspl_thresh",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
@ -629,8 +680,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"dspl_thresh",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -645,8 +696,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"dspl_arrows",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -661,8 +712,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"no_threshold",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
} else {
@ -675,8 +726,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"threshold",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -684,7 +735,7 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
// Runway designation block
gen_rw_designation( runway_half, heading,
rwname, start1_pct, end1_pct,
rwy_polys, texparams, slivers,
rwy_polys, slivers,
make_shapefiles );
// Generate remaining markings depending on type of runway
@ -723,8 +774,8 @@ 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,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -752,8 +803,8 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"rest",
rwy_polys, texparams,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -782,8 +833,8 @@ 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,
&shoulder_polys, &shoulder_tps,
rwy_polys,
shoulder_polys,
slivers,
make_shapefiles );
}
@ -791,43 +842,61 @@ void Runway::gen_rwy( superpoly_list *rwy_polys,
}
}
void Runway::BuildShoulder( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing )
void Runway::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing )
{
TGPolygon base, safe_base;
TGPolygon shoulder;
tgPolygon base, safe_base;
tgPolygon shoulder;
for (unsigned int i=0; i<shoulder_polys.size(); i++) {
shoulder = shoulder_polys[i].get_poly();
shoulder = shoulder_polys[i];
// Clip the new polygon against what ever has already been created.
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( shoulder );
tgPolygonFindSlivers( clipped, slivers );
tgPolygon clipped = tgPolygon::DiffWithAccumulator( shoulder );
tgPolygon::RemoveSlivers( clipped, slivers );
// 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] );
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 );
shoulder_polys[i] = split;
tgPolygonAddToClipperAccumulator( shoulder, false );
rwy_polys.push_back( shoulder_polys[i] );
if (apt_base)
{
// also clear a safe area around the runway
base = tgPolygonExpand( shoulder, 20.0);
safe_base = tgPolygonExpand( shoulder, 50.0);
tgPolygon::AddToAccumulator( shoulder );
// add this to the airport clearing
*apt_clearing = tgPolygonUnionClipper( safe_base, *apt_clearing );
// also clear a safe area around the runway
base = tgPolygon::Expand( shoulder, 20.0);
safe_base = tgPolygon::Expand( shoulder, 50.0);
// and add the clearing to the base
*apt_base = tgPolygonUnionClipper( base, *apt_base );
}
// add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing );
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
}
}
void Runway::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers )
{
tgPolygon shoulder;
for (unsigned int i=0; i<shoulder_polys.size(); i++) {
shoulder = shoulder_polys[i];
// Clip the new polygon against what ever has already been created.
tgPolygon clipped = tgPolygon::DiffWithAccumulator( shoulder );
tgPolygon::RemoveSlivers( clipped, slivers );
// Split long edges to create an object that can better flow with
// the surface terrain
tgPolygon split = tgPolygon::SplitLongEdges( clipped, 400.0 );
shoulder_polys[i] = split;
rwy_polys.push_back( shoulder_polys[i] );
tgPolygon::AddToAccumulator( shoulder );
}
}

View file

@ -32,34 +32,32 @@ using std::string;
// generate a simple runway. The routine modifies rwy_polys,
// texparams, and accum
void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
texparams_list *texparams,
poly_list& slivers )
void Runway::gen_simple_rwy( tgpolygon_list& rwy_polys,
tgcontour_list& slivers )
{
TGPolygon runway = gen_runway_w_mid( 0.0, 0.0 );
TGPolygon runway_half;
tgContour runway = gen_runway_w_mid( 0.0, 0.0 );
tgPolygon runway_half;
for ( int rwhalf=0; rwhalf<2; ++rwhalf ) {
if (rwhalf == 0) {
//Create the first half of the runway (first entry in apt.dat)
runway_half.erase();
runway_half.add_node( 0, runway.get_pt(0, 3) );
runway_half.add_node( 0, runway.get_pt(0, 4) );
runway_half.add_node( 0, runway.get_pt(0, 5) );
runway_half.add_node( 0, runway.get_pt(0, 2) );
runway_half.Erase();
runway_half.AddNode( 0, runway.GetNode(3) );
runway_half.AddNode( 0, runway.GetNode(4) );
runway_half.AddNode( 0, runway.GetNode(5) );
runway_half.AddNode( 0, runway.GetNode(2) );
}
else if (rwhalf == 1) {
//Create the second runway half from apt.dat
runway_half.erase();
runway_half.add_node( 0, runway.get_pt(0, 0) );
runway_half.add_node( 0, runway.get_pt(0, 1) );
runway_half.add_node( 0, runway.get_pt(0, 2) );
runway_half.add_node( 0, runway.get_pt(0, 5) );
runway_half.Erase();
runway_half.AddNode( 0, runway.GetNode(0) );
runway_half.AddNode( 0, runway.GetNode(1) );
runway_half.AddNode( 0, runway.GetNode(2) );
runway_half.AddNode( 0, runway.GetNode(5) );
}
double length = rwy.length / 2.0;
@ -68,7 +66,7 @@ void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
double heading = 0.0;
if (rwhalf == 0) {
heading = rwy.heading + 180.0;
heading = SGMiscd::normalizePeriodic(0, 360, rwy.heading + 180.0);
}
else if (rwhalf == 1) {
heading = rwy.heading;
@ -88,8 +86,7 @@ void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
0.0, 1.0, 0.0, 1.0,
heading,
"",
rwy_polys, texparams,
NULL, NULL,
rwy_polys,
slivers,
false );
}
@ -101,8 +98,7 @@ void Runway::gen_simple_rwy( superpoly_list *rwy_polys,
0.0, 0.28, 0.0, 1.0,
heading,
"",
rwy_polys, texparams,
NULL, NULL,
rwy_polys,
slivers,
false );
}

View file

@ -215,7 +215,7 @@ void ProcessList::Launch( string command, string work_dir, string file, AirportI
sprintf( arg, "--redirect-port=%d", GENAPT_PORT );
args.push_back(arg);
// Launch the child process
ProcessHandle ph = Process::launch(command, args, 0, &outPipe, &outPipe);
@ -587,7 +587,7 @@ long Scheduler::FindAirport( string icao )
void Scheduler::RetryAirport( AirportInfo* pai )
{
retryList.push_back( *pai );
// retryList.push_back( *pai );
}
bool Scheduler::AddAirports( long start_pos, tg::Rectangle* boundingBox )

View file

@ -58,11 +58,13 @@ Taxiway::Taxiway(char* definition)
lon = pt_x;
}
int Taxiway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, superpoly_list* rwy_lights, poly_list& slivers, TGPolygon* apt_base, TGPolygon* apt_clearing, bool make_shapefiles )
int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, bool make_shapefiles )
{
TGPolygon taxi;
TGPolygon base, safe_base;
tgContour taxi;
tgContour base, safe_base;
std::string material;
#if 0
void* ds_id = NULL; // If we are going to build shapefiles
void* l_id = NULL; // datasource and layer IDs
@ -71,6 +73,7 @@ int Taxiway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, sup
sprintf(ds_name, "./taxi_debug");
ds_id = tgShapefileOpenDatasource( ds_name );
}
#endif
if ( surface == 1 /* Asphalt */ )
{
@ -121,9 +124,7 @@ int Taxiway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, sup
// generate a poly for this segment
taxi = gen_wgs84_rect( lat, lon, heading, length, width );
TGSuperPoly sp;
TGTexParams tp;
#if 0
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
@ -133,21 +134,22 @@ int Taxiway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, sup
sprintf( feature_name, "original" );
tgShapefileCreateFeature( ds_id, l_id, taxi, feature_name );
}
#endif
TGPolygon clipped = tgPolygonDiffClipperWithAccumulator( taxi );
tgPolygonFindSlivers( clipped, slivers );
tgPolygon clipped = tgContour::DiffWithAccumulator( taxi );
tgPolygon::RemoveSlivers( clipped, slivers );
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours());
SG_LOG(SG_GENERAL, SG_DEBUG, "tw1 clipped = " << clipped.Contours());
sp.erase();
sp.set_poly( clipped );
sp.set_material( material );
sp.set_flag("taxi");
clipped.SetMaterial( material );
clipped.SetTexParams( taxi.GetNode(0), width, 250*SG_FEET_TO_METER, heading );
clipped.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( clipped );
rwy_polys->push_back( sp );
tgPolygonAddToClipperAccumulator( taxi, false );
tgContour::AddToAccumulator( taxi );
#if 0
/* If debugging this poly, write the poly, and clipped poly and the accum buffer into their own layers */
if ( make_shapefiles ) {
char layer_name[128];
@ -158,49 +160,162 @@ int Taxiway::BuildBtg( superpoly_list* rwy_polys, texparams_list* texparams, sup
sprintf( feature_name, "clipped" );
tgShapefileCreateFeature( ds_id, l_id, clipped, feature_name );
}
#endif
SG_LOG(SG_GENERAL, SG_DEBUG, "tp construct");
base = tgContour::Expand( taxi, 20.0);
tp = TGTexParams( taxi.get_pt(0,0).toSGGeod(), width, 250*SG_FEET_TO_METER, heading );
texparams->push_back( tp );
#if 0
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
if ( apt_base )
{
base = tgPolygonExpand( taxi, 20.0);
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "exp_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_base" );
tgShapefileCreateFeature( ds_id, l_id, base, feature_name );
}
safe_base = tgPolygonExpand( taxi, 50.0);
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
SG_LOG(SG_GENERAL, SG_INFO, "expanded safe poly: " << safe_base);
sprintf( layer_name, "exp_safe_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_safe_base" );
tgShapefileCreateFeature( ds_id, l_id, safe_base, feature_name );
}
// 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 );
sprintf( layer_name, "exp_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_base" );
tgShapefileCreateFeature( ds_id, l_id, base, feature_name );
}
#endif
safe_base = tgContour::Expand( taxi, 50.0);
#if 0
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
SG_LOG(SG_GENERAL, SG_INFO, "expanded safe poly: " << safe_base);
sprintf( layer_name, "exp_safe_base" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "exp_safe_base" );
tgShapefileCreateFeature( ds_id, l_id, safe_base, feature_name );
}
#endif
// add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing);
// and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base );
#if 0
if ( make_shapefiles )
{
tgShapefileCloseDatasource( ds_id );
}
#endif
return 0;
}
int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, bool make_shapefiles )
{
tgContour taxi;
std::string material;
#if 0
void* ds_id = NULL; // If we are going to build shapefiles
void* l_id = NULL; // datasource and layer IDs
if ( make_shapefiles ) {
char ds_name[128];
sprintf(ds_name, "./taxi_debug");
ds_id = tgShapefileOpenDatasource( ds_name );
}
#endif
if ( surface == 1 /* Asphalt */ )
{
if ( (width <= 50) && (lighting[1] == '6') ) {
material = "pa_taxiway";
} else {
material = "pa_tiedown";
}
}
else if ( surface == 2 /* Concrete */ )
{
if ( (width <= 50) && (lighting[1] == '6') ) {
material = "pc_taxiway";
} else {
material = "pc_tiedown";
}
}
else if ( surface == 3 /* Turf/Grass */ )
{
material = "grass_rwy";
}
else if ( surface == 4 /* Dirt */ || surface == 5 /* Gravel */ )
{
material = "dirt_rwy";
}
else if ( surface == 12 /* Dry Lakebed */ )
{
material = "lakebed_taxiway";
}
else if ( surface == 13 /* Water runway (buoy's?) */ )
{
// water
}
else if ( surface == 14 /* Snow / Ice */ )
{
// Ice
}
else if ( surface == 15 /* Transparent */ )
{
//Transparent texture
}
else
{
SG_LOG(SG_GENERAL, SG_WARN, "surface_code = " << surface);
throw sg_exception("unknown runway type!");
}
// generate a poly for this segment
taxi = gen_wgs84_rect( lat, lon, heading, length, width );
#if 0
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "original" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "original" );
tgShapefileCreateFeature( ds_id, l_id, taxi, feature_name );
}
#endif
tgPolygon clipped = tgContour::DiffWithAccumulator( taxi );
tgPolygon::RemoveSlivers( clipped, slivers );
SG_LOG(SG_GENERAL, SG_DEBUG, "tw2 clipped = " << clipped.Contours());
clipped.SetMaterial( material );
clipped.SetTexParams( taxi.GetNode(0), width, 250*SG_FEET_TO_METER, heading );
clipped.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, 0.0, 0.0, 1.0, 1.0 );
rwy_polys.push_back( clipped );
tgContour::AddToAccumulator( taxi );
#if 0
/* If debugging this poly, write the poly, and clipped poly and the accum buffer into their own layers */
if ( make_shapefiles ) {
char layer_name[128];
char feature_name[128];
sprintf( layer_name, "clipped" );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
sprintf( feature_name, "clipped" );
tgShapefileCreateFeature( ds_id, l_id, clipped, feature_name );
}
#endif
#if 0
if ( make_shapefiles )
{
tgShapefileCloseDatasource( ds_id );
}
#endif
return 0;
}

View file

@ -19,12 +19,16 @@ public:
Taxiway(char* def);
int BuildBtg( superpoly_list* taxi_polys,
texparams_list* texparams,
superpoly_list* taxi_lights,
poly_list& slivers,
TGPolygon* apt_base,
TGPolygon* apt_clearing,
int BuildBtg( tgpolygon_list& taxi_polys,
tglightcontour_list& taxi_lights,
tgcontour_list& slivers,
bool make_shapefiles );
int BuildBtg( tgpolygon_list& taxi_polys,
tglightcontour_list& taxi_lights,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing,
bool make_shapefiles );
private:

View file

@ -12,8 +12,8 @@
#endif
#include <simgear/compiler.h>
#include <simgear/math/SGMath.hxx>
#include <Polygon/polygon.hxx>
namespace tg {

View file

@ -1,4 +1,6 @@
include_directories(${GDAL_INCLUDE_DIR})
include( ${CGAL_USE_FILE} )
add_library(Polygon STATIC
chop-bin.cxx

File diff suppressed because it is too large Load diff

View file

@ -32,8 +32,10 @@
#include <simgear/compiler.h>
#include <simgear/math/sg_types.hxx>
#include <CGAL/Plane_3.h>
#include <Geometry/point3d.hxx>
#include <iostream>
#include <string>
#include <vector>
@ -44,8 +46,6 @@ class TGPolygon;
#include "clipper.hpp"
#define FG_MAX_VERTICES 1500000
typedef TGPolygon ClipPolyType;
typedef std::vector < point_list > polytype;
typedef polytype::iterator polytype_iterator;
typedef polytype::const_iterator const_polytype_iterator;
@ -291,6 +291,426 @@ void tgPolygonDumpClipper(const TGPolygon &poly);
// Output
std::ostream &operator<<(std::ostream &output, const TGPolygon &poly);
// WORK IN PROGRESS BEGIN ******************************************************
// Looking ato TGPolygon and TGSuperPoly, I think it would be best if we could
// templatize TGPolygon. We really want 4 mirror shapes
// 1 with SGGeode as nodes - to represent Geodetic coordinates
// 1 with SGVec2d as nodes - to represent texture coordinates
// 1 with SGVec3d as nodes - to represent normals
// 1 with int as nodes - to represent indicies into the node list
//
// The problem being, is that there are many type dependent implimenations needed
// For example:
// boolean operations, and calc_point_inside() should only be done on SGGeod polys
// most of the other formats are for data storage only.
//
// For the first attempt, I will just have TGPolygon with a list of contours.
// the extra data are stored in paralell vectors.
// This should also make TGSuperPoly obsolete
#include <Geometry/trinodes.hxx>
#include <Geometry/rectangle.hxx>
// forward declaration
class tgPolygon;
class tgContour
{
public:
tgContour() {
hole = false;
}
void Erase() {
node_list.clear();
}
void SetHole( bool h ) {
hole = h;
}
bool GetHole( void ) const {
return hole;
}
unsigned int GetSize( void ) const {
return node_list.size();
}
void AddNode( SGGeod n ) {
node_list.push_back( n );
}
void SetNode( unsigned int i, SGGeod n ) {
node_list[i] = n;
}
SGGeod GetNode( unsigned int i ) const {
return node_list[i];
}
void RemoveNodeAt( unsigned int idx ) {
if ( idx < node_list.size() ) {
node_list.erase( node_list.begin() + idx );
}
}
void RemoveNodeRange( unsigned int from, unsigned int to ) {
if ( ( from < to ) && ( to < node_list.size() ) ) {
node_list.erase( node_list.begin()+from,node_list.begin()+to );
}
}
tg::Rectangle GetBoundingBox( void ) const;
double GetMinimumAngle( void ) const;
double GetArea( void ) const;
static tgContour Snap( const tgContour& subject, double snap );
static tgContour RemoveDups( const tgContour& subject );
static tgContour RemoveCycles( const tgContour& subject );
static tgContour SplitLongEdges( const tgContour& subject, double dist );
static tgContour RemoveSpikes( const tgContour& subject );
static tgPolygon DiffWithAccumulator( const tgContour& subject );
static void AddToAccumulator( const tgContour& subject );
static tgContour AddColinearNodes( const tgContour& subject, TGTriNodes nodes );
// conversions
static ClipperLib::Polygon ToClipper( const tgContour& subject );
static tgContour FromClipper( const ClipperLib::Polygon& subject );
static tgContour Expand( const tgContour& subject, double offset );
// Friend for output
friend std::ostream& operator<< ( std::ostream&, const tgContour& );
private:
std::vector<SGGeod> node_list;
bool hole;
};
typedef std::vector <tgContour> tgcontour_list;
typedef tgcontour_list::iterator tgcontour_list_iterator;
typedef tgcontour_list::const_iterator const_tgcontour_list_iterator;
class tgTriangle
{
public:
tgTriangle( const SGGeod& p0, const SGGeod& p1, const SGGeod& p2 ) {
node_list.push_back( p0 );
node_list.push_back( p1 );
node_list.push_back( p2 );
tc_list.resize( 3, SGVec2d(0.0, 0.0) );
norm_list.resize( 3, SGVec3d(0.0, 0.0, 0.0) );
idx_list.resize( 3, -1 );
}
SGGeod GetNode( unsigned int i ) const {
return node_list[i];
}
SGVec2d GetTexCoord( unsigned int i ) const {
return tc_list[i];
}
void SetTexCoord( unsigned int i, const SGVec2d tc ) {
tc_list[i] = tc;
}
// Friend for output
friend std::ostream& operator<< ( std::ostream&, const tgTriangle& );
private:
std::vector<SGGeod> node_list;
std::vector<SGVec2d> tc_list;
std::vector<SGVec3d> norm_list;
std::vector<int> idx_list;
SGVec3d face_normal;
double face_area;
};
typedef std::vector <tgTriangle> tgtriangle_list;
typedef tgtriangle_list::iterator tgtriangle_list_iterator;
typedef tgtriangle_list::const_iterator const_tgtriangle_list_iterator;
typedef enum {
TG_TEX_BY_GEODE,
TG_TEX_BY_TPS_NOCLIP,
TG_TEX_BY_TPS_CLIPU,
TG_TEX_BY_TPS_CLIPV,
TG_TEX_BY_TPS_CLIPUV
} tgTexMethod;
class tgTexParams
{
public:
SGGeod ref;
double width;
double length;
double heading;
double minu;
double maxu;
double minv;
double maxv;
double min_clipu;
double max_clipu;
double min_clipv;
double max_clipv;
tgTexMethod method;
// Friend for output
friend std::ostream& operator<< ( std::ostream&, const tgTexParams& );
};
// Forward Declaration:
class tgPolygon;
typedef std::vector <tgPolygon> tgpolygon_list;
typedef tgpolygon_list::iterator tgpolygon_list_iterator;
typedef tgpolygon_list::const_iterator const_tgpolygon_list_iterator;
typedef void (*tgpolygon_texfunc)(void);
class tgPolygon
{
public:
void Erase( void ) {
contours.clear();
triangles.clear();
}
unsigned int Contours( void ) const {
return contours.size();
}
unsigned int ContourSize( unsigned int c ) const {
return contours[c].GetSize();
}
void AddContour( tgContour contour ) {
contours.push_back(contour);
}
tgContour GetContour( unsigned int c ) const {
return contours[c];
}
void DeleteContourAt( unsigned int idx ) {
if ( idx < contours.size() ) {
contours.erase( contours.begin() + idx );
}
}
unsigned int TotalNodes( void ) const;
SGGeod GetNode( unsigned int c, unsigned int i ) const {
return contours[c].GetNode( i );
}
void SetNode( unsigned int c, unsigned int i, const SGGeod& n ) {
contours[c].SetNode( i, n );
}
void AddNode( unsigned int c, const SGGeod& n ) {
// Make sure we have contour c. If we don't add it
while( contours.size() < c+1 ) {
tgContour dummy;
dummy.SetHole( false );
contours.push_back( dummy );
}
contours[c].AddNode( n );
}
tg::Rectangle GetBoundingBox( void ) const;
void InheritElevations( const tgPolygon& source );
unsigned int Triangles( void ) const {
return triangles.size();
}
void AddTriangle( const SGGeod& p1, const SGGeod p2, const SGGeod p3 ) {
triangles.push_back( tgTriangle( p1, p2, p3 ) );
}
SGGeod GetTriNode( unsigned int c, unsigned int i ) const {
return triangles[c].GetNode( i );
}
SGVec2d GetTriTexCoord( unsigned int c, unsigned int i ) const {
return triangles[c].GetTexCoord( i );
}
std::string GetMaterial( void ) const {
return material;
}
void SetMaterial( const std::string m ) {
material = m;
}
void SetTexParams( const SGGeod& ref, double width, double length, double heading ) {
tp.ref = ref;
tp.width = width;
tp.length = length;
tp.heading = heading;
}
void SetTexParams( const tgTexParams& t ) {
tp = t;
}
const tgTexParams& GetTexParams( void ) const {
return tp;
}
void SetTexLimits( double minu, double minv, double maxu, double maxv ) {
tp.minu = minu;
tp.minv = minv;
tp.maxu = maxu;
tp.maxv = maxv;
}
void SetTexMethod( tgTexMethod m ) {
tp.method = m;
}
void SetTexMethod( tgTexMethod m, double min_cu, double min_cv, double max_cu, double max_cv ) {
tp.method = m;
tp.min_clipu = min_cu;
tp.min_clipv = min_cv;
tp.max_clipu = max_cu;
tp.max_clipv = max_cv;
}
void Tesselate( void );
void Tesselate( std::vector<SGGeod> extra );
void Texture( void );
// Boolean operations
// TODO : Both should be constant
// what we really need is multiple accumulators
// init_accumulator should return a handle...
static tgPolygon Union( const tgContour& subject, tgPolygon& clip );
static tgPolygon Union( const tgPolygon& subject, tgPolygon& clip );
static tgPolygon Intersect( const tgPolygon& subject, const tgPolygon& clip );
static tgPolygon DiffWithAccumulator( const tgPolygon& subject );
static void AddToAccumulator( const tgPolygon& subject );
// Conversions
static ClipperLib::Polygons ToClipper( const tgPolygon& subject );
static tgPolygon FromClipper( const ClipperLib::Polygons& subject );
// other operations
static tgPolygon Snap( const tgPolygon& subject, double snap );
static tgPolygon StripHoles( const tgPolygon& subject );
static tgPolygon SplitLongEdges( const tgPolygon& subject, double dist );
static tgPolygon RemoveCycles( const tgPolygon& subject );
static tgPolygon RemoveDups( const tgPolygon& subject );
static tgPolygon RemoveBadContours( const tgPolygon& subject );
static tgPolygon Simplify( const tgPolygon& subject );
static tgPolygon RemoveTinyContours( const tgPolygon& subject );
static tgPolygon RemoveSpikes( const tgPolygon& subject );
static tgPolygon Expand( const tgPolygon& subject, double offset );
static void Chop( const tgPolygon& subject, const std::string& path, const std::string& type, bool withTexparams, bool preserve3d );
static void ToShapefile( const tgPolygon& subject, const std::string& datasource, const std::string& layer, const std::string& feature );
static void Tesselate( const tgPolygon& subject );
static tgPolygon AddColinearNodes( const tgPolygon& subject, TGTriNodes& nodes );
static void RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers );
static void MergeSlivers( tgpolygon_list& subjects, tgcontour_list& slivers );
void SaveToGzFile( gzFile& fp );
void LoadFromGzFile( gzFile& fp );
// Friend for output
friend std::ostream& operator<< ( std::ostream&, const tgPolygon& );
private:
tgcontour_list contours;
tgtriangle_list triangles;
std::string material;
std::string flag; // let's get rid of this....
tgTexParams tp;
};
class tgLight
{
public:
SGGeod pos;
SGVec3d norm;
};
typedef std::vector <tgLight> tglight_list;
typedef tglight_list::iterator tglight_list_iterator;
typedef tglight_list::const_iterator const_tglight_list_iterator;
class tgLightContour
{
public:
unsigned int ContourSize( void ) const {
return lights.size();
}
void AddLight( SGGeod p, SGVec3d n ) {
tgLight light;
light.pos = p;
light.norm = n;
lights.push_back(light);
}
SGGeod GetNode( unsigned int i ) const {
return lights[i].pos;
}
std::string GetFlag( void ) const {
return flag;
}
void SetFlag( const std::string f ) {
flag = f;
}
std::string GetType( void ) const {
return type;
}
void SetType( const std::string t ) {
type = t;
}
// TEMP TEMP TEMP : need to redo Airport.cxx methods
point_list TempGetPosListAsPoint3D( void ) {
point_list p3dlist;
for (unsigned int i=0; i<lights.size(); i++) {
p3dlist.push_back( Point3D::fromSGGeod( lights[i].pos ) );
}
return p3dlist;
}
point_list TempGetNormalListAsPoint3D( void ) {
point_list p3dlist;
for (unsigned int i=0; i<lights.size(); i++) {
p3dlist.push_back( Point3D::fromSGVec3( lights[i].norm ) );
}
return p3dlist;
}
// END TEMP TEMP TEMP
// Friend for output
friend std::ostream& operator<< ( std::ostream&, const tgLightContour& );
std::string type;
std::string flag;
tglight_list lights;
};
typedef std::vector <tgLightContour> tglightcontour_list;
typedef tglightcontour_list::iterator tglightcontour_list_iterator;
typedef tglightcontour_list::const_iterator const_tglightcontour_list_iterator;
#endif // _POLYGON_HXX

View file

@ -36,7 +36,7 @@
#include <string>
#include <vector>
#include "polygon.hxx"
#include <Polygon/polygon.hxx>
// TODO : Needs to be its own class
typedef std::vector < int > int_list;