1
0
Fork 0

Stability checkpoint for genapt850

- break up and expand shoulder polys, so they overlap runways.
  This keeps cracks from forming between the shoulder and runway
  do to roundoff error
- Add verbose option to polygon_tesselate functions to aid in debugging
  can set at runtime to produce triangulation output for just 1 poly.
- add remove_small_cycles to poly cleanup routines before triangulation
- more warnings cleanup in ClosePoly.cxx
- add more output in normal execution path, as some airports can go for
  hours without printing any status.  Hard to tell if it's locked up
This commit is contained in:
Peter Sadrozinski 2012-01-22 13:15:02 -05:00 committed by Christian Schmitt
parent 27c31404ca
commit 37a46c4075
17 changed files with 559 additions and 404 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@ Makefile.in
.deps .deps
*.o *.o
*.a *.a
*~
COPYING COPYING
INSTALL INSTALL
VERSION VERSION

View file

@ -828,7 +828,7 @@ void build_airport( string airport_id, float alt_m,
TGPolygon poly = rwy_polys[i].get_poly(); TGPolygon poly = rwy_polys[i].get_poly();
SG_LOG(SG_GENERAL, SG_DEBUG, "total size before = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size before = " << poly.total_size());
TGPolygon tri = polygon_tesselate_alt( poly ); TGPolygon tri = polygon_tesselate_alt( poly, false );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size());
TGPolygon tc; TGPolygon tc;
@ -844,7 +844,7 @@ void build_airport( string airport_id, float alt_m,
} }
SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating base"); SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating base");
TGPolygon base_tris = polygon_tesselate_alt( base_poly ); TGPolygon base_tris = polygon_tesselate_alt( base_poly, false );
#if 0 #if 0
// dump more debugging output // dump more debugging output

View file

