- Fixed issues where an entire landclass poly wold no triangulate.
- Increase epsilon when looking for intermediate nodes (setup method for calling function to specify the bounding box and error epsilon in case this had adverse effects on genapts) This fixes many of the small vertical gaps (T-Junctions) - Fix an issue with merge slivers. The clip mask optimization broke merge slivers. WHen merging the slivers with a poly segment, it also needs to be merged with the clip mask, so when the segments are seperated from the mask, they include the sliver. - Added to the shapefile debug. --debug_shape=tileid:all generates shapefiles for every polygon in the tile This is usefull to setup individual debug polys on subsequent passes. Also added load, clip, and with_slivers and clean layers for debugging
This commit is contained in:
parent
79bdae93fc
commit
346ae44e14
10 changed files with 361 additions and 90 deletions
|
@ -72,6 +72,7 @@ TGConstruct::TGConstruct():
|
||||||
useUKGrid(false),
|
useUKGrid(false),
|
||||||
writeSharedEdges(true),
|
writeSharedEdges(true),
|
||||||
useOwnSharedEdges(false),
|
useOwnSharedEdges(false),
|
||||||
|
debug_all(false),
|
||||||
ds_id((void*)-1)
|
ds_id((void*)-1)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -102,17 +103,22 @@ void TGConstruct::set_debug( std::string path, std::vector<string> defs )
|
||||||
|
|
||||||
if( tile == bucket.gen_index_str() ) {
|
if( tile == bucket.gen_index_str() ) {
|
||||||
dsd.erase(0, d_pos+1);
|
dsd.erase(0, d_pos+1);
|
||||||
std::stringstream ss(dsd);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while (ss >> i)
|
if ( dsd == "all" ) {
|
||||||
{
|
debug_all = true;
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Adding debug file " << i);
|
} else {
|
||||||
|
std::stringstream ss(dsd);
|
||||||
|
int i;
|
||||||
|
|
||||||
debug_shapes.push_back(i);
|
while (ss >> i)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Adding debug file " << i);
|
||||||
|
|
||||||
if (ss.peek() == ',')
|
debug_shapes.push_back(i);
|
||||||
ss.ignore();
|
|
||||||
|
if (ss.peek() == ',')
|
||||||
|
ss.ignore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,25 +128,55 @@ bool TGConstruct::IsDebugShape( unsigned int id )
|
||||||
{
|
{
|
||||||
bool is_debug = false;
|
bool is_debug = false;
|
||||||
|
|
||||||
for (unsigned int i=0; i<debug_shapes.size(); i++) {
|
/* Check global flag */
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "have debug id " << debug_shapes[i] << " looking for " << id );
|
if ( debug_all ) {
|
||||||
|
is_debug = true;
|
||||||
if ( debug_shapes[i] == id ) {
|
} else {
|
||||||
is_debug = true;
|
for (unsigned int i=0; i<debug_shapes.size(); i++) {
|
||||||
break;
|
if ( debug_shapes[i] == id ) {
|
||||||
|
is_debug = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_debug;
|
return is_debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGConstruct::WriteDebugShape( const char* layer_name, unsigned int area, unsigned int shape )
|
void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||||
|
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||||
|
|
||||||
|
shape.GetName( name );
|
||||||
|
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, name );
|
||||||
|
|
||||||
|
// close after each write
|
||||||
|
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TGConstruct::WriteDebugPoly( const char* layer_name, const char* name, const TGPolygon& poly )
|
||||||
{
|
{
|
||||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||||
|
|
||||||
sprintf( feature_name, "%s_%d", get_area_name( area ).c_str(), polys_clipped.get_shape( area, shape ).id );
|
tgShapefileCreateFeature( ds_id, l_id, poly, name );
|
||||||
tgShapefileCreateFeature( ds_id, l_id, polys_in.get_mask(area, shape), feature_name );
|
|
||||||
|
// close after each write
|
||||||
|
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TGConstruct::WriteDebugPolys( const char* layer_name, const poly_list& polys )
|
||||||
|
{
|
||||||
|
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||||
|
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||||
|
|
||||||
|
for( unsigned int i=0; i<polys.size(); i++ ) {
|
||||||
|
sprintf( feature_name, "poly_%d", i );
|
||||||
|
tgShapefileCreateFeature( ds_id, l_id, polys[i], feature_name );
|
||||||
|
}
|
||||||
|
|
||||||
// close after each write
|
// close after each write
|
||||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||||
|
@ -383,8 +419,8 @@ bool TGConstruct::load_poly(const string& path) {
|
||||||
|
|
||||||
sp.set_poly( poly );
|
sp.set_poly( poly );
|
||||||
sp.set_material( material );
|
sp.set_material( material );
|
||||||
|
|
||||||
shape.sps.push_back( sp );
|
shape.sps.push_back( sp );
|
||||||
|
|
||||||
if ( with_tp ) {
|
if ( with_tp ) {
|
||||||
shape.textured = true;
|
shape.textured = true;
|
||||||
shape.tps.push_back( tp );
|
shape.tps.push_back( tp );
|
||||||
|
@ -399,9 +435,14 @@ bool TGConstruct::load_poly(const string& path) {
|
||||||
|
|
||||||
// Once the full poly is loaded, build the clip mask
|
// Once the full poly is loaded, build the clip mask
|
||||||
shape.BuildMask();
|
shape.BuildMask();
|
||||||
|
shape.area = area;
|
||||||
shape.id = cur_id++;
|
shape.id = cur_id++;
|
||||||
|
|
||||||
polys_in.add_shape( area, shape );
|
polys_in.add_shape( area, shape );
|
||||||
|
|
||||||
|
if ( IsDebugShape( shape.id ) ) {
|
||||||
|
WriteDebugShape( "loaded", shape );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1172,6 +1213,8 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
|
||||||
int original_contours, result_contours;
|
int original_contours, result_contours;
|
||||||
bool done;
|
bool done;
|
||||||
int area, shape, segment, i, j;
|
int area, shape, segment, i, j;
|
||||||
|
int merged = 0;
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
for ( i = 0; i < (int)slivers_list.size(); i++ ) {
|
for ( i = 0; i < (int)slivers_list.size(); i++ ) {
|
||||||
slivers = slivers_list[i];
|
slivers = slivers_list[i];
|
||||||
|
@ -1179,6 +1222,8 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
|
||||||
for ( j = 0; j < slivers.contours(); ++j ) {
|
for ( j = 0; j < slivers.contours(); ++j ) {
|
||||||
// make the sliver polygon
|
// make the sliver polygon
|
||||||
contour = slivers.get_contour( j );
|
contour = slivers.get_contour( j );
|
||||||
|
total++;
|
||||||
|
|
||||||
sliver.erase();
|
sliver.erase();
|
||||||
sliver.add_contour( contour, 0 );
|
sliver.add_contour( contour, 0 );
|
||||||
done = false;
|
done = false;
|
||||||
|
@ -1190,6 +1235,8 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( shape = 0; shape < (int)clipped.area_size(area) && !done; ++shape ) {
|
for ( shape = 0; shape < (int)clipped.area_size(area) && !done; ++shape ) {
|
||||||
|
unsigned int shape_id = clipped.get_shape( area, shape ).id;
|
||||||
|
|
||||||
for ( segment = 0; segment < (int)clipped.shape_size(area, shape) && !done; ++segment ) {
|
for ( segment = 0; segment < (int)clipped.shape_size(area, shape) && !done; ++segment ) {
|
||||||
|
|
||||||
poly = clipped.get_poly( area, shape, segment );
|
poly = clipped.get_poly( area, shape, segment );
|
||||||
|
@ -1202,7 +1249,24 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
|
||||||
result_contours = result.contours();
|
result_contours = result.contours();
|
||||||
|
|
||||||
if ( original_contours == result_contours ) {
|
if ( original_contours == result_contours ) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, "MERGED SLIVER " << i << ", " << j << " into area " << get_area_name( (AreaType)area ) << " id: " << shape_id << " segment: " << segment );
|
||||||
|
|
||||||
clipped.set_poly( area, shape, segment, result );
|
clipped.set_poly( area, shape, segment, result );
|
||||||
|
merged++;
|
||||||
|
|
||||||
|
/* add the sliver to the clip_mask, too */
|
||||||
|
TGPolygon mask = clipped.get_mask( area, shape );
|
||||||
|
#if USE_CLIPPER
|
||||||
|
result = tgPolygonUnionClipper( mask, sliver );
|
||||||
|
#else
|
||||||
|
result = tgPolygonUnion( mask, sliver );
|
||||||
|
#endif
|
||||||
|
clipped.set_mask( area, shape, result );
|
||||||
|
|
||||||
|
if ( IsDebugShape( shape_id ) ) {
|
||||||
|
WriteDebugShape( "with_slivers", clipped.get_shape( area, shape ) );
|
||||||
|
}
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1210,10 +1274,14 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slivers_list.clear();
|
||||||
|
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << total - merged );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TGConstruct::ClipLandclassPolys( void ) {
|
bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
TGPolygon accum, clipped, tmp;
|
TGPolygon clipped, tmp;
|
||||||
TGPolygon remains;
|
TGPolygon remains;
|
||||||
TGPolygon safety_base;
|
TGPolygon safety_base;
|
||||||
poly_list slivers;
|
poly_list slivers;
|
||||||
|
@ -1221,13 +1289,21 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
Point3D p;
|
Point3D p;
|
||||||
point2d min, max;
|
point2d min, max;
|
||||||
|
|
||||||
|
#if !USE_ACCUMULATOR
|
||||||
|
TGPolygon accum;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get clip bounds
|
// Get clip bounds
|
||||||
min.x = bucket.get_center_lon() - 0.5 * bucket.get_width();
|
min.x = bucket.get_center_lon() - 0.5 * bucket.get_width();
|
||||||
min.y = bucket.get_center_lat() - 0.5 * bucket.get_height();
|
min.y = bucket.get_center_lat() - 0.5 * bucket.get_height();
|
||||||
max.x = bucket.get_center_lon() + 0.5 * bucket.get_width();
|
max.x = bucket.get_center_lon() + 0.5 * bucket.get_width();
|
||||||
max.y = bucket.get_center_lat() + 0.5 * bucket.get_height();
|
max.y = bucket.get_center_lat() + 0.5 * bucket.get_height();
|
||||||
|
|
||||||
|
#if USE_ACCUMULATOR
|
||||||
|
tgPolygonInitAccumulator();
|
||||||
|
#else
|
||||||
accum.erase();
|
accum.erase();
|
||||||
|
#endif
|
||||||
|
|
||||||
// set up clipping tile : and remember to add the nodes!
|
// set up clipping tile : and remember to add the nodes!
|
||||||
safety_base.erase();
|
safety_base.erase();
|
||||||
|
@ -1318,19 +1394,28 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
#if USE_CLIPPER
|
#if USE_CLIPPER
|
||||||
clipped = tgPolygonDiffClipper( tmp, accum );
|
clipped = tgPolygonDiffClipper( tmp, accum );
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#if USE_ACCUMULATOR
|
||||||
|
clipped = tgPolygonDiffWithAccumulator( tmp );
|
||||||
|
#else
|
||||||
clipped = tgPolygonDiff( tmp, accum );
|
clipped = tgPolygonDiff( tmp, accum );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// only add to output list if the clip left us with a polygon
|
// only add to output list if the clip left us with a polygon
|
||||||
if ( clipped.contours() > 0 ) {
|
if ( clipped.contours() > 0 ) {
|
||||||
|
|
||||||
|
#if FIND_SLIVERS
|
||||||
// move slivers from clipped polygon to slivers polygon
|
// move slivers from clipped polygon to slivers polygon
|
||||||
tgPolygonFindSlivers( clipped, slivers );
|
tgPolygonFindSlivers( clipped, slivers );
|
||||||
|
#endif
|
||||||
|
|
||||||
// add the sliverless result polygon to the clipped polys list
|
// add the sliverless result polygon to the clipped polys list
|
||||||
if ( clipped.contours() > 0 ) {
|
if ( clipped.contours() > 0 ) {
|
||||||
TGShape shape;
|
TGShape shape;
|
||||||
TGSuperPoly sp;
|
TGSuperPoly sp;
|
||||||
|
|
||||||
sp.set_material( get_area_name( (AreaType)i ) );
|
//sp.set_material( get_area_name( (AreaType)i ) );
|
||||||
|
|
||||||
// copy all of the superpolys and texparams
|
// copy all of the superpolys and texparams
|
||||||
shape.SetMask( clipped );
|
shape.SetMask( clipped );
|
||||||
|
@ -1339,47 +1424,81 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
shape.sps = polys_in.get_shape( i, j ).sps;
|
shape.sps = polys_in.get_shape( i, j ).sps;
|
||||||
shape.tps = polys_in.get_shape( i, j ).tps;
|
shape.tps = polys_in.get_shape( i, j ).tps;
|
||||||
|
|
||||||
shape.sps.push_back( sp );
|
// shape.sps.push_back( sp );
|
||||||
polys_clipped.add_shape( i, shape );
|
polys_clipped.add_shape( i, shape );
|
||||||
|
|
||||||
|
if ( IsDebugShape( shape.id ) ) {
|
||||||
|
WriteDebugShape( "clipped", shape );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_CLIPPER
|
#if USE_CLIPPER
|
||||||
accum = tgPolygonUnionClipper( tmp, accum );
|
accum = tgPolygonUnionClipper( tmp, accum );
|
||||||
|
// accum = tgPolygonUnionClipper( clipped, accum );
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if USE_ACCUMULATOR
|
||||||
|
tgPolygonAddToAccumulator( tmp );
|
||||||
|
// tgPolygonAddToAccumulator( clipped );
|
||||||
#else
|
#else
|
||||||
accum = tgPolygonUnion( tmp, accum );
|
accum = tgPolygonUnion( tmp, accum );
|
||||||
|
// accum = tgPolygonUnion( clipped, accum );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( debug_all || debug_shapes.size() ) {
|
||||||
|
// Dump the sliver list
|
||||||
|
WriteDebugPolys( "poly_slivers", slivers );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FIND_SLIVERS
|
||||||
// Now, merge any slivers with clipped polys
|
// Now, merge any slivers with clipped polys
|
||||||
merge_slivers(polys_clipped, slivers);
|
merge_slivers(polys_clipped, slivers);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
slivers.clear();
|
||||||
|
|
||||||
// finally, what ever is left over goes to ocean
|
// finally, what ever is left over goes to ocean
|
||||||
|
|
||||||
// clip to accum against original base tile
|
|
||||||
// remains = new gpc_polygon;
|
|
||||||
// remains->num_contours = 0;
|
|
||||||
// remains->contour = NULL;
|
|
||||||
#if USE_CLIPPER
|
#if USE_CLIPPER
|
||||||
remains = tgPolygonDiffClipper( safety_base, accum );
|
remains = tgPolygonDiffClipper( safety_base, accum );
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#if USE_ACCUMULATOR
|
||||||
|
remains = tgPolygonDiffWithAccumulator( safety_base );
|
||||||
|
#else
|
||||||
remains = tgPolygonDiff( safety_base, accum );
|
remains = tgPolygonDiff( safety_base, accum );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( remains.contours() > 0 ) {
|
if ( remains.contours() > 0 ) {
|
||||||
// cout << "remains contours = " << remains.contours() << endl;
|
// cout << "remains contours = " << remains.contours() << endl;
|
||||||
// move slivers from remains polygon to slivers polygon
|
// move slivers from remains polygon to slivers polygon
|
||||||
|
|
||||||
|
#if FIND_SLIVERS
|
||||||
tgPolygonFindSlivers( remains, slivers );
|
tgPolygonFindSlivers( remains, slivers );
|
||||||
|
#endif
|
||||||
// cout << " After sliver move:" << endl;
|
// cout << " After sliver move:" << endl;
|
||||||
// cout << " remains = " << remains.contours() << endl;
|
// cout << " remains = " << remains.contours() << endl;
|
||||||
// cout << " slivers = " << slivers.contours() << endl;
|
// cout << " slivers = " << slivers.contours() << endl;
|
||||||
|
|
||||||
|
#if FIND_SLIVERS
|
||||||
// merge any slivers with previously clipped
|
// merge any slivers with previously clipped
|
||||||
// neighboring polygons
|
// neighboring polygons
|
||||||
if ( slivers.size() > 0 ) {
|
if ( slivers.size() > 0 ) {
|
||||||
|
|
||||||
|
if ( debug_all || debug_shapes.size() ) {
|
||||||
|
// Dump the sliver list
|
||||||
|
WriteDebugPolys( "remains_slivers", slivers );
|
||||||
|
}
|
||||||
|
|
||||||
merge_slivers(polys_clipped, slivers);
|
merge_slivers(polys_clipped, slivers);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( remains.contours() > 0 ) {
|
if ( remains.contours() > 0 ) {
|
||||||
TGSuperPoly sp;
|
TGSuperPoly sp;
|
||||||
|
@ -1396,6 +1515,10 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_ACCUMULATOR
|
||||||
|
tgPolygonFreeAccumulator();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Once clipping is complete, intersect the individual segments with their clip masks
|
// Once clipping is complete, intersect the individual segments with their clip masks
|
||||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||||
|
@ -1666,7 +1789,7 @@ void TGConstruct::TesselatePolys( void )
|
||||||
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
||||||
|
|
||||||
if ( IsDebugShape( id ) ) {
|
if ( IsDebugShape( id ) ) {
|
||||||
WriteDebugShape( "preteselate", area, shape );
|
WriteDebugShape( "preteselate", polys_clipped.get_shape(area, shape) );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||||
|
@ -1834,16 +1957,20 @@ void TGConstruct::WriteBtgFile( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGConstruct::clean_clipped_polys() {
|
void TGConstruct::CleanClippedPolys() {
|
||||||
// Clean the polys
|
// Clean the polys
|
||||||
|
unsigned int before, after;
|
||||||
|
|
||||||
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
||||||
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||||
|
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
||||||
|
|
||||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||||
SG_LOG( SG_CLIPPER, SG_INFO, "Cleaning poly " << get_area_name( (AreaType)area ) <<
|
|
||||||
":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
|
|
||||||
|
|
||||||
if ( area == 3 ) {
|
before = poly.total_size();
|
||||||
|
|
||||||
|
if ( false ) {
|
||||||
poly = remove_cycles( poly );
|
poly = remove_cycles( poly );
|
||||||
poly = remove_dups( poly );
|
poly = remove_dups( poly );
|
||||||
poly = remove_bad_contours( poly );
|
poly = remove_bad_contours( poly );
|
||||||
|
@ -1859,8 +1986,19 @@ void TGConstruct::clean_clipped_polys() {
|
||||||
poly = remove_bad_contours( poly );
|
poly = remove_bad_contours( poly );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
after = poly.total_size();
|
||||||
|
|
||||||
|
if (before != after) {
|
||||||
|
SG_LOG( SG_CLIPPER, SG_INFO, "Cleanined poly " << get_area_name( (AreaType)area ) <<
|
||||||
|
":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " before: " << before << " after: " << after );
|
||||||
|
}
|
||||||
|
|
||||||
polys_clipped.set_poly( area, shape, segment, poly );
|
polys_clipped.set_poly( area, shape, segment, poly );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( IsDebugShape( id ) ) {
|
||||||
|
WriteDebugShape( "cleaned", polys_clipped.get_shape( area, shape ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1899,7 +2037,7 @@ void TGConstruct::CalcTextureCoordinates( void )
|
||||||
void TGConstruct::ConstructBucket() {
|
void TGConstruct::ConstructBucket() {
|
||||||
|
|
||||||
/* If we have some debug IDs, create a datasource */
|
/* If we have some debug IDs, create a datasource */
|
||||||
if ( debug_shapes.size() ) {
|
if ( debug_shapes.size() || debug_all ) {
|
||||||
sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() );
|
sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1927,6 +2065,11 @@ void TGConstruct::ConstructBucket() {
|
||||||
// Clip the Landclass polygons
|
// Clip the Landclass polygons
|
||||||
ClipLandclassPolys();
|
ClipLandclassPolys();
|
||||||
|
|
||||||
|
// STEP 5)
|
||||||
|
// Clean the polys - after this, we shouldn't change their shape (other than slightly for
|
||||||
|
// fix T-Junctions - as This is the end of the first pass for multicore design
|
||||||
|
CleanClippedPolys();
|
||||||
|
|
||||||
// STEP 5)
|
// STEP 5)
|
||||||
// Merge in Shared data (just add the nodes to the nodelist)
|
// Merge in Shared data (just add the nodes to the nodelist)
|
||||||
// When this step is complete, some nodes will have normals (from shared tiles)
|
// When this step is complete, some nodes will have normals (from shared tiles)
|
||||||
|
@ -1941,7 +2084,7 @@ void TGConstruct::ConstructBucket() {
|
||||||
// TODO : Needs to be part of clipping
|
// TODO : Needs to be part of clipping
|
||||||
// just before union : If we need to clean again after fixing tjunctions, make
|
// just before union : If we need to clean again after fixing tjunctions, make
|
||||||
// sure we don't alter the shape
|
// sure we don't alter the shape
|
||||||
clean_clipped_polys();
|
// CleanClippedPolys();
|
||||||
|
|
||||||
// STEP 7)
|
// STEP 7)
|
||||||
// Generate triangles - we can't generate the node-face lookup table
|
// Generate triangles - we can't generate the node-face lookup table
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/bucket/newbucket.hxx>
|
#include <simgear/bucket/newbucket.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
#include <Array/array.hxx>
|
#include <Array/array.hxx>
|
||||||
|
|
||||||
|
@ -51,6 +52,8 @@
|
||||||
#include "priorities.hxx"
|
#include "priorities.hxx"
|
||||||
|
|
||||||
#define USE_CLIPPER (0)
|
#define USE_CLIPPER (0)
|
||||||
|
#define FIND_SLIVERS (1)
|
||||||
|
#define USE_ACCUMULATOR (1)
|
||||||
|
|
||||||
class TGShape
|
class TGShape
|
||||||
{
|
{
|
||||||
|
@ -59,8 +62,14 @@ public:
|
||||||
bool textured;
|
bool textured;
|
||||||
superpoly_list sps;
|
superpoly_list sps;
|
||||||
texparams_list tps;
|
texparams_list tps;
|
||||||
|
AreaType area;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
|
|
||||||
|
void GetName( char* name ) const
|
||||||
|
{
|
||||||
|
sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id );
|
||||||
|
}
|
||||||
|
|
||||||
void SetMask( TGPolygon mask )
|
void SetMask( TGPolygon mask )
|
||||||
{
|
{
|
||||||
clip_mask = mask;
|
clip_mask = mask;
|
||||||
|
@ -84,17 +93,23 @@ public:
|
||||||
|
|
||||||
void IntersectPolys( void )
|
void IntersectPolys( void )
|
||||||
{
|
{
|
||||||
TGPolygon original, intersect;
|
if ( sps.size() > 1 ) {
|
||||||
|
TGPolygon original, intersect;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<sps.size(); i++)
|
||||||
|
{
|
||||||
|
original = sps[i].get_poly();
|
||||||
|
|
||||||
for (unsigned int i=0; i<sps.size(); i++)
|
|
||||||
{
|
|
||||||
original = sps[i].get_poly();
|
|
||||||
#ifdef USE_CLIPPER
|
#ifdef USE_CLIPPER
|
||||||
intersect = tgPolygonIntClipper( clip_mask, original );
|
intersect = tgPolygonIntClipper( clip_mask, original );
|
||||||
#else
|
#else
|
||||||
intersect = tgPolygonInt( clip_mask, original );
|
intersect = tgPolygonInt( clip_mask, original );
|
||||||
#endif
|
#endif
|
||||||
sps[i].set_poly( intersect );
|
|
||||||
|
sps[i].set_poly( intersect );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sps[0].set_poly( clip_mask );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -261,6 +276,8 @@ private:
|
||||||
// path to the debug shapes
|
// path to the debug shapes
|
||||||
std::string debug_path;
|
std::string debug_path;
|
||||||
|
|
||||||
|
bool debug_all;
|
||||||
|
|
||||||
// list of shapes to dump during debug
|
// list of shapes to dump during debug
|
||||||
std::vector<unsigned int> debug_shapes;
|
std::vector<unsigned int> debug_shapes;
|
||||||
|
|
||||||
|
@ -308,8 +325,8 @@ private:
|
||||||
void SaveSharedEdgeData( void );
|
void SaveSharedEdgeData( void );
|
||||||
|
|
||||||
// Polygon Cleaning
|
// Polygon Cleaning
|
||||||
|
void CleanClippedPolys( void );
|
||||||
void FixTJunctions( void );
|
void FixTJunctions( void );
|
||||||
void clean_clipped_polys( void );
|
|
||||||
|
|
||||||
// Tesselation
|
// Tesselation
|
||||||
void TesselatePolys( void );
|
void TesselatePolys( void );
|
||||||
|
@ -337,7 +354,9 @@ private:
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
bool IsDebugShape( unsigned int id );
|
bool IsDebugShape( unsigned int id );
|
||||||
void WriteDebugShape( const char* layer_name, unsigned int area, unsigned int shape );
|
void WriteDebugShape( const char* layer_name, const TGShape& shape );
|
||||||
|
void WriteDebugPoly( const char* layer_name, const char* name, const TGPolygon& poly );
|
||||||
|
void WriteDebugPolys( const char* layer_name, const poly_list& polys );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
|
|
|
@ -273,9 +273,6 @@ void TGMatch::load_neighbor_shared( SGBucket b, string work ) {
|
||||||
|
|
||||||
// try to load any missing shared data from our own shared data file
|
// try to load any missing shared data from our own shared data file
|
||||||
void TGMatch::load_missing_shared( SGBucket b, string work ) {
|
void TGMatch::load_missing_shared( SGBucket b, string work ) {
|
||||||
double clon = b.get_center_lon();
|
|
||||||
double clat = b.get_center_lat();
|
|
||||||
|
|
||||||
string base = work + "/Shared/";
|
string base = work + "/Shared/";
|
||||||
|
|
||||||
if ( !nw_flag ) {
|
if ( !nw_flag ) {
|
||||||
|
|
|
@ -142,6 +142,7 @@ public:
|
||||||
bool HasElevation() const; // does point have elevation data?
|
bool HasElevation() const; // does point have elevation data?
|
||||||
|
|
||||||
bool IsWithin( Point3D min, Point3D max ) const;
|
bool IsWithin( Point3D min, Point3D max ) const;
|
||||||
|
bool IsWithin( double xmin, double xmax, double ymin, double ymax ) const;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
double round(double d)
|
double round(double d)
|
||||||
|
@ -445,6 +446,12 @@ inline bool Point3D::IsWithin( Point3D min, Point3D max ) const
|
||||||
(max.n[PX] >= n[PX]) && (max.n[PY] >= n[PY]) );
|
(max.n[PX] >= n[PX]) && (max.n[PY] >= n[PY]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Point3D::IsWithin( double xmin, double xmax, double ymin, double ymax ) const
|
||||||
|
{
|
||||||
|
return ( (xmin <= n[PX]) && (ymin <= n[PY]) &&
|
||||||
|
(xmax >= n[PX]) && (ymax >= n[PY]) );
|
||||||
|
}
|
||||||
|
|
||||||
// FRIENDS
|
// FRIENDS
|
||||||
|
|
||||||
inline Point3D operator - (const Point3D& a)
|
inline Point3D operator - (const Point3D& a)
|
||||||
|
|
|
@ -34,33 +34,28 @@
|
||||||
// Divide segment if there are other existing points on it, return the
|
// Divide segment if there are other existing points on it, return the
|
||||||
// new polygon
|
// new polygon
|
||||||
void add_intermediate_nodes( int contour, const Point3D& start,
|
void add_intermediate_nodes( int contour, const Point3D& start,
|
||||||
const Point3D& end, point_list& tmp_nodes,
|
const Point3D& end, point_list& tmp_nodes,
|
||||||
TGPolygon *result )
|
TGPolygon *result,
|
||||||
|
const double bbEpsilon,
|
||||||
|
const double errEpsilon
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, " add_intermediate_nodes()");
|
|
||||||
char buf[200];
|
|
||||||
snprintf(buf, 199, " %.7f %.7f %.7f <=> %.7f %.7f %.7f\n",
|
|
||||||
start.x(), start.y(), start.z(), end.x(), end.y(), end.z() );
|
|
||||||
SG_LOG(SG_GENERAL, SG_BULK, buf);
|
|
||||||
|
|
||||||
|
|
||||||
Point3D new_pt;
|
Point3D new_pt;
|
||||||
bool found_extra = find_intermediate_node( start, end, tmp_nodes, &new_pt );
|
|
||||||
|
SG_LOG(SG_GENERAL, SG_BULK, " " << start << " <==> " << end );
|
||||||
|
|
||||||
|
bool found_extra = find_intermediate_node( start, end, tmp_nodes, &new_pt, bbEpsilon, errEpsilon );
|
||||||
|
|
||||||
if ( found_extra ) {
|
if ( found_extra ) {
|
||||||
// recurse with two sub segments
|
// recurse with two sub segments
|
||||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index]
|
// SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index]
|
||||||
// << " " << p1);
|
// << " " << p1);
|
||||||
add_intermediate_nodes( contour, start, new_pt, tmp_nodes,
|
add_intermediate_nodes( contour, start, new_pt, tmp_nodes, result, bbEpsilon, errEpsilon );
|
||||||
result );
|
|
||||||
|
|
||||||
result->add_node( contour, new_pt );
|
result->add_node( contour, new_pt );
|
||||||
SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt);
|
SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt);
|
||||||
|
|
||||||
add_intermediate_nodes( contour, new_pt, end, tmp_nodes,
|
add_intermediate_nodes( contour, new_pt, end, tmp_nodes, result, bbEpsilon, errEpsilon );
|
||||||
result );
|
|
||||||
} else {
|
|
||||||
// this segment does not need to be divided
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +83,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly,
|
||||||
result.add_node( i, p0 );
|
result.add_node( i, p0 );
|
||||||
|
|
||||||
// add intermediate points
|
// add intermediate points
|
||||||
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result );
|
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||||
|
|
||||||
// end of segment is beginning of next segment
|
// end of segment is beginning of next segment
|
||||||
}
|
}
|
||||||
|
@ -99,7 +94,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly,
|
||||||
result.add_node( i, p0 );
|
result.add_node( i, p0 );
|
||||||
|
|
||||||
// add intermediate points
|
// add intermediate points
|
||||||
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result );
|
add_intermediate_nodes( i, p0, p1, tmp_nodes, &result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||||
|
|
||||||
// end of segment is beginning of next segment
|
// end of segment is beginning of next segment
|
||||||
// 5/9/2000 CLO - this results in duplicating the last point
|
// 5/9/2000 CLO - this results in duplicating the last point
|
||||||
|
@ -135,7 +130,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly,
|
||||||
result.add_node( i, p0 );
|
result.add_node( i, p0 );
|
||||||
|
|
||||||
// add intermediate points
|
// add intermediate points
|
||||||
add_intermediate_nodes( i, p0, p1, poly_points, &result );
|
add_intermediate_nodes( i, p0, p1, poly_points, &result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||||
|
|
||||||
// end of segment is beginning of next segment
|
// end of segment is beginning of next segment
|
||||||
}
|
}
|
||||||
|
@ -146,7 +141,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly,
|
||||||
result.add_node( i, p0 );
|
result.add_node( i, p0 );
|
||||||
|
|
||||||
// add intermediate points
|
// add intermediate points
|
||||||
add_intermediate_nodes( i, p0, p1, poly_points, &result );
|
add_intermediate_nodes( i, p0, p1, poly_points, &result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||||
|
|
||||||
// maintain original hole flag setting
|
// maintain original hole flag setting
|
||||||
result.set_hole_flag( i, poly.get_hole_flag( i ) );
|
result.set_hole_flag( i, poly.get_hole_flag( i ) );
|
||||||
|
|
|
@ -37,8 +37,11 @@
|
||||||
// Divide segment if there are other existing points on it, return the
|
// Divide segment if there are other existing points on it, return the
|
||||||
// new polygon
|
// new polygon
|
||||||
void add_intermediate_nodes( int contour, const Point3D& start,
|
void add_intermediate_nodes( int contour, const Point3D& start,
|
||||||
const Point3D& end, const TGTriNodes& tmp_nodes,
|
const Point3D& end, const point_list& tmp_nodes,
|
||||||
TGPolygon *result );
|
TGPolygon *result,
|
||||||
|
const double bbEpsilon = SG_EPSILON*10,
|
||||||
|
const double errEpsilon = SG_EPSILON*4
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Search each segment for additional vertex points that may have been
|
// Search each segment for additional vertex points that may have been
|
||||||
|
|
|
@ -946,14 +946,16 @@ TGPolygon snap (const TGPolygon &poly, double grid_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static const double tgAirportEpsilon = SG_EPSILON / 10.0;
|
/* TODO : Verify this doesn't break genapt850 - may need an interface to
|
||||||
static const double tgAirportEpsilon = SG_EPSILON;
|
* specify bounding box and error values
|
||||||
|
*/
|
||||||
|
|
||||||
// Find a point in the given node list that lies between start and
|
// Find a point in the given node list that lies between start and
|
||||||
// end, return true if something found, false if nothing found.
|
// end, return true if something found, false if nothing found.
|
||||||
bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
const point_list& nodes, Point3D *result )
|
const point_list& nodes, Point3D *result,
|
||||||
|
double bbEpsilon, double errEpsilon
|
||||||
|
)
|
||||||
{
|
{
|
||||||
bool found_node = false;
|
bool found_node = false;
|
||||||
double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min;
|
double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min;
|
||||||
|
@ -991,8 +993,8 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
// cout << i << endl;
|
// cout << i << endl;
|
||||||
Point3D current = nodes[i];
|
Point3D current = nodes[i];
|
||||||
|
|
||||||
if ( (current.x() > (p_min.x() + (SG_EPSILON)))
|
if ( (current.x() > (p_min.x() + (bbEpsilon)))
|
||||||
&& (current.x() < (p_max.x() - (SG_EPSILON))) ) {
|
&& (current.x() < (p_max.x() - (bbEpsilon))) ) {
|
||||||
|
|
||||||
// printf( "found a potential candidate %.7f %.7f %.7f\n",
|
// printf( "found a potential candidate %.7f %.7f %.7f\n",
|
||||||
// current.x(), current.y(), current.z() );
|
// current.x(), current.y(), current.z() );
|
||||||
|
@ -1000,7 +1002,7 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
y_err = fabs(current.y() - (m * current.x() + b));
|
y_err = fabs(current.y() - (m * current.x() + b));
|
||||||
// cout << "y_err = " << y_err << endl;
|
// cout << "y_err = " << y_err << endl;
|
||||||
|
|
||||||
if ( y_err < tgAirportEpsilon ) {
|
if ( y_err < errEpsilon ) {
|
||||||
// cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
|
// cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
|
||||||
// cout << p_min << " < " << current << " < "
|
// cout << p_min << " < " << current << " < "
|
||||||
// << p_max << endl;
|
// << p_max << endl;
|
||||||
|
@ -1039,8 +1041,8 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
for ( int i = 0; i < (int)nodes.size(); ++i ) {
|
for ( int i = 0; i < (int)nodes.size(); ++i ) {
|
||||||
Point3D current = nodes[i];
|
Point3D current = nodes[i];
|
||||||
|
|
||||||
if ( (current.y() > (p_min.y() + (SG_EPSILON)))
|
if ( (current.y() > (p_min.y() + (bbEpsilon)))
|
||||||
&& (current.y() < (p_max.y() - (SG_EPSILON))) ) {
|
&& (current.y() < (p_max.y() - (bbEpsilon))) ) {
|
||||||
|
|
||||||
// printf( "found a potential candidate %.7f %.7f %.7f\n",
|
// printf( "found a potential candidate %.7f %.7f %.7f\n",
|
||||||
// current.x(), current.y(), current.z() );
|
// current.x(), current.y(), current.z() );
|
||||||
|
@ -1052,7 +1054,7 @@ bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
// cout << " (" << counter << ") x_err = " << x_err << endl;
|
// cout << " (" << counter << ") x_err = " << x_err << endl;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if ( x_err < tgAirportEpsilon ) {
|
if ( x_err < errEpsilon ) {
|
||||||
// cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
|
// cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
|
||||||
// cout << p_min << " < " << current << " < "
|
// cout << p_min << " < " << current << " < "
|
||||||
// << p_max << endl;
|
// << p_max << endl;
|
||||||
|
@ -1550,7 +1552,7 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) {
|
||||||
return (void*)layer;
|
return (void*)layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description )
|
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* description, bool has_pt_inside )
|
||||||
{
|
{
|
||||||
OGRLayer* layer = (OGRLayer*)l_id;
|
OGRLayer* layer = (OGRLayer*)l_id;
|
||||||
OGRPolygon* polygon = new OGRPolygon();
|
OGRPolygon* polygon = new OGRPolygon();
|
||||||
|
@ -1591,6 +1593,26 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile");
|
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile");
|
||||||
}
|
}
|
||||||
OGRFeature::DestroyFeature(feature);
|
OGRFeature::DestroyFeature(feature);
|
||||||
|
|
||||||
|
// TEST TEST TEST : Add the point inside - see if we can see it in QGIS
|
||||||
|
if ( has_pt_inside ) {
|
||||||
|
OGRPoint *point=new OGRPoint();
|
||||||
|
|
||||||
|
point->setX( poly.get_point_inside( i ).x() );
|
||||||
|
point->setY( poly.get_point_inside( i ).y() );
|
||||||
|
point->setZ( 0.0 );
|
||||||
|
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "DEBUG: SET POINT INSIDE " << description << " contour " << i << " is " << poly.get_point_inside( i ) );
|
||||||
|
|
||||||
|
feature = new OGRFeature( layer->GetLayerDefn() );
|
||||||
|
feature->SetField("ID", description);
|
||||||
|
feature->SetGeometry(point);
|
||||||
|
if( layer->CreateFeature( feature ) != OGRERR_NONE )
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile");
|
||||||
|
}
|
||||||
|
OGRFeature::DestroyFeature(feature);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,10 @@ TGPolygon remove_spikes( const TGPolygon& poly );
|
||||||
// Find a point in the given node list that lies between start and
|
// Find a point in the given node list that lies between start and
|
||||||
// end, return true if something found, false if nothing found.
|
// end, return true if something found, false if nothing found.
|
||||||
bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
bool find_intermediate_node( const Point3D& start, const Point3D& end,
|
||||||
const point_list& nodes, Point3D *result );
|
const point_list& nodes, Point3D *result,
|
||||||
|
const double bbEpsilon = SG_EPSILON*10,
|
||||||
|
const double errEpsilon = SG_EPSILON*4
|
||||||
|
);
|
||||||
|
|
||||||
// remove any degenerate contours
|
// remove any degenerate contours
|
||||||
TGPolygon remove_bad_contours( const TGPolygon &poly );
|
TGPolygon remove_bad_contours( const TGPolygon &poly );
|
||||||
|
@ -114,7 +117,7 @@ TGPolygon remove_small_contours( const TGPolygon &poly );
|
||||||
void tgShapefileInit( void );
|
void tgShapefileInit( void );
|
||||||
void* tgShapefileOpenDatasource( const char* datasource_name );
|
void* tgShapefileOpenDatasource( const char* datasource_name );
|
||||||
void* tgShapefileOpenLayer( void* ds_id, const char* layer_name );
|
void* tgShapefileOpenLayer( void* ds_id, const char* layer_name );
|
||||||
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* feature_name );
|
void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, const char* feature_name, bool has_point_inside = false );
|
||||||
void tgShapefileCloseLayer( void* l_id );
|
void tgShapefileCloseLayer( void* l_id );
|
||||||
void* tgShapefileCloseDatasource( void* ds_id );
|
void* tgShapefileCloseDatasource( void* ds_id );
|
||||||
|
|
||||||
|
|
|
@ -359,6 +359,8 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers )
|
||||||
in.delete_contour( i );
|
in.delete_contour( i );
|
||||||
} else {
|
} else {
|
||||||
// move sliver contour to out polygon
|
// move sliver contour to out polygon
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, " Found SLIVER!");
|
||||||
|
|
||||||
contour = in.get_contour( i );
|
contour = in.get_contour( i );
|
||||||
in.delete_contour( i );
|
in.delete_contour( i );
|
||||||
out.add_contour( contour, hole_flag );
|
out.add_contour( contour, hole_flag );
|
||||||
|
@ -703,6 +705,80 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Accumulator optimization ( to keep from massive data copies and format changes
|
||||||
|
gpc_polygon *gpc_accumulator = NULL;
|
||||||
|
|
||||||
|
void tgPolygonInitAccumulator( void )
|
||||||
|
{
|
||||||
|
gpc_accumulator = new gpc_polygon;
|
||||||
|
gpc_accumulator->num_contours = 0;
|
||||||
|
gpc_accumulator->contour = NULL;
|
||||||
|
gpc_accumulator->hole = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tgPolygonFreeAccumulator( void )
|
||||||
|
{
|
||||||
|
gpc_free_polygon( gpc_accumulator );
|
||||||
|
delete gpc_accumulator;
|
||||||
|
gpc_accumulator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tgPolygonAddToAccumulator( const TGPolygon& subject )
|
||||||
|
{
|
||||||
|
gpc_polygon *gpc_subject = new gpc_polygon;
|
||||||
|
gpc_subject->num_contours = 0;
|
||||||
|
gpc_subject->contour = NULL;
|
||||||
|
gpc_subject->hole = NULL;
|
||||||
|
make_gpc_poly( subject, gpc_subject );
|
||||||
|
|
||||||
|
gpc_polygon *gpc_result = new gpc_polygon;
|
||||||
|
gpc_result->num_contours = 0;
|
||||||
|
gpc_result->contour = NULL;
|
||||||
|
gpc_result->hole = NULL;
|
||||||
|
|
||||||
|
gpc_polygon_clip( GPC_UNION, gpc_subject, gpc_accumulator, gpc_result );
|
||||||
|
|
||||||
|
// free allocated memory
|
||||||
|
gpc_free_polygon( gpc_subject );
|
||||||
|
delete gpc_subject;
|
||||||
|
|
||||||
|
// throw away old accumulator : and use result for now on
|
||||||
|
gpc_free_polygon( gpc_accumulator );
|
||||||
|
delete gpc_accumulator;
|
||||||
|
gpc_accumulator = gpc_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject )
|
||||||
|
{
|
||||||
|
TGPolygon result;
|
||||||
|
|
||||||
|
gpc_polygon *gpc_subject = new gpc_polygon;
|
||||||
|
gpc_subject->num_contours = 0;
|
||||||
|
gpc_subject->contour = NULL;
|
||||||
|
gpc_subject->hole = NULL;
|
||||||
|
make_gpc_poly( subject, gpc_subject );
|
||||||
|
|
||||||
|
gpc_polygon *gpc_result = new gpc_polygon;
|
||||||
|
gpc_result->num_contours = 0;
|
||||||
|
gpc_result->contour = NULL;
|
||||||
|
gpc_result->hole = NULL;
|
||||||
|
|
||||||
|
gpc_polygon_clip( GPC_DIFF, gpc_subject, gpc_accumulator, gpc_result );
|
||||||
|
make_tg_poly( gpc_result, &result );
|
||||||
|
|
||||||
|
// free allocated memory
|
||||||
|
gpc_free_polygon( gpc_subject );
|
||||||
|
delete gpc_subject;
|
||||||
|
|
||||||
|
gpc_free_polygon( gpc_result );
|
||||||
|
delete gpc_result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Difference
|
// Difference
|
||||||
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||||
return polygon_clip( POLY_DIFF, subject, clip );
|
return polygon_clip( POLY_DIFF, subject, clip );
|
||||||
|
|
|
@ -256,6 +256,12 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers );
|
||||||
|
|
||||||
// wrapper functions for gpc polygon clip routines
|
// wrapper functions for gpc polygon clip routines
|
||||||
|
|
||||||
|
void tgPolygonInitAccumulator( void );
|
||||||
|
void tgPolygonFreeAccumulator( void );
|
||||||
|
void tgPolygonAddToAccumulator( const TGPolygon& subject );
|
||||||
|
TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject );
|
||||||
|
|
||||||
|
|
||||||
// Difference
|
// Difference
|
||||||
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );
|
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue