1
0
Fork 0

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:
Peter Sadrozinski 2012-08-26 12:41:25 -04:00 committed by Christian Schmitt
parent 346ae44e14
commit c1de74f4fa
12 changed files with 206 additions and 75 deletions

View file

@ -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 )

View file

@ -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;

View file

@ -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");

View file

@ -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;
}

View file

@ -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";

View file

@ -154,7 +154,7 @@ private:
ProcessInfoList plist;
Net::ServerSocket* pss;
int state;
int threads;
unsigned int threads;
ofstream csvfile;
Scheduler* scheduler;
};

View file

@ -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
}
}
}

View file

@ -69,7 +69,7 @@ public:
{
sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id );
}
void SetMask( TGPolygon mask )
{
clip_mask = mask;

View file

@ -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
}
}

View file

@ -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 );

View file

@ -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 );

View file

@ -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;