@ -325,6 +325,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
int i, j, k; int i, j, k;
Point3D p; Point3D p;
bool verbose_triangulation = false;
// parse main airport information // parse main airport information
double apt_lon = 0.0, apt_lat = 0.0; double apt_lon = 0.0, apt_lat = 0.0;
@ -334,16 +336,24 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
struct timeval cleanup_end; struct timeval cleanup_end;
struct timeval triangulation_start; struct timeval triangulation_start;
struct timeval triangulation_end; struct timeval triangulation_end;
struct timeval log_time;
// Find the average of all the runway long / lats // Find the average of all the runway and heliport long / lats
// TODO : Need runway object... int num_samples = 0;
for (i=0; i<runways.size(); i++) for (i=0; i<runways.size(); i++)
{ {
apt_lon += runways.at(i)->GetMidpoint().x(); apt_lon += runways[i]->GetMidpoint().x();
apt_lat += runways.at(i)->GetMidpoint().y(); apt_lat += runways[i]->GetMidpoint().y();
num_samples++;
} }
apt_lon = apt_lon / (double)runways.size(); for (i=0; i<helipads.size(); i++)
apt_lat = apt_lat / (double)runways.size(); {
apt_lon += helipads[i]->GetLoc().x();
apt_lat += helipads[i]->GetLoc().y();
num_samples++;
}
apt_lon = apt_lon / (double)num_samples;
apt_lat = apt_lat / (double)num_samples;
SGBucket b( apt_lon, apt_lat ); SGBucket b( apt_lon, apt_lat );
SG_LOG(SG_GENERAL, SG_DEBUG, b.gen_base_path() << "/" << b.gen_index_str()); SG_LOG(SG_GENERAL, SG_DEBUG, b.gen_base_path() << "/" << b.gen_index_str());
@ -368,7 +378,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( i=0; i<features.size(); i++ ) for ( i=0; i<features.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Build Feature Poly " << i << ": " << features[i]->GetDescription() ); SG_LOG(SG_GENERAL, SG_INFO, "Build Feature Poly " << i << " of " << features.size() << " : " << features[i]->GetDescription() );
// cut the linear feature in until we get the geometry right... // cut the linear feature in until we get the geometry right...
// features[i]->BuildBtg( altitude, &line_polys, &line_tps, &line_accum ); // features[i]->BuildBtg( altitude, &line_polys, &line_tps, &line_accum );
@ -380,9 +390,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "no markings"); SG_LOG(SG_GENERAL, SG_DEBUG, "no markings");
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished building Linear Features for " << icao << " at " << ctime(&log_time.tv_sec) );
// Build runways next // Build runways next
for (i=0; i<runways.size(); i++ ) for (i=0; i<runways.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build Runway " << i << " of " << runways.size());
if ( runways[i]->IsPrecision() ) if ( runways[i]->IsPrecision() )
{ {
if (boundary) if (boundary)
@ -393,13 +408,18 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing ); runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, &apt_base, &apt_clearing );
} }
} }
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished building runways for " << icao << " at " << ctime(&log_time.tv_sec) );
if (lightobjects.size()) if (lightobjects.size())
{ {
for ( i=0; i<lightobjects.size(); i++ ) for ( i=0; i<lightobjects.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build runway light " << i << " of " << lightobjects.size());
lightobjects[i]->BuildBtg( altitude, &rwy_lights ); lightobjects[i]->BuildBtg( altitude, &rwy_lights );
} }
} }
@ -407,6 +427,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// Build helipads (use runway poly- and texture list for this) // Build helipads (use runway poly- and texture list for this)
if (helipads.size()) if (helipads.size())
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Build helipad " << i << " of " << helipads.size());
for (i=0; i<helipads.size(); i++ ) for (i=0; i<helipads.size(); i++ )
{ {
if (boundary) if (boundary)
@ -419,12 +441,13 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
} }
} }
} }
// Build the pavements // Build the pavements
if (pavements.size()) if (pavements.size())
{ {
for ( i=0; i<pavements.size(); i++ ) for ( i=0; i<pavements.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Build Pavement Poly " << i << ": " << pavements[i]->GetDescription()); SG_LOG(SG_GENERAL, SG_DEBUG, "Build Pavement " << i << " of " << pavements.size() << " : " << pavements[i]->GetDescription());
if (boundary) if (boundary)
{ {
@ -441,9 +464,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "no pavements"); SG_LOG(SG_GENERAL, SG_DEBUG, "no pavements");
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished building pavements for " << icao << " at " << ctime(&log_time.tv_sec) );
// Build runway shoulders here // Build runway shoulders here
for (i=0; i<runways.size(); i++ ) for (i=0; i<runways.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Build Runway shoulder " << i << " of " << runways.size());
if ( runways[i]->GetsShoulder() ) if ( runways[i]->GetsShoulder() )
{ {
runways[i]->BuildShoulder( altitude, &rwy_polys, &rwy_tps, &accum ); runways[i]->BuildShoulder( altitude, &rwy_polys, &rwy_tps, &accum );
@ -453,10 +481,12 @@ void Airport::BuildBtg(const 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
if (boundary) if (boundary)
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Build user defined boundary " );
boundary->BuildBtg( altitude, &apt_base, &apt_clearing ); boundary->BuildBtg( altitude, &apt_base, &apt_clearing );
} }
if ( apt_base.total_size() == 0 ) if ( apt_base.total_size() == 0 )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated"); SG_LOG(SG_GENERAL, SG_ALERT, "no airport points generated");
return; return;
@ -464,7 +494,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
TGPolygon filled_base = tgPolygonStripHoles( apt_base ); TGPolygon filled_base = tgPolygonStripHoles( apt_base );
TGPolygon divided_base = tgPolygonSplitLongEdges( filled_base, 200.0 ); TGPolygon divided_base = tgPolygonSplitLongEdges( filled_base, 200.0 );
//TGPolygon base_poly = tgPolygonDiff( filled_base, accum );
TGPolygon base_poly = tgPolygonDiff( divided_base, accum ); TGPolygon base_poly = tgPolygonDiff( divided_base, accum );
gettimeofday(&build_end, NULL); gettimeofday(&build_end, NULL);
@ -477,6 +506,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
TGTriNodes tmp_nodes; TGTriNodes tmp_nodes;
// build temporary node list from runways... // build temporary node list from runways...
SG_LOG(SG_GENERAL, SG_INFO, "Build Node List " );
for ( k = 0; k < (int)rwy_polys.size(); ++k ) for ( k = 0; k < (int)rwy_polys.size(); ++k )
{ {
TGPolygon poly = rwy_polys[k].get_poly(); TGPolygon poly = rwy_polys[k].get_poly();
@ -484,7 +515,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( j = 0; j < poly.contour_size( i ); ++j ) for ( j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
@ -498,6 +530,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < poly.contour_size( i ); ++j ) for ( j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
@ -511,6 +544,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < poly.contour_size( i ); ++j ) for ( j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
@ -521,6 +555,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < base_poly.contour_size( i ); ++j ) for ( j = 0; j < base_poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( base_poly.get_pt(i, j) ); tmp_nodes.unique_add( base_poly.get_pt(i, j) );
//tmp_nodes.course_add( base_poly.get_pt(i, j) );
} }
} }
@ -531,9 +566,13 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < divided_base.contour_size( i ); ++j ) for ( j = 0; j < divided_base.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( divided_base.get_pt(i, j) ); tmp_nodes.unique_add( divided_base.get_pt(i, j) );
//tmp_nodes.course_add( divided_base.get_pt(i, j) );
} }
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished collecting nodes for " << icao << " at " << ctime(&log_time.tv_sec) );
// second pass : runways // second pass : runways
for ( k = 0; k < (int)rwy_polys.size(); ++k ) for ( k = 0; k < (int)rwy_polys.size(); ++k )
{ {
@ -564,6 +603,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
line_polys[k].set_poly( poly ); line_polys[k].set_poly( poly );
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished adding intermediate nodes for " << icao << " at " << ctime(&log_time.tv_sec) );
// One more pass to try to get rid of other yukky stuff // One more pass to try to get rid of other yukky stuff
for ( k = 0; k < (int)rwy_polys.size(); ++k ) for ( k = 0; k < (int)rwy_polys.size(); ++k )
@ -572,12 +613,10 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size());
poly = remove_cycles( poly );
poly = remove_dups( poly ); poly = remove_dups( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size());
poly = remove_bad_contours( poly ); poly = remove_bad_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_bad() = " << poly.total_size());
poly = remove_tiny_contours( poly ); poly = remove_tiny_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_tiny_contours() = " << poly.total_size());
rwy_polys[k].set_poly( poly ); rwy_polys[k].set_poly( poly );
} }
@ -588,12 +627,10 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size());
poly = remove_cycles( poly );
poly = remove_dups( poly ); poly = remove_dups( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size());
poly = remove_bad_contours( poly ); poly = remove_bad_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_bad() = " << poly.total_size());
poly = remove_tiny_contours( poly ); poly = remove_tiny_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_tiny_contours() = " << poly.total_size());
pvmt_polys[k].set_poly( poly ); pvmt_polys[k].set_poly( poly );
} }
@ -604,17 +641,16 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size());
poly = remove_cycles( poly );
poly = remove_dups( poly ); poly = remove_dups( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size());
poly = remove_bad_contours( poly ); poly = remove_bad_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_bad() = " << poly.total_size());
poly = remove_tiny_contours( poly ); poly = remove_tiny_contours( poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_tiny_contours() = " << poly.total_size());
line_polys[k].set_poly( poly ); line_polys[k].set_poly( poly );
} }
gettimeofday(&log_time, NULL);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished cleaning poly for " << icao << " at " << ctime(&log_time.tv_sec) );
SG_LOG(SG_GENERAL, SG_DEBUG, "add nodes base "); SG_LOG(SG_GENERAL, SG_DEBUG, "add nodes base ");
SG_LOG(SG_GENERAL, SG_DEBUG, " before: " << base_poly); SG_LOG(SG_GENERAL, SG_DEBUG, " before: " << base_poly);
@ -623,15 +659,10 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
base_poly = add_nodes_to_poly( base_poly, tmp_nodes ); base_poly = add_nodes_to_poly( base_poly, tmp_nodes );
SG_LOG(SG_GENERAL, SG_DEBUG, " after adding tmp_nodes: " << base_poly); SG_LOG(SG_GENERAL, SG_DEBUG, " after adding tmp_nodes: " << base_poly);
// write_polygon( base_poly, "base-add" ); base_poly = remove_cycles( base_poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "remove dups base ");
base_poly = remove_dups( base_poly ); base_poly = remove_dups( base_poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "remove bad contours base");
base_poly = remove_bad_contours( base_poly ); base_poly = remove_bad_contours( base_poly );
SG_LOG(SG_GENERAL, SG_DEBUG, "remove small contours base");
base_poly = remove_tiny_contours( base_poly ); base_poly = remove_tiny_contours( base_poly );
// write_polygon( base_poly, "base-fin" );
SG_LOG(SG_GENERAL, SG_DEBUG, " after clean up: " << base_poly);
gettimeofday(&cleanup_end, NULL); gettimeofday(&cleanup_end, NULL);
timersub(&cleanup_end, &cleanup_start, &cleanup_time); timersub(&cleanup_end, &cleanup_start, &cleanup_time);
@ -641,11 +672,19 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// tesselate the polygons and prepair them for final output // tesselate the polygons and prepair them for final output
for ( i = 0; i < (int)rwy_polys.size(); ++i ) for ( i = 0; i < (int)rwy_polys.size(); ++i )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating section = " << i << " flag = " << rwy_polys[i].get_flag()); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating runway poly = " << i << " of " << rwy_polys.size() << " : flag = " << rwy_polys[i].get_flag());
TGPolygon poly = rwy_polys[i].get_poly(); TGPolygon poly = rwy_polys[i].get_poly();
#if 0
if ( i == 62 ) {
tgChopNormalPolygon( "/home/pete", "Base", poly, false );
verbose_triangulation = true;
}
#endif
SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size());
TGPolygon tri = polygon_tesselate_alt( poly ); TGPolygon tri = polygon_tesselate_alt( poly, verbose_triangulation );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size());
TGPolygon tc; TGPolygon tc;
@ -658,11 +697,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// tesselate the polygons and prepair them for final output // tesselate the polygons and prepair them for final output
for ( i = 0; i < (int)pvmt_polys.size(); ++i ) for ( i = 0; i < (int)pvmt_polys.size(); ++i )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating section = " << i << " flag = " << pvmt_polys[i].get_flag()); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating pavement poly = " << i << " of " << pvmt_polys.size() << " : flag = " << pvmt_polys[i].get_flag());
TGPolygon poly = pvmt_polys[i].get_poly(); TGPolygon poly = pvmt_polys[i].get_poly();
SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size());
TGPolygon tri = polygon_tesselate_alt( poly ); TGPolygon tri = polygon_tesselate_alt( poly, false );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size());
TGPolygon tc; TGPolygon tc;
@ -682,27 +721,30 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// tesselate the polygons and prepair them for final output // tesselate the polygons and prepair them for final output
for ( i = 0; i < (int)line_polys.size(); ++i ) for ( i = 0; i < (int)line_polys.size(); ++i )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating section = " << i << " flag = " << line_polys[i].get_flag()); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating line poly = " << i << " of " << line_polys.size() << " : flag = " << line_polys[i].get_flag());
TGPolygon poly = line_polys[i].get_poly(); TGPolygon poly = line_polys[i].get_poly();
SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size());
TGPolygon tri = polygon_tesselate_alt( poly ); SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size());
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); TGPolygon tri = polygon_tesselate_alt( poly, false );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size());
TGPolygon tc; TGPolygon tc;
tc = linear_feature_tex_coords( tri, line_tps[i] ); tc = linear_feature_tex_coords( tri, line_tps[i] );
line_polys[i].set_tris( tri ); line_polys[i].set_tris( tri );
line_polys[i].set_texcoords( tc ); line_polys[i].set_texcoords( tc );
} }
#if 0 #if 1
{ {
string polypath = root + "/AirportArea"; tgChopNormalPolygon( "/home/pete", "Base", base_poly, false );
tgChopNormalPolygon( polypath, "Base", base_poly, false ); verbose_triangulation = true;
} }
#endif #endif
TGPolygon base_tris = polygon_tesselate_alt( base_poly );
SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly ");
TGPolygon base_tris = polygon_tesselate_alt( base_poly, verbose_triangulation );
gettimeofday(&triangulation_end, NULL); gettimeofday(&triangulation_end, NULL);
timersub(&triangulation_end, &triangulation_start, &triangulation_time); timersub(&triangulation_end, &triangulation_start, &triangulation_time);
@ -776,6 +818,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < tri_poly.contour_size(i); ++j ) for ( j = 0; j < tri_poly.contour_size(i); ++j )
{ {
p = tri_poly.get_pt( i, j ); p = tri_poly.get_pt( i, j );
SG_LOG(SG_GENERAL, SG_DEBUG, "adding runway point = " << p);
index = nodes.unique_add( p ); index = nodes.unique_add( p );
tri_v.push_back( index ); tri_v.push_back( index );
@ -878,6 +922,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( j = 0; j < base_tris.contour_size(i); ++j ) for ( j = 0; j < base_tris.contour_size(i); ++j )
{ {
p = base_tris.get_pt( i, j ); p = base_tris.get_pt( i, j );
SG_LOG(SG_GENERAL, SG_DEBUG, "adding base point " << p);
index = nodes.unique_add( p ); index = nodes.unique_add( p );
tri_v.push_back( index ); tri_v.push_back( index );
@ -916,6 +962,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( j = 0; j < divided_base.contour_size( i ); ++j ) for ( j = 0; j < divided_base.contour_size( i ); ++j )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "adding divided base point " << p);
nodes.unique_add( divided_base.get_pt(i, j) ); nodes.unique_add( divided_base.get_pt(i, j) );
} }
} }
@ -927,7 +975,22 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// it avoids biases introduced from the surrounding area if the // it avoids biases introduced from the surrounding area if the
// airport is located in a bowl or on a hill. // airport is located in a bowl or on a hill.
SG_LOG(SG_GENERAL, SG_DEBUG, " calcaverage elevation");
{
point_list dbg = nodes.get_node_list();
// dump the node list
SG_LOG(SG_GENERAL, SG_DEBUG, " node list size is " << dbg.size() );
for (unsigned int w = 0; w<dbg.size(); w++)
{
SG_LOG(SG_GENERAL, SG_DEBUG, " node " << w << " is " << dbg[w] );
}
}
double average = tgAverageElevation( root, elev_src, nodes.get_node_list() ); double average = tgAverageElevation( root, elev_src, nodes.get_node_list() );
SG_LOG(SG_GENERAL, SG_DEBUG, " done");
// cout << "average airport elevation = " << average << endl; // cout << "average airport elevation = " << average << endl;
// Now build the fitted airport surface ... // Now build the fitted airport surface ...

