1
0
Fork 0

fix runway shoulder base and clearing calculation.

- instead of expanding for each poly - account for shoulders when expanding base and clearing when building the runway.
- instead of doing a union for each base / clearing poly - add them to a list to do just one clip operation at the end.  This results in anoth 2-3% performance increase, and allows another 10 airports to build. just 4 don't build in addition to NZSP.
This commit is contained in:
Peter Sadrozinski 2012-11-23 19:34:35 -05:00
parent b971c2b344
commit 05f46adacb
13 changed files with 110 additions and 140 deletions

View file

@ -285,8 +285,8 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
tgcontour_list slivers; tgcontour_list slivers;
tgcontour_list line_slivers; tgcontour_list line_slivers;
tgPolygon apt_base; tgpolygon_list apt_base_polys;
tgPolygon apt_clearing; tgpolygon_list apt_clearing_polys;
// runways // runways
tgpolygon_list rwy_polys; tgpolygon_list rwy_polys;
@ -397,7 +397,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
} }
else else
{ {
runways[i]->BuildBtg( rwy_polys, rwy_lights, slivers, apt_base, apt_clearing, shapefile ); runways[i]->BuildBtg( rwy_polys, rwy_lights, slivers, apt_base_polys, apt_clearing_polys, shapefile );
} }
// Now try to merge any slivers we found // Now try to merge any slivers we found
@ -433,7 +433,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
} }
else else
{ {
helipads[i]->BuildBtg( rwy_polys, rwy_lights, slivers, apt_base, apt_clearing ); helipads[i]->BuildBtg( rwy_polys, rwy_lights, slivers, apt_base_polys, apt_clearing_polys );
} }
// Now try to merge any slivers we found // Now try to merge any slivers we found
@ -463,7 +463,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
} }
else else
{ {
pavements[i]->BuildBtg( pvmt_polys, slivers, apt_base, apt_clearing, shapefile ); pavements[i]->BuildBtg( pvmt_polys, slivers, apt_base_polys, apt_clearing_polys, shapefile );
} }
// Now try to merge any slivers we found // Now try to merge any slivers we found
@ -497,7 +497,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
} }
else else
{ {
taxiways[i]->BuildBtg( pvmt_polys, rwy_lights, slivers, apt_base, apt_clearing, shapefile ); taxiways[i]->BuildBtg( pvmt_polys, rwy_lights, slivers, apt_base_polys, apt_clearing_polys, shapefile );
} }
// Now try to merge any slivers we found // Now try to merge any slivers we found
@ -517,15 +517,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
if ( runways[i]->GetsShoulder() ) if ( runways[i]->GetsShoulder() )
{ {
slivers.clear(); slivers.clear();
if (boundary.size())
{
runways[i]->BuildShoulder( rwy_polys, slivers ); runways[i]->BuildShoulder( rwy_polys, slivers );
}
else
{
runways[i]->BuildShoulder( rwy_polys, slivers, apt_base, apt_clearing );
}
// Now try to merge any slivers we found // Now try to merge any slivers we found
tgPolygon::MergeSlivers( rwy_polys, slivers ); tgPolygon::MergeSlivers( rwy_polys, slivers );
@ -545,15 +537,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
if ( helipads[i]->GetsShoulder() ) if ( helipads[i]->GetsShoulder() )
{ {
slivers.clear(); slivers.clear();
if (boundary.size())
{
helipads[i]->BuildShoulder( rwy_polys, slivers ); helipads[i]->BuildShoulder( rwy_polys, slivers );
}
else
{
helipads[i]->BuildShoulder( rwy_polys, slivers, apt_base, apt_clearing );
}
// Now try to merge any slivers we found // Now try to merge any slivers we found
tgPolygon::MergeSlivers( rwy_polys, slivers ); tgPolygon::MergeSlivers( rwy_polys, slivers );
@ -563,6 +547,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
} }
// build the base and clearing if there's a boundary // build the base and clearing if there's a boundary
tgPolygon apt_base, apt_clearing;
if (boundary.size()) if (boundary.size())
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build " << boundary.size() << " Boundary Polys "); SG_LOG(SG_GENERAL, SG_INFO, "Build " << boundary.size() << " Boundary Polys ");
@ -573,6 +558,9 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "Build Userdefined boundary " << i + 1 << " of " << boundary.size()); SG_LOG(SG_GENERAL, SG_DEBUG, "Build Userdefined boundary " << i + 1 << " of " << boundary.size());
boundary[i]->BuildBtg( apt_base, apt_clearing, shapefile ); boundary[i]->BuildBtg( apt_base, apt_clearing, shapefile );
} }
} else {
apt_base = tgPolygon::Union( apt_base_polys );
apt_clearing = tgPolygon::Union( apt_clearing_polys );
} }
if ( apt_base.TotalNodes() == 0 ) if ( apt_base.TotalNodes() == 0 )
@ -592,9 +580,6 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
// add segments to polygons to remove any possible "T" // add segments to polygons to remove any possible "T"
// intersections // intersections
//TGTriNodes tmp_pvmt_nodes;
//TGTriNodes tmp_feat_nodes;
UniqueSGGeodSet tmp_pvmt_nodes; UniqueSGGeodSet tmp_pvmt_nodes;
UniqueSGGeodSet tmp_feat_nodes; UniqueSGGeodSet tmp_feat_nodes;
@ -791,7 +776,7 @@ void Airport::BuildBtg(const std::string& root, const string_list& elev_src )
intersecting contours */ intersecting contours */
base_poly = tgPolygon::Simplify( base_poly ); base_poly = tgPolygon::Simplify( base_poly );
SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly "); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly : " << base_poly.Contours() << " contours " );
base_poly.Tesselate(); base_poly.Tesselate();
SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly - done : Triangles = " << base_poly.Triangles()); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly - done : Triangles = " << base_poly.Triangles());
// should we texture base here? // should we texture base here?

