1
0
Fork 0

Stability checkpoint

- When adding intermediate nodes, keep linear feature nodes list seperate from the rest, as they are
  seperate accumulation buffers.
- Revert expand poly by 5cm.  It broke more airports than it fixed :(
- Going back to GPC as well.

Feature Fixes
- finally got around to the last segment in closed linear features.
  I think I am feature complete now.

Remaining issues.
- I still see terrain holes between the base and clearing polys when an airport traverses a tile
  boundary.  I'm not sure where to start here, as genapt doesn't really know about the tile boundary.
  (Is the clearing part of the tile construction? - need to look into this)
)
This commit is contained in:
Peter Sadrozinski 2012-02-04 16:34:35 -05:00 committed by Christian Schmitt
parent 372cbdf38f
commit 1090e602c2
16 changed files with 651 additions and 392 deletions

View file

@ -359,7 +359,10 @@ static TGPolygon calc_elevations( TGAptSurface &surf,
void Airport::BuildBtg(const string& root, const string_list& elev_src ) void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
ClipPolyType accum; ClipPolyType accum;
// try to keep line accumulator in clipper format for speed...
ClipPolyType line_accum; ClipPolyType line_accum;
TGPolygon apt_base; TGPolygon apt_base;
TGPolygon apt_clearing; TGPolygon apt_clearing;
@ -432,9 +435,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int i=0; i<features.size(); i++ ) for ( unsigned int i=0; i<features.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build Feature Poly " << i << " of " << features.size() << " : " << 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...
// features[i]->BuildBtg( altitude, &line_polys, &line_tps, &line_accum );
features[i]->BuildBtg( altitude, &line_polys, &line_tps, &line_accum, &rwy_lights ); features[i]->BuildBtg( altitude, &line_polys, &line_tps, &line_accum, &rwy_lights );
} }
} }
@ -472,7 +472,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int i=0; i<lightobjects.size(); i++ ) for ( unsigned int i=0; i<lightobjects.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build runway light " << i << " of " << lightobjects.size()); 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 );
} }
} }
@ -483,7 +482,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int i=0; i<helipads.size(); i++ ) for ( unsigned int i=0; i<helipads.size(); i++ )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build helipad " << i << " of " << helipads.size()); SG_LOG(SG_GENERAL, SG_INFO, "Build helipad " << i << " of " << helipads.size());
if (boundary) if (boundary)
{ {
helipads[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, NULL, NULL ); helipads[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &rwy_lights, &accum, NULL, NULL );
@ -502,6 +500,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build Pavement " << i << " of " << pavements.size() << " : " << pavements[i]->GetDescription()); SG_LOG(SG_GENERAL, SG_INFO, "Build Pavement " << i << " of " << pavements.size() << " : " << pavements[i]->GetDescription());
#if 0
if (i == 30) {
sglog().setLogLevels( SG_GENERAL, SG_BULK );
} else {
sglog().setLogLevels( SG_GENERAL, SG_INFO );
}
#endif
if (boundary) if (boundary)
{ {
pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, NULL, NULL ); pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, NULL, NULL );
@ -535,7 +541,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
if (boundary) if (boundary)
{ {
SG_LOG(SG_GENERAL, SG_INFO, "Build user defined boundary " ); SG_LOG(SG_GENERAL, SG_INFO, "Build user defined boundary " );
boundary->BuildBtg( altitude, &apt_base, &apt_clearing ); boundary->BuildBtg( altitude, &apt_base, &apt_clearing );
} }
@ -556,7 +561,8 @@ void Airport::BuildBtg(const 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_nodes; TGTriNodes tmp_pvmt_nodes;
TGTriNodes tmp_feat_nodes;
// build temporary node list from runways... // build temporary node list from runways...
SG_LOG(SG_GENERAL, SG_INFO, "Build Node List " ); SG_LOG(SG_GENERAL, SG_INFO, "Build Node List " );
@ -568,8 +574,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( int j = 0; j < poly.contour_size( i ); ++j ) for ( int j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_pvmt_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
@ -582,13 +587,12 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( int j = 0; j < poly.contour_size( i ); ++j ) for ( int j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_pvmt_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
// and linear features // and linear features ( keep Linear feature nodes seperate)
for ( unsigned int k = 0; k < line_polys.size(); ++k ) for ( unsigned int k = 0; k < line_polys.size(); ++k )
{ {
TGPolygon poly = line_polys[k].get_poly(); TGPolygon poly = line_polys[k].get_poly();
@ -596,8 +600,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( int j = 0; j < poly.contour_size( i ); ++j ) for ( int j = 0; j < poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( poly.get_pt(i, j) ); tmp_feat_nodes.unique_add( poly.get_pt(i, j) );
//tmp_nodes.course_add( poly.get_pt(i, j) );
} }
} }
} }
@ -607,8 +610,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( int j = 0; j < base_poly.contour_size( i ); ++j ) for ( int j = 0; j < base_poly.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( base_poly.get_pt(i, j) ); tmp_pvmt_nodes.unique_add( base_poly.get_pt(i, j) );
//tmp_nodes.course_add( base_poly.get_pt(i, j) );
} }
} }
@ -618,8 +620,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
for ( int j = 0; j < divided_base.contour_size( i ); ++j ) for ( int j = 0; j < divided_base.contour_size( i ); ++j )
{ {
tmp_nodes.unique_add( divided_base.get_pt(i, j) ); tmp_pvmt_nodes.unique_add( divided_base.get_pt(i, j) );
//tmp_nodes.course_add( divided_base.get_pt(i, j) );
} }
} }
@ -630,9 +631,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int k = 0; k < rwy_polys.size(); ++k ) for ( unsigned int k = 0; k < rwy_polys.size(); ++k )
{ {
TGPolygon poly = rwy_polys[k].get_poly(); TGPolygon poly = rwy_polys[k].get_poly();
poly = add_nodes_to_poly( poly, tmp_nodes ); poly = add_nodes_to_poly( poly, tmp_pvmt_nodes );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size());
rwy_polys[k].set_poly( poly ); rwy_polys[k].set_poly( poly );
} }
@ -640,9 +640,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int k = 0; k < pvmt_polys.size(); ++k ) for ( unsigned int k = 0; k < pvmt_polys.size(); ++k )
{ {
TGPolygon poly = pvmt_polys[k].get_poly(); TGPolygon poly = pvmt_polys[k].get_poly();
poly = add_nodes_to_poly( poly, tmp_nodes ); poly = add_nodes_to_poly( poly, tmp_pvmt_nodes );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size());
pvmt_polys[k].set_poly( poly ); pvmt_polys[k].set_poly( poly );
} }
@ -650,9 +649,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( unsigned int k = 0; k < line_polys.size(); ++k ) for ( unsigned int k = 0; k < line_polys.size(); ++k )
{ {
TGPolygon poly = line_polys[k].get_poly(); TGPolygon poly = line_polys[k].get_poly();
poly = add_nodes_to_poly( poly, tmp_nodes ); poly = add_nodes_to_poly( poly, tmp_feat_nodes );
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size()); SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size());
line_polys[k].set_poly( poly ); line_polys[k].set_poly( poly );
} }
@ -707,9 +705,10 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
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);
SG_LOG(SG_GENERAL, SG_DEBUG, " tmp_nodes size = " << tmp_nodes.get_node_list().size()); SG_LOG(SG_GENERAL, SG_DEBUG, " tmp_pvmt_nodes size = " << tmp_pvmt_nodes.get_node_list().size());
SG_LOG(SG_GENERAL, SG_DEBUG, " tmp_feat_nodes size = " << tmp_feat_nodes.get_node_list().size());
base_poly = add_nodes_to_poly( base_poly, tmp_nodes ); base_poly = add_nodes_to_poly( base_poly, tmp_pvmt_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);
base_poly = remove_cycles( base_poly ); base_poly = remove_cycles( base_poly );
@ -755,9 +754,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
TGPolygon poly = pvmt_polys[i].get_poly(); TGPolygon poly = pvmt_polys[i].get_poly();
#if 0 #if 0
if ( i == 62 ) { if ( i == 0 ) {
tgChopNormalPolygon( "/home/pete", "Base", poly, false ); tgChopNormalPolygon( "/home/pete", "Base", poly, false );
verbose_triangulation = true; verbose_triangulation = true;
} else {
verbose_triangulation = false;
} }
#endif #endif
@ -787,9 +788,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
TGPolygon poly = line_polys[i].get_poly(); TGPolygon poly = line_polys[i].get_poly();
#if 0 #if 0
if ( i == 62 ) { if ( i == 4558 ) {
tgChopNormalPolygon( "/home/pete", "Base", poly, false ); tgChopNormalPolygon( "/home/pete", "Base", poly, false );
verbose_triangulation = true; verbose_triangulation = true;
} else {
verbose_triangulation = false;
} }
#endif #endif
@ -813,6 +816,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly "); SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly ");
TGPolygon base_tris = polygon_tesselate_alt( base_poly, verbose_triangulation ); TGPolygon base_tris = polygon_tesselate_alt( base_poly, verbose_triangulation );
SG_LOG(SG_GENERAL, SG_INFO, "Tesselating base poly - done");
gettimeofday(&triangulation_end, NULL); gettimeofday(&triangulation_end, NULL);
timersub(&triangulation_end, &triangulation_start, &triangulation_time); timersub(&triangulation_end, &triangulation_start, &triangulation_time);
@ -868,6 +873,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
SG_LOG(SG_GENERAL, SG_DEBUG, "found normal for this airport = " << tmp); SG_LOG(SG_GENERAL, SG_DEBUG, "found normal for this airport = " << tmp);
SG_LOG(SG_GENERAL, SG_INFO, "Adding runway nodes and normals");
for ( unsigned int k = 0; k < rwy_polys.size(); ++k ) for ( unsigned int k = 0; k < rwy_polys.size(); ++k )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k); SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k);
@ -886,9 +892,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( int j = 0; j < tri_poly.contour_size(i); ++j ) for ( int 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 );
SG_LOG(SG_GENERAL, SG_DEBUG, "added rwy point " << p << " at " << index );
tri_v.push_back( index ); tri_v.push_back( index );
// use 'the' normal // use 'the' normal
@ -906,6 +911,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
} }
} }
SG_LOG(SG_GENERAL, SG_INFO, "Adding pavement nodes and normals");
for ( unsigned int k = 0; k < pvmt_polys.size(); ++k ) for ( unsigned int k = 0; k < pvmt_polys.size(); ++k )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k); SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k);
@ -925,6 +931,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
p = tri_poly.get_pt( i, j ); p = tri_poly.get_pt( i, j );
index = nodes.unique_add( p ); index = nodes.unique_add( p );
SG_LOG(SG_GENERAL, SG_DEBUG, "added pvmnt point " << p << " at " << index );
tri_v.push_back( index ); tri_v.push_back( index );
// use 'the' normal // use 'the' normal
@ -942,6 +949,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
} }
} }
SG_LOG(SG_GENERAL, SG_INFO, "Adding line nodes and normals");
for ( unsigned int k = 0; k < line_polys.size(); ++k ) for ( unsigned int k = 0; k < line_polys.size(); ++k )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k); SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k);
@ -961,6 +969,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
{ {
p = tri_poly.get_pt( i, j ); p = tri_poly.get_pt( i, j );
index = nodes.unique_add( p ); index = nodes.unique_add( p );
SG_LOG(SG_GENERAL, SG_DEBUG, "added line point " << p << " at " << index );
tri_v.push_back( index ); tri_v.push_back( index );
// use 'the' normal // use 'the' normal
@ -982,6 +991,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
std::vector< SGVec2f > base_txs; std::vector< SGVec2f > base_txs;
int_list base_tc; int_list base_tc;
SG_LOG(SG_GENERAL, SG_INFO, "Adding base nodes and normals");
for ( int i = 0; i < base_tris.contours(); ++i ) for ( int i = 0; i < base_tris.contours(); ++i )
{ {
tri_v.clear(); tri_v.clear();
@ -990,9 +1000,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
for ( int j = 0; j < base_tris.contour_size(i); ++j ) for ( int 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 );
SG_LOG(SG_GENERAL, SG_DEBUG, "added base point " << p << " at " << index );
tri_v.push_back( index ); tri_v.push_back( index );
index = normals.unique_add( vn ); index = normals.unique_add( vn );
@ -1025,14 +1034,12 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// on rare occasion, one or more of the divided base points can be // on rare occasion, one or more of the divided base points can be
// missed. Make sure they are all in the node list so we can // missed. Make sure they are all in the node list so we can
// build a proper skirt. // build a proper skirt.
for ( int i = 0; i < divided_base.contours(); ++i ) for ( int i = 0; i < divided_base.contours(); ++i )
{ {
for ( int j = 0; j < divided_base.contour_size( i ); ++j ) for ( int j = 0; j < divided_base.contour_size( i ); ++j )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "adding divided base point " << p); index = nodes.unique_add( divided_base.get_pt(i, j) );
SG_LOG(SG_GENERAL, SG_DEBUG, "added base point " << divided_base.get_pt(i, j) << " at " << index );
nodes.unique_add( divided_base.get_pt(i, j) );
} }
} }
@ -1044,7 +1051,6 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
// 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"); SG_LOG(SG_GENERAL, SG_DEBUG, " calcaverage elevation");
{ {
point_list dbg = nodes.get_node_list(); point_list dbg = nodes.get_node_list();
@ -1057,14 +1063,13 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
} }
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 ...
// calculation min/max coordinates of airport area // calculation min/max coordinates of airport area
SG_LOG(SG_GENERAL, SG_DEBUG, " calculation min/max coordinates of airport area"); SG_LOG(SG_GENERAL, SG_INFO, " calculation min/max coordinates of airport area");
Point3D min_deg(9999.0, 9999.0, 0), max_deg(-9999.0, -9999.0, 0); Point3D min_deg(9999.0, 9999.0, 0), max_deg(-9999.0, -9999.0, 0);
for ( unsigned int j = 0; j < nodes.get_node_list().size(); ++j ) for ( unsigned int j = 0; j < nodes.get_node_list().size(); ++j )
@ -1072,27 +1077,32 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
Point3D p = nodes.get_node_list()[j]; Point3D p = nodes.get_node_list()[j];
if ( p.lon() < min_deg.lon() ) if ( p.lon() < min_deg.lon() )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lon from node " << j << " is " << p.lon() );
min_deg.setlon( p.lon() ); min_deg.setlon( p.lon() );
} }
if ( p.lon() > max_deg.lon() ) if ( p.lon() > max_deg.lon() )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lon from node " << j << " is " << p.lon() );
max_deg.setlon( p.lon() ); max_deg.setlon( p.lon() );
} }
if ( p.lat() < min_deg.lat() ) if ( p.lat() < min_deg.lat() )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lat from node " << j << " is " << p.lat() );
min_deg.setlat( p.lat() ); min_deg.setlat( p.lat() );
} }
if ( p.lat() > max_deg.lat() ) if ( p.lat() > max_deg.lat() )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lat from node " << j << " is " << p.lat() );
max_deg.setlat( p.lat() ); max_deg.setlat( p.lat() );
} }
} }
SG_LOG(SG_GENERAL, SG_INFO, "Before extending for lights: min = " << min_deg << " max = " << max_deg );
// extend the min/max coordinates of airport area to cover all // extend the min/max coordinates of airport area to cover all
// lights as well // lights as well
SG_LOG(SG_GENERAL, SG_DEBUG, " extend the min/max coordinates of airport area to cover all lights as well : num rwy lights is " << rwy_lights.size() ); SG_LOG(SG_GENERAL, SG_DEBUG, " extend the min/max coordinates of airport area to cover all lights as well : num rwy lights is " << rwy_lights.size() );
for ( unsigned int i = 0; i < rwy_lights.size(); ++i ) for ( unsigned int i = 0; i < rwy_lights.size(); ++i )
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, " extend the min/max coordinates of airport area to cover all lights as well : rwy light " << i << "has " << rwy_lights[i].get_poly().get_contour(0).size() << " lights " ); SG_LOG(SG_GENERAL, SG_DEBUG, " extend the min/max coordinates of airport area to cover all lights as well : rwy light " << i << "has " << rwy_lights[i].get_poly().get_contour(0).size() << " lights " );
@ -1128,7 +1138,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
max_deg.setlon( max_deg.lon() + 0.01 * dlon ); max_deg.setlon( max_deg.lon() + 0.01 * dlon );
min_deg.setlat( min_deg.lat() - 0.01 * dlat ); min_deg.setlat( min_deg.lat() - 0.01 * dlat );
max_deg.setlat( max_deg.lat() + 0.01 * dlat ); max_deg.setlat( max_deg.lat() + 0.01 * dlat );
SG_LOG(SG_GENERAL, SG_DEBUG, "min = " << min_deg << " max = " << max_deg ); SG_LOG(SG_GENERAL, SG_INFO, "min = " << min_deg << " max = " << max_deg );
TGAptSurface apt_surf( root, elev_src, min_deg, max_deg, average ); TGAptSurface apt_surf( root, elev_src, min_deg, max_deg, average );
SG_LOG(SG_GENERAL, SG_DEBUG, "Airport surface created"); SG_LOG(SG_GENERAL, SG_DEBUG, "Airport surface created");

