diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx index a0e50e01..e50f5a1b 100644 --- a/src/Airports/GenAirports850/airport.cxx +++ b/src/Airports/GenAirports850/airport.cxx @@ -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; iBuildBtg( &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; iBuildBtg( &apt_base, &apt_clearing, false ); + } } if ( apt_base.total_size() == 0 ) diff --git a/src/Airports/GenAirports850/airport.hxx b/src/Airports/GenAirports850/airport.hxx index f5ed48a1..7f5669eb 100644 --- a/src/Airports/GenAirports850/airport.hxx +++ b/src/Airports/GenAirports850/airport.hxx @@ -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; diff --git a/src/Airports/GenAirports850/closedpoly.cxx b/src/Airports/GenAirports850/closedpoly.cxx index 086eeaaa..6118b0fe 100644 --- a/src/Airports/GenAirports850/closedpoly.cxx +++ b/src/Airports/GenAirports850/closedpoly.cxx @@ -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"); diff --git a/src/Airports/GenAirports850/parser.cxx b/src/Airports/GenAirports850/parser.cxx index 655a6845..ea02daac 100644 --- a/src/Airports/GenAirports850/parser.cxx +++ b/src/Airports/GenAirports850/parser.cxx @@ -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; } diff --git a/src/Airports/GenAirports850/scheduler.cxx b/src/Airports/GenAirports850/scheduler.cxx index 2dcfafad..4047e669 100644 --- a/src/Airports/GenAirports850/scheduler.cxx +++ b/src/Airports/GenAirports850/scheduler.cxx @@ -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"; diff --git a/src/Airports/GenAirports850/scheduler.hxx b/src/Airports/GenAirports850/scheduler.hxx index ef6c8b57..55e28b80 100644 --- a/src/Airports/GenAirports850/scheduler.hxx +++ b/src/Airports/GenAirports850/scheduler.hxx @@ -154,7 +154,7 @@ private: ProcessInfoList plist; Net::ServerSocket* pss; int state; - int threads; + unsigned int threads; ofstream csvfile; Scheduler* scheduler; }; diff --git a/src/BuildTiles/Main/construct.cxx b/src/BuildTiles/Main/construct.cxx index ff2c17ce..3c2a5350 100644 --- a/src/BuildTiles/Main/construct.cxx +++ b/src/BuildTiles/Main/construct.cxx @@ -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; inum_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 ); diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index 8fa454f5..b514d1b0 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -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 ); diff --git a/src/Prep/OGRDecode/ogr-decode.cxx b/src/Prep/OGRDecode/ogr-decode.cxx index a7a1e728..cd89f91e 100644 --- a/src/Prep/OGRDecode/ogr-decode.cxx +++ b/src/Prep/OGRDecode/ogr-decode.cxx @@ -45,7 +45,8 @@ #include /* 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;