View file

@ -51,7 +51,7 @@ public:
void AddFeatures( FeatureList* feature_list ) void AddFeatures( FeatureList* feature_list )
{ {
for (int i=0; i<feature_list->size(); i++) for (unsigned int i=0; i<feature_list->size(); i++)
{ {
features.push_back( feature_list->at(i) ); features.push_back( feature_list->at(i) );
} }

View file

@ -172,6 +172,39 @@ TGPolygon gen_wgs84_area( Point3D end1, Point3D end2,
return result_list; return result_list;
} }
TGPolygon gen_wgs84_rect( double lat, double lon, double heading, double length, double width )
{
TGPolygon result_list;
double ptlat, ptlon, r;
Point3D 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 );
// 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 );
// 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 );
// 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 );
return result_list;
}
// generate a section of texture // generate a section of texture
void gen_tex_section( const TGPolygon& runway, void gen_tex_section( const TGPolygon& runway,

View file

@ -25,6 +25,9 @@ TGPolygon gen_wgs84_area( Point3D end1, Point3D end2,
double alt_m, double alt_m,
bool add_mid ); bool add_mid );
TGPolygon gen_wgs84_rect( double lat, double lon, double heading, double length, double width );
void gen_tex_section( const TGPolygon& runway, void gen_tex_section( const TGPolygon& runway,
double startl_pct, double endl_pct, double startl_pct, double endl_pct,
double startw_pct, double endw_pct, double startw_pct, double endw_pct,

View file

@ -10,6 +10,15 @@
#include "convex_hull.hxx" #include "convex_hull.hxx"
#include "closedpoly.hxx" #include "closedpoly.hxx"
static void stringPurifier( string& s )
{
for ( string::iterator it = s.begin(), itEnd = s.end(); it!=itEnd; ++it) {
if ( static_cast<unsigned int>(*it) < 32 || static_cast<unsigned int>(*it) > 127 ) {
(*it) = ' ';
}
}
}
ClosedPoly::ClosedPoly( char* desc ) ClosedPoly::ClosedPoly( char* desc )
{ {
is_pavement = false; is_pavement = false;
@ -17,6 +26,7 @@ ClosedPoly::ClosedPoly( char* desc )
if ( desc ) if ( desc )
{ {
description = desc; description = desc;
stringPurifier(description);
} }
else else
{ {
@ -38,6 +48,7 @@ ClosedPoly::ClosedPoly( int st, float s, float th, char* desc )
if ( desc ) if ( desc )
{ {
description = desc; description = desc;
stringPurifier(description);
} }
else else
{ {
@ -65,7 +76,7 @@ void ClosedPoly::AddNode( BezNode* node )
{ {
if (!cur_feature) if (!cur_feature)
{ {
string feature_desc = description + ":"; string feature_desc = description + " - ";
if (boundary) if (boundary)
{ {
feature_desc += "hole"; feature_desc += "hole";
@ -84,10 +95,10 @@ void ClosedPoly::AddNode( BezNode* node )
void ClosedPoly::CreateConvexHull( void ) void ClosedPoly::CreateConvexHull( void )
{ {
TGPolygon convexHull; TGPolygon convexHull;
point_list nodes; point_list nodes;
Point3D p; Point3D p;
int i; unsigned int i;
if (boundary->size() > 2) if (boundary->size() > 2)
{ {
@ -105,7 +116,7 @@ void ClosedPoly::CreateConvexHull( void )
} }
} }
int ClosedPoly::CloseCurContour() void ClosedPoly::CloseCurContour()
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Close Contour"); SG_LOG(SG_GENERAL, SG_DEBUG, "Close Contour");
@ -151,7 +162,7 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst )
Point3D cp2; Point3D cp2;
int curve_type = CURVE_LINEAR; int curve_type = CURVE_LINEAR;
int i; unsigned int i;
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating a contour with " << src->size() << " nodes"); SG_LOG(SG_GENERAL, SG_DEBUG, "Creating a contour with " << src->size() << " nodes");
@ -346,7 +357,7 @@ void ClosedPoly::ExpandContour( point_list& src, TGPolygon& dst, double dist )
double h1; double h1;
double o1; double o1;
double az2; double az2;
int i; unsigned int i;
// iterate through each bezier node in the contour // iterate through each bezier node in the contour
for (i=0; i<src.size(); i++) for (i=0; i<src.size(); i++)
@ -427,7 +438,7 @@ void ClosedPoly::ExpandContour( point_list& src, TGPolygon& dst, double dist )
} }
// finish the poly - convert to TGPolygon, and tesselate // finish the poly - convert to TGPolygon, and tesselate
int ClosedPoly::Finish() void ClosedPoly::Finish()
{ {
point_list dst_contour; point_list dst_contour;
@ -448,7 +459,7 @@ int ClosedPoly::Finish()
pre_tess.add_contour( dst_contour, 0 ); pre_tess.add_contour( dst_contour, 0 );
// The convert the hole contours // The convert the hole contours
for (int i=0; i<holes.size(); i++) for (unsigned int i=0; i<holes.size(); i++)
{ {
dst_contour.clear(); dst_contour.clear();
ConvertContour( holes[i], &dst_contour ); ConvertContour( holes[i], &dst_contour );
@ -574,4 +585,6 @@ int ClosedPoly::BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clear
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( pre_tess, *apt_base ); *apt_base = tgPolygonUnion( pre_tess, *apt_base );
} }
return 1;
} }

View file

@ -24,8 +24,8 @@ public:
inline string GetDescription() { return description; } inline string GetDescription() { return description; }
void AddNode( BezNode* node ); void AddNode( BezNode* node );
int CloseCurContour(); void CloseCurContour();
int Finish(); void Finish();
// Build BTG for airport base for airports with boundary // Build BTG for airport base for airports with boundary
int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing ); int BuildBtg( float alt_m, TGPolygon* apt_base, TGPolygon* apt_clearing );

View file

@ -68,21 +68,23 @@ double tgAverageElevation( const string &root, const string_list elev_src,
} }
while ( !done ) { while ( !done ) {
// find first node with -9999 elevation // find first node with -9999 elevation
Point3D first(0.0); Point3D first(0.0);
bool found_one = false; bool found_one = false;
for ( i = 0; i < points.size(); ++i ) { for ( i = 0; i < points.size(); ++i ) {
if ( points[i].z() < -9000.0 && !found_one ) { if ( points[i].z() < -9000.0 && !found_one ) {
first = points[i]; first = points[i];
SG_LOG( SG_GENERAL, SG_DEBUG, "founf first = " << first );
found_one = true; found_one = true;
} }
} }
if ( found_one ) { if ( found_one ) {
SGBucket b( first.x(), first.y() ); SGBucket b( first.x(), first.y() );
string base = b.gen_base_path(); string base = b.gen_base_path();
// try the various elevation sources // try the various elevation sources
i = 0; i = 0;
bool found_file = false; bool found_file = false;
while ( !found_file && i < elev_src.size() ) { while ( !found_file && i < elev_src.size() ) {
@ -98,7 +100,7 @@ double tgAverageElevation( const string &root, const string_list elev_src,
// this will fill in a zero structure if no array data // this will fill in a zero structure if no array data
// found/opened // found/opened
array.parse( b ); array.parse( b );
// this will do a hasty job of removing voids by inserting // this will do a hasty job of removing voids by inserting
// data from the nearest neighbor (sort of) // data from the nearest neighbor (sort of)

View file

@ -125,7 +125,7 @@ int main(int argc, char **argv)
setup_default_elevation_sources(elev_src); setup_default_elevation_sources(elev_src);
// Set verbose // Set verbose
// sglog().setLogLevels( SG_GENERAL, SG_BULK ); // sglog().setLogLevels( SG_GENERAL, SG_BULK );
sglog().setLogLevels( SG_GENERAL, SG_INFO ); sglog().setLogLevels( SG_GENERAL, SG_INFO );
SG_LOG(SG_GENERAL, SG_INFO, "Run genapt"); SG_LOG(SG_GENERAL, SG_INFO, "Run genapt");

View file

@ -345,6 +345,8 @@ void Parser::Parse()
} }
gettimeofday(&parse_end, NULL); gettimeofday(&parse_end, NULL);
timersub(&parse_end, &parse_start, &parse_time); timersub(&parse_end, &parse_start, &parse_time);
SG_LOG( SG_GENERAL, SG_ALERT, "Finished parsing airport " << airport_icaos[i] << " at " << ctime(&parse_end.tv_sec) );
// write the airport BTG // write the airport BTG
if (cur_airport) if (cur_airport)
@ -536,9 +538,13 @@ ClosedPoly* Parser::ParsePavement( char* line )
if (numParams == 4) if (numParams == 4)
{ {
d = strstr(line,desc); d = strstr(line,desc);
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly with st " << st << " smoothness " << s << " thexture heading " << th << " and description " << d);
}
else
{
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly with st " << st << " smoothness " << s << " thexture heading " << th );
} }
SG_LOG(SG_GENERAL, SG_DEBUG, "Creating Closed Poly with st " << st << " smoothness " << s << " thexture heading " << th << " and description " << d);
poly = new ClosedPoly(st, s, th, d); poly = new ClosedPoly(st, s, th, d);
return poly; return poly;
@ -599,178 +605,146 @@ int Parser::ParseLine(char* line)
BezNode* cur_node = NULL; BezNode* cur_node = NULL;
// Get the number code if (*line != '#')
tok = strtok(line, " \t\r\n");
if (tok)
{ {
line += strlen(tok)+1; // Get the number code
code = atoi(tok); tok = strtok(line, " \t\r\n");
switch(code) if (tok)
{ {
case LAND_AIRPORT_CODE: line += strlen(tok)+1;
case SEA_AIRPORT_CODE: code = atoi(tok);
if (cur_state == STATE_NONE)
{ switch(code)
{
case LAND_AIRPORT_CODE:
case SEA_AIRPORT_CODE:
if (cur_state == STATE_NONE)
{
SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing land airport: " << line);
cur_airport = new Airport( code, line );
}
else
{
SetState( STATE_DONE );
}
break;
case HELIPORT_CODE:
if (cur_state == STATE_NONE)
{
SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing heliport: " << line);
cur_airport = new Airport( code, line );
}
else
{
SetState( STATE_DONE );
}
break;
case LAND_RUNWAY_CODE:
SetState( STATE_PARSE_SIMPLE ); SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing land airport: " << line); SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing runway: " << line);
cur_airport = new Airport( code, line ); cur_runway = new Runway(line);
} if (cur_airport)
else {
{ cur_airport->AddRunway( cur_runway );
SetState( STATE_DONE ); }
} break;
break;
case HELIPORT_CODE: case WATER_RUNWAY_CODE:
if (cur_state == STATE_NONE)
{
SetState( STATE_PARSE_SIMPLE ); SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing heliport: " << line); SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing water runway: " << line);
cur_airport = new Airport( code, line ); cur_waterrunway = new WaterRunway(line);
} if (cur_airport)
else {
{ cur_airport->AddWaterRunway( cur_waterrunway );
SetState( STATE_DONE ); }
} break;
break; case HELIPAD_CODE:
SetState( STATE_PARSE_SIMPLE );
case LAND_RUNWAY_CODE: SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing helipad: " << line);
SetState( STATE_PARSE_SIMPLE ); cur_helipad = new Helipad(line);
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing runway: " << line); if (cur_airport)
cur_runway = new Runway(line); {
if (cur_airport) cur_airport->AddHelipad( cur_helipad );
{ }
cur_airport->AddRunway( cur_runway ); break;
}
break; case PAVEMENT_CODE:
SetState( STATE_PARSE_PAVEMENT );
case WATER_RUNWAY_CODE: cur_pavement = ParsePavement( line );
SetState( STATE_PARSE_SIMPLE ); break;
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing water runway: " << line);
cur_waterrunway = new WaterRunway(line); case LINEAR_FEATURE_CODE:
if (cur_airport) SetState( STATE_PARSE_FEATURE );
{ cur_feat = ParseFeature( line );
cur_airport->AddWaterRunway( cur_waterrunway ); break;
}
break; case BOUNDRY_CODE:
case HELIPAD_CODE: SetState( STATE_PARSE_BOUNDARY );
SetState( STATE_PARSE_SIMPLE ); cur_boundary = ParseBoundary( line );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing helipad: " << line); break;
cur_helipad = new Helipad(line);
if (cur_airport) case NODE_CODE:
{ case BEZIER_NODE_CODE:
cur_airport->AddHelipad( cur_helipad ); SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing node: " << line);
} cur_node = ParseNode( code, line, prev_node );
break;
if ( prev_node && (cur_node != prev_node) )
case PAVEMENT_CODE: {
SetState( STATE_PARSE_PAVEMENT ); // prev node is done - process it\n");
cur_pavement = ParsePavement( line ); if ( cur_state == STATE_PARSE_PAVEMENT )
break; {
cur_pavement->AddNode( prev_node );
case LINEAR_FEATURE_CODE: }
SetState( STATE_PARSE_FEATURE ); else if ( cur_state == STATE_PARSE_FEATURE )
cur_feat = ParseFeature( line ); {
break; cur_feat->AddNode( prev_node );
}
case BOUNDRY_CODE: else if ( cur_state == STATE_PARSE_BOUNDARY )
SetState( STATE_PARSE_BOUNDARY ); {
cur_boundary = ParseBoundary( line ); cur_boundary->AddNode( prev_node );
break; }
}
case NODE_CODE:
case BEZIER_NODE_CODE: prev_node = cur_node;
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing node: " << line); break;
cur_node = ParseNode( code, line, prev_node );
case CLOSE_NODE_CODE:
if ( prev_node && (cur_node != prev_node) ) case CLOSE_BEZIER_NODE_CODE:
{ SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing close loop node: " << line);
// prev node is done - process it\n"); cur_node = ParseNode( code, line, prev_node );
if ( cur_state == STATE_PARSE_PAVEMENT ) if ( cur_state == STATE_PARSE_PAVEMENT )
{ {
cur_pavement->AddNode( prev_node ); if (cur_node != prev_node)
} {
else if ( cur_state == STATE_PARSE_FEATURE ) cur_pavement->AddNode( prev_node );
{ cur_pavement->AddNode( cur_node );
cur_feat->AddNode( prev_node ); }
else
{
cur_pavement->AddNode( cur_node );
}
cur_pavement->CloseCurContour();
} }
else if ( cur_state == STATE_PARSE_BOUNDARY ) else if ( cur_state == STATE_PARSE_BOUNDARY )
{ {
cur_boundary->AddNode( prev_node ); if (cur_node != prev_node)
{
cur_boundary->AddNode( prev_node );
cur_boundary->AddNode( cur_node );
}
else
{
cur_boundary->AddNode( cur_node );
}
cur_boundary->CloseCurContour();
} }
} else if ( cur_state == STATE_PARSE_FEATURE )
prev_node = cur_node;
break;
case CLOSE_NODE_CODE:
case CLOSE_BEZIER_NODE_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing close loop node: " << line);
cur_node = ParseNode( code, line, prev_node );
if ( cur_state == STATE_PARSE_PAVEMENT )
{
if (cur_node != prev_node)
{ {
cur_pavement->AddNode( prev_node );
cur_pavement->AddNode( cur_node );
}
else
{
cur_pavement->AddNode( cur_node );
}
cur_pavement->CloseCurContour();
}
else if ( cur_state == STATE_PARSE_BOUNDARY )
{
if (cur_node != prev_node)
{
cur_boundary->AddNode( prev_node );
cur_boundary->AddNode( cur_node );
}
else
{
cur_boundary->AddNode( cur_node );
}
cur_boundary->CloseCurContour();
}
else if ( cur_state == STATE_PARSE_FEATURE )
{
if (cur_node != prev_node)
{
cur_feat->AddNode( prev_node );
cur_feat->AddNode( cur_node );
}
else
{
cur_feat->AddNode( cur_node );
}
if (cur_airport)
{
cur_feat->Finish();
cur_airport->AddFeature( cur_feat );
}
cur_feat = NULL;
SetState( STATE_NONE );
}
prev_node = NULL;
cur_node = NULL;
break;
case TERM_NODE_CODE:
case TERM_BEZIER_NODE_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing termination node: " << line);
if ( cur_state == STATE_PARSE_FEATURE )
{
// we have some bad data - termination nodes right after the
// linear feature declaration - can't do anything with a
// single point - detect and delete.
if ( prev_node )
{
cur_node = ParseNode( code, line, prev_node );
if (cur_node != prev_node) if (cur_node != prev_node)
{ {
cur_feat->AddNode( prev_node ); cur_feat->AddNode( prev_node );
@ -785,87 +759,122 @@ int Parser::ParseLine(char* line)
cur_feat->Finish(); cur_feat->Finish();
cur_airport->AddFeature( cur_feat ); cur_airport->AddFeature( cur_feat );
} }
cur_feat = NULL;
SetState( STATE_NONE );
} }
else prev_node = NULL;
cur_node = NULL;
break;
case TERM_NODE_CODE:
case TERM_BEZIER_NODE_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing termination node: " << line);
if ( cur_state == STATE_PARSE_FEATURE )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "Parsing termination node with no previous nodes!!!" ); // we have some bad data - termination nodes right after the
// linear feature declaration - can't do anything with a
// this feature is bogus... // single point - detect and delete.
delete cur_feat; if ( prev_node )
{
cur_node = ParseNode( code, line, prev_node );
if (cur_node != prev_node)
{
cur_feat->AddNode( prev_node );
cur_feat->AddNode( cur_node );
}
else
{
cur_feat->AddNode( cur_node );
}
if (cur_airport)
{
cur_feat->Finish();
cur_airport->AddFeature( cur_feat );
}
}
else
{
SG_LOG(SG_GENERAL, SG_ALERT, "Parsing termination node with no previous nodes!!!" );
// this feature is bogus...
delete cur_feat;
}
cur_feat = NULL;
SetState( STATE_NONE );
} }
cur_feat = NULL; prev_node = NULL;
SetState( STATE_NONE ); cur_node = NULL;
} break;
prev_node = NULL;
cur_node = NULL; case AIRPORT_VIEWPOINT_CODE:
break; SetState( STATE_PARSE_SIMPLE );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing viewpoint: " << line);
case AIRPORT_VIEWPOINT_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case AIRPLANE_STARTUP_LOCATION_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing viewpoint: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airplane startup location: " << line);
case AIRPLANE_STARTUP_LOCATION_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case LIGHT_BEACON_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing airplane startup location: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing light beacon: " << line);
case LIGHT_BEACON_CODE: cur_beacon = new Beacon(line);
SetState( STATE_PARSE_SIMPLE ); cur_airport->AddBeacon( cur_beacon );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing light beacon: " << line); break;
cur_beacon = new Beacon(line); case WINDSOCK_CODE:
cur_airport->AddBeacon( cur_beacon ); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing windsock: " << line);
case WINDSOCK_CODE: cur_windsock = new Windsock(line);
SetState( STATE_PARSE_SIMPLE ); cur_airport->AddWindsock( cur_windsock );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing windsock: " << line); break;
cur_windsock = new Windsock(line); case TAXIWAY_SIGN:
cur_airport->AddWindsock( cur_windsock ); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing taxiway sign: " << line);
case TAXIWAY_SIGN: cur_sign = new Sign(line);
SetState( STATE_PARSE_SIMPLE ); cur_airport->AddSign( cur_sign );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing taxiway sign: " << line); break;
cur_sign = new Sign(line); case LIGHTING_OBJECT:
cur_airport->AddSign( cur_sign ); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing lighting object: " << line);
case LIGHTING_OBJECT: cur_object = new LightingObj(line);
SetState( STATE_PARSE_SIMPLE ); cur_airport->AddObj( cur_object );
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing lighting object: " << line); break;
cur_object = new LightingObj(line); case COMM_FREQ1_CODE:
cur_airport->AddObj( cur_object ); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 1: " << line);
case COMM_FREQ1_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ2_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 1: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 2: " << line);
case COMM_FREQ2_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ3_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 2: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 3: " << line);
case COMM_FREQ3_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ4_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 3: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 4: " << line);
case COMM_FREQ4_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ5_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 4: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 5: " << line);
case COMM_FREQ5_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ6_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 5: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 6: " << line);
case COMM_FREQ6_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case COMM_FREQ7_CODE:
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 6: " << line); SetState( STATE_PARSE_SIMPLE );
break; SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 7: " << line);
case COMM_FREQ7_CODE: break;
SetState( STATE_PARSE_SIMPLE ); case END_OF_FILE :
SG_LOG(SG_GENERAL, SG_DEBUG, "Parsing commfreq 7: " << line); SG_LOG(SG_GENERAL, SG_DEBUG, "Reached end of file");
break; SetState( STATE_DONE );
case END_OF_FILE : break;
SG_LOG(SG_GENERAL, SG_DEBUG, "Reached end of file"); }
SetState( STATE_DONE );
break;
} }
} }
return cur_state; return cur_state;
} }

View file

@ -136,8 +136,8 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
case 4: // Dirt case 4: // Dirt
case 5: // Gravel case 5: // Gravel
SG_LOG( SG_GENERAL, SG_DEBUG, "Build Runway: Turf, Dirt or Gravel" << rwy.surface ); SG_LOG( SG_GENERAL, SG_DEBUG, "Build Runway: Turf, Dirt or Gravel" << rwy.surface );
gen_simple_rwy( alt_m, material, rwy_polys, texparams, accum ); gen_simple_rwy( alt_m, material, rwy_polys, texparams, accum );
gen_runway_lights( alt_m, rwy_lights ); gen_runway_lights( alt_m, rwy_lights );
break; break;
case 12: // dry lakebed case 12: // dry lakebed
@ -164,10 +164,10 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
if (apt_base) if (apt_base)
{ {
// generate area around runways // generate area around runways
base = gen_runway_area_w_extend( 0.0, rwy.width * 0.25, -rwy.overrun[0], -rwy.overrun[1], rwy.width * 0.25); base = gen_runway_area_w_extend( 0.0, 20.0, -rwy.overrun[0], -rwy.overrun[1], 20.0);
// also clear a safe area around the runway // also clear a safe area around the runway
safe_base = gen_runway_area_w_extend( 0.0, rwy.width, -rwy.overrun[0], -rwy.overrun[1], rwy.width ); safe_base = gen_runway_area_w_extend( 0.0, 180.0, -rwy.overrun[0], -rwy.overrun[1], 50.0 );
// add this to the airport clearing // add this to the airport clearing
*apt_clearing = tgPolygonUnion(safe_base, *apt_clearing); *apt_clearing = tgPolygonUnion(safe_base, *apt_clearing);

View file

@ -354,7 +354,7 @@ void Runway::BuildShoulder( float alt_m,
} else SG_LOG(SG_GENERAL, SG_ALERT, "Unknown shoulder surface code = " << rwy.shoulder ); } else SG_LOG(SG_GENERAL, SG_ALERT, "Unknown shoulder surface code = " << rwy.shoulder );
} else if (rwy.shoulder == 0){ // We add a fake shoulder if the runway has an asphalt or concrete surface } else if (rwy.shoulder == 0){ // We add a fake shoulder if the runway has an asphalt or concrete surface
shoulder_width = 1; shoulder_width = 1.0;
if (rwy.surface == 1){ if (rwy.surface == 1){
shoulder_surface = "pa_shoulder_f"; shoulder_surface = "pa_shoulder_f";
} else if (rwy.surface == 2){ } else if (rwy.surface == 2){
@ -365,6 +365,13 @@ void Runway::BuildShoulder( float alt_m,
SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder surface is: " << shoulder_surface ); SG_LOG(SG_GENERAL, SG_DEBUG, "Shoulder surface is: " << shoulder_surface );
if (shoulder_width > 0.0f) { if (shoulder_width > 0.0f) {
// we need to break these shoulders up into managable pieces, as we're asked to triangulate
// 3-4 km long by 1m wide strips - jrs-can't handle it.
double max_dist = (double)shoulder_width * 50.0f;
int numSegs = (rwy.length / max_dist) + 1;
double dist = rwy.length / (double)numSegs;
// Create both shoulder sides // Create both shoulder sides
for (int i=0; i<2; ++i){ for (int i=0; i<2; ++i){
double step; double step;
@ -374,44 +381,40 @@ void Runway::BuildShoulder( float alt_m,
/* If the are 'equal' there's a good chance roundoff error can create a */ /* If the are 'equal' there's a good chance roundoff error can create a */
/* REALY thin long polygon, which causes a segfault */ /* REALY thin long polygon, which causes a segfault */
if (i == 0){ if (i == 0){
step= (rwy.width + shoulder_width)*0.5 - 0.00001; step= (rwy.width + shoulder_width)*0.5;
} else if (i == 1) { } else if (i == 1) {
step= -(rwy.width + shoulder_width)*0.5 + 0.00001; step= -(rwy.width + shoulder_width)*0.5;
} }
double left_hdg = rwy.heading - 90.0; double left_hdg = rwy.heading - 90.0;
if ( left_hdg < 0 ) { left_hdg += 360.0; } if ( left_hdg < 0 ) { left_hdg += 360.0; }
geo_direct_wgs_84 ( alt_m, rwy.lat[0], rwy.lon[0], left_hdg, geo_direct_wgs_84 ( alt_m, rwy.lat[0], rwy.lon[0], left_hdg, step, &lat, &lon, &r );
step, &lat, &lon, &r ); Point3D ref = Point3D( lon, lat, 0.0f );
Point3D shoulder1 = Point3D( lon, lat, 0.0f ); for (int j=0; j<numSegs; j++)
{
geo_direct_wgs_84 ( alt_m, ref.y(), ref.x(), rwy.heading, (j*dist), &lat, &lon, &r );
TGPolygon shoulderSegment = gen_wgs84_rect( lat, lon, rwy.heading, dist+0.2, shoulder_width+0.5 );
geo_direct_wgs_84 ( alt_m, rwy.lat[1], rwy.lon[1], left_hdg, TGSuperPoly sp;
step, &lat, &lon, &r ); TGTexParams tp;
TGPolygon clipped = tgPolygonDiff( shoulderSegment, *accum );
Point3D shoulder2 = Point3D( lon, lat, 0.0f ); sp.erase();
sp.set_poly( clipped );
sp.set_material( shoulder_surface );
rwy_polys->push_back( sp );
TGPolygon shoulder = gen_wgs84_area( shoulder1, shoulder2, 0.0, 0.0, 0.0, shoulder_width, rwy.heading, alt_m, false); *accum = tgPolygonUnion( shoulderSegment, *accum );
TGSuperPoly sp; tp = TGTexParams( shoulderSegment.get_pt(0,0), -shoulder_width, dist, rwy.heading );
TGTexParams tp; if (i == 0){
TGPolygon clipped = tgPolygonDiff( shoulder, *accum ); tp.set_maxu(0);
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 ); tp.set_minu(1);
}
sp.erase(); texparams->push_back( tp );
sp.set_poly( split );
sp.set_material( shoulder_surface );
rwy_polys->push_back( sp );
*accum = tgPolygonUnion( shoulder, *accum );
tp = TGTexParams( shoulder.get_pt(0,0), shoulder_width , rwy.length + 2, rwy.heading );
if (i == 1){
tp.set_maxu(0);
tp.set_minu(1);
} }
texparams->push_back( tp );
} }
} }
} }

View file

@ -63,6 +63,8 @@ TGArray::TGArray( const string &file ):
for (int i = 0; i < ARRAY_SIZE_1; i++) for (int i = 0; i < ARRAY_SIZE_1; i++)
in_data[i] = new int[ARRAY_SIZE_1]; in_data[i] = new int[ARRAY_SIZE_1];
SG_LOG(SG_GENERAL, SG_ALERT, "ps TGArray CONstructor called." );
TGArray::open(file); TGArray::open(file);
} }
@ -75,7 +77,7 @@ bool TGArray::open( const string& file_base ) {
string array_name = file_base + ".arr.gz"; string array_name = file_base + ".arr.gz";
array_in = new sg_gzifstream( array_name ); array_in = new sg_gzifstream( array_name );
if ( ! array_in->is_open() ) { if ( ! array_in->is_open() ) {
SG_LOG(SG_GENERAL, SG_DEBUG, " Cannot open " << array_name ); SG_LOG(SG_GENERAL, SG_DEBUG, " ps: Cannot open " << array_name );
success = false; success = false;
} else { } else {
SG_LOG(SG_GENERAL, SG_DEBUG, " Opening array data file: " << array_name ); SG_LOG(SG_GENERAL, SG_DEBUG, " Opening array data file: " << array_name );
@ -89,7 +91,7 @@ bool TGArray::open( const string& file_base ) {
// can do a really stupid/crude fit on the fly, but it will // can do a really stupid/crude fit on the fly, but it will
// not be nearly as nice as what the offline terrafit utility // not be nearly as nice as what the offline terrafit utility
// would have produced. // would have produced.
SG_LOG(SG_GENERAL, SG_DEBUG, " Cannot open " << fitted_name ); SG_LOG(SG_GENERAL, SG_DEBUG, " ps: Cannot open " << fitted_name );
} else { } else {
SG_LOG(SG_GENERAL, SG_DEBUG, " Opening fitted data file: " << fitted_name ); SG_LOG(SG_GENERAL, SG_DEBUG, " Opening fitted data file: " << fitted_name );
} }

View file

@ -50,8 +50,6 @@ extern "C" {
#include "trisegs.hxx" #include "trisegs.hxx"
using std::copy; using std::copy;
using std::cout;
using std::endl;
using std::ostream_iterator; using std::ostream_iterator;
using std::sort; using std::sort;
using std::vector; using std::vector;
@ -117,7 +115,7 @@ static bool intersects( Point3D p0, Point3D p1, double x, Point3D *result ) {
// basic triangulation of a polygon with out adding points or // basic triangulation of a polygon with out adding points or
// splitting edges, this should triangulate around interior holes. // splitting edges, this should triangulate around interior holes.
void polygon_tesselate( const TGPolygon &p, int polygon_tesselate( const TGPolygon &p,
const point_list &extra_nodes, const point_list &extra_nodes,
triele_list &elelist, triele_list &elelist,
point_list &out_pts, point_list &out_pts,
@ -125,8 +123,7 @@ void polygon_tesselate( const TGPolygon &p,
{ {
struct triangulateio in, out, vorout; struct triangulateio in, out, vorout;
int i; int i;
int success = 0;
tri_flags = "pzqenXYYQ";
// make sure all elements of these structs point to "NULL" // make sure all elements of these structs point to "NULL"
zero_triangulateio( &in ); zero_triangulateio( &in );
@ -272,7 +269,7 @@ void polygon_tesselate( const TGPolygon &p,
// no new points on boundary (Y), no internal segment // no new points on boundary (Y), no internal segment
// splitting (YY), no quality refinement (q) // splitting (YY), no quality refinement (q)
// Quite (Q) // Quite (Q)
triangulate( (char *)tri_flags.c_str(), &in, &out, &vorout ); success = triangulate( (char *)tri_flags.c_str(), &in, &out, &vorout );
// TEMPORARY // TEMPORARY
// write_tri_data(&out); // write_tri_data(&out);
@ -280,33 +277,36 @@ void polygon_tesselate( const TGPolygon &p,
// now copy the results back into the corresponding TGTriangle // now copy the results back into the corresponding TGTriangle
// structures // structures
// triangles if (success >= 0) {
elelist.clear();
int n1, n2, n3; // triangles
double attribute; elelist.clear();
for ( i = 0; i < out.numberoftriangles; ++i ) { int n1, n2, n3;
n1 = out.trianglelist[i * 3]; double attribute;
n2 = out.trianglelist[i * 3 + 1]; for ( i = 0; i < out.numberoftriangles; ++i ) {
n3 = out.trianglelist[i * 3 + 2]; n1 = out.trianglelist[i * 3];
if ( out.numberoftriangleattributes > 0 ) { n2 = out.trianglelist[i * 3 + 1];
attribute = out.triangleattributelist[i]; n3 = out.trianglelist[i * 3 + 2];
} else { if ( out.numberoftriangleattributes > 0 ) {
attribute = 0.0; attribute = out.triangleattributelist[i];
} else {
attribute = 0.0;
}
// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
elelist.push_back( TGTriEle( n1, n2, n3, attribute ) );
}
// output points
out_pts.clear();
double x, y, z;
for ( i = 0; i < out.numberofpoints; ++i ) {
x = out.pointlist[i * 2 ];
y = out.pointlist[i * 2 + 1];
z = out.pointattributelist[i];
out_pts.push_back( Point3D(x, y, z) );
} }
// cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
elelist.push_back( TGTriEle( n1, n2, n3, attribute ) );
} }
// output points
out_pts.clear();
double x, y, z;
for ( i = 0; i < out.numberofpoints; ++i ) {
x = out.pointlist[i * 2 ];
y = out.pointlist[i * 2 + 1];
z = out.pointattributelist[i];
out_pts.push_back( Point3D(x, y, z) );
}
// free mem allocated to the "Triangle" structures // free mem allocated to the "Triangle" structures
free(in.pointlist); free(in.pointlist);
free(in.pointattributelist); free(in.pointattributelist);
@ -327,6 +327,8 @@ void polygon_tesselate( const TGPolygon &p,
free(vorout.pointattributelist); free(vorout.pointattributelist);
free(vorout.edgelist); free(vorout.edgelist);
free(vorout.normlist); free(vorout.normlist);
return success;
} }
@ -336,7 +338,7 @@ void polygon_tesselate( const TGPolygon &p,
// wrapper for the polygon_tesselate() function. Note, this routine // wrapper for the polygon_tesselate() function. Note, this routine
// will modify the points_inside list for your polygon. // will modify the points_inside list for your polygon.
TGPolygon polygon_tesselate_alt( TGPolygon &p ) { TGPolygon polygon_tesselate_alt( TGPolygon &p, bool verbose ) {
TGPolygon result; TGPolygon result;
point_list extra_nodes; point_list extra_nodes;
result.erase(); result.erase();
@ -358,25 +360,42 @@ TGPolygon polygon_tesselate_alt( TGPolygon &p ) {
// 2. Do a final triangulation of the entire polygon // 2. Do a final triangulation of the entire polygon
triele_list trieles; triele_list trieles;
point_list nodes; point_list nodes;
// polygon_tesselate( p, extra_nodes, trieles, nodes, "pzYYenQ" ); string flags;
polygon_tesselate( p, extra_nodes, trieles, nodes, "pzenQ" ); if (verbose) {
flags = "pzqenXYY";
} else {
flags = "pzqenXYYQ";
}
// 3. Convert the tesselated output to a list of tringles. if ( polygon_tesselate( p, extra_nodes, trieles, nodes, flags ) >= 0 ) {
// basically a polygon with a contour for every triangle // 3. Convert the tesselated output to a list of tringles.
for ( i = 0; i < (int)trieles.size(); ++i ) { // basically a polygon with a contour for every triangle
TGTriEle t = trieles[i]; for ( i = 0; i < (int)trieles.size(); ++i ) {
Point3D p1 = nodes[ t.get_n1() ]; TGTriEle t = trieles[i];
Point3D p2 = nodes[ t.get_n2() ]; Point3D p1 = nodes[ t.get_n1() ];
Point3D p3 = nodes[ t.get_n3() ]; Point3D p2 = nodes[ t.get_n2() ];
result.add_node( i, p1 ); Point3D p3 = nodes[ t.get_n3() ];
result.add_node( i, p2 ); result.add_node( i, p1 );
result.add_node( i, p3 ); result.add_node( i, p2 );
result.add_node( i, p3 );
}
}
// check the result for nan point
for (int c = 0; c < result.contours(); c++) {
point_list contour = result.get_contour( c );
for ( int d = 0; d < (int)contour.size(); ++d ) {
if ( isnan( contour[d].x() ) || isnan( contour[d].y() ) ) {
printf("Uh-oh - got nan from tesselation\n");
exit(0);
}
}
} }
return result; return result;
} }
TGPolygon polygon_tesselate_alt_with_extra( TGPolygon &p, const point_list& extra_nodes ) { TGPolygon polygon_tesselate_alt_with_extra( TGPolygon &p, const point_list& extra_nodes, bool verbose ) {
TGPolygon result; TGPolygon result;
result.erase(); result.erase();
int i; int i;
@ -394,18 +413,25 @@ TGPolygon polygon_tesselate_alt_with_extra( TGPolygon &p, const point_list& extr
// 2. Do a final triangulation of the entire polygon // 2. Do a final triangulation of the entire polygon
triele_list trieles; triele_list trieles;
point_list nodes; point_list nodes;
polygon_tesselate( p, extra_nodes, trieles, nodes, "pzenQ" ); string flags;
if (verbose) {
flags = "VVpzqenXYY";
} else {
flags = "pzqenXYYQ";
}
// 3. Convert the tesselated output to a list of tringles. if ( polygon_tesselate( p, extra_nodes, trieles, nodes, flags ) >= 0 ) {
// basically a polygon with a contour for every triangle // 3. Convert the tesselated output to a list of tringles.
for ( i = 0; i < (int)trieles.size(); ++i ) { // basically a polygon with a contour for every triangle
TGTriEle t = trieles[i]; for ( i = 0; i < (int)trieles.size(); ++i ) {
Point3D p1 = nodes[ t.get_n1() ]; TGTriEle t = trieles[i];
Point3D p2 = nodes[ t.get_n2() ]; Point3D p1 = nodes[ t.get_n1() ];
Point3D p3 = nodes[ t.get_n3() ]; Point3D p2 = nodes[ t.get_n2() ];
result.add_node( i, p1 ); Point3D p3 = nodes[ t.get_n3() ];
result.add_node( i, p2 ); result.add_node( i, p1 );
result.add_node( i, p3 ); result.add_node( i, p2 );
result.add_node( i, p3 );
}
} }
return result; return result;
@ -598,7 +624,7 @@ static void calc_point_inside( TGContourNode *node, TGPolygon &p ) {
} }
static void print_contour_tree( TGContourNode *node, string indent ) { static void print_contour_tree( TGContourNode *node, string indent ) {
cout << indent << node->get_contour_num() << endl; // cout << indent << node->get_contour_num() << endl;
indent += " "; indent += " ";
for ( int i = 0; i < node->get_num_kids(); ++i ) { for ( int i = 0; i < node->get_num_kids(); ++i ) {
@ -997,7 +1023,7 @@ static point_list reduce_contour_degeneracy( const point_list& contour ) {
// remove bad node from contour. But only remove one node. If // remove bad node from contour. But only remove one node. If
// the 'badness' is caused by coincident adjacent nodes, we don't // the 'badness' is caused by coincident adjacent nodes, we don't
// want to remove both of them, just one (either will do.) // want to remove both of them, just one (either will do.)
cout << "found a bad node = " << bad_node << endl; // cout << "found a bad node = " << bad_node << endl;
point_list tmp; tmp.clear(); point_list tmp; tmp.clear();
bool found_one = false; bool found_one = false;
for ( int j = 0; j < (int)result.size(); ++j ) { for ( int j = 0; j < (int)result.size(); ++j ) {
@ -1045,11 +1071,11 @@ static point_list remove_small_cycles( const point_list& contour ) {
result.push_back( contour[i] ); result.push_back( contour[i] );
for ( unsigned int j = i + 1; j < contour.size(); ++j ) { for ( unsigned int j = i + 1; j < contour.size(); ++j ) {
if ( contour[i] == contour[j] && i + 4 > j ) { if ( contour[i] == contour[j] && i + 4 > j ) {
cout << "detected a small cycle: i = " // cout << "detected a small cycle: i = "
<< i << " j = " << j << endl; // << i << " j = " << j << endl;
for ( unsigned int k = i; k <= j; ++k ) { //for ( unsigned int k = i; k <= j; ++k ) {
cout << " " << contour[k] << endl; // cout << " " << contour[k] << endl;
} //}
i = j; i = j;
} }
} }

View file

@ -53,7 +53,7 @@ inline double triangle_area( const Point3D p1,
// basic triangulation of a polygon with out adding points or // basic triangulation of a polygon with out adding points or
// splitting edges // splitting edges
void polygon_tesselate( const TGPolygon &p, int polygon_tesselate( const TGPolygon &p,
const point_list &extra_nodes, const point_list &extra_nodes,
triele_list &elelist, triele_list &elelist,
point_list &out_pts, point_list &out_pts,
@ -64,10 +64,10 @@ void polygon_tesselate( const TGPolygon &p,
// with one contour per tesselated triangle. This is mostly just a // with one contour per tesselated triangle. This is mostly just a
// wrapper for the polygon_tesselate() function. Note, this routine // wrapper for the polygon_tesselate() function. Note, this routine
// will modify the points_inside list for your polygon. // will modify the points_inside list for your polygon.
TGPolygon polygon_tesselate_alt( TGPolygon &p ); TGPolygon polygon_tesselate_alt( TGPolygon &p, bool verbose );
TGPolygon polygon_tesselate_alt_with_extra( TGPolygon &p, TGPolygon polygon_tesselate_alt_with_extra( TGPolygon &p,
const point_list &extra_nodes ); const point_list &extra_nodes, bool verbose );
// calculate some "arbitrary" point inside each of the polygons contours // calculate some "arbitrary" point inside each of the polygons contours
void calc_points_inside( TGPolygon& p ); void calc_points_inside( TGPolygon& p );

View file

@ -36,8 +36,8 @@
#define FG_PROXIMITY_EPSILON 0.000001 #define FG_PROXIMITY_EPSILON 0.000001
#define FG_COURSE_EPSILON 0.0003 //#define FG_COURSE_EPSILON 0.0003
#define FG_COURSE_EPSILON 0.0001
class TGTriNodes { class TGTriNodes {