View file

@ -88,34 +88,42 @@ class BezNode
public: public:
BezNode( Point3D l ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f) BezNode( Point3D l ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f)
{ {
loc = l; loc = l;
mark = 0; mark = 0;
light = 0; light = 0;
term = false;
close = false;
} }
BezNode( double lat, double lon ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f) BezNode( double lat, double lon ) : prev_cp(0.0f, 0.0f, 0.0f), next_cp(0.0f, 0.0f, 0.0f)
{ {
loc = Point3D( lon, lat, 0.0f ); loc = Point3D( lon, lat, 0.0f );
mark = 0; mark = 0;
light = 0; light = 0;
term = false;
close = false;
} }
BezNode( Point3D l, Point3D cp ) BezNode( Point3D l, Point3D cp )
{ {
loc = l; loc = l;
next_cp = cp; next_cp = cp;
prev_cp = Mirror(cp); prev_cp = Mirror(cp);
mark = 0; mark = 0;
light = 0; light = 0;
term = false;
close = false;
} }
BezNode( double lat, double lon, double cp_lat, double cp_lon ) BezNode( double lat, double lon, double cp_lat, double cp_lon )
{ {
loc = Point3D( lon, lat, 0.0f ); loc = Point3D( lon, lat, 0.0f );
next_cp = Point3D( cp_lon, cp_lat, 0.0f ); next_cp = Point3D( cp_lon, cp_lat, 0.0f );
prev_cp = Mirror( next_cp ); prev_cp = Mirror( next_cp );
mark = 0; mark = 0;
light = 0; light = 0;
term = false;
close = false;
} }
Point3D Mirror( Point3D pt ) Point3D Mirror( Point3D pt )
@ -144,6 +152,16 @@ public:
return light; return light;
} }
void SetClose( bool c )
{
close = c;
}
void SetTerm( bool t )
{
term = t;
}
bool IsAt( double lat, double lon ) bool IsAt( double lat, double lon )
{ {
return ( (loc.lat() == lat) && (loc.lon() == lon) ); return ( (loc.lat() == lat) && (loc.lon() == lon) );
@ -199,6 +217,8 @@ private:
Point3D next_cp; Point3D next_cp;
unsigned int mark; unsigned int mark;
unsigned int light; unsigned int light;
bool term;
bool close;
}; };

View file

@ -132,7 +132,7 @@ void ClosedPoly::CloseCurContour()
if (cur_feature) if (cur_feature)
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "We still have an active linear feature - add the first node to close it"); SG_LOG(SG_GENERAL, SG_DEBUG, "We still have an active linear feature - add the first node to close it");
cur_feature->Finish(); cur_feature->Finish(true);
features.push_back(cur_feature); features.push_back(cur_feature);
cur_feature = NULL; cur_feature = NULL;
@ -535,6 +535,7 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours"); SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours");
// do this before clipping and generating the base // do this before clipping and generating the base
pre_tess = remove_bad_contours( pre_tess );
pre_tess = remove_dups( pre_tess ); pre_tess = remove_dups( pre_tess );
pre_tess = reduce_degeneracy( pre_tess ); pre_tess = reduce_degeneracy( pre_tess );
@ -545,15 +546,36 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
// SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: contour " << c << " pt " << pt << ": (" << pre_tess.get_pt(c, pt).x() << "," << pre_tess.get_pt(c, pt).y() << ")" ); // SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: contour " << c << " pt " << pt << ": (" << pre_tess.get_pt(c, pt).x() << "," << pre_tess.get_pt(c, pt).y() << ")" );
// } // }
//} //}
//SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours");
//for (int i=0; i<pre_tess.contours(); i++)
//{
// SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original countour " << i << " has " << pre_tess.contour_size(i) << " points" );
//}
// grow pretess by a little bit // grow pretess by a little bit
pre_tess = tgPolygonExpand( pre_tess, 0.05); // 5cm //pre_tess = tgPolygonExpand( pre_tess, 0.05); // 5cm
TGSuperPoly sp; TGSuperPoly sp;
TGTexParams tp; TGTexParams tp;
TGPolygon clipped = tgPolygonDiff( pre_tess, *accum ); SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: expanded poly has " << pre_tess.contours() << " contours");
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: clipped poly has " << clipped.contours() << " contours"); for (int i=0; i<pre_tess.contours(); i++)
{
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: expanded countour " << i << " has " << pre_tess.contour_size(i) << " points" );
}
#if 1
TGPolygon clipped = tgPolygonDiffClipper( pre_tess, *accum );
#else
TGPolygon clipped = tgPolygonDiff( pre_tess, *accum );
#endif
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: clipped poly has " << clipped.contours() << " contours");
for (int i=0; i<clipped.contours(); i++)
{
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: clipped poly countour " << i << " has " << clipped.contour_size(i) << " points" );
}
TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 ); TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: split poly has " << split.contours() << " contours"); SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: split poly has " << split.contours() << " contours");
@ -564,7 +586,11 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
rwy_polys->push_back( sp ); rwy_polys->push_back( sp );
SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours()); SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours());
#if 1
*accum = tgPolygonUnionClipper( pre_tess, *accum );
#else
*accum = tgPolygonUnion( pre_tess, *accum ); *accum = tgPolygonUnion( pre_tess, *accum );
#endif
tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading ); tp = TGTexParams( pre_tess.get_pt(0,0), 5.0, 5.0, texture_heading );
texparams->push_back( tp ); texparams->push_back( tp );
@ -581,10 +607,10 @@ int ClosedPoly::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list
safe_base = tgPolygonExpand( pre_tess, 50.0); safe_base = tgPolygonExpand( pre_tess, 50.0);
// add this to the airport clearing // add this to the airport clearing
*apt_clearing = tgPolygonUnion( safe_base, *apt_clearing); *apt_clearing = tgPolygonUnionClipper( safe_base, *apt_clearing);
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( base, *apt_base ); *apt_base = tgPolygonUnionClipper( base, *apt_base );
} }
} }
} }

View file

@ -32,7 +32,7 @@ Helipad::Helipad(char* definition)
// int fscanf(FILE *stream, const char *format, ...); // int fscanf(FILE *stream, const char *format, ...);
sscanf(definition, "%s %lf %lf %lf %lf %lf %d %d %d %lf %d", sscanf(definition, "%s %lf %lf %lf %lf %lf %d %d %d %lf %d",
&heli.designator, &heli.lat, &heli.lon, &heli.heading, &heli.length, &heli.width, &heli.surface, heli.designator, &heli.lat, &heli.lon, &heli.heading, &heli.length, &heli.width, &heli.surface,
&heli.marking, &heli.shoulder, &heli.smoothness, &heli.edge_lights); &heli.marking, &heli.shoulder, &heli.smoothness, &heli.edge_lights);
SG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width ); SG_LOG(SG_GENERAL, SG_DEBUG, "Read helipad: (" << heli.lon << "," << heli.lat << ") heading: " << heli.heading << " length: " << heli.length << " width: " << heli.width );
@ -131,7 +131,7 @@ void Helipad::BuildBtg( float alt_m,
// Now generate the helipad lights // Now generate the helipad lights
superpoly_list s = gen_helipad_lights(); superpoly_list s = gen_helipad_lights();
for ( int i = 0; i < s.size(); ++i ) { for ( unsigned int i = 0; i < s.size(); ++i ) {
rwy_lights->push_back( s[i] ); rwy_lights->push_back( s[i] );
} }
} }

View file

@ -10,7 +10,7 @@
#include "linearfeature.hxx" #include "linearfeature.hxx"
#include "math.h" #include "math.h"
void LinearFeature::ConvertContour( BezContour* src ) void LinearFeature::ConvertContour( BezContour* src, bool closed )
{ {
BezNode* prevNode; BezNode* prevNode;
BezNode* curNode; BezNode* curNode;
@ -243,9 +243,9 @@ void LinearFeature::ConvertContour( BezContour* src )
Point3D destLoc = nextNode->GetLoc(); Point3D destLoc = nextNode->GetLoc();
geo_inverse_wgs_84( curLoc.y(), curLoc.x(), destLoc.y(), destLoc.x(), &az1, &az2, &dist); geo_inverse_wgs_84( curLoc.y(), curLoc.x(), destLoc.y(), destLoc.x(), &az1, &az2, &dist);
if (dist > 10.0) if (dist > 100.0)
{ {
int num_segs = (dist / 10.0f) + 1; int num_segs = (dist / 100.0f) + 1;
for (int p=0; p<num_segs; p++) for (int p=0; p<num_segs; p++)
{ {
@ -267,21 +267,42 @@ void LinearFeature::ConvertContour( BezContour* src )
// now set set prev and cur locations for the next iteration // now set set prev and cur locations for the next iteration
prevLoc = curLoc; prevLoc = curLoc;
curLoc = nextLoc; curLoc = nextLoc;
SG_LOG(SG_GENERAL, SG_DEBUG, "Set prevLoc = (" << prevLoc.x() << "," << prevLoc.y() << ") and curLoc = (" << curLoc.x() << "," << curLoc.y() << ")" );
} }
} }
else else
{ {
nextLoc = nextNode->GetLoc();
// just add the one vertex - dist is small // just add the one vertex - dist is small
points.push_back( curLoc ); points.push_back( curLoc );
SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at (" << curLoc.x() << "," << curLoc.y() << ")"); SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at (" << curLoc.x() << "," << curLoc.y() << ")");
prevLoc = curLoc;
curLoc = nextLoc;
SG_LOG(SG_GENERAL, SG_DEBUG, "Set prevLoc = (" << prevLoc.x() << "," << prevLoc.y() << ") and curLoc = (" << curLoc.x() << "," << curLoc.y() << ")" );
} }
} }
} }
// TEST TEST TEST : This should do it
#if 1
if (closed)
{
SG_LOG(SG_GENERAL, SG_DEBUG, "Closed COntour : adding last node at (" << curLoc.x() << "," << curLoc.y() << ")");
// need to add the markings for last segment
points.push_back( curLoc );
}
#endif
// TEST TEST TEST
// check for marking that goes all the way to the end... // check for marking that goes all the way to the end...
if (cur_mark) if (cur_mark)
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::ConvertContour Marking from " << cur_mark->start_idx << " with type " << cur_mark->type << " ends at the end of the contour: " << points.size() ); SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::ConvertContour Marking from " << cur_mark->start_idx << " with type " << cur_mark->type << " ends at the end of the contour: " << points.size() );
cur_mark->end_idx = points.size()-1; cur_mark->end_idx = points.size()-1;
@ -290,8 +311,8 @@ void LinearFeature::ConvertContour( BezContour* src )
} }
// check for lighting that goes all the way to the end... // check for lighting that goes all the way to the end...
if (cur_light) if (cur_light)
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::ConvertContour Lighting from " << cur_light->start_idx << " with type " << cur_light->type << " ends at the end of the contour: " << points.size() ); SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::ConvertContour Lighting from " << cur_light->start_idx << " with type " << cur_light->type << " ends at the end of the contour: " << points.size() );
cur_light->end_idx = points.size()-1; cur_light->end_idx = points.size()-1;
@ -477,7 +498,7 @@ Point3D midpoint( Point3D p0, Point3D p1 )
return Point3D( (p0.x() + p1.x()) / 2, (p0.y() + p1.y()) / 2, (p0.z() + p1.z()) / 2 ); return Point3D( (p0.x() + p1.x()) / 2, (p0.y() + p1.y()) / 2, (p0.z() + p1.z()) / 2 );
} }
int LinearFeature::Finish() int LinearFeature::Finish( bool closed )
{ {
TGPolygon poly; TGPolygon poly;
TGPolygon normals_poly; TGPolygon normals_poly;
@ -499,7 +520,7 @@ int LinearFeature::Finish()
// create the inner and outer boundaries to generate polys // create the inner and outer boundaries to generate polys
// this generates 2 point lists for the contours, and remembers // this generates 2 point lists for the contours, and remembers
// the start stop points for markings and lights // the start stop points for markings and lights
ConvertContour( &contour ); ConvertContour( &contour, closed );
// now generate the supoerpoly and texparams lists for markings // now generate the supoerpoly and texparams lists for markings
for (unsigned int i=0; i<marks.size(); i++) for (unsigned int i=0; i<marks.size(); i++)
@ -782,11 +803,8 @@ int LinearFeature::Finish()
cur_light_dist += light_delta; cur_light_dist += light_delta;
} }
// add the remaining distance to the last light // start next segment at the correct distance
// cur_light_dist += modf( dist, &intpart ); cur_light_dist = cur_light_dist - dist;
// remove
cur_light_dist = fmod (cur_light_dist, light_delta);
} }
} }
@ -817,24 +835,28 @@ int LinearFeature::BuildBtg(float alt_m, superpoly_list* line_polys, texparams_l
{ {
TGPolygon poly; TGPolygon poly;
TGPolygon clipped; TGPolygon clipped;
//TGPolygon split;
SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::BuildBtg: " << description); SG_LOG(SG_GENERAL, SG_DEBUG, "\nLinearFeature::BuildBtg: " << description);
for ( unsigned int i = 0; i < marking_polys.size(); i++) for ( unsigned int i = 0; i < marking_polys.size(); i++)
{ {
poly = marking_polys[i].get_poly(); poly = marking_polys[i].get_poly();
SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: clipping poly " << i << " of " << marking_polys.size() ); SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: clipping poly " << i << " of " << marking_polys.size() );
#if 1
clipped = tgPolygonDiff( poly, *line_accum );
#else
clipped = tgPolygonDiffClipper( poly, *line_accum ); clipped = tgPolygonDiffClipper( poly, *line_accum );
#endif
// TGPolygon split = tgPolygonSplitLongEdges( clipped, 400.0 );
// SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: split poly has " << split.contours() << " contours");
marking_polys[i].set_poly( clipped ); marking_polys[i].set_poly( clipped );
line_polys->push_back( marking_polys[i] ); line_polys->push_back( marking_polys[i] );
#if 1
*line_accum = tgPolygonUnion( poly, *line_accum );
#else
*line_accum = tgPolygonUnionClipper( poly, *line_accum ); *line_accum = tgPolygonUnionClipper( poly, *line_accum );
#endif
line_tps->push_back( marking_tps[i] ); line_tps->push_back( marking_tps[i] );
} }

View file

@ -91,8 +91,9 @@ public:
contour.push_back( b ); contour.push_back( b );
} }
int Finish(); int Finish( bool closed );
int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, ClipPolyType* line_accum, superpoly_list* lights ); int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, ClipPolyType* line_accum, superpoly_list* lights );
int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, Polygons* line_accum, superpoly_list* lights );
private: private:
Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by ); Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by );
@ -108,7 +109,7 @@ private:
LightingList lights; LightingList lights;
Lighting* cur_light; Lighting* cur_light;
void ConvertContour( BezContour* src ); void ConvertContour( BezContour* src, bool closed );
// text description // text description
string description; string description;

View file

@ -19,10 +19,15 @@ Beacon::Beacon( char* definition )
Sign::Sign( char* definition ) Sign::Sign( char* definition )
{ {
char sgdef[256]; char sgdef[256];
double def_heading;
sscanf(definition, "%lf %lf %lf %d %d %s", &lat, &lon, &heading, &reserved, &size, sgdef ); sscanf(definition, "%lf %lf %lf %d %d %s", &lat, &lon, &def_heading, &reserved, &size, sgdef );
SG_LOG(SG_GENERAL, SG_DEBUG, "Read Sign: (" << lon << "," << lat << ") heading " << heading << " size " << size << " definition: " << sgdef ); // 850 format sign heading is the heading which points away from the visible numbers
// Flightgear wants the heading to be the heading in which the sign is read
heading = -def_heading + 360.0;
SG_LOG(SG_GENERAL, SG_DEBUG, "Read Sign: (" << lon << "," << lat << ") heading " << def_heading << " size " << size << " definition: " << sgdef << " calc view heading: " << heading );
sgn_def = sgdef; sgn_def = sgdef;
} }

View file

@ -309,7 +309,6 @@ void Parser::AddAirports( long start_pos, float min_lat, float min_lon, float ma
void Parser::Parse() void Parser::Parse()
{ {
char tmp[2048]; char tmp[2048];
int i;
struct timeval parse_start; struct timeval parse_start;
struct timeval parse_end; struct timeval parse_end;
struct timeval parse_time; struct timeval parse_time;
@ -325,7 +324,7 @@ void Parser::Parse()
} }
// for each position in parse_positions, parse an airport // for each position in parse_positions, parse an airport
for (i=0; i<parse_positions.size(); i++) for ( unsigned int i=0; i < parse_positions.size(); i++)
{ {
SetState(STATE_NONE); SetState(STATE_NONE);
in.clear(); in.clear();
@ -502,6 +501,9 @@ BezNode* Parser::ParseNode( int type, char* line, BezNode* prevNode )
} }
} }
curNode->SetTerm( term );
curNode->SetClose( close );
return curNode; return curNode;
} }
@ -533,7 +535,7 @@ ClosedPoly* Parser::ParsePavement( char* line )
char *d = NULL; char *d = NULL;
int numParams; int numParams;
numParams = sscanf(line, "%d %f %f %ls", &st, &s, &th, desc); numParams = sscanf(line, "%d %f %f %s", &st, &s, &th, desc);
if (numParams == 4) if (numParams == 4)
{ {
@ -557,7 +559,7 @@ ClosedPoly* Parser::ParseBoundary( char* line )
char *d = NULL; char *d = NULL;
int numParams; int numParams;
numParams = sscanf(line, "%ls", desc); numParams = sscanf(line, "%s", desc);
if (numParams == 1) if (numParams == 1)
{ {
@ -595,6 +597,8 @@ int Parser::SetState( int state )
} }
cur_state = state; cur_state = state;
return cur_state;
} }
// TODO: This should be a loop here, and main should just pass the file name and airport code... // TODO: This should be a loop here, and main should just pass the file name and airport code...
@ -756,7 +760,7 @@ int Parser::ParseLine(char* line)
} }
if (cur_airport) if (cur_airport)
{ {
cur_feat->Finish(); cur_feat->Finish( true );
cur_airport->AddFeature( cur_feat ); cur_airport->AddFeature( cur_feat );
} }
cur_feat = NULL; cur_feat = NULL;
@ -790,7 +794,7 @@ int Parser::ParseLine(char* line)
} }
if (cur_airport) if (cur_airport)
{ {
cur_feat->Finish(); cur_feat->Finish( false );
cur_airport->AddFeature( cur_feat ); cur_airport->AddFeature( cur_feat );
} }
} }

View file

