From b007979a38ce848fef108556e43dbed87d79b58f Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Sat, 22 Dec 2012 09:16:14 -0500 Subject: [PATCH] - multithreaded tgconstruct --- src/BuildTiles/Main/main.cxx | 187 +++++----- src/BuildTiles/Main/tgconstruct.cxx | 299 ++++++++-------- src/BuildTiles/Main/tgconstruct.hxx | 233 ++++++------- src/BuildTiles/Main/tgconstruct_cleanup.cxx | 2 + src/BuildTiles/Main/tgconstruct_poly.cxx | 5 +- src/BuildTiles/Main/tgconstruct_shared.cxx | 365 ++++++++++---------- src/BuildTiles/Main/tglandclass.hxx | 2 +- src/Lib/terragear/tg_nodes.cxx | 6 - src/Lib/terragear/tg_nodes.hxx | 57 +-- src/Lib/terragear/tg_unique_tgnode.hxx | 7 +- 10 files changed, 537 insertions(+), 626 deletions(-) diff --git a/src/BuildTiles/Main/main.cxx b/src/BuildTiles/Main/main.cxx index db26b8e1..c5298f29 100644 --- a/src/BuildTiles/Main/main.cxx +++ b/src/BuildTiles/Main/main.cxx @@ -117,6 +117,8 @@ int main(int argc, char **argv) { } } + int num_threads = 8; + if ( share_dir == "" ) { share_dir = work_dir + "/Shared"; } @@ -149,125 +151,118 @@ int main(int argc, char **argv) { exit(-1); } - // main construction data management class : Stage 1 + // three identical work queues + SGLockedQueue wq[3]; + + // First generate the workqueue of buckets to construct if (tile_id == -1) { // build all the tiles in an area SG_LOG(SG_GENERAL, SG_ALERT, "Building tile(s) within given bounding box"); + SGBucket b_min( min ); SGBucket b_max( max ); if ( b_min == b_max ) { - TGConstruct* all_stages; - - all_stages = new TGConstruct(); - all_stages->set_cover( cover ); - all_stages->set_paths( work_dir, share_dir, output_dir, load_dirs ); - all_stages->set_options( ignoreLandmass, nudge ); - all_stages->set_bucket( b_min ); - all_stages->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); - - all_stages->ConstructBucketStage1(); - all_stages->ConstructBucketStage2(); - all_stages->ConstructBucketStage3(); - - delete all_stages; + for (unsigned int q=0; q<3; q++) { + wq[q].push( b_min ); + } } else { - SGBucket b_cur; - int dx, dy, i, j; - int total_buckets, cur_bucket; + int dx, dy; + int i, j; sgBucketDiff(b_min, b_max, &dx, &dy); + SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries"); SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy); - // construct stage 1 - total_buckets = (dx+1) * (dy + 1); - cur_bucket = 0; for ( j = 0; j <= dy; j++ ) { for ( i = 0; i <= dx; i++ ) { - b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); - - TGConstruct* stage1; - stage1 = new TGConstruct(); - stage1->set_cover( cover ); - stage1->set_paths( work_dir, share_dir, output_dir, load_dirs ); - stage1->set_options( ignoreLandmass, nudge ); - stage1->set_bucket( b_cur ); - stage1->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); - - SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 1: Construct bucket " << cur_bucket++ << " of " << total_buckets ); - stage1->ConstructBucketStage1(); - stage1->SaveToIntermediateFiles(1); - - delete stage1; - } - } - - // construct stage 2 - cur_bucket = 0; - for ( j = 0; j <= dy; j++ ) { - for ( i = 0; i <= dx; i++ ) { - b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); - - TGConstruct* stage2; - stage2 = new TGConstruct(); - stage2->set_cover( cover ); - stage2->set_paths( work_dir, share_dir, output_dir, load_dirs ); - stage2->set_options( ignoreLandmass, nudge ); - stage2->set_bucket( b_cur ); - stage2->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); - - SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 2: Construct bucket " << cur_bucket++ << " of " << total_buckets ); - stage2->LoadFromIntermediateFiles(1); - stage2->ConstructBucketStage2(); - stage2->SaveToIntermediateFiles(2); - - delete stage2; - } - } - - // construct stage 3 - cur_bucket = 0; - for ( j = 0; j <= dy; j++ ) { - for ( i = 0; i <= dx; i++ ) { - b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); - - TGConstruct* stage3; - stage3 = new TGConstruct(); - stage3->set_cover( cover ); - stage3->set_paths( work_dir, share_dir, output_dir, load_dirs ); - stage3->set_options( ignoreLandmass, nudge ); - stage3->set_bucket( b_cur ); - stage3->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); - - SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 3: Construct bucket " << cur_bucket++ << " of " << total_buckets ); - stage3->LoadFromIntermediateFiles(2); - stage3->ConstructBucketStage3(); - - delete stage3; + for (unsigned int q=0; q<3; q++) { + wq[q].push( sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j) ); + } } } } } else { // construct the specified tile SG_LOG(SG_GENERAL, SG_ALERT, "Building tile " << tile_id); - SGBucket b( tile_id ); - TGConstruct* all_stages; - - all_stages = new TGConstruct(); - all_stages->set_cover( cover ); - all_stages->set_paths( work_dir, share_dir, output_dir, load_dirs ); - all_stages->set_options( ignoreLandmass, nudge ); - all_stages->set_bucket( b ); - all_stages->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); - - all_stages->ConstructBucketStage1(); - all_stages->ConstructBucketStage2(); - all_stages->ConstructBucketStage3(); - - delete all_stages; + for (unsigned int q=0; q<3; q++) { + wq[q].push( SGBucket( tile_id ) ); + } } + // now create the worker threads for stage 1 + std::vector constructs; + + for (int i=0; iset_cover( cover ); + construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); + construct->set_options( ignoreLandmass, nudge ); + construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); + constructs.push_back( construct ); + } + + // start all threads + for (unsigned int i=0; istart(); + } + // wait for all threads to complete + for (unsigned int i=0; ijoin(); + } + // delete the stage 1 construct objects + for (unsigned int i=0; iset_cover( cover ); + construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); + construct->set_options( ignoreLandmass, nudge ); + construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); + constructs.push_back( construct ); + } + + // start all threads + for (unsigned int i=0; istart(); + } + // wait for all threads to complete + for (unsigned int i=0; ijoin(); + } + // delete the stage 2 construct objects + for (unsigned int i=0; iset_cover( cover ); + construct->set_paths( work_dir, share_dir, output_dir, load_dirs ); + construct->set_options( ignoreLandmass, nudge ); + construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); + constructs.push_back( construct ); + } + + // start all threads + for (unsigned int i=0; istart(); + } + // wait for all threads to complete + for (unsigned int i=0; ijoin(); + } + // delete the stage 2 construct objects + for (unsigned int i=0; i& q) : + workQueue(q), + stage(s), ignoreLandmass(false), debug_all(false), ds_id((void*)-1), isOcean(false) -{ } +{ + total_tiles = q.size(); +} // Destructor @@ -66,175 +70,170 @@ void TGConstruct::set_options( bool ignore_lm, double n ) { nudge = n; } -// master construction routine -// TODO : Split each step into its own function, and move -// into seperate files by major functionality -// loading, clipping, tesselating, normals, and output -// Also, we are still calculating some thing more than one -// (like face area - need to move this into superpoly ) -void TGConstruct::ConstructBucketStage1() { - SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); +void TGConstruct::run() +{ + unsigned int tiles_complete; - /* If we have some debug IDs, create a datasource */ - if ( debug_shapes.size() || debug_all ) { - sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); - SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); - } else { - strcpy( ds_name, "" ); - } + // as long as we have feometry to parse, do so + while ( !workQueue.empty() ) { + bucket = workQueue.pop(); + tiles_complete = total_tiles - workQueue.size(); - // STEP 1) - // Load grid of elevation data (Array), and add the nodes - LoadElevationArray( true ); + // assume non ocean tile until proven otherwise + isOcean = false; - // STEP 2) - // Clip 2D polygons against one another - SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass polys" ); - if ( LoadLandclassPolys() == 0 ) { - // don't build the tile if there is no 2d data ... it *must* - // be ocean and the sim can build the tile on the fly. - SetOceanTile(); - return; - } + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Construct in " << bucket.gen_base_path() << " tile " << tiles_complete << " of " << total_tiles ); - // STEP 3) - // Load the land use polygons if the --cover option was specified - if ( get_cover().size() > 0 ) { - SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass raster" ); - load_landcover(); - } - - // STEP 4) - // Clip the Landclass polygons - SG_LOG(SG_GENERAL, SG_ALERT, " - Clipping landclass polys" ); - 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 - SG_LOG(SG_GENERAL, SG_ALERT, " - Cleaning landclass polys" ); - nodes.init_spacial_query(); - CleanClippedPolys(); - - // STEP 6) - // Save the tile boundary info for stage 2 (just x,y coords of points on the boundary) - SaveSharedEdgeData( 1 ); -} - -void TGConstruct::ConstructBucketStage2() { - if ( !IsOceanTile() ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); - - /* If we have some debug IDs, create a datasource */ if ( debug_shapes.size() || debug_all ) { sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); - SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); } else { strcpy( ds_name, "" ); } - // STEP 7) - // Need the array of elevation data for stage 2, but don't add the nodes - we already have them - LoadElevationArray( false ); - - // STEP 8) - // Merge in Shared data - should just be x,y nodes on the borders from stage1 - LoadSharedEdgeData( 1 ); - - // STEP 9) - // Fix T-Junctions by finding nodes that lie close to polygon edges, and - // inserting them into the edge - SG_LOG(SG_GENERAL, SG_ALERT, " - Fix T-Junctions" ); - nodes.init_spacial_query(); - FixTJunctions(); - - // STEP 10) - // Generate triangles - we can't generate the node-face lookup table - // until all polys are tesselated, as extra nodes can still be generated - SG_LOG(SG_GENERAL, SG_ALERT, " - Tesselate" ); - TesselatePolys(); - - // STEP 12) - // Generate triangle vertex coordinates to node index lists - // NOTE: After this point, no new nodes can be added - SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Nodes Per Vertex"); - LookupNodesPerVertex(); - - // STEP 13) - // Interpolate elevations, and flatten stuff - SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Elevation Per Node"); - CalcElevations(); - - // STEP 14) - // Generate face_connected list - needed for saving the edge data - SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node"); - LookupFacesPerNode(); - - // STEP 15) - // Save the tile boundary info for stage 3 - // includes elevation info, and a list of connected triangles - nodes.init_spacial_query(); - SaveSharedEdgeData( 2 ); - } -} - -void TGConstruct::ConstructBucketStage3() { - if ( !IsOceanTile() ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); - - /* If we have some debug IDs, create a datasource */ - if ( debug_shapes.size() || debug_all ) { - sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); - SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); - } else { - strcpy( ds_name, "" ); + if ( stage > 1 ) { + LoadFromIntermediateFiles( stage-1 ); } - SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node (again)"); - LookupFacesPerNode(); + switch( stage ) { + case 1: + // STEP 1) + // Load grid of elevation data (Array), and add the nodes + LoadElevationArray( true ); - // STEP 16) - // Load in the neighbor faces and elevation data - LoadSharedEdgeDataStage2(); + // STEP 2) + // Clip 2D polygons against one another + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Loading landclass polys" ); + if ( LoadLandclassPolys() == 0 ) { + // don't build the tile if there is no 2d data ... it *must* + // be ocean and the sim can build the tile on the fly. + isOcean = true; + break; + } - // STEP 17) - // Average out the elevation for nodes on tile boundaries - SG_LOG(SG_GENERAL, SG_ALERT, " - Average Edge Node Elevations"); - AverageEdgeElevations(); + // STEP 3) + // Load the land use polygons if the --cover option was specified + if ( get_cover().size() > 0 ) { + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Loading landclass raster" ); + load_landcover(); + } - // STEP 18) - // Calculate Face Normals - SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Face Normals"); - CalcFaceNormals(); + // STEP 4) + // Clip the Landclass polygons + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Clipping landclass polys" ); + ClipLandclassPolys(); - // STEP 19) - // Calculate Point Normals - SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Point Normals"); - CalcPointNormals(); + // 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 + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Cleaning landclass polys" ); + nodes.init_spacial_query(); + CleanClippedPolys(); + break; + + case 2: + if ( !IsOceanTile() ) { + // STEP 6) + // Need the array of elevation data for stage 2, but don't add the nodes - we already have them + LoadElevationArray( false ); + + // STEP 7) + // Fix T-Junctions by finding nodes that lie close to polygon edges, and + // inserting them into the edge + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Fix T-Junctions" ); + nodes.init_spacial_query(); + FixTJunctions(); + + // STEP 8) + // Generate triangles - we can't generate the node-face lookup table + // until all polys are tesselated, as extra nodes can still be generated + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Tesselate" ); + TesselatePolys(); + + // STEP 9) + // Generate triangle vertex coordinates to node index lists + // NOTE: After this point, no new nodes can be added + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Lookup Nodes Per Vertex"); + LookupNodesPerVertex(); + + // STEP 10) + // Interpolate elevations, and flatten stuff + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Calculate Elevation Per Node"); + CalcElevations(); + + // ONLY do this when saving edge nodes... + // STEP 11) + // Generate face-connected list - needed for saving the edge data + // SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Lookup Faces Per Node"); + // LookupFacesPerNode(); + } + break; + + case 3: + if ( !IsOceanTile() ) { + // STEP 12 + // Generate face-connectd list (again) - it was needed to save faces of the + // edge nodes, but saving the entire tile is i/o intensive - it's faster + // too just recompute the list + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Lookup Faces Per Node (again)"); + LookupFacesPerNode(); + + // STEP 13) + // Average out the elevation for nodes on tile boundaries + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Average Edge Node Elevations"); + AverageEdgeElevations(); + + // STEP 14) + // Calculate Face Normals + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Calculate Face Normals"); + CalcFaceNormals(); + + // STEP 15) + // Calculate Point Normals + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Calculate Point Normals"); + CalcPointNormals(); #if 0 - // STEP 20) - if ( c.get_cover().size() > 0 ) { - // Now for all the remaining "default" land cover polygons, assign - // each one it's proper type from the land use/land cover - // database. - fix_land_cover_assignments( c ); - } + // STEP 16) + if ( c.get_cover().size() > 0 ) { + // Now for all the remaining "default" land cover polygons, assign + // each one it's proper type from the land use/land cover + // database. + fix_land_cover_assignments( c ); + } #endif - // STEP 21) - // Calculate Texture Coordinates - SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Texture Coordinates"); - CalcTextureCoordinates(); + // STEP 17) + // Calculate Texture Coordinates + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Calculate Texture Coordinates"); + CalcTextureCoordinates(); - // STEP 22) - // Generate the btg file - SG_LOG(SG_GENERAL, SG_ALERT, " - Generate BTG File"); - WriteBtgFile(); + // STEP 18) + // Generate the btg file + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Generate BTG File"); + WriteBtgFile(); - // STEP 23) - // Write Custom objects to .stg file - SG_LOG(SG_GENERAL, SG_ALERT, " - Generate Custome Objects"); - AddCustomObjects(); + // STEP 19) + // Write Custom objects to .stg file + SG_LOG(SG_GENERAL, SG_ALERT, bucket.gen_index_str() << " - Generate Custome Objects"); + AddCustomObjects(); + } + break; + } + + if ( ( stage < 3 ) && ( !IsOceanTile() ) ) { + // Save data for next stage + if ( stage == 2 ) { + nodes.init_spacial_query(); // for stage 2 only... + } + SaveSharedEdgeData( stage ); + SaveToIntermediateFiles( stage ); + } + + // Clean up for next work queue item + array.close(); + polys_in.clear(); + polys_clipped.clear(); + nodes.clear(); + neighbor_faces.clear(); } } \ No newline at end of file diff --git a/src/BuildTiles/Main/tgconstruct.hxx b/src/BuildTiles/Main/tgconstruct.hxx index 8f4ad27b..20f47da8 100644 --- a/src/BuildTiles/Main/tgconstruct.hxx +++ b/src/BuildTiles/Main/tgconstruct.hxx @@ -30,6 +30,8 @@ # error This library requires C++ #endif +#include +#include #define TG_MAX_AREA_TYPES 128 @@ -56,9 +58,109 @@ typedef std::vector < TGNeighborFaces > neighbor_face_list; typedef neighbor_face_list::iterator neighbor_face_list_iterator; typedef neighbor_face_list::const_iterator const_neighbor_face_list_iterator; -class TGConstruct { +class TGConstruct : public SGThread +{ +public: + // Constructor + TGConstruct(unsigned int s, SGLockedQueue& q); + + // Destructor + ~TGConstruct(); + + // New shared edge matching + void SaveToIntermediateFiles( int stage ); + void LoadFromIntermediateFiles( int stage ); + + int load_landcover (); + double measure_roughness( tgContour &contour ); + AreaType get_landcover_type (const LandCover &cover, double xpos, double ypos, double dx, double dy); + void make_area( const LandCover &cover, tgpolygon_list& polys, + double x1, double y1, double x2, double y2, + double half_dx, double half_dy ); + + // land cover file + inline std::string get_cover () const { return cover; } + inline void set_cover (const std::string &s) { cover = s; } + + // paths + void set_paths( const std::string work, const std::string share, const std::string output, const std::vector load_dirs ); + void set_options( bool ignore_lm, double n ); + + // TODO : REMOVE + inline TGNodes* get_nodes() { return &nodes; } + + // node list in geodetic coords (with fixed elevation) + inline void get_geod_nodes( std::vector& points ) const { nodes.get_geod_nodes( points ); } + + // normal list (for each point) in cart coords (for smooth shading) + inline void get_point_normals( std::vector& normals ) const { nodes.get_normals( normals ); } + + // Debug + void set_debug( std::string path, std::vector area_defs, std::vector shape_defs ); private: + virtual void run(); + + // Ocean tile or not + bool IsOceanTile() { return isOcean; } + + // Load Data + void LoadElevationArray( bool add_nodes ); + int LoadLandclassPolys( void ); + + // Clip Data + bool ClipLandclassPolys( void ); + + // Clip Helpers +// void move_slivers( TGPolygon& in, TGPolygon& out ); +// void merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_list ); + + // Shared edge Matching + void SaveSharedEdgeData( int stage ); + void LoadSharedEdgeData( int stage ); + + void LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ); + void ReadNeighborFaces( gzFile& fp ); + void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const; + TGNeighborFaces* AddNeighborFaces( const SGGeod& node ); + TGNeighborFaces* FindNeighborFaces( const SGGeod& node ); + + // Polygon Cleaning + void CleanClippedPolys( void ); + void FixTJunctions( void ); + + // Tesselation + void TesselatePolys( void ); + + // Elevation and Flattening + void CalcElevations( void ); + void AverageEdgeElevations( void ); + + // Normals and texture coords + void LookupNodesPerVertex( void ); + void LookupFacesPerNode( void ); + void CalcFaceNormals( void ); + void CalcPointNormals( void ); + void CalcTextureCoordinates( void ); + // Helpers + SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const; + + // Output + void WriteBtgFile( void ); + void AddCustomObjects( void ); + + // Misc + void calc_normals( std::vector& geod_nodes, std::vector& wgs84_nodes, tgPolygon& sp ); + + // debug + bool IsDebugShape( unsigned int id ); + bool IsDebugArea( unsigned int area ); + +private: + // construct stage to perform + SGLockedQueue& workQueue; + unsigned int total_tiles; + unsigned int stage; // path to land-cover file (if any) std::string cover; @@ -113,135 +215,6 @@ private: // Neighbor Faces neighbor_face_list neighbor_faces; - -private: - // Ocean tile or not - void SetOceanTile() { isOcean = true; } - bool IsOceanTile() { return isOcean; } - - // Load Data - void LoadElevationArray( bool add_nodes ); - int LoadLandclassPolys( void ); - - // Clip Data - bool ClipLandclassPolys( void ); - - // Clip Helpers -// void move_slivers( TGPolygon& in, TGPolygon& out ); - void merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_list ); - - // Shared edge Matching - void SaveSharedEdgeDataStage2( void ); - void LoadSharedEdgeDataStage2( void ); - void LoadSharedEdgeData( int stage ); - void LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ); - - void SaveSharedEdgeData( int stage ); - - void ReadNeighborFaces( gzFile& fp ); - void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const; - TGNeighborFaces* AddNeighborFaces( const SGGeod& node ); - TGNeighborFaces* FindNeighborFaces( const SGGeod& node ); - - // Polygon Cleaning - void CleanClippedPolys( void ); - void FixTJunctions( void ); - - // Tesselation - void TesselatePolys( void ); - - // Elevation and Flattening - void CalcElevations( void ); - void AverageEdgeElevations( void ); - - // Normals and texture coords - void LookupNodesPerVertex( void ); - void LookupFacesPerNode( void ); - void CalcFaceNormals( void ); - void CalcPointNormals( void ); - void CalcTextureCoordinates( void ); - // Helpers - SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const; - - // Output - void WriteBtgFile( void ); - void AddCustomObjects( void ); - - // Misc - void calc_normals( std::vector& geod_nodes, std::vector& wgs84_nodes, tgPolygon& sp ); - - // debug - bool IsDebugShape( unsigned int id ); - bool IsDebugArea( unsigned int area ); - -public: - // Constructor - TGConstruct(); - - // Destructor - ~TGConstruct(); - - void set_bucket( SGBucket b ) { bucket = b; } - - // New shared edge matching - void SaveToIntermediateFiles( int stage ); - void LoadFromIntermediateFiles( int stage ); - - // Three stage construct - void ConstructBucketStage1(); - void ConstructBucketStage2(); - void ConstructBucketStage3(); - - int load_landcover (); - double measure_roughness( tgContour &contour ); - AreaType get_landcover_type (const LandCover &cover, double xpos, double ypos, double dx, double dy); - void make_area( const LandCover &cover, tgpolygon_list& polys, - double x1, double y1, double x2, double y2, - double half_dx, double half_dy ); - - // land cover file - inline std::string get_cover () const { return cover; } - inline void set_cover (const std::string &s) { cover = s; } - - // paths - void set_paths( const std::string work, const std::string share, const std::string output, const std::vector load_dirs ); - -#if 0 - inline std::string get_work_base() const { return work_base; } - inline void set_work_base( const std::string s ) { work_base = s; } - inline std::string get_output_base() const { return output_base; } - inline void set_output_base( const std::string s ) { output_base = s; } - inline std::string get_share_base() const { return share_base; } - inline void set_share_base( const std::string s ) { share_base = s; } - inline void set_load_dirs( const std::vector ld ) { load_dirs = ld; } -#endif - - void set_options( bool ignore_lm, double n ); - -#if 0 - // UK grid flag - inline bool get_useUKGrid() const { return useUKGrid; } - inline void set_useUKGrid( const bool b ) { useUKGrid = b; } - - // Nudge - inline void set_nudge( double n ) { nudge = n; } - - // ignore landmass flag - inline void set_ignore_landmass( const bool b) { ignoreLandmass = b; } -#endif - - // TODO : REMOVE - inline TGNodes* get_nodes() { return &nodes; } - - // node list in geodetic coords (with fixed elevation) - inline void get_geod_nodes( std::vector& points ) const { nodes.get_geod_nodes( points ); } - - // normal list (for each point) in cart coords (for smooth - // shading) - inline void get_point_normals( std::vector& normals ) const { nodes.get_normals( normals ); } - - // Debug - void set_debug( std::string path, std::vector area_defs, std::vector shape_defs ); }; diff --git a/src/BuildTiles/Main/tgconstruct_cleanup.cxx b/src/BuildTiles/Main/tgconstruct_cleanup.cxx index 78f763ce..36037e70 100644 --- a/src/BuildTiles/Main/tgconstruct_cleanup.cxx +++ b/src/BuildTiles/Main/tgconstruct_cleanup.cxx @@ -58,6 +58,7 @@ void TGConstruct::FixTJunctions( void ) { } } +#if 0 // Attempt to merge slivers into a list of polygons. // // For each sliver contour, see if a union with another polygon yields @@ -78,6 +79,7 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l sliver_list.clear(); } +#endif void TGConstruct::CleanClippedPolys() { // Clean the polys diff --git a/src/BuildTiles/Main/tgconstruct_poly.cxx b/src/BuildTiles/Main/tgconstruct_poly.cxx index 808c1473..6efef46a 100644 --- a/src/BuildTiles/Main/tgconstruct_poly.cxx +++ b/src/BuildTiles/Main/tgconstruct_poly.cxx @@ -73,7 +73,7 @@ int TGConstruct::LoadLandclassPolys( void ) { } else { int area; std::string material; - gzFile fp =gzopen( p.c_str(), "rb" ); + gzFile fp = gzopen( p.c_str(), "rb" ); unsigned int count; sgReadUInt( fp, &count ); @@ -107,13 +107,14 @@ int TGConstruct::LoadLandclassPolys( void ) { } } } + gzclose( fp ); gzclose( fp ); SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file()); } } // of directory file children } - + SG_LOG(SG_GENERAL, SG_ALERT, " Total polys read in this tile: " << total_polys_read ); return total_polys_read; diff --git a/src/BuildTiles/Main/tgconstruct_shared.cxx b/src/BuildTiles/Main/tgconstruct_shared.cxx index cb44b6df..1d4b4445 100644 --- a/src/BuildTiles/Main/tgconstruct_shared.cxx +++ b/src/BuildTiles/Main/tgconstruct_shared.cxx @@ -36,11 +36,10 @@ using std::string; void TGConstruct::SaveSharedEdgeData( int stage ) { - string filepath; - switch( stage ) { case 1: { + string filepath; std::vector north, south, east, west; int nCount; @@ -102,12 +101,189 @@ void TGConstruct::SaveSharedEdgeData( int stage ) // neighboors needs to be completed. So after all border nodes' elevations // are updated, we'll need to traverse all of these point lists, and update // any border nodes elevation as well - SaveSharedEdgeDataStage2(); + string dir; + string file; + std::vector north, south, east, west; + int nCount; + + nodes.get_geod_edge( bucket, north, south, east, west ); + + dir = share_base + "/stage2/" + bucket.gen_base_path(); + + SGPath sgp( dir ); + sgp.append( "dummy" ); + sgp.create_dir( 0755 ); + + // north edge + file = dir + "/" + bucket.gen_index_str() + "_north_edge"; + gzFile fp; + if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) { + SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" ); + return; + } + sgClearWriteError(); + + nCount = north.size(); + sgWriteInt( fp, nCount ); + for (int i=0; i north, south, east, west; + SGBucket nb, sb, eb, wb; + double clon = bucket.get_center_lon(); + double clat = bucket.get_center_lat(); + + // Read North tile and add its southern nodes + nb = sgBucketOffset(clon, clat, 0, 1); + LoadNeighboorEdgeDataStage1( nb, north, south, east, west ); + // Add southern nodes from northern tile + for (unsigned int i=0; i north, south, east, west; - int nCount; - - nodes.get_geod_edge( bucket, north, south, east, west ); - - dir = share_base + "/stage2/" + bucket.gen_base_path(); - - SGPath sgp( dir ); - sgp.append( "dummy" ); - sgp.create_dir( 0755 ); - - // north edge - file = dir + "/" + bucket.gen_index_str() + "_north_edge"; - gzFile fp; - if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) { - SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" ); - return; - } - sgClearWriteError(); - - nCount = north.size(); - sgWriteInt( fp, nCount ); - for (int i=0; i& } } -void TGConstruct::LoadSharedEdgeData( int stage ) -{ - switch( stage ) { - case 1: - { - // we need to read just 4 buckets for stage 1 - 1 for each edge - std::vector north, south, east, west; - SGBucket nb, sb, eb, wb; - double clon = bucket.get_center_lon(); - double clat = bucket.get_center_lat(); - - // Read North tile and add its southern nodes - nb = sgBucketOffset(clon, clat, 0, 1); - LoadNeighboorEdgeDataStage1( nb, north, south, east, west ); - // Add southern nodes from northern tile - for (unsigned int i=0; i node_list; };