View file

@ -415,7 +415,7 @@ std::string ClosedPoly::GetMaterial( int surface )
return material; return material;
} }
int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, std::string& shapefile_name ) int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, tgpolygon_list& apt_base_polys, tgpolygon_list& apt_clearing_polys, std::string& shapefile_name )
{ {
if (is_pavement && pre_tess.Contours() ) if (is_pavement && pre_tess.Contours() )
{ {
@ -427,10 +427,10 @@ int ClosedPoly::BuildBtg( tgpolygon_list& rwy_polys, tgcontour_list& slivers, tg
safe_base = tgPolygon::Expand( pre_tess, 50.0); safe_base = tgPolygon::Expand( pre_tess, 50.0);
// add this to the airport clearing // add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing); apt_clearing_polys.push_back( safe_base );
// and add the clearing to the base // and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base ); apt_base_polys.push_back( base );
} }
// clean up to save ram : we're done here... // clean up to save ram : we're done here...

View file

@ -30,8 +30,8 @@ public:
int BuildBtg( tgpolygon_list& rwy_polys, int BuildBtg( tgpolygon_list& rwy_polys,
tgcontour_list& slivers, tgcontour_list& slivers,
tgPolygon& apt_base, tgpolygon_list& apt_base_polys,
tgPolygon& apt_clearing, tgpolygon_list& apt_clearing_polys,
std::string& shapefile_name ); std::string& shapefile_name );
FeatureList* GetFeatures() FeatureList* GetFeatures()
@ -63,11 +63,14 @@ private:
BezContour* cur_contour; BezContour* cur_contour;
// outer boundary as convex hull // outer boundary as convex hull
point_list hull; // point_list hull;
// Converted polygon after parsing complete // Converted polygon after parsing complete
tgPolygon pre_tess; tgPolygon pre_tess;
// shoulders after BTG built
tgpolygon_list shoulder_polys;
// pavement definitions have multiple linear features (markings and lights for each contour) // pavement definitions have multiple linear features (markings and lights for each contour)
LinearFeature* cur_feature; LinearFeature* cur_feature;
FeatureList features; FeatureList features;

View file

@ -200,14 +200,15 @@ void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
void Helipad::BuildBtg( tgpolygon_list& rwy_polys, void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights, tglightcontour_list& rwy_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgPolygon& apt_base, tgpolygon_list& apt_base_polys,
tgPolygon& apt_clearing ) tgpolygon_list& apt_clearing_polys )
{ {
BuildBtg( rwy_polys, rwy_lights, slivers ); BuildBtg( rwy_polys, rwy_lights, slivers );
// generate area around helipad // generate area around helipad
double length, width; double length, width;
tgContour base, safe_base; tgContour base_contour, safe_base_contour;
tgPolygon base, safe_base;
length = heli.length; length = heli.length;
width = heli.width; width = heli.width;
@ -219,45 +220,20 @@ void Helipad::BuildBtg( tgpolygon_list& rwy_polys,
width += 2.0; width += 2.0;
} }
base = gen_helipad_area_w_extend(length * 0.25 , width * 0.25 ); base_contour = gen_helipad_area_w_extend(length * 0.25 , width * 0.25 );
base = tgContour::Snap( base, gSnap ); base_contour = tgContour::Snap( base_contour, gSnap );
base.AddContour( base_contour );
// also clear a safe area around the pad // also clear a safe area around the pad
safe_base = gen_helipad_area_w_extend( length * 0.5, width * 0.5 ); safe_base_contour = gen_helipad_area_w_extend( length * 0.5, width * 0.5 );
safe_base = tgContour::Snap( safe_base, gSnap ); safe_base_contour = tgContour::Snap( safe_base_contour, gSnap );
safe_base.AddContour( safe_base_contour );
// add this to the airport clearing // add this to the airport clearing
apt_clearing = tgPolygon::Union(safe_base, apt_clearing); apt_clearing_polys.push_back( safe_base );
// and add the clearing to the base // and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base ); apt_base_polys.push_back( base );
}
void Helipad::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing )
{
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 );
}
// base and clearing calculated when generating the shoulders
} }
void Helipad::BuildShoulder( tgpolygon_list& rwy_polys, void Helipad::BuildShoulder( tgpolygon_list& rwy_polys,

View file

@ -30,8 +30,8 @@ public:
void BuildBtg( tgpolygon_list& heli_polys, void BuildBtg( tgpolygon_list& heli_polys,
tglightcontour_list& heli_lights, tglightcontour_list& heli_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgPolygon& apt_base, tgpolygon_list& apt_base_polys,
tgPolygon& apt_clearing ); tgpolygon_list& apt_clearing_polys );
SGGeod GetLoc() SGGeod GetLoc()
{ {
@ -46,11 +46,6 @@ public:
void BuildShoulder( tgpolygon_list& rwy_polys, void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers ); tgcontour_list& slivers );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing );
private: private:
struct TGRunway { struct TGRunway {
// data for helipad // data for helipad

View file

@ -166,25 +166,35 @@ int Runway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights
return 0; return 0;
} }
int Runway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, std::string& shapefile_name ) int Runway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgpolygon_list& apt_base_polys, tgpolygon_list& apt_clearing_polys, std::string& shapefile_name )
{ {
tgContour base, safe_base; tgContour base_contour, safe_base_contour;
tgPolygon base, safe_base;
double shoulder_width = 0.0;
BuildBtg( rwy_polys, rwy_lights, slivers, shapefile_name ); BuildBtg( rwy_polys, rwy_lights, slivers, shapefile_name );
// generate area around runways // generate area around runways
base = gen_runway_area_w_extend( 20.0, -rwy.overrun[0], -rwy.overrun[1], 20.0 ); if ( (rwy.shoulder > 0) && (rwy.surface < 3) ) {
base = tgContour::Snap( base, gSnap ); shoulder_width += 22.0;
} else if ( (rwy.surface == 1) || (rwy.surface == 2) ) {
shoulder_width += 2.0;
}
base_contour = gen_runway_area_w_extend( 20.0, -rwy.overrun[0], -rwy.overrun[1], shoulder_width + 20.0 );
base_contour = tgContour::Snap( base_contour, gSnap );
base.AddContour( base_contour );
// also clear a safe area around the runway // 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_contour = gen_runway_area_w_extend( 180.0, -rwy.overrun[0], -rwy.overrun[1], shoulder_width + 50.0 );
safe_base = tgContour::Snap( safe_base, gSnap ); safe_base_contour = tgContour::Snap( safe_base_contour, gSnap );
safe_base.AddContour( safe_base_contour );
// add this to the airport clearing // add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing ); apt_clearing_polys.push_back( safe_base );
// and add the clearing to the base // and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base ); apt_base_polys.push_back( base );
return 0; return 0;
} }