@ -40,8 +40,8 @@ Runway::Runway(char* definition)
// int fscanf(FILE *stream, const char *format, ...); // int fscanf(FILE *stream, const char *format, ...);
sscanf(definition, "%lf %d %d %lf %d %d %d %s %lf %lf %lf %lf %d %d %d %d %s %lf %lf %lf %lf %d %d %d %d", sscanf(definition, "%lf %d %d %lf %d %d %d %s %lf %lf %lf %lf %d %d %d %d %s %lf %lf %lf %lf %d %d %d %d",
&rwy.width, &rwy.surface, &rwy.shoulder, &rwy.smoothness, &rwy.centerline_lights, &rwy.edge_lights, &rwy.dist_remain_signs, &rwy.width, &rwy.surface, &rwy.shoulder, &rwy.smoothness, &rwy.centerline_lights, &rwy.edge_lights, &rwy.dist_remain_signs,
&rwy.rwnum[0], &rwy.lat[0], &rwy.lon[0], &rwy.threshold[0], &rwy.overrun[0], &rwy.marking[0], &rwy.approach_lights[0], &rwy.tz_lights[0], &rwy.reil[0], rwy.rwnum[0], &rwy.lat[0], &rwy.lon[0], &rwy.threshold[0], &rwy.overrun[0], &rwy.marking[0], &rwy.approach_lights[0], &rwy.tz_lights[0], &rwy.reil[0],
&rwy.rwnum[1], &rwy.lat[1], &rwy.lon[1], &rwy.threshold[1], &rwy.overrun[1], &rwy.marking[1], &rwy.approach_lights[1], &rwy.tz_lights[1], &rwy.reil[1] rwy.rwnum[1], &rwy.lat[1], &rwy.lon[1], &rwy.threshold[1], &rwy.overrun[1], &rwy.marking[1], &rwy.approach_lights[1], &rwy.tz_lights[1], &rwy.reil[1]
); );
// calculate runway heading and length (used a lot) // calculate runway heading and length (used a lot)
@ -53,7 +53,7 @@ Runway::Runway(char* definition)
WaterRunway::WaterRunway(char* definition) WaterRunway::WaterRunway(char* definition)
{ {
sscanf(definition, "%lf %d %s %lf %lf %s %lf %lf", &width, &buoys, &rwnum[0], &lat[0], &lon[0], &rwnum[1], &lat[1], &lon[1]); sscanf(definition, "%lf %d %s %lf %lf %s %lf %lf", &width, &buoys, rwnum[0], &lat[0], &lon[0], rwnum[1], &lat[1], &lon[1]);
SG_LOG(SG_GENERAL, SG_DEBUG, "Read water runway: (" << lon[0] << "," << lat[0] << ") to (" << lon[1] << "," << lat[1] << ") width: " << width << " buoys = " << buoys ); SG_LOG(SG_GENERAL, SG_DEBUG, "Read water runway: (" << lon[0] << "," << lat[0] << ") to (" << lon[1] << "," << lat[1] << ") width: " << width << " buoys = " << buoys );
} }
@ -175,4 +175,6 @@ int Runway::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* te
// and add the clearing to the base // and add the clearing to the base
*apt_base = tgPolygonUnion( base, *apt_base ); *apt_base = tgPolygonUnion( base, *apt_base );
} }
return 0;
} }

View file

