Some fixes
- genapt850 : some airports (LSMM) have multiple airport boundaries. This caused a lot of the airport to not get a smoothed base (so some landclass polys were not clipped against the airport). Changed boundary from a single ClosedPolygon to a list. Seems to work. Some misc warnings cleanup in scheduler, and parser - Clipper using accumulator results in a significant speed boots - enable clipper and the accumulator by default. - ogr-decode - most of the crashes I'm getting are due to non-continuous roads. Within a line string, I create adjacent polys that snap correctly. On the ends, I generate 90 degree angles. Some linestrings should be consecutive. As a workaround, I am now extending every start and end poly of linestrings by 0.1 meters. It makes it better, but I need to do a better job of creating continuous roads. This will require some preprocessing of the entire shapefile. (Perhaps all line data shapefiles, to handle correct overpass / underpass logic)
This commit is contained in:
parent
346ae44e14
commit
c1de74f4fa
12 changed files with 206 additions and 75 deletions
|
@ -85,7 +85,6 @@ Airport::Airport( int c, char* def)
|
|||
}
|
||||
|
||||
altitude *= SG_FEET_TO_METER;
|
||||
boundary = NULL;
|
||||
|
||||
dbg_rwy_poly = 0;
|
||||
dbg_pvmt_poly = 0;
|
||||
|
@ -149,9 +148,9 @@ Airport::~Airport()
|
|||
delete signs[i];
|
||||
}
|
||||
|
||||
if (boundary)
|
||||
for (unsigned int i=0; i<boundary.size(); i++)
|
||||
{
|
||||
delete boundary;
|
||||
delete boundary[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,7 +635,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
make_shapefiles = false;
|
||||
}
|
||||
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
runways[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, NULL, NULL, make_shapefiles );
|
||||
}
|
||||
|
@ -670,7 +669,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
SG_LOG(SG_GENERAL, SG_INFO, "Build helipad " << i + 1 << " of " << helipads.size());
|
||||
slivers.clear();
|
||||
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
helipads[i]->BuildBtg( &rwy_polys, &rwy_tps, &rwy_lights, &accum, slivers, NULL, NULL );
|
||||
}
|
||||
|
@ -700,7 +699,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
make_shapefiles = false;
|
||||
}
|
||||
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
pavements[i]->BuildBtg( &pvmt_polys, &pvmt_tps, &accum, slivers, NULL, NULL, make_shapefiles );
|
||||
}
|
||||
|
@ -738,7 +737,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
make_shapefiles = false;
|
||||
}
|
||||
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
taxiways[i]->BuildBtg( &pvmt_polys, &pvmt_tps, &rwy_lights, &accum, slivers, NULL, NULL, make_shapefiles );
|
||||
}
|
||||
|
@ -767,7 +766,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
slivers.clear();
|
||||
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
runways[i]->BuildShoulder( &rwy_polys, &rwy_tps, &accum, slivers, NULL, NULL );
|
||||
}
|
||||
|
@ -807,10 +806,13 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
}
|
||||
|
||||
// build the base and clearing if there's a boundary
|
||||
if (boundary)
|
||||
if (boundary.size())
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Build user defined boundary " );
|
||||
boundary->BuildBtg( &apt_base, &apt_clearing, false );
|
||||
for ( unsigned int i=0; i<boundary.size(); i++ )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Build Userdefined boundary " << i + 1 << " of " << boundary.size());
|
||||
boundary[i]->BuildBtg( &apt_base, &apt_clearing, false );
|
||||
}
|
||||
}
|
||||
|
||||
if ( apt_base.total_size() == 0 )
|
||||
|
|
|
@ -70,9 +70,9 @@ public:
|
|||
return features.size();
|
||||
}
|
||||
|
||||
void SetBoundary( ClosedPoly* bndry )
|
||||
void AddBoundary( ClosedPoly* bndry )
|
||||
{
|
||||
boundary = bndry;
|
||||
boundary.push_back( bndry );
|
||||
}
|
||||
|
||||
void AddWindsock( Windsock* windsock )
|
||||
|
@ -132,7 +132,7 @@ private:
|
|||
BeaconList beacons;
|
||||
SignList signs;
|
||||
HelipadList helipads;
|
||||
ClosedPoly* boundary;
|
||||
PavementList boundary;
|
||||
|
||||
// stats
|
||||
SGTimeStamp build_time;
|
||||
|
|
|
@ -546,7 +546,7 @@ int ClosedPoly::BuildBtg( TGPolygon* apt_base, TGPolygon* apt_clearing, bool mak
|
|||
TGPolygon base, safe_base;
|
||||
|
||||
// verify the poly has been generated
|
||||
if ( pre_tess.contours() )
|
||||
if ( pre_tess.contours() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "BuildBtg: original poly has " << pre_tess.contours() << " contours");
|
||||
|
||||
|
|
|
@ -357,7 +357,7 @@ int Parser::SetState( int state )
|
|||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Closing and Adding boundary");
|
||||
cur_boundary->Finish();
|
||||
cur_airport->SetBoundary( cur_boundary );
|
||||
cur_airport->AddBoundary( cur_boundary );
|
||||
cur_boundary = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -301,7 +301,7 @@ void ProcessList::HandleFinished( void )
|
|||
for ( unsigned int i=0; i< plist.size(); i++ ) {
|
||||
switch ( plist[i].GetState() ) {
|
||||
case P_STATE_DONE:
|
||||
plist[i].SetErrorString( "success" );
|
||||
plist[i].SetErrorString( (char *)"success" );
|
||||
|
||||
// holding the list lock - only one thread can write to the csvfile at a time
|
||||
csvfile << plist[i].GetInfo() << "\n";
|
||||
|
|
|
@ -154,7 +154,7 @@ private:
|
|||
ProcessInfoList plist;
|
||||
Net::ServerSocket* pss;
|
||||
int state;
|
||||
int threads;
|
||||
unsigned int threads;
|
||||
ofstream csvfile;
|
||||
Scheduler* scheduler;
|
||||
};
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
|
||||
using std::string;
|
||||
|
||||
double gSnap = 0.00000001; // approx 1 mm
|
||||
//double gSnap = 0.00000001; // approx 1 mm
|
||||
double gSnap = 0.0000001; // approx 1 cm
|
||||
|
||||
static const double cover_size = 1.0 / 120.0;
|
||||
static const double half_cover_size = cover_size * 0.5;
|
||||
|
@ -146,12 +147,12 @@ bool TGConstruct::IsDebugShape( unsigned int id )
|
|||
void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
|
||||
{
|
||||
char name[64];
|
||||
|
||||
shape.GetName( name );
|
||||
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
shape.GetName( name );
|
||||
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, name );
|
||||
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, "test" );
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
|
@ -1236,7 +1237,7 @@ 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 );
|
||||
|
@ -1300,7 +1301,13 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
max.y = bucket.get_center_lat() + 0.5 * bucket.get_height();
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonInitAccumulator();
|
||||
|
||||
#if USE_CLIPPER
|
||||
tgPolygonInitClipperAccumulator();
|
||||
#else
|
||||
tgPolygonInitGPCAccumulator();
|
||||
#endif
|
||||
|
||||
#else
|
||||
accum.erase();
|
||||
#endif
|
||||
|
@ -1344,6 +1351,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
#endif
|
||||
|
||||
}
|
||||
|
||||
} else if ( is_water_area( i ) ) {
|
||||
for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
|
||||
#if USE_CLIPPER
|
||||
|
@ -1363,6 +1371,13 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Dump the masks
|
||||
if ( debug_all || debug_shapes.size() ) {
|
||||
WriteDebugPoly( "land_mask", "", land_mask );
|
||||
WriteDebugPoly( "water_mask", "", water_mask );
|
||||
WriteDebugPoly( "island_mask", "", island_mask );
|
||||
}
|
||||
|
||||
// process polygons in priority order
|
||||
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
||||
for( j = 0; j < (int)polys_in.area_size(i); ++j ) {
|
||||
|
@ -1391,8 +1406,20 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
if ( IsDebugShape( polys_in.get_shape( i, j ).id ) ) {
|
||||
char name[32];
|
||||
sprintf(name, "shape %d,%d", i,j);
|
||||
WriteDebugPoly( "pre-clip", name, tmp );
|
||||
}
|
||||
|
||||
#if USE_CLIPPER
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
clipped = tgPolygonDiffClipperWithAccumulator( tmp );
|
||||
#else
|
||||
clipped = tgPolygonDiffClipper( tmp, accum );
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
|
@ -1402,6 +1429,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// only add to output list if the clip left us with a polygon
|
||||
if ( clipped.contours() > 0 ) {
|
||||
|
||||
|
@ -1413,14 +1441,13 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
// 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 ) );
|
||||
|
||||
// copy all of the superpolys and texparams
|
||||
shape.SetMask( clipped );
|
||||
shape.textured = polys_in.get_textured( i, j );
|
||||
shape.id = polys_in.get_shape( i, j ).id;
|
||||
|
||||
shape.area= polys_in.get_shape( i, j ).area;
|
||||
shape.sps = polys_in.get_shape( i, j ).sps;
|
||||
shape.tps = polys_in.get_shape( i, j ).tps;
|
||||
|
||||
|
@ -1431,19 +1458,22 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
WriteDebugShape( "clipped", shape );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_CLIPPER
|
||||
accum = tgPolygonUnionClipper( tmp, accum );
|
||||
// accum = tgPolygonUnionClipper( clipped, accum );
|
||||
#else
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonAddToClipperAccumulator( tmp );
|
||||
#else
|
||||
accum = tgPolygonUnionClipper( tmp, accum );
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonAddToAccumulator( tmp );
|
||||
// tgPolygonAddToAccumulator( clipped );
|
||||
#else
|
||||
accum = tgPolygonUnion( tmp, accum );
|
||||
// accum = tgPolygonUnion( clipped, accum );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1461,10 +1491,16 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
#endif
|
||||
|
||||
slivers.clear();
|
||||
|
||||
|
||||
// finally, what ever is left over goes to ocean
|
||||
#if USE_CLIPPER
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
remains = tgPolygonDiffClipperWithAccumulator( safety_base );
|
||||
#else
|
||||
remains = tgPolygonDiffClipper( safety_base, accum );
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
|
@ -1516,8 +1552,14 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
}
|
||||
|
||||
#if USE_ACCUMULATOR
|
||||
tgPolygonFreeAccumulator();
|
||||
#endif
|
||||
|
||||
#if USE_CLIPPER
|
||||
tgPolygonFreeClipperAccumulator();
|
||||
#else
|
||||
tgPolygonFreeGPCAccumulator();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Once clipping is complete, intersect the individual segments with their clip masks
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
|
@ -1723,11 +1765,13 @@ void TGConstruct::CalcFaceNormals( void )
|
|||
void TGConstruct::CalcPointNormals( void )
|
||||
{
|
||||
// traverse triangle structure building the face normal table
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals: 0%");
|
||||
|
||||
Point3D normal;
|
||||
point_list wgs84_nodes = nodes.get_wgs84_nodes_as_Point3d();
|
||||
|
||||
unsigned int ten_percent = nodes.size() / 10;
|
||||
unsigned int cur_percent = 10;
|
||||
|
||||
for ( unsigned int i = 0; i<nodes.size(); i++ ) {
|
||||
TGNode node = nodes.get_node( i );
|
||||
TGFaceList faces = node.GetFaces();
|
||||
|
@ -1735,6 +1779,12 @@ void TGConstruct::CalcPointNormals( void )
|
|||
|
||||
Point3D average( 0.0 );
|
||||
|
||||
if ( i == ten_percent ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals: " << cur_percent << "%" );
|
||||
ten_percent += nodes.size() / 10;
|
||||
cur_percent += 10;
|
||||
}
|
||||
|
||||
// for each triangle that shares this node
|
||||
for ( unsigned int j = 0; j < faces.size(); ++j ) {
|
||||
unsigned int at = faces[j].area;
|
||||
|
@ -1958,47 +2008,55 @@ void TGConstruct::WriteBtgFile( void )
|
|||
}
|
||||
|
||||
void TGConstruct::CleanClippedPolys() {
|
||||
// Clean the polys
|
||||
unsigned int before, after;
|
||||
|
||||
// Clean the polys
|
||||
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;
|
||||
|
||||
|
||||
// step 1 : snap
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
|
||||
before = poly.total_size();
|
||||
|
||||
if ( false ) {
|
||||
poly = remove_cycles( poly );
|
||||
poly = remove_dups( poly );
|
||||
poly = remove_bad_contours( poly );
|
||||
poly = tgPolygonSimplify( poly );
|
||||
poly = remove_tiny_contours( poly );
|
||||
poly = remove_spikes( poly );
|
||||
poly = remove_dups( poly );
|
||||
poly = remove_bad_contours( poly );
|
||||
poly = remove_tiny_contours( poly );
|
||||
} else {
|
||||
poly = snap(poly, gSnap);
|
||||
poly = remove_dups( 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 );
|
||||
}
|
||||
|
||||
poly = snap(poly, gSnap);
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
WriteDebugShape( "cleaned", polys_clipped.get_shape( area, shape ) );
|
||||
WriteDebugShape( "snapped", polys_clipped.get_shape( area, shape ) );
|
||||
}
|
||||
|
||||
// step 2 : remove_dups
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
poly = remove_dups( poly );
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
WriteDebugShape( "rem dupes", polys_clipped.get_shape( area, shape ) );
|
||||
}
|
||||
|
||||
// step 3 : remove_bad_contours
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
TGPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
poly = remove_bad_contours( poly );
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
WriteDebugShape( "rem bad contours", polys_clipped.get_shape( area, shape ) );
|
||||
}
|
||||
|
||||
// todo - add up all segments in a shape for printout
|
||||
#if 0
|
||||
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 );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
{
|
||||
sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id );
|
||||
}
|
||||
|
||||
|
||||
void SetMask( TGPolygon mask )
|
||||
{
|
||||
clip_mask = mask;
|
||||
|
|
|
@ -1553,10 +1553,10 @@ void* tgShapefileOpenLayer( void* ds_id, const char* layer_name ) {
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
|
||||
for ( int i = 0; i < poly.contours(); i++ ) {
|
||||
bool skip_ring=false;
|
||||
point_list contour = poly.get_contour( i );
|
||||
|
@ -1595,6 +1595,7 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c
|
|||
OGRFeature::DestroyFeature(feature);
|
||||
|
||||
// TEST TEST TEST : Add the point inside - see if we can see it in QGIS
|
||||
#if 0
|
||||
if ( has_pt_inside ) {
|
||||
OGRPoint *point=new OGRPoint();
|
||||
|
||||
|
@ -1613,6 +1614,7 @@ void tgShapefileCreateFeature( void* ds_id, void* l_id, const TGPolygon &poly, c
|
|||
}
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -709,7 +709,7 @@ TGPolygon polygon_clip_clipper( clip_op poly_op, const TGPolygon& subject, const
|
|||
// Accumulator optimization ( to keep from massive data copies and format changes
|
||||
gpc_polygon *gpc_accumulator = NULL;
|
||||
|
||||
void tgPolygonInitAccumulator( void )
|
||||
void tgPolygonInitGPCAccumulator( void )
|
||||
{
|
||||
gpc_accumulator = new gpc_polygon;
|
||||
gpc_accumulator->num_contours = 0;
|
||||
|
@ -717,7 +717,7 @@ void tgPolygonInitAccumulator( void )
|
|||
gpc_accumulator->hole = NULL;
|
||||
}
|
||||
|
||||
void tgPolygonFreeAccumulator( void )
|
||||
void tgPolygonFreeGPCAccumulator( void )
|
||||
{
|
||||
gpc_free_polygon( gpc_accumulator );
|
||||
delete gpc_accumulator;
|
||||
|
@ -801,6 +801,69 @@ TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip ) {
|
|||
|
||||
|
||||
|
||||
|
||||
// Accumulator optimization ( to keep from massive data copies and format changes
|
||||
ClipperLib::Polygons clipper_accumulator;
|
||||
|
||||
void tgPolygonInitClipperAccumulator( void )
|
||||
{
|
||||
clipper_accumulator.clear();
|
||||
}
|
||||
|
||||
void tgPolygonFreeClipperAccumulator( void )
|
||||
{
|
||||
clipper_accumulator.clear();
|
||||
}
|
||||
|
||||
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject )
|
||||
{
|
||||
ClipperLib::Polygons clipper_subject;
|
||||
make_clipper_poly( subject, &clipper_subject );
|
||||
|
||||
ClipperLib::ExPolygons clipper_result;
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_accumulator, ClipperLib::ptClip);
|
||||
|
||||
c.Execute(ClipperLib::ctUnion, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
|
||||
// verify each result is simple
|
||||
ClipperLib::Polygons simple_result = clipper_simplify( clipper_result );
|
||||
|
||||
clipper_accumulator.clear();
|
||||
clipper_accumulator = simple_result;
|
||||
}
|
||||
|
||||
TGPolygon tgPolygonDiffClipperWithAccumulator( const TGPolygon& subject )
|
||||
{
|
||||
TGPolygon result;
|
||||
|
||||
ClipperLib::Polygons clipper_subject;
|
||||
make_clipper_poly( subject, &clipper_subject );
|
||||
|
||||
ClipperLib::ExPolygons clipper_result;
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
c.Clear();
|
||||
c.AddPolygons(clipper_subject, ClipperLib::ptSubject);
|
||||
c.AddPolygons(clipper_accumulator, ClipperLib::ptClip);
|
||||
|
||||
c.Execute(ClipperLib::ctDifference, clipper_result, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
|
||||
|
||||
// verify each result is simple
|
||||
ClipperLib::Polygons simple_result = clipper_simplify( clipper_result );
|
||||
|
||||
make_tg_poly_from_clipper( simple_result, &result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// CLIPPER
|
||||
TGPolygon tgPolygonDiffClipper( const TGPolygon& subject, const TGPolygon& clip ) {
|
||||
return polygon_clip_clipper( POLY_DIFF, subject, clip );
|
||||
|
|
|
@ -256,8 +256,8 @@ void tgPolygonFindSlivers( TGPolygon& in, poly_list& slivers );
|
|||
|
||||
// wrapper functions for gpc polygon clip routines
|
||||
|
||||
void tgPolygonInitAccumulator( void );
|
||||
void tgPolygonFreeAccumulator( void );
|
||||
void tgPolygonInitGPCAccumulator( void );
|
||||
void tgPolygonFreeGPCAccumulator( void );
|
||||
void tgPolygonAddToAccumulator( const TGPolygon& subject );
|
||||
TGPolygon tgPolygonDiffWithAccumulator( const TGPolygon& subject );
|
||||
|
||||
|
@ -276,6 +276,11 @@ TGPolygon tgPolygonUnion( const TGPolygon& subject, const TGPolygon& clip );
|
|||
|
||||
// wrapper for clipper clip routines
|
||||
|
||||
void tgPolygonInitClipperAccumulator( void );
|
||||
void tgPolygonFreeClipperAccumulator( void );
|
||||
void tgPolygonAddToClipperAccumulator( const TGPolygon& subject );
|
||||
TGPolygon tgPolygonDiffClipperWithAccumulator( const TGPolygon& subject );
|
||||
|
||||
// Difference
|
||||
TGPolygon tgPolygonDiffClipper( const TGPolygon& subject, const TGPolygon& clip );
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
#include <ogrsf_frmts.h>
|
||||
|
||||
/* stretch endpoints to reduce slivers in linear data ~.1 meters */
|
||||
#define EP_STRETCH (0.000001)
|
||||
// #define EP_STRETCH (0.000001)
|
||||
#define EP_STRETCH (0.1)
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
|
Loading…
Reference in a new issue