View file

@ -39,18 +39,13 @@ public:
int BuildBtg( tgpolygon_list& rwy_polys, int BuildBtg( tgpolygon_list& rwy_polys,
tglightcontour_list& rwy_lights, tglightcontour_list& rwy_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgPolygon& apt_base, tgpolygon_list& apt_base_polys,
tgPolygon& apt_clearing, tgpolygon_list& apt_clearing_polys,
std::string& shapefile_name ); std::string& shapefile_name );
void BuildShoulder( tgpolygon_list& rwy_polys, void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers ); tgcontour_list& slivers );
void BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers,
tgPolygon& apt_base,
tgPolygon& apt_clearing );
private: private:
struct TGRunway { struct TGRunway {
// data for whole runway // data for whole runway

View file

@ -847,9 +847,7 @@ void Runway::gen_rwy( tgpolygon_list& rwy_polys,
} }
void Runway::BuildShoulder( tgpolygon_list& rwy_polys, void Runway::BuildShoulder( tgpolygon_list& rwy_polys,
tgcontour_list& slivers, tgcontour_list& slivers )
tgPolygon& apt_base,
tgPolygon& apt_clearing )
{ {
tgPolygon base, safe_base; tgPolygon base, safe_base;
tgPolygon shoulder; tgPolygon shoulder;
@ -867,40 +865,6 @@ void Runway::BuildShoulder( tgpolygon_list& rwy_polys,
shoulder_polys[i] = split; shoulder_polys[i] = split;
rwy_polys.push_back( shoulder_polys[i] ); rwy_polys.push_back( shoulder_polys[i] );
tgPolygon::AddToAccumulator( shoulder );
// 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 = 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 ); tgPolygon::AddToAccumulator( shoulder );
} }
} }