@ -372,6 +372,9 @@ void Runway::BuildShoulder( float alt_m,
int numSegs = (rwy.length / max_dist) + 1; int numSegs = (rwy.length / max_dist) + 1;
double dist = rwy.length / (double)numSegs; double dist = rwy.length / (double)numSegs;
//int numSegs = 1;
//double dist = rwy.length;
// 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;
@ -395,18 +398,25 @@ void Runway::BuildShoulder( float alt_m,
for (int j=0; j<numSegs; j++) for (int j=0; j<numSegs; j++)
{ {
geo_direct_wgs_84 ( alt_m, ref.y(), ref.x(), rwy.heading, (j*dist), &lat, &lon, &r ); 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 ); TGPolygon shoulderSegment = gen_wgs84_rect( lat, lon, rwy.heading, dist, shoulder_width+0.1 );
TGSuperPoly sp; TGSuperPoly sp;
TGTexParams tp; TGTexParams tp;
#if 1
TGPolygon clipped = tgPolygonDiff( shoulderSegment, *accum ); TGPolygon clipped = tgPolygonDiff( shoulderSegment, *accum );
#else
TGPolygon clipped = tgPolygonDiffClipper( shoulderSegment, *accum );
#endif
sp.erase(); sp.erase();
sp.set_poly( clipped ); sp.set_poly( clipped );
sp.set_material( shoulder_surface ); sp.set_material( shoulder_surface );
rwy_polys->push_back( sp ); rwy_polys->push_back( sp );
#if 1
*accum = tgPolygonUnion( shoulderSegment, *accum ); *accum = tgPolygonUnion( shoulderSegment, *accum );
#else
*accum = tgPolygonUnionClipper( shoulderSegment, *accum );
#endif
tp = TGTexParams( shoulderSegment.get_pt(0,0), -shoulder_width, dist, rwy.heading ); tp = TGTexParams( shoulderSegment.get_pt(0,0), -shoulder_width, dist, rwy.heading );
if (i == 0){ if (i == 0){

View file

@ -46,7 +46,8 @@
#include <simgear/math/SGMath.hxx> #include <simgear/math/SGMath.hxx>
const double fgPoint3_Epsilon = 0.0000001; //const double fgPoint3_Epsilon = 0.0000001;
const double fgPoint3_Epsilon = 0.000001;
enum {PX, PY, PZ}; // axes enum {PX, PY, PZ}; // axes

View file

@ -349,16 +349,12 @@ TGPolygon polygon_tesselate_alt( TGPolygon &p, bool verbose ) {
// Bail right away if polygon is empty // Bail right away if polygon is empty
if ( p.contours() == 0 ) { if ( p.contours() == 0 ) {
return result; return result;
} }
// 1. Robustly find a point inside each contour that is not // 1. Robustly find a point inside each contour that is not
// inside any other contour // inside any other contour
calc_points_inside( p ); calc_points_inside( p );
for ( i = 0; i < p.contours(); ++i ) {
//cout << "final point inside =" << p.get_point_inside( i )
// << endl;
}
// 2. Do a final triangulation of the entire polygon // 2. Do a final triangulation of the entire polygon
triele_list trieles; triele_list trieles;
@ -366,8 +362,21 @@ TGPolygon polygon_tesselate_alt( TGPolygon &p, bool verbose ) {
string flags; string flags;
if (verbose) { if (verbose) {
flags = "pzqenXYY"; flags = "pzqenXYY";
// flags = "pzqenXY"; // allow adding interior points
} else { } else {
flags = "pzqenXYYQ"; flags = "pzqenXYYQ";
// flags = "pzqenXYQ"; // allow adding interior points
}
// check the input for nan point
for (int c = 0; c < p.contours(); c++) {
point_list contour = p.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 before tesselation\n");
exit(0);
}
}
} }
if ( polygon_tesselate( p, extra_nodes, trieles, nodes, flags ) >= 0 ) { if ( polygon_tesselate( p, extra_nodes, trieles, nodes, flags ) >= 0 ) {

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 4.5.5 * * Version : 4.6.5 *
* Date : 6 October 2011 * * Date : 17 January 2011 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2011 * * Copyright : Angus Johnson 2010-2012 *
* * * *
* License: * * License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. * * Use, modification & distribution is subject to Boost Software License Ver 1. *
@ -21,6 +21,14 @@
* Springer; 1 edition (January 4, 2005) * * Springer; 1 edition (January 4, 2005) *
* http://books.google.com/books?q=vatti+clipping+agoston * * http://books.google.com/books?q=vatti+clipping+agoston *
* * * *
* See also: *
* "Polygon Offsetting by Computing Winding Numbers" *
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 2428, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/ *******************************************************************************/
#ifndef clipper_hpp #ifndef clipper_hpp
@ -39,8 +47,8 @@ enum PolyType { ptSubject, ptClip };
//By far the most widely used winding rules for polygon filling are //By far the most widely used winding rules for polygon filling are
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
//see http://www.songho.ca/opengl/gl_tessellation.html#winding_rules //see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero }; enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
typedef signed long long long64; typedef signed long long long64;
typedef unsigned long long ulong64; typedef unsigned long long ulong64;
@ -71,6 +79,9 @@ bool Orientation(const Polygon &poly);
double Area(const Polygon &poly); double Area(const Polygon &poly);
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double MiterLimit = 2); double delta, JoinType jointype = jtSquare, double MiterLimit = 2);
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys);
void SimplifyPolygons(Polygons &polys);
void ReversePoints(Polygon& p); void ReversePoints(Polygon& p);
void ReversePoints(Polygons& p); void ReversePoints(Polygons& p);
@ -193,13 +204,13 @@ public:
Clipper(); Clipper();
~Clipper(); ~Clipper();
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
Polygons &solution, Polygons &solution,
PolyFillType subjFillType = pftEvenOdd, PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd); PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
ExPolygons &solution, ExPolygons &solution,
PolyFillType subjFillType = pftEvenOdd, PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd); PolyFillType clipFillType = pftEvenOdd);
void Clear(); void Clear();
bool ReverseSolution() {return m_ReverseOutput;}; bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;}; void ReverseSolution(bool value) {m_ReverseOutput = value;};
@ -221,8 +232,8 @@ private:
bool m_ReverseOutput; bool m_ReverseOutput;
void DisposeScanbeamList(); void DisposeScanbeamList();
void SetWindingCount(TEdge& edge); void SetWindingCount(TEdge& edge);
bool IsNonZeroFillType(const TEdge& edge) const; bool IsEvenOddFillType(const TEdge& edge) const;
bool IsNonZeroAltFillType(const TEdge& edge) const; bool IsEvenOddAltFillType(const TEdge& edge) const;
void InsertScanbeam(const long64 Y); void InsertScanbeam(const long64 Y);
long64 PopScanbeam(); long64 PopScanbeam();
void InsertLocalMinimaIntoAEL(const long64 botY); void InsertLocalMinimaIntoAEL(const long64 botY);

View file

@ -540,6 +540,38 @@ void make_tg_poly_from_clipper( const Polygons& in, TGPolygon *out )
} }
} }
Polygons clipper_simplify( ExPolygons &in )
{
Polygons out;
Polygon contour;
for (unsigned int i=0; i<in.size(); i++)
{
const struct ExPolygon* pg = &in[i];
// first the boundary
contour = pg->outer;
if ( !Orientation( contour ) ) {
ReversePoints( contour );
}
out.push_back( contour );
// then the holes
for (unsigned int j = 0; j < pg->holes.size(); j++)
{
contour = pg->holes[j];
if ( Orientation( contour ) ) {
ReversePoints( contour );
}
out.push_back( contour );
}
}
// Now simplify
SimplifyPolygons(out);
return out;
}
TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip ) TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const TGPolygon& clip )
{ {
@ -572,7 +604,11 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
c.AddPolygons(clipper_clip, ptClip); c.AddPolygons(clipper_clip, ptClip);
c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd); c.Execute(op, clipper_result, pftEvenOdd, pftEvenOdd);
make_tg_poly_from_clipper_ex( clipper_result, &result );
// verify each result is simple
Polygons simple_result = clipper_simplify( clipper_result );
make_tg_poly_from_clipper( simple_result, &result );
return result; return result;
} }
@ -608,7 +644,6 @@ TGPolygon tgPolygonUnionClipper( const TGPolygon& subject, const TGPolygon& clip
return polygon_clip_clipper( POLY_UNION, subject, clip ); return polygon_clip_clipper( POLY_UNION, subject, clip );
} }
// canonify the polygon winding, outer contour must be anti-clockwise, // canonify the polygon winding, outer contour must be anti-clockwise,
// all inner contours must be clockwise. // all inner contours must be clockwise.
TGPolygon polygon_canonify( const TGPolygon& in_poly ) { TGPolygon polygon_canonify( const TGPolygon& in_poly ) {

View file

@ -275,7 +275,6 @@ TGPolygon tgPolygonDiffClipper( const TGPolygon& subject, const TGPolygon& clip
// Union // Union
TGPolygon tgPolygonUnionClipper( const TGPolygon& subject, const TGPolygon& clip ); TGPolygon tgPolygonUnionClipper( const TGPolygon& subject, const TGPolygon& clip );
// Expand / Shrink // Expand / Shrink
TGPolygon tgPolygonExpand(const TGPolygon &poly, double delta); TGPolygon tgPolygonExpand(const TGPolygon &poly, double delta);