1
0
Fork 0

- 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:
Peter Sadrozinski 2012-08-19 19:49:12 -04:00 committed by Christian Schmitt
parent 79bdae93fc
commit 346ae44e14
10 changed files with 361 additions and 90 deletions

View file

@ -72,6 +72,7 @@ TGConstruct::TGConstruct():
useUKGrid(false),
writeSharedEdges(true),
useOwnSharedEdges(false),
debug_all(false),
ds_id((void*)-1)
{ }
@ -102,6 +103,10 @@ void TGConstruct::set_debug( std::string path, std::vector<string> defs )
if( tile == bucket.gen_index_str() ) {
dsd.erase(0, d_pos+1);
if ( dsd == "all" ) {
debug_all = true;
} else {
std::stringstream ss(dsd);
int i;
@ -116,31 +121,62 @@ void TGConstruct::set_debug( std::string path, std::vector<string> defs )
}
}
}
}
}
bool TGConstruct::IsDebugShape( unsigned int id )
{
bool is_debug = false;
/* Check global flag */
if ( debug_all ) {
is_debug = true;
} else {
for (unsigned int i=0; i<debug_shapes.size(); i++) {
SG_LOG(SG_GENERAL, SG_ALERT, "have debug id " << debug_shapes[i] << " looking for " << id );
if ( debug_shapes[i] == id ) {
is_debug = true;
break;
}
}
}
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 );
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, polys_in.get_mask(area, shape), feature_name );
tgShapefileCreateFeature( ds_id, l_id, poly, 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
ds_id = tgShapefileCloseDatasource( ds_id );
@ -383,8 +419,8 @@ bool TGConstruct::load_poly(const string& path) {
sp.set_poly( poly );
sp.set_material( material );
shape.sps.push_back( sp );
if ( with_tp ) {
shape.textured = true;
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
shape.BuildMask();
shape.area = area;
shape.id = cur_id++;
polys_in.add_shape( area, shape );
if ( IsDebugShape( shape.id ) ) {
WriteDebugShape( "loaded", shape );
}
}
return true;
@ -1172,6 +1213,8 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, poly_list& slivers_list
int original_contours, result_contours;
bool done;
int area, shape, segment, i, j;
int merged = 0;
int total = 0;
for ( i = 0; i < (int)slivers_list.size(); 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 ) {
// make the sliver polygon
contour = slivers.get_contour( j );
total++;
sliver.erase();
sliver.add_contour( contour, 0 );
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 ) {
unsigned int shape_id = clipped.get_shape( area, shape ).id;
for ( segment = 0; segment < (int)clipped.shape_size(area, shape) && !done; ++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();
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 );
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;
}
}
@ -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 ) {
TGPolygon accum, clipped, tmp;
TGPolygon clipped, tmp;
TGPolygon remains;
TGPolygon safety_base;
poly_list slivers;
@ -1221,13 +1289,21 @@ bool TGConstruct::ClipLandclassPolys( void ) {
Point3D p;
point2d min, max;
#if !USE_ACCUMULATOR
TGPolygon accum;
#endif
// Get clip bounds
min.x = bucket.get_center_lon() - 0.5 * bucket.get_width();
min.y = bucket.get_center_lat() - 0.5 * bucket.get_height();
max.x = bucket.get_center_lon() + 0.5 * bucket.get_width();
max.y = bucket.get_center_lat() + 0.5 * bucket.get_height();
#if USE_ACCUMULATOR
tgPolygonInitAccumulator();
#else
accum.erase();
#endif
// set up clipping tile : and remember to add the nodes!
safety_base.erase();
@ -1318,19 +1394,28 @@ bool TGConstruct::ClipLandclassPolys( void ) {
#if USE_CLIPPER
clipped = tgPolygonDiffClipper( tmp, accum );
#else
#if USE_ACCUMULATOR
clipped = tgPolygonDiffWithAccumulator( tmp );
#else
clipped = tgPolygonDiff( tmp, accum );
#endif
#endif
// only add to output list if the clip left us with a polygon
if ( clipped.contours() > 0 ) {
#if FIND_SLIVERS
// move slivers from clipped polygon to slivers polygon
tgPolygonFindSlivers( clipped, slivers );
#endif
// add the sliverless result polygon to the clipped polys list
if ( clipped.contours() > 0 ) {
TGShape shape;
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
shape.SetMask( clipped );
@ -1339,47 +1424,81 @@ bool TGConstruct::ClipLandclassPolys( void ) {
shape.sps = polys_in.get_shape( i, j ).sps;
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 );
if ( IsDebugShape( shape.id ) ) {
WriteDebugShape( "clipped", shape );
}
}
}
#if USE_CLIPPER
accum = tgPolygonUnionClipper( tmp, accum );
// accum = tgPolygonUnionClipper( clipped, accum );
#else
#if USE_ACCUMULATOR
tgPolygonAddToAccumulator( tmp );
// tgPolygonAddToAccumulator( clipped );
#else
accum = tgPolygonUnion( tmp, accum );
// accum = tgPolygonUnion( clipped, accum );
#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
merge_slivers(polys_clipped, slivers);
#endif
slivers.clear();
// 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
remains = tgPolygonDiffClipper( safety_base, accum );
#else
#if USE_ACCUMULATOR
remains = tgPolygonDiffWithAccumulator( safety_base );
#else
remains = tgPolygonDiff( safety_base, accum );
#endif
#endif
if ( remains.contours() > 0 ) {
// cout << "remains contours = " << remains.contours() << endl;
// move slivers from remains polygon to slivers polygon
#if FIND_SLIVERS
tgPolygonFindSlivers( remains, slivers );
#endif
// cout << " After sliver move:" << endl;
// cout << " remains = " << remains.contours() << endl;
// cout << " slivers = " << slivers.contours() << endl;
#if FIND_SLIVERS
// merge any slivers with previously clipped
// neighboring polygons
if ( slivers.size() > 0 ) {
if ( debug_all || debug_shapes.size() ) {
// Dump the sliver list
WriteDebugPolys( "remains_slivers", slivers );
}
merge_slivers(polys_clipped, slivers);
}
#endif
if ( remains.contours() > 0 ) {
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
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
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;
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++ ) {
@ -1834,16 +1957,20 @@ void TGConstruct::WriteBtgFile( void )
}
}
void TGConstruct::clean_clipped_polys() {
void TGConstruct::CleanClippedPolys() {
// Clean the polys
unsigned int before, after;
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
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++ ) {
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_dups( poly );
poly = remove_bad_contours( poly );
@ -1859,8 +1986,19 @@ void TGConstruct::clean_clipped_polys() {
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 );
}
if ( IsDebugShape( id ) ) {
WriteDebugShape( "cleaned", polys_clipped.get_shape( area, shape ) );
}
}
}
}
@ -1899,7 +2037,7 @@ void TGConstruct::CalcTextureCoordinates( void )
void TGConstruct::ConstructBucket() {
/* 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() );
}
@ -1927,6 +2065,11 @@ void TGConstruct::ConstructBucket() {
// Clip the Landclass polygons
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)
// Merge in Shared data (just add the nodes to the nodelist)
// 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
// just before union : If we need to clean again after fixing tjunctions, make
// sure we don't alter the shape
clean_clipped_polys();
// CleanClippedPolys();
// STEP 7)
// Generate triangles - we can't generate the node-face lookup table

View file

@ -39,6 +39,7 @@
#include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <Array/array.hxx>
@ -51,6 +52,8 @@
#include "priorities.hxx"
#define USE_CLIPPER (0)
#define FIND_SLIVERS (1)
#define USE_ACCUMULATOR (1)
class TGShape
{
@ -59,8 +62,14 @@ public:
bool textured;
superpoly_list sps;
texparams_list tps;
AreaType area;
unsigned int id;
void GetName( char* name ) const
{
sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id );
}
void SetMask( TGPolygon mask )
{
clip_mask = mask;
@ -84,18 +93,24 @@ public:
void IntersectPolys( void )
{
if ( sps.size() > 1 ) {
TGPolygon original, intersect;
for (unsigned int i=0; i<sps.size(); i++)
{
original = sps[i].get_poly();
#ifdef USE_CLIPPER
intersect = tgPolygonIntClipper( clip_mask, original );
#else
intersect = tgPolygonInt( clip_mask, original );
#endif
sps[i].set_poly( intersect );
}
} else {
sps[0].set_poly( clip_mask );
}
}
};
@ -261,6 +276,8 @@ private:
// path to the debug shapes
std::string debug_path;
bool debug_all;
// list of shapes to dump during debug
std::vector<unsigned int> debug_shapes;
@ -308,8 +325,8 @@ private:
void SaveSharedEdgeData( void );
// Polygon Cleaning
void CleanClippedPolys( void );
void FixTJunctions( void );
void clean_clipped_polys( void );
// Tesselation
void TesselatePolys( void );
@ -337,7 +354,9 @@ private:
// debug
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:
// Constructor

View file

@ -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
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/";
if ( !nw_flag ) {

View file

@ -142,6 +142,7 @@ public:
bool HasElevation() const; // does point have elevation data?
bool IsWithin( Point3D min, Point3D max ) const;
bool IsWithin( double xmin, double xmax, double ymin, double ymax ) const;
#ifdef _MSC_VER
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]) );
}
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
inline Point3D operator - (const Point3D& a)

View file

@ -35,32 +35,27 @@
// new polygon
void add_intermediate_nodes( int contour, const Point3D& start,
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;
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 ) {
// recurse with two sub segments
// SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << p0 << " " << nodes[extra_index]
// << " " << p1);
add_intermediate_nodes( contour, start, new_pt, tmp_nodes,
result );
add_intermediate_nodes( contour, start, new_pt, tmp_nodes, result, bbEpsilon, errEpsilon );
result->add_node( contour, new_pt );
SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt);
add_intermediate_nodes( contour, new_pt, end, tmp_nodes,
result );
} else {
// this segment does not need to be divided
add_intermediate_nodes( contour, new_pt, end, tmp_nodes, result, bbEpsilon, errEpsilon );
}
}
@ -88,7 +83,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly,
result.add_node( i, p0 );
// 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
}
@ -99,7 +94,7 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly,
result.add_node( i, p0 );
// 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
// 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 );
// 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
}
@ -146,7 +141,7 @@ TGPolygon add_tgnodes_to_poly( const TGPolygon& poly,
result.add_node( i, p0 );
// 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
result.set_hole_flag( i, poly.get_hole_flag( i ) );

View file

@ -37,8 +37,11 @@
// Divide segment if there are other existing points on it, return the
// new polygon
void add_intermediate_nodes( int contour, const Point3D& start,
const Point3D& end, const TGTriNodes& tmp_nodes,
TGPolygon *result );
const Point3D& end, const point_list& tmp_nodes,
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

View file

@ -946,14 +946,16 @@ TGPolygon snap (const TGPolygon &poly, double grid_size)
}
// static const double tgAirportEpsilon = SG_EPSILON / 10.0;
static const double tgAirportEpsilon = SG_EPSILON;
/* TODO : Verify this doesn't break genapt850 - may need an interface to
* specify bounding box and error values
*/
// Find a point in the given node list that lies between start and
// end, return true if something found, false if nothing found.
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;
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;
Point3D current = nodes[i];
if ( (current.x() > (p_min.x() + (SG_EPSILON)))
&& (current.x() < (p_max.x() - (SG_EPSILON))) ) {
if ( (current.x() > (p_min.x() + (bbEpsilon)))
&& (current.x() < (p_max.x() - (bbEpsilon))) ) {
// printf( "found a potential candidate %.7f %.7f %.7f\n",
// 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));
// cout << "y_err = " << y_err << endl;
if ( y_err < tgAirportEpsilon ) {
if ( y_err < errEpsilon ) {
// cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
// cout << p_min << " < " << current << " < "
// << 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 ) {
Point3D current = nodes[i];
if ( (current.y() > (p_min.y() + (SG_EPSILON)))
&& (current.y() < (p_max.y() - (SG_EPSILON))) ) {
if ( (current.y() > (p_min.y() + (bbEpsilon)))
&& (current.y() < (p_max.y() - (bbEpsilon))) ) {
// printf( "found a potential candidate %.7f %.7f %.7f\n",
// 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;
// }
if ( x_err < tgAirportEpsilon ) {
if ( x_err < errEpsilon ) {
// cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
// cout << p_min << " < " << current << " < "
// << p_max << endl;
@ -1550,7 +1552,7 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) {
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;
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");
}
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);
}
}
}

View file

@ -100,7 +100,10 @@ TGPolygon remove_spikes( const TGPolygon& poly );
// Find a point in the given node list that lies between start and
// end, return true if something found, false if nothing found.
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
TGPolygon remove_bad_contours( const TGPolygon &poly );
@ -114,7 +117,7 @@ TGPolygon remove_small_contours( const TGPolygon &poly );
void tgShapefileInit( void );
void* tgShapefileOpenDatasource( const char* datasource_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* tgShapefileCloseDatasource( void* ds_id );

View file

@ -359,6 +359,8 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers )
in.delete_contour( i );
} else {
// move sliver contour to out polygon
SG_LOG(SG_GENERAL, SG_INFO, " Found SLIVER!");
contour = in.get_contour( i );
in.delete_contour( i );
out.add_contour( contour, hole_flag );
@ -703,6 +705,80 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
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
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip ) {
return polygon_clip( POLY_DIFF, subject, clip );

View file

@ -256,6 +256,12 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers );
// wrapper functions for gpc polygon clip routines
void tgPolygonInitAccumulator( void );
void tgPolygonFreeAccumulator( void );
void tgPolygonAddToAccumulator( const TGPolygon& subject );
TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject );
// Difference
TGPolygon tgPolygonDiff( const TGPolygon& subject, const TGPolygon& clip );