View file

@ -159,21 +159,24 @@ int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_light
return 0; return 0;
} }
int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgPolygon& apt_base, tgPolygon& apt_clearing, std::string& shapefile_name ) int Taxiway::BuildBtg( tgpolygon_list& rwy_polys, tglightcontour_list& rwy_lights, tgcontour_list& slivers, tgpolygon_list& apt_base_polys, tgpolygon_list& apt_clearing_polys, std::string& shapefile_name )
{ {
tgContour base, safe_base; tgContour base_contour, safe_base_contour;
tgPolygon base, safe_base;
BuildBtg( rwy_polys, rwy_lights, slivers, shapefile_name ); BuildBtg( rwy_polys, rwy_lights, slivers, shapefile_name );
base = tgContour::Expand( taxi_contour, 20.0); base_contour = tgContour::Expand( taxi_contour, 20.0);
base.AddContour( base_contour );
safe_base = tgContour::Expand( taxi_contour, 50.0); safe_base_contour = tgContour::Expand( taxi_contour, 50.0);
safe_base.AddContour( safe_base_contour );
// add this to the airport clearing // add this to the airport clearing
apt_clearing = tgPolygon::Union( safe_base, apt_clearing); apt_clearing_polys.push_back( safe_base );
// and add the clearing to the base // and add the clearing to the base
apt_base = tgPolygon::Union( base, apt_base ); apt_base_polys.push_back( base );
return 0; return 0;
} }

View file

@ -19,8 +19,8 @@ public:
int BuildBtg( tgpolygon_list& taxi_polys, int BuildBtg( tgpolygon_list& taxi_polys,
tglightcontour_list& taxi_lights, tglightcontour_list& taxi_lights,
tgcontour_list& slivers, tgcontour_list& slivers,
tgPolygon& apt_base, tgpolygon_list& apt_base_polys,
tgPolygon& apt_clearing, tgpolygon_list& apt_clearing_polys,
std::string& shapefile_name ); std::string& shapefile_name );
private: private:

View file

@ -282,7 +282,7 @@ int main(int argc, char* argv[])
if (argc > 5 && strcasecmp(argv[5], "EVENODD") == 0) if (argc > 5 && strcasecmp(argv[5], "EVENODD") == 0)
clip_pft = pftEvenOdd; clip_pft = pftEvenOdd;
cout << "\nclipping ... "; cout << "\nclipping ... \n";
Clipper c; Clipper c;
c.AddPolygons(subject, ptSubject); c.AddPolygons(subject, ptSubject);
@ -302,6 +302,15 @@ int main(int argc, char* argv[])
// cout << "\nEllapsed: " << elapsed; // cout << "\nEllapsed: " << elapsed;
// } // }
for ( int i=0; i<solution.size(); i++ ) {
Polygon contour = solution[i];
if ( Orientation( contour ) ) {
cout << "solution contour " << i << " is true \n";
} else {
cout << "solution contour " << i << " is false \n";
}
}
if (succeeded) { if (succeeded) {
SaveToFile("solution.txt", solution, precision); SaveToFile("solution.txt", solution, precision);
SaveToFileOstream("solution_ostream", solution ); SaveToFileOstream("solution_ostream", solution );

View file

@ -2305,6 +2305,35 @@ tgPolygon tgPolygon::Union( const tgPolygon& subject, tgPolygon& clip )
return result; return result;
} }
tgPolygon tgPolygon::Union( const tgpolygon_list& polys )
{
ClipperLib::Polygons clipper_result;
ClipperLib::Clipper c;
TGTriNodes all_nodes;
tgPolygon result;
/* before union - gather all nodes */
for ( unsigned int i=0; i<polys.size(); i++ ) {
for ( unsigned int j = 0; j < polys[i].Contours(); ++j ) {
for ( unsigned int k = 0; k < polys[i].ContourSize( j ); ++k ) {
all_nodes.unique_add( Point3D::fromSGGeod( polys[i].GetNode(j, k) ) );
}
}
}
c.Clear();
for (unsigned int i=0; i<polys.size(); i++) {
ClipperLib::Polygons clipper_clip = tgPolygon::ToClipper( polys[i] );
c.AddPolygons(clipper_clip, ClipperLib::ptSubject);
}
c.Execute(ClipperLib::ctUnion, clipper_result, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
result = tgPolygon::FromClipper( clipper_result );
result = tgPolygon::AddColinearNodes( result, all_nodes );
return result;
}
tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip ) tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip )
{ {
tgPolygon result; tgPolygon result;

View file

@ -594,6 +594,7 @@ public:
static void SetDump( bool dmp ); static void SetDump( bool dmp );
static tgPolygon Union( const tgContour& subject, tgPolygon& clip ); static tgPolygon Union( const tgContour& subject, tgPolygon& clip );
static tgPolygon Union( const tgPolygon& subject, tgPolygon& clip ); static tgPolygon Union( const tgPolygon& subject, tgPolygon& clip );
static tgPolygon Union( const tgpolygon_list& polys );
static tgPolygon Diff( const tgPolygon& subject, tgPolygon& clip ); static tgPolygon Diff( const tgPolygon& subject, tgPolygon& clip );
static tgPolygon Intersect( const tgPolygon& subject, const tgPolygon& clip ); static tgPolygon Intersect( const tgPolygon& subject, const tgPolygon& clip );