From 6edeadd86ed747a2d466c8aff64aadbe13fd4e9d Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Sun, 2 Dec 2012 14:53:21 -0500 Subject: [PATCH] removed tgshape - each area is now just a list of polys fixed linear data texturing fixed water area spacial query adjustment - works just like linear query, now --- src/BuildTiles/Main/CMakeLists.txt | 2 - src/BuildTiles/Main/main.cxx | 21 +- src/BuildTiles/Main/tgconstruct.cxx | 42 +- src/BuildTiles/Main/tgconstruct.hxx | 23 +- src/BuildTiles/Main/tgconstruct_cleanup.cxx | 94 ++-- src/BuildTiles/Main/tgconstruct_clip.cxx | 71 +-- src/BuildTiles/Main/tgconstruct_debug.cxx | 78 +-- src/BuildTiles/Main/tgconstruct_elevation.cxx | 233 +++++---- src/BuildTiles/Main/tgconstruct_lookup.cxx | 42 +- src/BuildTiles/Main/tgconstruct_math.cxx | 52 +- src/BuildTiles/Main/tgconstruct_output.cxx | 52 +- src/BuildTiles/Main/tgconstruct_poly.cxx | 41 +- src/BuildTiles/Main/tgconstruct_shared.cxx | 83 ++-- src/BuildTiles/Main/tgconstruct_tesselate.cxx | 58 ++- src/BuildTiles/Main/tgconstruct_texture.cxx | 156 +----- src/BuildTiles/Main/tglandclass.cxx | 20 +- src/BuildTiles/Main/tglandclass.hxx | 113 ++--- src/BuildTiles/Main/tgshape.cxx | 129 ----- src/BuildTiles/Main/tgshape.hxx | 69 --- src/Lib/Geometry/tg_nodes.cxx | 456 +++++++----------- src/Lib/Geometry/tg_nodes.hxx | 210 +++----- src/Lib/Polygon/polygon.cxx | 126 ++--- src/Lib/Polygon/polygon.hxx | 42 +- src/Lib/Polygon/tg_unique_geod.hxx | 17 + src/Lib/Polygon/tg_unique_tgnode.hxx | 262 ++++++++++ 25 files changed, 1010 insertions(+), 1482 deletions(-) delete mode 100644 src/BuildTiles/Main/tgshape.cxx delete mode 100644 src/BuildTiles/Main/tgshape.hxx create mode 100644 src/Lib/Polygon/tg_unique_tgnode.hxx diff --git a/src/BuildTiles/Main/CMakeLists.txt b/src/BuildTiles/Main/CMakeLists.txt index 1636d89a..5c421b7f 100644 --- a/src/BuildTiles/Main/CMakeLists.txt +++ b/src/BuildTiles/Main/CMakeLists.txt @@ -15,8 +15,6 @@ add_executable(tg-construct tgconstruct_texture.cxx tglandclass.cxx tglandclass.hxx - tgshape.cxx - tgshape.hxx priorities.cxx priorities.hxx usgs.cxx diff --git a/src/BuildTiles/Main/main.cxx b/src/BuildTiles/Main/main.cxx index 946524cf..f427cf12 100644 --- a/src/BuildTiles/Main/main.cxx +++ b/src/BuildTiles/Main/main.cxx @@ -18,12 +18,6 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. // - - -// TODO TODO TODO : Get rid of construct - data hiding is moretrouble than it's worth right now. -// constantly needing to call set after every operation.... - - #ifdef HAVE_CONFIG_H # include #endif @@ -184,12 +178,15 @@ int main(int argc, char **argv) { } else { SGBucket b_cur; int dx, dy, i, j; + int total_buckets, cur_bucket; 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); @@ -202,14 +199,23 @@ int main(int argc, char **argv) { 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 ); + SGTimeStamp build_start; + build_start.stamp(); + stage1->ConstructBucketStage1(); stage1->SaveToIntermediateFiles(1); + SGTimeStamp build_end; + build_end.stamp(); + + SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 1: finshed in " << build_end - build_start ); 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); @@ -222,6 +228,7 @@ int main(int argc, char **argv) { 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); @@ -231,6 +238,7 @@ int main(int argc, char **argv) { } // 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); @@ -243,6 +251,7 @@ int main(int argc, char **argv) { 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(); diff --git a/src/BuildTiles/Main/tgconstruct.cxx b/src/BuildTiles/Main/tgconstruct.cxx index 450301b1..ed710826 100644 --- a/src/BuildTiles/Main/tgconstruct.cxx +++ b/src/BuildTiles/Main/tgconstruct.cxx @@ -73,9 +73,7 @@ void TGConstruct::set_options( bool ignore_lm, double n ) { // Also, we are still calculating some thing more than one // (like face area - need to move this into superpoly ) void TGConstruct::ConstructBucketStage1() { - // First, set the precision of floating point logging: - SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); - SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); + 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 ) { @@ -91,6 +89,7 @@ void TGConstruct::ConstructBucketStage1() { // 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. @@ -101,16 +100,20 @@ void TGConstruct::ConstructBucketStage1() { // 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) @@ -120,9 +123,7 @@ void TGConstruct::ConstructBucketStage1() { void TGConstruct::ConstructBucketStage2() { if ( !IsOceanTile() ) { - // First, set the precision of floating point logging: - SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); - SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); + 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 ) { @@ -143,43 +144,43 @@ void TGConstruct::ConstructBucketStage2() { // 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 11) - // Optimize the node list now since linear add is faster than sorted add. - // no more nodes can be added from this point on - nodes.SortNodes(); - // 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 + // 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() ) { - // First, set the precision of floating point logging: - SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); - SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); + 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 ) { @@ -189,20 +190,26 @@ void TGConstruct::ConstructBucketStage3() { strcpy( ds_name, "" ); } + SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node (again)"); + LookupFacesPerNode(); + // STEP 16) // Load in the neighbor faces and elevation data LoadSharedEdgeDataStage2(); // STEP 17) // Average out the elevation for nodes on tile boundaries + SG_LOG(SG_GENERAL, SG_ALERT, " - Average Edge Node Elevations"); AverageEdgeElevations(); // STEP 18) // Calculate Face Normals + SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Face Normals"); CalcFaceNormals(); // STEP 19) // Calculate Point Normals + SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Point Normals"); CalcPointNormals(); #if 0 @@ -217,14 +224,17 @@ void TGConstruct::ConstructBucketStage3() { // STEP 21) // Calculate Texture Coordinates + SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Texture Coordinates"); CalcTextureCoordinates(); // STEP 22) // Generate the btg file + SG_LOG(SG_GENERAL, SG_ALERT, " - Generate BTG File"); WriteBtgFile(); // STEP 23) // Write Custom objects to .stg file + SG_LOG(SG_GENERAL, SG_ALERT, " - Generate Custome Objects"); AddCustomObjects(); } -} +} \ No newline at end of file diff --git a/src/BuildTiles/Main/tgconstruct.hxx b/src/BuildTiles/Main/tgconstruct.hxx index fda359c9..db2d2665 100644 --- a/src/BuildTiles/Main/tgconstruct.hxx +++ b/src/BuildTiles/Main/tgconstruct.hxx @@ -38,24 +38,24 @@ #include #include "tglandclass.hxx" +#include "priorities.hxx" #define FIND_SLIVERS (0) // Stage2 shared edge data struct TGNeighborFaces { public: - Point3D node; + SGGeod node; double_list elevations; // we'll take the average double_list face_areas; - point_list face_normals; + std::vector face_normals; }; 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 { private: @@ -135,16 +135,15 @@ private: // Shared edge Matching void SaveSharedEdgeDataStage2( void ); void LoadSharedEdgeDataStage2( void ); - void WriteSharedEdgeNeighboorFaces( gzFile& fp, Point3D pt ); void LoadSharedEdgeData( int stage ); - void LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, point_list& south, point_list& east, point_list& west ); + 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, Point3D pt ); - TGNeighborFaces* AddNeighborFaces( Point3D node ); - TGNeighborFaces* FindNeighborFaces( Point3D node ); + void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const; + TGNeighborFaces* AddNeighborFaces( const SGGeod& node ); + TGNeighborFaces* FindNeighborFaces( const SGGeod& node ); // Polygon Cleaning void CleanClippedPolys( void ); @@ -164,9 +163,7 @@ private: void CalcPointNormals( void ); void CalcTextureCoordinates( void ); // Helpers - SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ); - TGPolygon linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp ); - TGPolygon area_tex_coords( const TGPolygon& tri ); + SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const; // Output void WriteBtgFile( void ); @@ -179,10 +176,6 @@ private: bool IsDebugShape( unsigned int id ); bool IsDebugArea( unsigned int area ); - 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 TGConstruct(); diff --git a/src/BuildTiles/Main/tgconstruct_cleanup.cxx b/src/BuildTiles/Main/tgconstruct_cleanup.cxx index b97d4a70..b66e0b79 100644 --- a/src/BuildTiles/Main/tgconstruct_cleanup.cxx +++ b/src/BuildTiles/Main/tgconstruct_cleanup.cxx @@ -40,25 +40,25 @@ using std::string; void TGConstruct::FixTJunctions( void ) { int before, after; std::vector points; - nodes.get_geod_nodes( points ); + tg::Rectangle bb; // traverse each poly, and add intermediate nodes for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for( unsigned int j = 0; j < polys_clipped.area_size(i); ++j ) { - for( unsigned int k = 0; k < polys_clipped.shape_size(i, j); ++k ) { - tgPolygon current = polys_clipped.get_poly(i, j, k); + tgPolygon current = polys_clipped.get_poly(i, j); + bb = current.GetBoundingBox(); + nodes.get_geod_inside( bb.getMin(), bb.getMax(), points ); - before = current.TotalNodes(); - current = tgPolygon::AddColinearNodes( current, points ); - after = current.TotalNodes(); + before = current.TotalNodes(); + current = tgPolygon::AddColinearNodes( current, points ); + after = current.TotalNodes(); - if (before != after) { - SG_LOG( SG_CLIPPER, SG_INFO, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << "-" << k << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after ); - } - - /* Save it back */ - polys_clipped.set_poly( i, j, k, current ); + if (before != after) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after ); } + + /* Save it back */ + polys_clipped.set_poly( i, j, current ); } } } @@ -76,23 +76,7 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l continue; } - for ( unsigned int s = 0; s < clipped.area_size(area) && sliver_list.size(); ++s ) { - TGShape shape = clipped.get_shape( area, s ); - - unsigned int before = sliver_list.size(); - sliver_list = tgPolygon::MergeSlivers( shape.polys, sliver_list ); - unsigned int after = sliver_list.size(); - - if (before != after) { - shape.BuildMask(); - -#if 0 - if ( IsDebugShape( shape.id ) ) { - WriteDebugShape( "with_slivers", shape ); - } -#endif - } - } + sliver_list = tgPolygon::MergeSlivers( polys_clipped.get_polys(area), sliver_list ); } SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << sliver_list.size() ); @@ -101,54 +85,32 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l } void TGConstruct::CleanClippedPolys() { - // 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; - + for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { // 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); - poly = tgPolygon::Snap(poly, gSnap); - polys_clipped.set_poly( area, shape, segment, poly ); - } + tgPolygon poly = polys_clipped.get_poly(area, p); + poly = tgPolygon::Snap(poly, gSnap); - if ( IsDebugShape( id ) ) { - tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "snapped", "" ); + if ( IsDebugShape( poly.GetId() ) ) { + tgPolygon::ToShapefile( poly, ds_name, "snapped", "" ); } // 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 = tgPolygon::RemoveDups( poly ); - polys_clipped.set_poly( area, shape, segment, poly ); - } + poly = tgPolygon::RemoveDups( poly ); - if ( IsDebugShape( id ) ) { - tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_dups", "" ); + if ( IsDebugShape( poly.GetId() ) ) { + tgPolygon::ToShapefile( poly, ds_name, "rem_dups", "" ); } // 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 = tgPolygon::RemoveBadContours( poly ); - polys_clipped.set_poly( area, shape, segment, poly ); + poly = tgPolygon::RemoveBadContours( poly ); + + if ( IsDebugShape( poly.GetId() ) ) { + tgPolygon::ToShapefile( poly, ds_name, "rem_bcs", "" ); } - if ( IsDebugShape( id ) ) { - tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_bcs", "" ); - } - -// 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 - + polys_clipped.set_poly(area, p, poly); } } } @@ -167,10 +129,10 @@ void TGConstruct::AverageEdgeElevations( void ) elevation = elevation / num_elevations; /* Find this node, and update it's elevation */ - int idx = nodes.find( faces.node.toSGGeod() ); + int idx = nodes.find( faces.node ); if (idx != -1) { - TGNode node = nodes.get_node( idx ); + TGNode const& node = nodes.get_node( idx ); if ( !node.GetFixedPosition() ) { // set elevation as the average between all tiles that have it diff --git a/src/BuildTiles/Main/tgconstruct_clip.cxx b/src/BuildTiles/Main/tgconstruct_clip.cxx index e436f4c2..2b2d8b4d 100644 --- a/src/BuildTiles/Main/tgconstruct_clip.cxx +++ b/src/BuildTiles/Main/tgconstruct_clip.cxx @@ -77,16 +77,16 @@ bool TGConstruct::ClipLandclassPolys( void ) { for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) { if ( is_landmass_area( i ) && !ignoreLandmass ) { for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) { - land_list.push_back( polys_in.get_mask(i, j) ); + land_list.push_back( polys_in.get_poly(i, j) ); } } else if ( is_water_area( i ) ) { for (unsigned int j = 0; j < polys_in.area_size(i); j++) { - water_list.push_back( polys_in.get_mask(i, j) ); + water_list.push_back( polys_in.get_poly(i, j) ); } } else if ( is_island_area( i ) ) { for (unsigned int j = 0; j < polys_in.area_size(i); j++) { - island_list.push_back( polys_in.get_mask(i, j) ); + island_list.push_back( polys_in.get_poly(i, j) ); } } } @@ -106,10 +106,10 @@ bool TGConstruct::ClipLandclassPolys( void ) { for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) { debug_area = IsDebugArea( i ); for( j = 0; j < (int)polys_in.area_size(i); ++j ) { - tgPolygon current = polys_in.get_mask(i, j); - debug_shape = IsDebugShape( polys_in.get_shape( i, j ).id ); + tgPolygon& current = polys_in.get_poly(i, j); + debug_shape = IsDebugShape( polys_in.get_poly( i, j ).GetId() ); - SG_LOG( SG_CLIPPER, SG_INFO, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_shape( i, j ).id ); + SG_LOG( SG_CLIPPER, SG_DEBUG, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_poly( i, j ).GetId() ); tmp = current; @@ -122,18 +122,17 @@ bool TGConstruct::ClipLandclassPolys( void ) { if ( is_water_area( i ) ) { // clip against island mask tmp = tgPolygon::Diff( tmp, island_mask ); - } if ( debug_area || debug_shape ) { char layer[32]; char name[32]; - sprintf(layer, "pre_clip_%d", polys_in.get_shape( i, j ).id ); + sprintf(layer, "pre_clip_%d", polys_in.get_poly( i, j ).GetId() ); sprintf(name, "shape %d,%d", i,j); tgPolygon::ToShapefile( tmp, ds_name, layer, name ); - sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id ); + sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() ); accum.ToShapefiles( ds_name, layer ); } @@ -143,7 +142,7 @@ bool TGConstruct::ClipLandclassPolys( void ) { char layer[32]; char name[32]; - sprintf(layer, "post_clip_%d", polys_in.get_shape( i, j ).id ); + sprintf(layer, "post_clip_%d", polys_in.get_poly( i, j ).GetId() ); sprintf(name, "shape %d,%d", i,j); tgPolygon::ToShapefile( clipped, ds_name, layer, name ); @@ -159,18 +158,11 @@ bool TGConstruct::ClipLandclassPolys( void ) { // add the sliverless result polygon to the clipped polys list if ( clipped.Contours() > 0 ) { - TGShape shape; - // 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.polys = polys_in.get_shape( i, j ).polys; + clipped.SetId( polys_in.get_poly( i, j ).GetId() ); // shape.sps.push_back( sp ); - polys_clipped.add_shape( i, shape ); + polys_clipped.add_poly( i, clipped ); #if 0 if ( debug_area || debug_shape ) { @@ -183,7 +175,7 @@ bool TGConstruct::ClipLandclassPolys( void ) { accum.Add( tmp ); if ( debug_area || debug_shape ) { char layer[32]; - sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id ); + sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() ); accum.ToShapefiles( ds_name, layer ); } @@ -192,6 +184,7 @@ bool TGConstruct::ClipLandclassPolys( void ) { } } +#if 0 if ( debug_all || debug_shapes.size() || debug_areas.size() ) { // Dump the sliver list char name[32]; @@ -200,6 +193,7 @@ bool TGConstruct::ClipLandclassPolys( void ) { tgContour::ToShapefile( slivers[i], ds_name, "slivers", name ); } } +#endif #if FIND_SLIVERS // Now, merge any slivers with clipped polys @@ -234,40 +228,23 @@ bool TGConstruct::ClipLandclassPolys( void ) { #endif if ( remains.Contours() > 0 ) { - TGShape shape; - - string material = get_area_name(get_sliver_target_area_type()); - remains.SetMaterial( material ); - - shape.SetMask( remains ); - shape.textured = false; - shape.polys.push_back( remains ); - - polys_clipped.add_shape( (int)get_sliver_target_area_type(), shape ); - } - } - - // 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++ ) { - SG_LOG( SG_CLIPPER, SG_INFO, "Seperating segments from clip mask for " << get_area_name( (AreaType)area ) << ":" << shape+1 << " of " << polys_clipped.area_size(area) ); - polys_clipped.get_shape(area, shape).IntersectPolys(); + remains.SetMaterial( get_area_name(get_sliver_target_area_type()) ); + polys_clipped.add_poly( (int)get_sliver_target_area_type(), remains ); } } // Now make sure any newly added intersection nodes are added to the tgnodes for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { - for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - for (unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++) { - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon& poly = polys_clipped.get_poly( area, p ); - SG_LOG( SG_CLIPPER, SG_INFO, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) ); + SG_LOG( SG_CLIPPER, SG_DEBUG, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) ); - for (unsigned int con=0; con < poly.Contours(); con++) { - for (unsigned int node = 0; node < poly.ContourSize( con ); node++) { - // ensure we have all nodes... - nodes.unique_add( poly.GetNode( con, node ) ); - } + for (unsigned int con=0; con < poly.Contours(); con++) { + for (unsigned int n = 0; n < poly.ContourSize( con ); n++) { + // ensure we have all nodes... + TGNode const& node = poly.GetNode( con, n ); + nodes.unique_add( node ); } } } diff --git a/src/BuildTiles/Main/tgconstruct_debug.cxx b/src/BuildTiles/Main/tgconstruct_debug.cxx index a7566abb..2824978d 100644 --- a/src/BuildTiles/Main/tgconstruct_debug.cxx +++ b/src/BuildTiles/Main/tgconstruct_debug.cxx @@ -35,8 +35,6 @@ using std::string; void TGConstruct::set_debug( std::string path, std::vector area_defs, std::vector shape_defs ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Set debug Path " << path); - debug_path = path; /* Find any ids for our tile */ @@ -131,78 +129,4 @@ bool TGConstruct::IsDebugArea( unsigned int area ) } return is_debug; -} - -#if 0 -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 ); - - tgShapefileCreateFeature( ds_id, l_id, shape.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 ); - - 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; iget_node_list(); - node_list sorted_nodes; - for (unsigned int i=0; i raw_nodes; - SGGeoc p; double e1, e2, e3, min; int n1, n2, n3; - SG_LOG(SG_GENERAL, SG_ALERT, "fixing node heights"); - for (int i = 0; i < (int)nodes.size(); ++i) { - TGNode node = nodes.get_node( i ); + TGNode const& node = nodes.get_node( i ); SGGeod pos = node.GetPosition(); if ( !node.GetFixedPosition() ) { @@ -113,122 +86,136 @@ void TGConstruct::CalcElevations( void ) // now flatten some stuff for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { if ( is_lake_area( (AreaType)area ) ) { - for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { - for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { + for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); + tgPolygon poly = polys_clipped.get_poly( area, p ); - SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) ); - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + n1 = poly.GetTriIdx( tri, 0 ); + e1 = nodes.get_node(n1).GetPosition().getElevationM(); + n2 = poly.GetTriIdx( tri, 1 ); + e2 = nodes.get_node(n2).GetPosition().getElevationM(); + n3 = poly.GetTriIdx( tri, 2 ); + e3 = nodes.get_node(n3).GetPosition().getElevationM(); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - n1 = poly.GetTriIdx( tri, 0 ); - e1 = nodes.get_node(n1).GetPosition().getElevationM(); - n2 = poly.GetTriIdx( tri, 1 ); - e2 = nodes.get_node(n2).GetPosition().getElevationM(); - n3 = poly.GetTriIdx( tri, 2 ); - e3 = nodes.get_node(n3).GetPosition().getElevationM(); + min = e1; + if ( e2 < min ) { min = e2; } + if ( e3 < min ) { min = e3; } - min = e1; - if ( e2 < min ) { min = e2; } - if ( e3 < min ) { min = e3; } - - nodes.SetElevation( n1, min ); - nodes.SetElevation( n2, min ); - nodes.SetElevation( n3, min ); - } + nodes.SetElevation( n1, min ); + nodes.SetElevation( n2, min ); + nodes.SetElevation( n3, min ); } } } if ( is_stream_area( (AreaType)area ) ) { - for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { - for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { + for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); + tgPolygon poly = polys_clipped.get_poly( area, p ); - SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) ); - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + n1 = poly.GetTriIdx( tri, 0 ); + e1 = nodes.get_node(n1).GetPosition().getElevationM(); + n2 = poly.GetTriIdx( tri, 1 ); + e2 = nodes.get_node(n2).GetPosition().getElevationM(); + n3 = poly.GetTriIdx( tri, 2 ); + e3 = nodes.get_node(n3).GetPosition().getElevationM(); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - n1 = poly.GetTriIdx( tri, 0 ); - e1 = nodes.get_node(n1).GetPosition().getElevationM(); - n2 = poly.GetTriIdx( tri, 1 ); - e2 = nodes.get_node(n2).GetPosition().getElevationM(); - n3 = poly.GetTriIdx( tri, 2 ); - e3 = nodes.get_node(n3).GetPosition().getElevationM(); + min = e1; + SGGeod src = raw_nodes[n1]; - min = e1; - p = SGGeoc::fromGeod( raw_nodes[n1] ); + if ( e2 < min ) { min = e2; src = raw_nodes[n2]; } + if ( e3 < min ) { min = e3; src = raw_nodes[n3]; } - if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); } - if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); } - - double d1 = distanceSphere( p, raw_nodes[n1] ); - double d2 = distanceSphere( p, raw_nodes[n2] ); - double d3 = distanceSphere( p, raw_nodes[n3] ); - - double max1 = d1 * 0.20 + min; - double max2 = d2 * 0.20 + min; - double max3 = d3 * 0.20 + min; - - if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); } - if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); } - if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); } + double d1, d2, d3; + if ( min == e1 ) { + d1 = 0.0f; + } else { + d1 = SGGeodesy::distanceM( src, raw_nodes[n1] ); } + if ( min == e2 ) { + d2 = 0.0f; + } else { + d2 = SGGeodesy::distanceM( src, raw_nodes[n2] ); + } + if ( min == e3 ) { + d3 = 0.0f; + } else { + d3 = SGGeodesy::distanceM( src, raw_nodes[n3] ); + } + + double max1 = d1 * 0.20 + min; + double max2 = d2 * 0.20 + min; + double max3 = d3 * 0.20 + min; + + if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); } + if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); } + if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); } } } } if ( is_road_area( (AreaType)area ) ) { - for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { - for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { + for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); + tgPolygon poly = polys_clipped.get_poly( area, p ); - SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) ); - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + n1 = poly.GetTriIdx( tri, 0 ); + e1 = nodes.get_node(n1).GetPosition().getElevationM(); + n2 = poly.GetTriIdx( tri, 1 ); + e2 = nodes.get_node(n2).GetPosition().getElevationM(); + n3 = poly.GetTriIdx( tri, 2 ); + e3 = nodes.get_node(n3).GetPosition().getElevationM(); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - n1 = poly.GetTriIdx( tri, 0 ); - e1 = nodes.get_node(n1).GetPosition().getElevationM(); - n2 = poly.GetTriIdx( tri, 1 ); - e2 = nodes.get_node(n2).GetPosition().getElevationM(); - n3 = poly.GetTriIdx( tri, 2 ); - e3 = nodes.get_node(n3).GetPosition().getElevationM(); + min = e1; + SGGeod src = raw_nodes[n1]; - min = e1; - p = SGGeoc::fromGeod( raw_nodes[n1] ); + if ( e2 < min ) { min = e2; src = raw_nodes[n2]; } + if ( e3 < min ) { min = e3; src = raw_nodes[n3]; } - if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); } - if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); } - - double d1 = distanceSphere( p, raw_nodes[n1] ); - double d2 = distanceSphere( p, raw_nodes[n2] ); - double d3 = distanceSphere( p, raw_nodes[n3] ); - - double max1 = d1 * 0.30 + min; - double max2 = d2 * 0.30 + min; - double max3 = d3 * 0.30 + min; - - if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); } - if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); } - if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); } + double d1, d2, d3; + if ( min == e1 ) { + d1 = 0.0f; + } else { + d1 = SGGeodesy::distanceM( src, raw_nodes[n1] ); } + if ( min == e2 ) { + d2 = 0.0f; + } else { + d2 = SGGeodesy::distanceM( src, raw_nodes[n2] ); + } + if ( min == e3 ) { + d3 = 0.0f; + } else { + d3 = SGGeodesy::distanceM( src, raw_nodes[n3] ); + } + + double max1 = d1 * 0.30 + min; + double max2 = d2 * 0.30 + min; + double max3 = d3 * 0.30 + min; + + if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); } + if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); } + if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); } } } } if ( is_ocean_area( (AreaType)area ) ) { - for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { - for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { + for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) ); + tgPolygon poly = polys_clipped.get_poly( area, p ); - SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) ); - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + n1 = poly.GetTriIdx( tri, 0 ); + n2 = poly.GetTriIdx( tri, 1 ); + n3 = poly.GetTriIdx( tri, 2 ); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - n1 = poly.GetTriIdx( tri, 0 ); - n2 = poly.GetTriIdx( tri, 1 ); - n3 = poly.GetTriIdx( tri, 2 ); - - nodes.SetElevation( n1, 0.0 ); - nodes.SetElevation( n2, 0.0 ); - nodes.SetElevation( n3, 0.0 ); - } + nodes.SetElevation( n1, 0.0 ); + nodes.SetElevation( n2, 0.0 ); + nodes.SetElevation( n3, 0.0 ); } } } diff --git a/src/BuildTiles/Main/tgconstruct_lookup.cxx b/src/BuildTiles/Main/tgconstruct_lookup.cxx index c00d44ec..bbe58de5 100644 --- a/src/BuildTiles/Main/tgconstruct_lookup.cxx +++ b/src/BuildTiles/Main/tgconstruct_lookup.cxx @@ -34,27 +34,21 @@ // indexes into the node array (cast as unsigned long) void TGConstruct::LookupNodesPerVertex( void ) { - SG_LOG(SG_GENERAL, SG_ALERT, "LookupNodesPerVertex"); - // for each node, traverse all the triangles - and create face lists for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { - for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { - tgPolygon poly = polys_clipped.get_poly( area, shape, segment ); + for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon& poly = polys_clipped.get_poly( area, p ); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - for (unsigned int vertex = 0; vertex < 3; vertex++) { - int idx = nodes.find( poly.GetTriNode( tri, vertex ) ); - if (idx >= 0) { - poly.SetTriIdx( tri, vertex, idx ); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << poly.GetTriNode( tri, vertex ) ); - exit(0); - } + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + for (unsigned int vertex = 0; vertex < 3; vertex++) { + int idx = nodes.find( poly.GetTriNode( tri, vertex ) ); + if (idx >= 0) { + poly.SetTriIdx( tri, vertex, idx ); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << poly.GetTriNode( tri, vertex ) ); + exit(0); } } - - polys_clipped.set_poly( area, shape, segment, poly ); } } } @@ -62,19 +56,15 @@ void TGConstruct::LookupNodesPerVertex( void ) void TGConstruct::LookupFacesPerNode( void ) { - SG_LOG(SG_GENERAL, SG_ALERT, "LookupFacesPerNode"); - // Add each face that includes a node to the node's face list for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { - for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { - tgPolygon poly = polys_clipped.get_poly(area, shape, segment); + for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon const& poly = polys_clipped.get_poly(area, p ); - for (unsigned int tri=0; tri < poly.Triangles(); tri++) { - for (int v = 0; v < 3; v++) { - int i = poly.GetTriIdx( tri, v ); - nodes.AddFace( i, area, shape, segment, tri ); - } + for (unsigned int tri=0; tri < poly.Triangles(); tri++) { + for (int v = 0; v < 3; v++) { + int i = poly.GetTriIdx( tri, v ); + nodes.AddFace( i, area, p, tri ); } } } diff --git a/src/BuildTiles/Main/tgconstruct_math.cxx b/src/BuildTiles/Main/tgconstruct_math.cxx index 0c02a822..e3298c86 100644 --- a/src/BuildTiles/Main/tgconstruct_math.cxx +++ b/src/BuildTiles/Main/tgconstruct_math.cxx @@ -29,19 +29,7 @@ #include "tgconstruct.hxx" -//using std::string; - -#if 0 -double TGConstruct::calc_tri_area( int_list& triangle_nodes ) { - SGGeod p1 = nodes.get_node( triangle_nodes[0] ).GetPosition(); - SGGeod p2 = nodes.get_node( triangle_nodes[1] ).GetPosition(); - SGGeod p3 = nodes.get_node( triangle_nodes[2] ).GetPosition(); - - return triangle_area( p1, p2, p3 ); -} -#endif - -SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) { +SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const { SGVec3f v1, v2; SGVec3f normal; @@ -111,11 +99,9 @@ void TGConstruct::CalcFaceNormals( void ) nodes.get_geod_nodes( geod_nodes ); for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { - for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { - SG_LOG( SG_CLIPPER, SG_INFO, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_in.area_size(area) ); - calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, shape, segment ) ); - } + for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_in.area_size(area) ); + calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, p ) ); } } } @@ -123,9 +109,7 @@ 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: 0%"); - - SGVec3d normal; + SGVec3f normal; double face_area; std::vector wgs84_nodes; @@ -135,15 +119,15 @@ void TGConstruct::CalcPointNormals( void ) unsigned int cur_percent = 1; for ( unsigned int i = 0; iface_areas.size(); for ( int j = 0; j < num_faces; j++ ) { - normal = neighbor_faces->face_normals[j].toSGVec3d(); + normal = neighbor_faces->face_normals[j]; face_area = neighbor_faces->face_areas[j]; normal *= face_area; @@ -178,7 +161,6 @@ void TGConstruct::CalcPointNormals( void ) } average /= total_area; - SGVec3f n = SGVec3f( average.x(), average.y(), average.z() ); - nodes.SetNormal( i, n ); + nodes.SetNormal( i, average ); } -} +} \ No newline at end of file diff --git a/src/BuildTiles/Main/tgconstruct_output.cxx b/src/BuildTiles/Main/tgconstruct_output.cxx index 208a7c4a..36be2be1 100644 --- a/src/BuildTiles/Main/tgconstruct_output.cxx +++ b/src/BuildTiles/Main/tgconstruct_output.cxx @@ -135,45 +135,35 @@ void TGConstruct::WriteBtgFile( void ) int_list pt_n, tri_n, strip_n; int_list tri_tc, strip_tc; - SG_LOG(SG_GENERAL, SG_INFO, "Output triangles" ); - for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { // only tesselate non holes if ( !is_hole_area( area ) ) { - for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { - SG_LOG( SG_CLIPPER, SG_INFO, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" << - shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) ); + for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + SG_LOG( SG_CLIPPER, SG_DEBUG, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) ); - tgPolygon poly = polys_clipped.get_poly(area, shape, segment); - string material = polys_clipped.get_material(area, shape, segment); + tgPolygon poly = polys_clipped.get_poly(area, p); + string material = poly.GetMaterial(); - SG_LOG(SG_GENERAL, SG_INFO, " num tris " << poly.Triangles() ); + for (unsigned int k = 0; k < poly.Triangles(); ++k) { + tri_v.clear(); + tri_n.clear(); + tri_tc.clear(); + for (int l = 0; l < 3; ++l) { + index = poly.GetTriIdx( k, l ); + tri_v.push_back( index ); - for (unsigned int k = 0; k < poly.Triangles(); ++k) { - tri_v.clear(); - tri_n.clear(); - tri_tc.clear(); - for (int l = 0; l < 3; ++l) { - index = poly.GetTriIdx( k, l ); - tri_v.push_back( index ); + // add the node's normal + index = normals.add( nodes.GetNormal( index ) ); + tri_n.push_back( index ); - // add the node's normal - index = normals.add( nodes.GetNormal( index ) ); - tri_n.push_back( index ); - - index = texcoords.add( poly.GetTriTexCoord( k, l ) ); - tri_tc.push_back( index ); - } - tris_v.push_back( tri_v ); - tris_n.push_back( tri_n ); - tris_tc.push_back( tri_tc ); - - material = polys_clipped.get_material(area, shape, segment); - SG_LOG(SG_GENERAL, SG_INFO, "Add tri material " << material); - - tri_materials.push_back( material ); + index = texcoords.add( poly.GetTriTexCoord( k, l ) ); + tri_tc.push_back( index ); } + tris_v.push_back( tri_v ); + tris_n.push_back( tri_n ); + tris_tc.push_back( tri_tc ); + + tri_materials.push_back( material ); } } } diff --git a/src/BuildTiles/Main/tgconstruct_poly.cxx b/src/BuildTiles/Main/tgconstruct_poly.cxx index cf76696b..e3edb37e 100644 --- a/src/BuildTiles/Main/tgconstruct_poly.cxx +++ b/src/BuildTiles/Main/tgconstruct_poly.cxx @@ -37,20 +37,6 @@ using std::string; static unsigned int cur_poly_id = 0; -// Add a polygon to the clipper. - only used by load_osgb36_poly - make that function more like ogr load -void TGConstruct::add_poly( int area, tgPolygon &poly, string material ) { - TGShape shape; - - if ( area < TG_MAX_AREA_TYPES ) { - poly.SetMaterial( material ); - shape.polys.push_back( poly ); - polys_in.add_shape( area, shape ); - } else { - SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " << area); - exit(-1); - } -} - bool TGConstruct::load_poly(const string& path) { bool poly3d = false; bool with_tp = false; @@ -114,11 +100,11 @@ bool TGConstruct::load_poly(const string& path) { // Generate a new Shape for the poly - TGShape shape; tgPolygon poly; SGGeod p; - + for (k=0; k> x; @@ -213,24 +199,19 @@ bool TGConstruct::load_poly(const string& path) { poly.SetMaterial( material ); if ( with_tp ) { - shape.textured = true; + poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, -1, 0, 1, 0 ); } else { - shape.textured = false; + poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() ); } - shape.polys.push_back( poly ); in >> skipcomment; - } - // Once the full poly is loaded, build the clip mask - shape.BuildMask(); - shape.area = area; - shape.id = cur_poly_id++; + poly.SetId( cur_poly_id++ ); + polys_in.add_poly( area, poly ); - polys_in.add_shape( area, shape ); - - if ( IsDebugShape( shape.id ) ) { - tgPolygon::ToShapefile( shape.mask, ds_name, "loaded", "" ); + if ( IsDebugShape( poly.GetId() ) ) { + tgPolygon::ToShapefile( poly, ds_name, "loaded", "" ); + } } } @@ -260,7 +241,7 @@ int TGConstruct::LoadLandclassPolys( void ) { } simgear::PathList files = d.children(simgear::Dir::TYPE_FILE); - SG_LOG( SG_CLIPPER, SG_ALERT, files.size() << " Polys in " << d.path() ); + SG_LOG( SG_CLIPPER, SG_DEBUG, files.size() << " Polys in " << d.path() ); BOOST_FOREACH(const SGPath& p, files) { if (p.file_base() != tile_str) { @@ -274,7 +255,7 @@ int TGConstruct::LoadLandclassPolys( void ) { // skipped! } else { load_poly( p.str() ); - SG_LOG(SG_GENERAL, SG_ALERT, " Loaded " << p.file()); + SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file()); ++count; } } // of directory file children diff --git a/src/BuildTiles/Main/tgconstruct_shared.cxx b/src/BuildTiles/Main/tgconstruct_shared.cxx index a5287b8e..40633215 100644 --- a/src/BuildTiles/Main/tgconstruct_shared.cxx +++ b/src/BuildTiles/Main/tgconstruct_shared.cxx @@ -96,7 +96,7 @@ void TGConstruct::SaveSharedEdgeData( int stage ) { // for stage 2, we need enough info on a node to average out elevation and // generate a correct normal - // we will use the Point3D, as stage1 above, then a point list per node + // we will use a geod, as stage1 above, then a geod list per node // to store the neighboors. // // NOTE: Some neighboors (likely 2) are on the shared border. @@ -110,12 +110,12 @@ void TGConstruct::SaveSharedEdgeData( int stage ) } } -void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt ) +void TGConstruct::WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const { // find all neighboors of this point - int n = nodes.find( pt.toSGGeod() ); - TGNode node = nodes.get_node( n ); - TGFaceList faces = node.GetFaces(); + int n = nodes.find( pt ); + TGNode const& node = nodes.get_node( n ); + TGFaceList const& faces = node.GetFaces(); // write the number of neighboor faces sgWriteInt( fp, faces.size() ); @@ -123,20 +123,16 @@ void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt ) // write out each face normal and size for (unsigned int j=0; j= 0) { - TGNode local = nodes.get_node( idx ); + TGNode const& local = nodes.get_node( idx ); pFaces->elevations.push_back( local.GetPosition().getElevationM() ); } } @@ -212,7 +208,7 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp ) pFaces->face_areas.push_back( area ); sgReadVec3( fp, normal ); - pFaces->face_normals.push_back( Point3D::fromSGVec3( normal ) ); + pFaces->face_normals.push_back( normal ); } } } @@ -246,7 +242,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void ) for (int i=0; i& north, std::vector& south, std::vector& east, std::vector& west ) { string dir; string file; gzFile fp; - Point3D pt; + SGGeod pt; int nCount; dir = share_base + "/stage1/" + b.gen_base_path(); @@ -445,33 +442,33 @@ void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, p if (fp) { // North sgReadInt( fp, &nCount ); - SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary"); + SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary"); 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(); @@ -495,28 +492,28 @@ void TGConstruct::LoadSharedEdgeData( int stage ) LoadNeighboorEdgeDataStage1( nb, north, south, east, west ); // Add southern nodes from northern tile for (unsigned int i=0; i #endif -//#include #include -#include -//#include - #include "tgconstruct.hxx" -//using std::string; - void TGConstruct::TesselatePolys( void ) { // tesselate the polygons and prepair them for final output @@ -42,38 +36,40 @@ void TGConstruct::TesselatePolys( void ) SGGeod min, max; 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 p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon poly = polys_clipped.get_poly(area, p ); - if ( IsDebugShape( id ) ) { - tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "preteselate", "" ); + if ( IsDebugShape( poly.GetId() ) ) { + tgPolygon::ToShapefile( poly, ds_name, "preteselate", "" ); } - for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { - tgPolygon poly = polys_clipped.get_poly(area, shape, segment); + tg::Rectangle rect = poly.GetBoundingBox(); + nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra ); - tg::Rectangle rect = poly.GetBoundingBox(); - nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra ); + SG_LOG( SG_CLIPPER, SG_DEBUG, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " << + p+1 << " of " << (int)polys_clipped.area_size(area) << ": id = " << poly.GetId() ); - SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " << - shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) << - ": id = " << id ); + if ( IsDebugShape( poly.GetId() ) ) { + SG_LOG( SG_CLIPPER, SG_INFO, poly ); + } - if ( IsDebugShape( id ) ) { - SG_LOG( SG_CLIPPER, SG_INFO, poly ); + poly.Tesselate( poly_extra ); + + polys_clipped.set_poly( area, p, poly ); + } + } + + + for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { + for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon& poly = polys_clipped.get_poly(area, p ); + + // ensure all added nodes are accounted for + for (unsigned int k=0; k < poly.Triangles(); k++) { + for (int l = 0; l < 3; l++) { + // ensure we have all nodes... + nodes.unique_add( poly.GetTriNode( k, l ) ); } - - poly.Tesselate( poly_extra ); - - // ensure all added nodes are accounted for - for (unsigned int k=0; k < poly.Triangles(); k++) { - for (int l = 0; l < 3; l++) { - // ensure we have all nodes... - nodes.unique_add( poly.GetTriNode( k, l ) ); - } - } - - polys_clipped.set_poly( area, shape, segment, poly ); } } } diff --git a/src/BuildTiles/Main/tgconstruct_texture.cxx b/src/BuildTiles/Main/tgconstruct_texture.cxx index 19cb7842..d3ef266f 100644 --- a/src/BuildTiles/Main/tgconstruct_texture.cxx +++ b/src/BuildTiles/Main/tgconstruct_texture.cxx @@ -25,161 +25,19 @@ # include #endif -#include -#include #include - #include "tgconstruct.hxx" -TGPolygon TGConstruct::area_tex_coords( const TGPolygon& tri ) -{ - TGPolygon result; - result.erase(); - - // lots of conversion needed to use simgear API - perhaps we need a new simgear API? - for (int c=0; c conv_geods; - point_list tex_coords; - - for (int i = 0; i < (int)nodes.size(); ++i ) - { - SGGeod conv_geod = SGGeod::fromDegM( nodes[i].x(), nodes[i].y(), nodes[i].z() ); - SG_LOG(SG_GENERAL, SG_DEBUG, "geod pt = " << nodes[i] ); - conv_geods.push_back( conv_geod ); - } - - // now calculate texture coordinates - // generate identity interger list... - std::vector< int > node_idx; - for (int i = 0; i < (int)conv_geods.size(); i++) { - node_idx.push_back(i); - } - - std::vector< SGVec2f > tp_list = sgCalcTexCoords( bucket, conv_geods, node_idx ); - // generate a contour of texture coordinates from the tp list - for (int i = 0; i < (int)tp_list.size(); i++) - { - tex_coords.push_back( Point3D::fromSGVec2( tp_list[i] ) ); - } - result.add_contour( tex_coords, 0 ); - } - - return result; -} - -TGPolygon TGConstruct::linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp ) -{ - TGPolygon result; - int i, j; - - result.erase(); - - SGGeod ref = tp.get_ref(); - double width = tp.get_width(); - double length = tp.get_length(); - double heading = tp.get_heading(); - double minu = tp.get_minu(); - double maxu = tp.get_maxu(); - double minv = tp.get_minv(); - double maxv = tp.get_maxv(); - SG_LOG( SG_GENERAL, SG_DEBUG, "section ref = " << ref ); - SG_LOG( SG_GENERAL, SG_DEBUG, " width = " << width ); - SG_LOG( SG_GENERAL, SG_DEBUG, " length = " << length ); - SG_LOG( SG_GENERAL, SG_DEBUG, " heading = " << heading ); - SG_LOG( SG_GENERAL, SG_DEBUG, " minv = " << minv ); - SG_LOG( SG_GENERAL, SG_DEBUG, " maxv = " << maxv ); - SG_LOG( SG_GENERAL, SG_DEBUG, " heading = " << heading ); - - Point3D p, t; - double x, y, tx, ty; - - for ( i = 0; i < tri.contours(); ++i ) - { - for ( j = 0; j < tri.contour_size( i ); ++j ) - { - p = tri.get_pt( i, j ); - SG_LOG(SG_GENERAL, SG_DEBUG, "tex coords for contour " << i << " point " << j << ": " << p ); - - // - // 1. Calculate distance and bearing from the center of - // the feature - // - - // given alt, lat1, lon1, lat2, lon2, calculate starting - // and ending az1, az2 and distance (s). Lat, lon, and - // azimuth are in degrees. distance in meters - double az1, az2, dist; - geo_inverse_wgs_84( 0, ref.getLatitudeDeg(), ref.getLongitudeDeg(), p.y(), p.x(), - &az1, &az2, &dist ); - SG_LOG(SG_GENERAL, SG_DEBUG, "basic course from ref = " << az2); - - // - // 2. Rotate this back into a coordinate system where Y - // runs the length of the runway and X runs crossways. - // - - double course = az2 - heading; - while ( course < -360 ) { course += 360; } - while ( course > 360 ) { course -= 360; } - SG_LOG( SG_GENERAL, SG_DEBUG, - " course = " << course << " dist = " << dist ); - - // - // 3. Convert from polar to cartesian coordinates - // - - x = sin( course * SGD_DEGREES_TO_RADIANS ) * dist; - y = cos( course * SGD_DEGREES_TO_RADIANS ) * dist; - SG_LOG(SG_GENERAL, SG_DEBUG, " x = " << x << " y = " << y); - - // - // 4. Map x, y point into texture coordinates - // - double tmp; - - tmp = x / width; - tx = tmp * (maxu - minu) + minu; - - if ( tx < -1.0 ) { tx = -1.0; } - if ( tx > 1.0 ) { tx = 1.0; } - - SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ")"); - - ty = (y/length) + minv; - SG_LOG(SG_GENERAL, SG_DEBUG, " (" << ty << ")"); - - t = Point3D( tx, ty, 0 ); - SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ", " << ty << ")"); - - result.add_node( i, t ); - } - } - - return result; -} - void TGConstruct::CalcTextureCoordinates( void ) { for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { - for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { - 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, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " << - shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() ); + for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) { + tgPolygon poly = polys_clipped.get_poly(area, p); + SG_LOG( SG_CLIPPER, SG_DEBUG, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " << + p+1 << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() ); - if ( polys_clipped.get_textured( area, shape ) ) { - SG_LOG(SG_GENERAL, SG_DEBUG, "USE TEXTURE PARAMS for tex coord calculations" ); - poly.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, -1, -1, 1, 1 ); - } else { - SG_LOG(SG_GENERAL, SG_DEBUG, "USE SIMGEAR for tex coord calculations" ); - poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() ); - } - poly.Texture( ); - polys_clipped.set_poly(area, shape, segment, poly); - } + poly.Texture( ); + polys_clipped.set_poly(area, p, poly); } } -} +} \ No newline at end of file diff --git a/src/BuildTiles/Main/tglandclass.cxx b/src/BuildTiles/Main/tglandclass.cxx index cac0a1ec..803b5e1d 100644 --- a/src/BuildTiles/Main/tglandclass.cxx +++ b/src/BuildTiles/Main/tglandclass.cxx @@ -38,7 +38,7 @@ void TGLandclass::clear(void) int i; for (i=0; i #include -#define TG_MAX_AREA_TYPES 128 -#include "tgshape.hxx" +#include + +#define TG_MAX_AREA_TYPES 128 class TGLandclass { @@ -46,108 +47,50 @@ public: inline unsigned int area_size( unsigned int area ) { - return shapes[area].size(); - } - inline unsigned int shape_size( unsigned int area, unsigned int shape ) - { - return shapes[area][shape].polys.size(); + return polys[area].size(); } - inline void add_shape( unsigned int area, TGShape shape ) + inline tgPolygon const& get_poly( unsigned int area, unsigned int poly ) const { - shapes[area].push_back( shape ); + return polys[area][poly]; } - inline TGShape& get_shape( unsigned int area, unsigned int shape ) + inline tgPolygon & get_poly( unsigned int area, unsigned int poly ) { - return shapes[area][shape]; + return polys[area][poly]; + } + inline void add_poly( unsigned int area, const tgPolygon& p ) + { + polys[area].push_back( p ); + } + inline void set_poly( unsigned int area, unsigned int poly, const tgPolygon& p ) + { + polys[area][poly] = p; } - inline tgPolygon get_mask( unsigned int area, unsigned int shape ) + inline tgpolygon_list& get_polys( unsigned int area ) { - return shapes[area][shape].mask; + return polys[area]; } - inline void set_mask( unsigned int area, unsigned int shape, tgPolygon mask ) + + inline const SGVec3f& get_face_normal( unsigned int area, unsigned int poly, unsigned int tri ) const { - shapes[area][shape].mask = mask; + return polys[area][poly].GetTriFaceNormal( tri ); } - inline bool get_textured( unsigned int area, unsigned int shape ) + inline double get_face_area( unsigned int area, unsigned int poly, unsigned int tri ) { - return shapes[area][shape].textured; - } - inline void set_textured( unsigned int area, unsigned int shape, bool t ) - { - shapes[area][shape].textured = t; + return polys[area][poly].GetTriFaceArea( tri ); } - inline tgPolygon& get_poly( unsigned int area, unsigned int shape, unsigned int segment ) + inline std::string get_material( unsigned int area, unsigned int poly ) { - return shapes[area][shape].polys[segment]; + return polys[area][poly].GetMaterial(); } - inline void set_poly( unsigned int area, unsigned int shape, unsigned int segment, const tgPolygon& sp ) + inline const tgTexParams& get_texparams( unsigned int area, unsigned int poly ) { - shapes[area][shape].polys[segment] = sp; + return polys[area][poly].GetTexParams(); } -#if 0 - inline TGPolygon get_tris( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].sps[segment].get_tris(); - } - inline void set_tris( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon tris ) - { - shapes[area][shape].sps[segment].set_tris( tris ); - } -#endif - - inline Point3D get_face_normal( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri ) - { - return Point3D::fromSGVec3( shapes[area][shape].polys[segment].GetTriFaceNormal( tri ) ); - } - - inline double get_face_area( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri ) - { - return shapes[area][shape].polys[segment].GetTriFaceArea( tri ); - } - -#if 0 - inline std::string get_flag( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].sps[segment].get_flag(); - } -#endif - - inline std::string get_material( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].polys[segment].GetMaterial(); - } - inline const tgTexParams& get_texparams( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].polys[segment].GetTexParams(); - } - -/* - inline TGPolygon get_texcoords( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].sps[segment].get_texcoords(); - } - inline void set_texcoords( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon tcs ) - { - return shapes[area][shape].sps[segment].set_texcoords( tcs ); - } -*/ - -/* - inline TGPolyNodes get_tri_idxs( unsigned int area, unsigned int shape, unsigned int segment ) - { - return shapes[area][shape].sps[segment].get_tri_idxs(); - } - inline void set_tri_idxs( unsigned int area, unsigned int shape, unsigned int segment, TGPolyNodes tis ) - { - return shapes[area][shape].sps[segment].set_tri_idxs( tis ); - } -*/ - void SaveToGzFile( gzFile& fp ); void LoadFromGzFile( gzFile& fp ); @@ -155,7 +98,7 @@ public: friend std::ostream& operator<< ( std::ostream&, const TGLandclass& ); private: - shape_list shapes[TG_MAX_AREA_TYPES]; + tgpolygon_list polys[TG_MAX_AREA_TYPES]; }; #endif // _TGLANDCLASS_HXX diff --git a/src/BuildTiles/Main/tgshape.cxx b/src/BuildTiles/Main/tgshape.cxx deleted file mode 100644 index 54e1ec72..00000000 --- a/src/BuildTiles/Main/tgshape.cxx +++ /dev/null @@ -1,129 +0,0 @@ -// TGShape.cxx -- Class to handle polygons shapes generated in ogr-decode -// A shape may consist of many polygons when it is generated -// from a polyline. They are kept together to speed up clipping -// but also must be represented as seperate polygons in order to -// keep track of textur parameters. -// -// Written by Curtis Olson, started May 1999. -// -// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -// -// $Id: construct.cxx,v 1.4 2004-11-19 22:25:49 curt Exp $ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "tgshape.hxx" - -void TGShape::GetName( char* name ) const -{ - sprintf( name, "%s_%d", get_area_name( (AreaType)area ).c_str(), id ); -} - -void TGShape::SetMask( const tgPolygon& m ) -{ - mask = m; -} - -void TGShape::BuildMask( void ) -{ - mask = tgPolygon::Union( polys ); -} - -void TGShape::IntersectPolys( void ) -{ - if ( polys.size() > 1 ) { - for (unsigned int i=0; i -#include -#include - -#include -#include - -#include "priorities.hxx" - -class TGShape -{ -public: - tgpolygon_list polys; - tgPolygon mask; - bool textured; - AreaType area; - unsigned int id; - - void GetName( char* name ) const; - void SetMask( const tgPolygon& mask ); - void BuildMask( void ); - void IntersectPolys( void ); - void SaveToGzFile( gzFile& fp ); - void LoadFromGzFile( gzFile& fp ); - - // Friend for output to stream - friend std::ostream& operator<< ( std::ostream&, const TGShape& ); -}; - -typedef std::vector < TGShape > shape_list; -typedef shape_list::iterator shape_list_iterator; -typedef shape_list::const_iterator const_shape_list_iterator; - -#endif // _TGSHAPE_HXX \ No newline at end of file diff --git a/src/Lib/Geometry/tg_nodes.cxx b/src/Lib/Geometry/tg_nodes.cxx index 0de198b4..cd95e2c3 100644 --- a/src/Lib/Geometry/tg_nodes.cxx +++ b/src/Lib/Geometry/tg_nodes.cxx @@ -1,146 +1,17 @@ #include -#include - #include "tg_nodes.hxx" -// compare node's positions (x, then y) -int compare_position(const TGNode& n1, const TGNode& n2) -{ - SGGeod pos1 = n1.GetPosition(); - SGGeod pos2 = n2.GetPosition(); - - if ( pos1.getLongitudeDeg() == pos2.getLongitudeDeg() ) { - return ( pos1.getLatitudeDeg() < pos2.getLatitudeDeg() ); - } else { - return ( pos1.getLongitudeDeg() < pos2.getLongitudeDeg() ); - } -} - -int fuzzy_compare_xposition(const TGNode& n1, const TGNode& n2) -{ - SGGeod pos1 = n1.GetPosition(); - SGGeod pos2 = n2.GetPosition(); - - if ( fabs(pos1.getLongitudeDeg() - pos2.getLongitudeDeg()) < FG_PROXIMITY_EPSILON ) { - /* if x coords are within vacinity, then pos1 < pos2 */ - return 1; - } else { - return compare_position( n1, n2 ); - } -} - -void TGNodes::SortNodes( void ) -{ - std::sort(tg_node_list.begin(), tg_node_list.end(), compare_position); - sorted = true; -} -// Find the index of the specified point (compair to the same -// tolerance as unique_add(). Returns -1 if not found. -int TGNodes::sorted_find( const SGGeod& p ) const { - TGNode node( p ); - const_node_list_iterator lb, ub; - - // first, find the range to search - ub=lower_bound( tg_node_list.begin(), tg_node_list.end(), node, fuzzy_compare_xposition ); - lb=upper_bound( tg_node_list.begin(), tg_node_list.end(), node, fuzzy_compare_xposition ); - - // then do a normal linear search in the range - if ( lb != tg_node_list.end() ) { - for ( ; lb != ub; ++lb ) { - if ( close_enough_2d(p, lb->GetPosition()) ) { - return std::distance( tg_node_list.begin(), lb ); - } - } - } - - return -1; -} - -int TGNodes::linear_find( const SGGeod& p ) const { - const_node_list_iterator current, last; - SGGeod pos; - int counter = 0; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - for ( ; current != last; ++current ) { - pos = current->GetPosition(); - if ( close_enough_2d(p, pos ) ) { - return counter; - } - - ++counter; - } - - return -1; -} - -void TGNodes::linear_unique_add( const SGGeod& p ) { - node_list_iterator current, last; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - - for ( ; current != last; ++current ) { - if ( close_enough_2d(p, (*current).GetPosition() ) ) { - return; - } - - } - - TGNode node( p ); - node.SetFixedPosition( false ); - - // add to list - tg_node_list.push_back( node ); -} - -void TGNodes::linear_unique_add_fixed_elevation( const SGGeod& p ) { - node_list_iterator current, last; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - - for ( ; current != last; ++current ) { - if ( close_enough_2d(p, (*current).GetPosition() ) ) { - - // Force the match to our position, and mark as fixed - (*current).SetPosition( p ); - (*current).SetFixedPosition( true ); - - return; - } - - } - - TGNode node( p ); - node.SetFixedPosition( true ); - - // add to list - tg_node_list.push_back( node ); -} - -void TGNodes::get_geod_nodes( std::vector& points ) const { - const_node_list_iterator current, last; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - - points.clear(); - for ( ; current != last; ++current ) { - points.push_back( (*current).GetPosition() ); - } -} - -// TODO: if the list is sorted, we should be able to get the range from x=min to x=max, -// then within that range, add each point where y is within ymin, max -// still linear search, but should be less points const double fgPoint3_Epsilon = 0.000001; +#define USE_SPACIAL_QUERY + +#ifndef USE_SPACIAL_QUERY + +void TGNodes::init_spacial_query( void ) +{ + kd_tree_valid = true; +} + static bool IsWithin( const SGGeod pt, double xmin, double xmax, double ymin, double ymax ) { return ( (xmin <= pt.getLongitudeDeg()) && (ymin <= pt.getLatitudeDeg()) && @@ -157,41 +28,32 @@ static bool IsAlmostWithin( const SGGeod pt, const SGGeod& min, const SGGeod& ma max.getLatitudeDeg() + fgPoint3_Epsilon ) ); } -void TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector& points ) const { - const_node_list_iterator current, last; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - +bool TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector& points ) const { points.clear(); - for ( ; current != last; ++current ) { - SGGeod pt = (*current).GetPosition(); + for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) { + SGGeod const& pt = tg_node_list[i].GetPosition(); if ( IsAlmostWithin( pt, min, max ) ) { points.push_back( pt ); } } + + return true; } -void TGNodes::get_geod_edge( const SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ) const { - const_node_list_iterator current, last; +bool TGNodes::get_geod_edge( const SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ) const { double north_compare = b.get_center_lat() + 0.5 * b.get_height(); double south_compare = b.get_center_lat() - 0.5 * b.get_height(); double east_compare = b.get_center_lon() + 0.5 * b.get_width(); double west_compare = b.get_center_lon() - 0.5 * b.get_width(); - // find all points on the edges - current = tg_node_list.begin(); - last = tg_node_list.end(); - north.clear(); south.clear(); east.clear(); west.clear(); - for ( ; current != last; ++current ) { - SGGeod pt = (*current).GetPosition(); + for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) { + SGGeod const& pt = tg_node_list[i].GetPosition(); // may save the same point twice - so we get all the corners if ( fabs(pt.getLatitudeDeg() - north_compare) < SG_EPSILON) { @@ -207,36 +69,171 @@ void TGNodes::get_geod_edge( const SGBucket& b, std::vector& north, std: west.push_back( pt ); } } + + return true; +} + +#else + +// The spacial search utilizes the boost tuple construct. +// The k-d tree is generated in two dimensions. and the first element of the tuple is this 2d point +// the second element of the tuple is the elevation of this point +// Three dimensional queries is a bit overkill, but the code, although faster, is slightly more cumbersome + +// get function for the property map - needed for cgal trait extension +My_point_property_map::reference get(My_point_property_map, My_point_property_map::key_type p) { + return boost::get<0>(p); +} + +// Build the k-d tree +void TGNodes::init_spacial_query( void ) +{ + tg_kd_tree.clear(); + + for(unsigned int i = 0; i < tg_node_list.size(); i++) { + // generate the tuple + Point pt( tg_node_list[i].GetPosition().getLongitudeDeg(), tg_node_list[i].GetPosition().getLatitudeDeg() ); + double e( tg_node_list[i].GetPosition().getElevationM() ); + Point_and_Elevation pande(pt, e); + + // and insert into tree + tg_kd_tree.insert( pande ); + } + + kd_tree_valid = true; +} + +// Spacial Queries using CGAL and boost tuple + +// This query finds all nodes within the bounding box +bool TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector& points ) const { + points.clear(); + + // Have we generated the k-d tree? + if ( !kd_tree_valid ) { + SG_LOG(SG_GENERAL, SG_ALERT, "get_geod_inside called with invalid kdtree" ); + exit(0); + return false; + } + + // define an exact rectangulat range query (fuzziness=0) + Point ll( min.getLongitudeDeg() - fgPoint3_Epsilon, min.getLatitudeDeg() - fgPoint3_Epsilon ); + Point ur( max.getLongitudeDeg() + fgPoint3_Epsilon, max.getLatitudeDeg() + fgPoint3_Epsilon ); + Fuzzy_bb exact_bb(ll, ur); + + // list of tuples as a result + std::list result; + std::list::iterator it; + + // perform the query + tg_kd_tree.search(std::back_inserter( result ), exact_bb); + + // and convert the tuples back into SGGeod + for ( it = result.begin(); it != result.end(); it++ ) { + points.push_back( SGGeod::fromDegM( boost::get<0>(*it).x(), boost::get<0>(*it).y(), boost::get<1>(*it) ) ); + } + + return true; +} + +// This query finds all nodes along the tile borders (north, south, east and west) +bool TGNodes::get_geod_edge( const SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ) const { + double north_compare = b.get_center_lat() + 0.5 * b.get_height(); + double south_compare = b.get_center_lat() - 0.5 * b.get_height(); + double east_compare = b.get_center_lon() + 0.5 * b.get_width(); + double west_compare = b.get_center_lon() - 0.5 * b.get_width(); + + Point ll; + Point ur; + Fuzzy_bb exact_bb; + + std::list result; + std::list::iterator it; + + north.clear(); + south.clear(); + east.clear(); + west.clear(); + + // Have we generated the k-d tree? + if ( !kd_tree_valid ) { + SG_LOG(SG_GENERAL, SG_ALERT, "get_geod_edge called with invalid kdtree" ); + exit(0); + return false; + } + + // find northern points + ll = Point( west_compare - fgPoint3_Epsilon, north_compare - fgPoint3_Epsilon ); + ur = Point( east_compare + fgPoint3_Epsilon, north_compare + fgPoint3_Epsilon ); + exact_bb = Fuzzy_bb(ll, ur); + result.clear(); + tg_kd_tree.search(std::back_inserter( result ), exact_bb); + for ( it = result.begin(); it != result.end(); it++ ) { + north.push_back( SGGeod::fromDegM( boost::get<0>(*it).x(), boost::get<0>(*it).y(), boost::get<1>(*it) ) ); + } + + // find southern points + ll = Point( west_compare - fgPoint3_Epsilon, south_compare - fgPoint3_Epsilon ); + ur = Point( east_compare + fgPoint3_Epsilon, south_compare + fgPoint3_Epsilon ); + exact_bb = Fuzzy_bb(ll, ur); + result.clear(); + + tg_kd_tree.search(std::back_inserter( result ), exact_bb); + for ( it = result.begin(); it != result.end(); it++ ) { + south.push_back( SGGeod::fromDegM( boost::get<0>(*it).x(), boost::get<0>(*it).y(), boost::get<1>(*it) ) ); + } + + // find eastern points + ll = Point( east_compare - fgPoint3_Epsilon, south_compare - fgPoint3_Epsilon ); + ur = Point( east_compare + fgPoint3_Epsilon, north_compare + fgPoint3_Epsilon ); + exact_bb = Fuzzy_bb(ll, ur); + result.clear(); + + tg_kd_tree.search(std::back_inserter( result ), exact_bb); + for ( it = result.begin(); it != result.end(); it++ ) { + east.push_back( SGGeod::fromDegM( boost::get<0>(*it).x(), boost::get<0>(*it).y(), boost::get<1>(*it) ) ); + } + + // find western points + ll = Point( west_compare - fgPoint3_Epsilon, south_compare - fgPoint3_Epsilon ); + ur = Point( west_compare + fgPoint3_Epsilon, north_compare + fgPoint3_Epsilon ); + exact_bb = Fuzzy_bb(ll, ur); + result.clear(); + + tg_kd_tree.search(std::back_inserter( result ), exact_bb); + for ( it = result.begin(); it != result.end(); it++ ) { + west.push_back( SGGeod::fromDegM( boost::get<0>(*it).x(), boost::get<0>(*it).y(), boost::get<1>(*it) ) ); + } + + return true; +} + +#endif + +void TGNodes::get_geod_nodes( std::vector& points ) const { + points.clear(); + for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) { + points.push_back( tg_node_list[i].GetPosition() ); + } } void TGNodes::get_wgs84_nodes( std::vector& points ) const { - const_node_list_iterator current, last; - - current = tg_node_list.begin(); - last = tg_node_list.end(); - points.clear(); - for ( ; current != last; ++current ) { - points.push_back( (*current).GetWgs84() ); + for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) { + points.push_back( tg_node_list[i].GetWgs84() ); } } void TGNodes::get_normals( std::vector& normals ) const { - const_node_list_iterator current, last; - - // see if point already exists - current = tg_node_list.begin(); - last = tg_node_list.end(); - normals.clear(); - for ( ; current != last; ++current ) { - normals.push_back( (*current).GetNormal() ); + for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) { + normals.push_back( tg_node_list[i].GetNormal() ); } } void TGNodes::Dump( void ) { for (unsigned int i=0; i + +#include +//#include +//#include + +#include +#include +#include +#include +#include /* Just use two dimensional lookup - elevation is a trait */ +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_2 Point; +typedef boost::tuple Point_and_Elevation; + +//definition of the property map +struct My_point_property_map{ + typedef Point value_type; + typedef const value_type& reference; + typedef const Point_and_Elevation& key_type; + typedef boost::readable_property_map_tag category; +}; + +//typedef CGAL::Search_traits_2 Traits; +typedef CGAL::Search_traits_2 Traits_base; +typedef CGAL::Search_traits_adapter Traits; + +typedef CGAL::Fuzzy_iso_box Fuzzy_bb; +typedef CGAL::Kd_tree Tree; + + #include #include -//#include #include +#include + #define FG_PROXIMITY_EPSILON 0.000001 #define FG_COURSE_EPSILON 0.0001 -// for each node, we'll need a vector to lookup all triangles the node -// is a member of. -struct TGFaceLookup { - unsigned int area; - unsigned int shape; - unsigned int seg; - unsigned int tri; -}; -typedef std::vector < TGFaceLookup > TGFaceList; - - -class TGNode { -public: - TGNode() { - // constructor for serialization only - } - - TGNode( SGGeod p ) { - position = p; - CalcWgs84(); - - fixed_position = false; // no matter what - don't move x, y, or z (likely a hole around an airport generated ny genapts) - fixed_normal = false; // no matter what - don't modify the normal - likely on a normal generated on a shared edge - - faces.clear(); - } - - inline void SetFixedPosition( bool fix ) - { - if (!fixed_position) { - fixed_position = fix; - } - } - - inline void CalcWgs84() - { - wgs84 = SGVec3d::fromGeod(position); - } - - inline void AddFace( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri ) - { - TGFaceLookup face; - face.area = area; - face.shape = shape; - face.seg = segment; - face.tri = tri; - - faces.push_back( face ); - } - - inline TGFaceList GetFaces( void ) const { return faces; } - inline bool GetFixedPosition( void ) const { return fixed_position; } - inline void SetFixedNormal( bool fix ) { fixed_normal = fix; } - inline bool GetFixedNormal( void ) const { return fixed_normal; } - inline SGVec3d GetWgs84( void ) const { return wgs84; } - - inline void SetPosition( const SGGeod& p ) - { - if (!fixed_position) { - position = p; - CalcWgs84(); - } - } - - inline void SetElevation( double z ) - { - if (!fixed_position) { - position.setElevationM( z ); - CalcWgs84(); - } - } - - inline SGGeod GetPosition( void ) const { return position; } - inline void SetNormal( const SGVec3f& n ) { normal = n; } - inline SGVec3f GetNormal( void ) const { return normal; } - - void SaveToGzFile( gzFile& fp ); - void LoadFromGzFile( gzFile& fp ); - // Friends for serialization - friend std::ostream& operator<< ( std::ostream&, const TGNode& ); - -private: - SGGeod position; - SGVec3f normal; - SGVec3d wgs84; - - bool fixed_position; - bool fixed_normal; - - TGFaceList faces; -}; -typedef std::vector < TGNode > node_list; -typedef node_list::iterator node_list_iterator; -typedef node_list::const_iterator const_node_list_iterator; /* This class handles ALL of the nodes in a tile : 3d nodes in elevation data, 2d nodes generated from landclass, etc) */ class TGNodes { public: // Constructor and destructor - TGNodes( void ) { - sorted = false; + TGNodes( void ) { + kd_tree_valid = false; } + ~TGNodes( void ) {} // delete all the data out of node_list inline void clear() { - tg_node_list.clear(); - sorted = false; + kd_tree_valid = false; } // Add a point to the point list if it doesn't already exist. // Returns the index (starting at zero) of the point in the list. void unique_add( const SGGeod& p ) { - if ( !sorted ) { - linear_unique_add( p ); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); - exit(0); - } + TGNode n(p); + n.SetFixedPosition(false); + tg_node_list.add(n); + kd_tree_valid = false; + } + + void unique_add( const TGNode& n ) { + tg_node_list.add(n); + kd_tree_valid = false; } // Add a point to the point list if it doesn't already exist // (checking all three dimensions.) Returns the index (starting // at zero) of the point in the list. void unique_add_fixed_elevation( const SGGeod& p ) { - if ( !sorted ) { - linear_unique_add_fixed_elevation( p ); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); - exit(0); - } + TGNode n(p); + n.SetFixedPosition(true); + tg_node_list.add(n); + kd_tree_valid = false; } // Find the index of the specified point (compair to the same // tolerance as unique_add(). Returns -1 if not found. int find( const SGGeod& p ) const { - if ( sorted ) { - return sorted_find( p ); - } else { - return linear_find( p ); - } + TGNode n(p); + return tg_node_list.find(n); } - void SortNodes( void ); + void init_spacial_query( void ); + void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); } SGVec3f GetNormal( int idx ) const { return tg_node_list[idx].GetNormal(); } void SetNormal( int idx, SGVec3f n ) { tg_node_list[idx].SetNormal( n ); } - // return the master node list - inline node_list& get_node_list() { return tg_node_list; } - inline const node_list& get_node_list() const { return tg_node_list; } - // return a point list of geodetic nodes void get_geod_nodes( std::vector& points ) const; // Find all the nodes within a bounding box - void get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector& points ) const; + bool get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector& points ) const; // Find a;; the nodes on the tile edges - void get_geod_edge( const SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ) const; + bool get_geod_edge( const SGBucket& b, std::vector& north, std::vector& south, std::vector& east, std::vector& west ) const; // return a point list of wgs84 nodes void get_wgs84_nodes( std::vector& points ) const; @@ -187,32 +121,32 @@ public: // return a point list of normals void get_normals( std::vector& normals ) const; - // return the ith point - inline TGNode get_node( int i ) const { return tg_node_list[i]; } + // return the ith point (constant) + inline TGNode const& get_node( int i ) const { return tg_node_list[i]; } + inline TGNode& get_node( int i ) { return tg_node_list[i]; } - inline void AddFace( int i, unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri ) + TGNode const& operator[]( int index ) const { + return tg_node_list[index]; + } + + + inline void AddFace( int i, unsigned int area, unsigned int poly, unsigned int tri ) { - tg_node_list[i].AddFace( area, shape, segment, tri ); + tg_node_list[i].AddFace( area, poly, tri ); } // return the size of the node list inline size_t size() const { return tg_node_list.size(); } void Dump( void ); + void SaveToGzFile( gzFile& fp ); void LoadFromGzFile( gzFile& fp ); - - // Friends for serialization - friend std::ostream& operator<< ( std::ostream&, const TGNodes& ); - + private: - void linear_unique_add( const SGGeod& p ); - void linear_unique_add_fixed_elevation( const SGGeod& p ); - - int sorted_find( const SGGeod& p ) const; - int linear_find( const SGGeod& p ) const; - node_list tg_node_list; - bool sorted; + UniqueTGNodeSet tg_node_list; + Tree tg_kd_tree; + bool kd_tree_valid; // return true of the two points are "close enough" as defined by // FG_PROXIMITY_EPSILON diff --git a/src/Lib/Polygon/polygon.cxx b/src/Lib/Polygon/polygon.cxx index 31d8ec0f..1fada60c 100644 --- a/src/Lib/Polygon/polygon.cxx +++ b/src/Lib/Polygon/polygon.cxx @@ -36,7 +36,6 @@ #include #include "polygon.hxx" -#include "tg_unique_geod.hxx" #ifdef _MSC_VER # define LONG_LONG_MAX LLONG_MAX @@ -2235,6 +2234,9 @@ tgPolygon tgPolygon::Expand( const tgPolygon& subject, double offset ) result.SetMaterial( subject.GetMaterial() ); result.SetTexParams( subject.GetTexParams() ); + result.SetMaterial( subject.GetMaterial() ); + result.SetTexParams( subject.GetTexParams() ); + return result; } @@ -2280,6 +2282,9 @@ tgPolygon tgPolygon::Union( const tgPolygon& subject, tgPolygon& clip ) result = tgPolygon::FromClipper( clipper_result ); result = tgPolygon::AddColinearNodes( result, all_nodes ); + result.SetMaterial( subject.GetMaterial() ); + result.SetTexParams( subject.GetTexParams() ); + return result; } @@ -2337,6 +2342,9 @@ tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip ) result = tgPolygon::FromClipper( clipper_result ); result = tgPolygon::AddColinearNodes( result, all_nodes ); + result.SetMaterial( subject.GetMaterial() ); + result.SetTexParams( subject.GetTexParams() ); + return result; } @@ -2794,21 +2802,15 @@ void tgPolygon::LoadFromGzFile( gzFile& fp ) // load the triangles sgReadUInt( fp, &count ); - SG_LOG(SG_GENERAL, SG_INFO, " load " << count << " triangles" ); - for (unsigned int i = 0; i < count; i++) { triangle.LoadFromGzFile( fp ); AddTriangle(triangle); } - SG_LOG(SG_GENERAL, SG_INFO, " load texparams" ); - // Load the tex params tp.LoadFromGzFile( fp ); // and the rest - SG_LOG(SG_GENERAL, SG_INFO, " load material" ); - sgReadString( fp, &strbuff ); if ( strbuff ) { material = strbuff; @@ -3486,28 +3488,19 @@ void tgAccumulator::Add( const tgPolygon& subject ) accum.push_back( clipper_subject ); } - std::vector node_list; - std::vector tc_list; - std::vector norm_list; - std::vector idx_list; - - SGVec3f face_normal; - double face_area; - - void tgTriangle::SaveToGzFile( gzFile& fp ) { // Save the three nodes, and their attributes for (unsigned int i = 0; i < 3; i++) { sgWriteGeod( fp, node_list[i] ); - sgWriteVec2( fp, tc_list[i] ); - sgWritedVec3( fp, norm_list[i] ); + // sgWriteVec2( fp, tc_list[i] ); + // sgWritedVec3( fp, norm_list[i] ); // not calculated until stage 3 sgWriteInt( fp, idx_list[i] ); } // and the area, and face normal - sgWriteVec3( fp, face_normal ); - sgWriteDouble( fp, face_area ); + // sgWriteVec3( fp, face_normal ); // not calculated until stage3 + // sgWriteDouble( fp, face_area ); // not calculated until stage3 } void tgTriangle::LoadFromGzFile( gzFile& fp ) @@ -3515,57 +3508,76 @@ void tgTriangle::LoadFromGzFile( gzFile& fp ) // Load the nodelist for (unsigned int i = 0; i < 3; i++) { sgReadGeod( fp, node_list[i] ); - sgReadVec2( fp, tc_list[i] ); - sgReaddVec3( fp, norm_list[i] ); + // sgReadVec2( fp, tc_list[i] ); + // sgReaddVec3( fp, norm_list[i] ); sgReadInt( fp, &idx_list[i] ); } // and the area, and face normal - sgReadVec3( fp, face_normal ); - sgReadDouble( fp, &face_area ); + // sgReadVec3( fp, face_normal ); + // sgReadDouble( fp, &face_area ); } void tgTexParams::SaveToGzFile( gzFile& fp ) { // Save the parameters - sgWriteGeod( fp, ref ); - - sgWriteDouble( fp, width ); - sgWriteDouble( fp, length ); - sgWriteDouble( fp, heading ); - - sgWriteDouble( fp, minu ); - sgWriteDouble( fp, maxu ); - sgWriteDouble( fp, minv ); - sgWriteDouble( fp, maxv ); - - sgWriteDouble( fp, min_clipu ); - sgWriteDouble( fp, max_clipu ); - sgWriteDouble( fp, min_clipv ); - sgWriteDouble( fp, max_clipv ); - sgWriteInt( fp, (int)method ); + + if ( method == TG_TEX_BY_GEODE ) { + sgWriteDouble( fp, center_lat ); + } else { + sgWriteGeod( fp, ref ); + sgWriteDouble( fp, width ); + sgWriteDouble( fp, length ); + sgWriteDouble( fp, heading ); + + sgWriteDouble( fp, minu ); + sgWriteDouble( fp, maxu ); + sgWriteDouble( fp, minv ); + sgWriteDouble( fp, maxv ); + + if ( (method == TG_TEX_BY_TPS_CLIPU) || + (method == TG_TEX_BY_TPS_CLIPUV) ) { + sgWriteDouble( fp, min_clipu ); + sgWriteDouble( fp, max_clipu ); + } + + if ( (method == TG_TEX_BY_TPS_CLIPV) || + (method == TG_TEX_BY_TPS_CLIPUV) ) { + sgWriteDouble( fp, min_clipv ); + sgWriteDouble( fp, max_clipv ); + } + } } void tgTexParams::LoadFromGzFile( gzFile& fp ) { // Load the parameters - sgReadGeod( fp, ref ); - - sgReadDouble( fp, &width ); - sgReadDouble( fp, &length ); - sgReadDouble( fp, &heading ); - - sgReadDouble( fp, &minu ); - sgReadDouble( fp, &maxu ); - sgReadDouble( fp, &minv ); - sgReadDouble( fp, &maxv ); - - sgReadDouble( fp, &min_clipu ); - sgReadDouble( fp, &max_clipu ); - sgReadDouble( fp, &min_clipv ); - sgReadDouble( fp, &max_clipv ); - sgReadInt( fp, (int*)&method ); -} + if ( method == TG_TEX_BY_GEODE ) { + sgReadDouble( fp, ¢er_lat ); + } else { + sgReadGeod( fp, ref ); + sgReadDouble( fp, &width ); + sgReadDouble( fp, &length ); + sgReadDouble( fp, &heading ); + + sgReadDouble( fp, &minu ); + sgReadDouble( fp, &maxu ); + sgReadDouble( fp, &minv ); + sgReadDouble( fp, &maxv ); + + if ( (method == TG_TEX_BY_TPS_CLIPU) || + (method == TG_TEX_BY_TPS_CLIPUV) ) { + sgReadDouble( fp, &min_clipu ); + sgReadDouble( fp, &max_clipu ); + } + + if ( (method == TG_TEX_BY_TPS_CLIPV) || + (method == TG_TEX_BY_TPS_CLIPUV) ) { + sgReadDouble( fp, &min_clipv ); + sgReadDouble( fp, &max_clipv ); + } + } +} \ No newline at end of file diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index 3d13eb1f..f34be04d 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -314,6 +314,9 @@ std::ostream &operator<<(std::ostream &output, const TGPolygon &poly); #include #include +#include "tg_unique_geod.hxx" + + // forward declaration class tgPolygon; @@ -352,6 +355,10 @@ public: SGGeod GetNode( unsigned int i ) const { return node_list[i]; } + SGGeod const& operator[]( int index ) const { + return node_list[index]; + } + void RemoveNodeAt( unsigned int idx ) { if ( idx < node_list.size() ) { node_list.erase( node_list.begin() + idx ); @@ -423,7 +430,7 @@ public: idx_list.resize( 3, -1 ); } - SGGeod GetNode( unsigned int i ) const { + SGGeod const& GetNode( unsigned int i ) const { return node_list[i]; } std::vector& GetNodeList( void ) { @@ -449,7 +456,7 @@ public: void SetFaceNormal( const SGVec3f& n ) { face_normal = n; }; - SGVec3f GetFaceNormal( void ) const { + SGVec3f const& GetFaceNormal( void ) const { return face_normal; } @@ -527,7 +534,6 @@ typedef void (*tgpolygon_texfunc)(void); class tgPolygon { public: - void Erase( void ) { contours.clear(); triangles.clear(); @@ -539,7 +545,7 @@ public: unsigned int ContourSize( unsigned int c ) const { return contours[c].GetSize(); } - void AddContour( tgContour contour ) { + void AddContour( tgContour const& contour ) { contours.push_back(contour); } tgContour GetContour( unsigned int c ) const { @@ -551,10 +557,10 @@ public: } } - unsigned int TotalNodes( void ) const; - SGGeod GetNode( unsigned int c, unsigned int i ) const { - return contours[c].GetNode( i ); + + SGGeod const& GetNode( unsigned int c, unsigned int i ) const { + return contours[c][i]; } void SetNode( unsigned int c, unsigned int i, const SGGeod& n ) { contours[c].SetNode( i, n ); @@ -600,7 +606,7 @@ public: void SetTriFaceNormal( unsigned int c, const SGVec3f& n ) { triangles[c].SetFaceNormal( n ); } - SGVec3f GetTriFaceNormal( unsigned int c ) const { + SGVec3f const& GetTriFaceNormal( unsigned int c ) const { return triangles[c].GetFaceNormal(); } void SetTriFaceArea( unsigned int c, double a ) { @@ -610,12 +616,20 @@ public: return triangles[c].GetFaceArea(); } - std::string GetMaterial( void ) const { + std::string const& GetMaterial( void ) const { return material; } - void SetMaterial( const std::string m ) { + void SetMaterial( const std::string& m ) { material = m; } + + unsigned int GetId( void ) const { + return id; + } + void SetId( unsigned int i ) { + id = i; + } + void SetTexParams( const SGGeod& ref, double width, double length, double heading ) { tp.ref = ref; tp.width = width; @@ -650,7 +664,6 @@ public: tp.center_lat = cl; } - void Tesselate( void ); void Tesselate( const std::vector& extra ); @@ -708,9 +721,10 @@ private: tgcontour_list contours; tgtriangle_list triangles; - std::string material; - std::string flag; // let's get rid of this.... - tgTexParams tp; + std::string material; + std::string flag; // let's get rid of this.... + unsigned int id; // unique polygon id for debug + tgTexParams tp; }; class tgLight diff --git a/src/Lib/Polygon/tg_unique_geod.hxx b/src/Lib/Polygon/tg_unique_geod.hxx index 74c4b17a..5f5e3fde 100644 --- a/src/Lib/Polygon/tg_unique_geod.hxx +++ b/src/Lib/Polygon/tg_unique_geod.hxx @@ -1,3 +1,6 @@ +#ifndef _TG_UNIQUE_SGGEOD_HXX +#define _TG_UNIQUE_SGGEOD_HXX + #include #include @@ -117,6 +120,18 @@ public: return index; } + SGGeod const& operator[]( int index ) const { + return geod_list[index]; + } + + SGGeod& operator[]( int index ) { + return geod_list[index]; + } + + size_t size( void ) const { + return geod_list.size(); + } + std::vector& get_list( void ) { return geod_list; } void get_node_list(); @@ -124,3 +139,5 @@ private: unique_geod_set index_list; std::vector geod_list; }; + +#endif /* _TG_UNIQUE_SGGEOD_HXX */ \ No newline at end of file diff --git a/src/Lib/Polygon/tg_unique_tgnode.hxx b/src/Lib/Polygon/tg_unique_tgnode.hxx new file mode 100644 index 00000000..af008028 --- /dev/null +++ b/src/Lib/Polygon/tg_unique_tgnode.hxx @@ -0,0 +1,262 @@ +#ifndef _TG_UNIQUE_TGNODE_HXX +#define _TG_UNIQUE_TGNODE_HXX + +#include +#include + +#include +#include + +// Implement Unique TGNode list + +// We use a hash to store the indices. All iterators returned from find are +// constant, because modifying a value will modify the hash - rendering the +// set invalid. +// Selection of the bucket is tightly linked to the key equality function. +// If any value is considered equal to another, than the hash function MUST +// compute the same hash for each value. +// So close_enough_2d will remain our testo of equality. It simply rounds to +// 6 decimal places. Our hash function will round to 5, so at most 10 points in the +// same bucket. +// We could experiment with making it so 1 point per bucket, but I'm nervous... + +#define PROXIMITY_MULTIPLIER (100000) +#define PROXIMITY_EPSILON ((double) 1 / (double)( PROXIMITY_MULTIPLIER * 10 ) ) + +// for each node, we'll need a vector to lookup all triangles the node +// is a member of. +struct TGFaceLookup { + unsigned int area; + unsigned int poly; + unsigned int tri; +}; +typedef std::vector < TGFaceLookup > TGFaceList; + + +class TGNode { +public: + TGNode() { + // constructor for serialization only + } + + TGNode( SGGeod p ) { + position = p; + CalcWgs84(); + + fixed_position = false; // no matter what - don't move x, y, or z (likely a hole around an airport generated ny genapts) + faces.clear(); + } + + inline void SetFixedPosition( bool fix ) + { + if (!fixed_position) { + fixed_position = fix; + } + } + + inline void CalcWgs84() + { + wgs84 = SGVec3d::fromGeod(position); + } + + inline void AddFace( unsigned int area, unsigned int poly, unsigned int tri ) + { + TGFaceLookup face; + face.area = area; + face.poly = poly; + face.tri = tri; + + faces.push_back( face ); + } + + inline TGFaceList const& GetFaces( void ) const { return faces; } + inline bool GetFixedPosition( void ) const { return fixed_position; } + inline SGVec3d const& GetWgs84( void ) const { return wgs84; } + + inline void SetPosition( const SGGeod& p ) + { + if (!fixed_position) { + position = p; + CalcWgs84(); + } + } + + inline void SetElevation( double z ) + { + if (!fixed_position) { + position.setElevationM( z ); + CalcWgs84(); + } + } + + inline SGGeod const& GetPosition( void ) const { return position; } + inline void SetNormal( const SGVec3f& n ) { normal = n; } + inline SGVec3f GetNormal( void ) const { return normal; } + + void SaveToGzFile( gzFile& fp ) { + sgWriteGeod( fp, position ); + sgWriteInt( fp, (int)fixed_position ); + + // Don't save the facelist per node + // it's much faster to just redo the lookup + } + + void LoadFromGzFile( gzFile& fp ) { + int temp; + + sgReadGeod( fp, position ); + CalcWgs84(); + + sgReadInt( fp, &temp ); + fixed_position = (bool)temp; + } + + // Friends for serialization + friend std::ostream& operator<< ( std::ostream&, const TGNode& ); + +private: + SGGeod position; + SGVec3f normal; + SGVec3d wgs84; + + bool fixed_position; + + TGFaceList faces; +}; + +class TGNodeIndex { +public: + TGNodeIndex( SGGeod g ) { + geod = g; + + std::size_t FNV_prime; + std::size_t offset_basis; + + switch( sizeof( std::size_t ) ) { + case 4: // 32 bit system + default: + FNV_prime = 16777619ULL; + offset_basis = 2166136261ULL; + break; + + case 8: // 64 bit system + FNV_prime = 1099511628211ULL; + offset_basis = 14695981039346656037ULL; + break; + } + + hash = (std::size_t)offset_basis; + + /* only hash lon, lat - we want to detect dups in 2d only */ + unsigned long long raw_pt[2]; + raw_pt[0] = (unsigned long long)( SGMisc::round(geod.getLongitudeDeg() * PROXIMITY_MULTIPLIER) ); + raw_pt[1] = (unsigned long long)( SGMisc::round(geod.getLatitudeDeg() * PROXIMITY_MULTIPLIER) ); + + unsigned char* it = (unsigned char*)raw_pt; + for ( unsigned i=0; i +{ + std::size_t operator()(TGNodeIndex const& gi) const { + return gi.GetHash(); + } +}; + +typedef boost::unordered_set unique_tgnode_set; +typedef unique_tgnode_set::iterator unique_tgnode_set_iterator; +typedef unique_tgnode_set::const_iterator const_unique_tgnode_set_iterator; + +class UniqueTGNodeSet { +public: + UniqueTGNodeSet() {} + + unsigned int add( const TGNode& n ) { + unique_tgnode_set_iterator it; + TGNodeIndex lookup( n.GetPosition() ); + + it = index_list.find( lookup ); + if ( it == index_list.end() ) { + lookup.SetOrderedIndex( node_list.size() ); + index_list.insert( lookup ); + + node_list.push_back(n); + } else { + lookup = *it; + } + + return lookup.GetOrderedIndex(); + } + + int find( const TGNode& n ) const { + unique_tgnode_set_iterator it; + TGNodeIndex lookup( n.GetPosition() ); + int index = -1; + + it = index_list.find( lookup ); + if ( it != index_list.end() ) { + index = it->GetOrderedIndex(); + } + + return index; + } + + TGNode const& operator[]( int index ) const { + return node_list[index]; + } + + TGNode& operator[]( int index ) { + return node_list[index]; + } + + size_t size( void ) const { + return node_list.size(); + } + + std::vector& get_list( void ) { return node_list; } + + void SaveToGzFile( gzFile& fp ) { + // Just save the node_list - rebuild the index list on load + sgWriteUInt( fp, node_list.size() ); + for (unsigned int i=0; i node_list; +}; + +#endif /* _TG_UNIQUE_TGNODE_HXX */ \ No newline at end of file