From c336c134bf0c6ae8ec920ec09daf91c1d9fc3762 Mon Sep 17 00:00:00 2001 From: Peter Sadrozinski Date: Wed, 17 Oct 2012 18:56:54 -0400 Subject: [PATCH] Use binary gzip files to store intermediate and shared edge files Sort the nodelist to speedup node lookup after all nodes inserted retrieve the node list just once in flatten elevation --- src/BuildTiles/Main/tgconstruct.cxx | 41 +-- src/BuildTiles/Main/tgconstruct.hxx | 8 +- src/BuildTiles/Main/tgconstruct_elevation.cxx | 8 +- src/BuildTiles/Main/tgconstruct_lookup.cxx | 3 +- src/BuildTiles/Main/tgconstruct_shared.cxx | 279 +++++++++--------- src/BuildTiles/Main/tglandclass.cxx | 34 ++- src/BuildTiles/Main/tglandclass.hxx | 4 + src/BuildTiles/Main/tgshape.cxx | 59 +++- src/BuildTiles/Main/tgshape.hxx | 10 +- src/Lib/Geometry/point3d.hxx | 11 + src/Lib/Geometry/tg_nodes.cxx | 240 ++++++++++++++- src/Lib/Geometry/tg_nodes.hxx | 66 ++++- src/Lib/Polygon/polygon.cxx | 45 ++- src/Lib/Polygon/polygon.hxx | 3 + src/Lib/Polygon/superpoly.cxx | 108 ++++++- src/Lib/Polygon/superpoly.hxx | 6 + src/Lib/Polygon/texparams.cxx | 28 +- src/Lib/Polygon/texparams.hxx | 3 + 18 files changed, 757 insertions(+), 199 deletions(-) diff --git a/src/BuildTiles/Main/tgconstruct.cxx b/src/BuildTiles/Main/tgconstruct.cxx index 2a5e5586..4a1f771a 100644 --- a/src/BuildTiles/Main/tgconstruct.cxx +++ b/src/BuildTiles/Main/tgconstruct.cxx @@ -84,8 +84,8 @@ void TGConstruct::ConstructBucketStage1() { } // STEP 1) - // Load grid of elevation data (Array) - LoadElevationArray(); + // Load grid of elevation data (Array), and add the nodes + LoadElevationArray( true ); // STEP 2) // Clip 2D polygons against one another @@ -131,37 +131,42 @@ void TGConstruct::ConstructBucketStage2() { } // STEP 7) - // Need the array of elevation data for stage 2 - LoadElevationArray(); + // Need the array of elevation data for stage 2, but don't add the nodes - we already have them + LoadElevationArray( false ); - // STEP 6) + // STEP 8) // Merge in Shared data - should just be x,y nodes on the borders from stage1 LoadSharedEdgeData( 1 ); - // STEP 7) + // STEP 9) // Fix T-Junctions by finding nodes that lie close to polygon edges, and // inserting them into the edge FixTJunctions(); - // STEP 8) + // 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 TesselatePolys(); - // STEP 9) + // 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 LookupNodesPerVertex(); - // STEP 10) + // STEP 13) // Interpolate elevations, and flatten stuff CalcElevations(); - // STEP 11) + // STEP 14) // Generate face_connected list LookupFacesPerNode(); - // STEP 12) + // STEP 15) // Save the tile boundary info for stage 3 // includes elevation info, and a list of connected triangles SaveSharedEdgeData( 2 ); @@ -182,22 +187,24 @@ void TGConstruct::ConstructBucketStage3() { strcpy( ds_name, "" ); } + // STEP 16) // Load in the neighbor faces and elevation data LoadSharedEdgeDataStage2(); - // STEP 12) + // STEP 17) // Average out the elevation for nodes on tile boundaries AverageEdgeElevations(); - // STEP 12) + // STEP 18) // Calculate Face Normals CalcFaceNormals(); - // STEP 13) + // STEP 19) // Calculate Point Normals CalcPointNormals(); #if 0 + // STEP 20) if ( c.get_cover().size() > 0 ) { // Now for all the remaining "default" land cover polygons, assign // each one it's proper type from the land use/land cover @@ -206,15 +213,15 @@ void TGConstruct::ConstructBucketStage3() { } #endif - // STEP 14) + // STEP 21) // Calculate Texture Coordinates CalcTextureCoordinates(); - // STEP 16) + // STEP 22) // Generate the btg file WriteBtgFile(); - // STEP 17) + // STEP 23) // Write Custom objects to .stg file AddCustomObjects(); } diff --git a/src/BuildTiles/Main/tgconstruct.hxx b/src/BuildTiles/Main/tgconstruct.hxx index 66ec9840..592fea52 100644 --- a/src/BuildTiles/Main/tgconstruct.hxx +++ b/src/BuildTiles/Main/tgconstruct.hxx @@ -120,7 +120,7 @@ private: bool IsOceanTile() { return isOcean; } // Load Data - void LoadElevationArray( void ); + void LoadElevationArray( bool add_nodes ); int LoadLandclassPolys( void ); // Load Data Helpers bool load_poly(const std::string& path); @@ -135,14 +135,14 @@ private: // Shared edge Matching void SaveSharedEdgeDataStage2( void ); void LoadSharedEdgeDataStage2( void ); - void WriteSharedEdgeNeighboorFaces( std::ofstream& ofs_e, Point3D pt ); + 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 SaveSharedEdgeData( int stage ); - void ReadNeighborFaces( std::ifstream& ifs_e ); - void WriteNeighborFaces( std::ofstream& ofs_e, Point3D pt ); + void ReadNeighborFaces( gzFile& fp ); + void WriteNeighborFaces( gzFile& fp, Point3D pt ); TGNeighborFaces* AddNeighborFaces( Point3D node ); TGNeighborFaces* FindNeighborFaces( Point3D node ); diff --git a/src/BuildTiles/Main/tgconstruct_elevation.cxx b/src/BuildTiles/Main/tgconstruct_elevation.cxx index e0b6b5b5..81b456bd 100644 --- a/src/BuildTiles/Main/tgconstruct_elevation.cxx +++ b/src/BuildTiles/Main/tgconstruct_elevation.cxx @@ -32,7 +32,7 @@ using std::string; // Load elevation data from an Array file (a regular grid of elevation data) // and return list of fitted nodes. -void TGConstruct::LoadElevationArray( void ) { +void TGConstruct::LoadElevationArray( bool add_nodes ) { string base = bucket.gen_base_path(); int i; @@ -49,6 +49,7 @@ void TGConstruct::LoadElevationArray( void ) { array.parse( bucket ); array.remove_voids( ); + if ( add_nodes ) { point_list corner_list = array.get_corner_list(); for (unsigned int i=0; i= 0) { tri_nodes.add_node( tri, idx ); } else { + SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << tris.get_pt( tri, vertex ) ); exit(0); } } diff --git a/src/BuildTiles/Main/tgconstruct_shared.cxx b/src/BuildTiles/Main/tgconstruct_shared.cxx index fe327a7d..dfa2182a 100644 --- a/src/BuildTiles/Main/tgconstruct_shared.cxx +++ b/src/BuildTiles/Main/tgconstruct_shared.cxx @@ -28,6 +28,7 @@ #include #include +#include #include @@ -37,8 +38,7 @@ using std::string; void TGConstruct::SaveSharedEdgeData( int stage ) { - string dir; - string file; + string filepath; switch( stage ) { case 1: @@ -48,48 +48,47 @@ void TGConstruct::SaveSharedEdgeData( int stage ) nodes.get_geod_edge( bucket, north, south, east, west ); - dir = share_base + "/stage1/" + bucket.gen_base_path(); + filepath = share_base + "/stage1/" + bucket.gen_base_path() + "/" + bucket.gen_index_str() + "_edges"; + SGPath file(filepath); + file.create_dir( 0755 ); - SGPath sgp( dir ); - sgp.append( "dummy" ); - sgp.create_dir( 0755 ); + gzFile fp; + if ( (fp = gzopen( filepath.c_str(), "wb9" )) == NULL ) { + SG_LOG( SG_GENERAL, SG_INFO, "ERROR: opening " << file.str() << " for writing!" ); + return; + } - file = dir + "/" + bucket.gen_index_str() + "_edges"; - std::ofstream ofs_e( file.c_str() ); - - // first, set the precision - ofs_e << std::setprecision(12); - ofs_e << std::fixed; + sgClearWriteError(); // north nCount = north.size(); - ofs_e << nCount << "\n"; + sgWriteInt( fp, nCount ); for (int i=0; i> count; + sgReadInt( fp, &count ); for (int i=0; i> node; + sgReadPoint3D( fp, node ); // look to see if we already have this node // If we do, (it's a corner) add more faces to it. @@ -205,16 +203,16 @@ void TGConstruct::ReadNeighborFaces( std::ifstream& in ) // remember all of the elevation data for the node, so we can average pFaces->elevations.push_back( node.z() ); - in >> num_faces; + sgReadInt( fp, &num_faces ); for (int j=0; j> area; + sgReadDouble( fp, &area ); pFaces->face_areas.push_back( area ); - in >> normal; + sgReadPoint3D( fp, normal ); pFaces->face_normals.push_back( normal ); } } @@ -225,7 +223,6 @@ void TGConstruct::SaveSharedEdgeDataStage2( void ) string dir; string file; point_list north, south, east, west; - std::ofstream ofs_e; int nCount; nodes.get_geod_edge( bucket, north, south, east, west ); @@ -239,110 +236,123 @@ void TGConstruct::SaveSharedEdgeDataStage2( void ) // north edge file = dir + "/" + bucket.gen_index_str() + "_north_edge"; - ofs_e.open( file.c_str() ); - ofs_e << std::setprecision(12); - ofs_e << std::fixed; + gzFile fp; + if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) { + SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" ); + return; + } + sgClearWriteError(); nCount = north.size(); - ofs_e << nCount << "\n"; + sgWriteInt( fp, nCount ); for (int i=0; i> nCount; + sgReadInt( fp, &nCount ); SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary"); for (int i=0; i> pt; + sgReadPoint3D( fp, pt ); north.push_back(pt); } // South - ifs_edges >> nCount; + sgReadInt( fp, &nCount ); SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " south boundary"); for (int i=0; i> pt; + sgReadPoint3D( fp, pt ); south.push_back(pt); } // East - ifs_edges >> nCount; + sgReadInt( fp, &nCount ); SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " east boundary"); for (int i=0; i> pt; + sgReadPoint3D( fp, pt ); east.push_back(pt); } // West - ifs_edges >> nCount; + sgReadInt( fp, &nCount ); SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " west boundary"); for (int i=0; i> pt; + sgReadPoint3D( fp, pt ); west.push_back(pt); } - ifs_edges.close(); + gzclose( fp ); } } @@ -517,6 +529,7 @@ void TGConstruct::LoadFromIntermediateFiles( int stage ) { string dir; string file; + gzFile fp; bool read_ok = false; switch( stage ) { @@ -524,18 +537,18 @@ void TGConstruct::LoadFromIntermediateFiles( int stage ) { dir = share_base + "/stage1/" + bucket.gen_base_path(); file = dir + "/" + bucket.gen_index_str() + "_clipped_polys"; + fp = gzopen( file.c_str(), "rb" ); - std::ifstream ifs_cp( file.c_str() ); - if ( ifs_cp.good() ) { - ifs_cp >> polys_clipped; - ifs_cp.close(); + if ( fp ) { + polys_clipped.LoadFromGzFile( fp ); + gzclose( fp ); file = dir + "/" + bucket.gen_index_str() + "_nodes"; + fp = gzopen( file.c_str(), "rb" ); - std::ifstream ifs_n( file.c_str() ); - if ( ifs_n.good() ) { - ifs_n >> nodes; - ifs_n.close(); + if ( fp ) { + nodes.LoadFromGzFile( fp ); + gzclose( fp ); read_ok = true; } @@ -548,18 +561,18 @@ void TGConstruct::LoadFromIntermediateFiles( int stage ) { dir = share_base + "/stage2/" + bucket.gen_base_path(); file = dir + "/" + bucket.gen_index_str() + "_clipped_polys"; + fp = gzopen( file.c_str(), "rb" ); - std::ifstream ifs_cp( file.c_str() ); - if ( ifs_cp.good() ) { - ifs_cp >> polys_clipped; - ifs_cp.close(); + if ( fp ) { + polys_clipped.LoadFromGzFile( fp ); + gzclose( fp ); file = dir + "/" + bucket.gen_index_str() + "_nodes"; + fp = gzopen( file.c_str(), "rb" ); - std::ifstream ifs_n( file.c_str() ); - if ( ifs_n.good() ) { - ifs_n >> nodes; - ifs_n.close(); + if ( fp ) { + nodes.LoadFromGzFile( fp ); + gzclose( fp ); read_ok = true; } diff --git a/src/BuildTiles/Main/tglandclass.cxx b/src/BuildTiles/Main/tglandclass.cxx index 27fb2065..1bc58149 100644 --- a/src/BuildTiles/Main/tglandclass.cxx +++ b/src/BuildTiles/Main/tglandclass.cxx @@ -31,6 +31,7 @@ #endif #include "tglandclass.hxx" +#include void TGLandclass::clear(void) { @@ -61,6 +62,22 @@ std::istream& operator >> ( std::istream& in, TGLandclass& lc) return in; } +void TGLandclass::LoadFromGzFile(gzFile& fp) +{ + int i, j, count; + + // Load all landclass shapes + for (i=0; i +#include #define TG_MAX_AREA_TYPES 128 #include "tgshape.hxx" @@ -147,6 +149,8 @@ public: { return shapes[area][shape].sps[segment].set_tri_idxs( tis ); } + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); // Friends for serialization friend std::istream& operator>> ( std::istream&, TGLandclass& ); diff --git a/src/BuildTiles/Main/tgshape.cxx b/src/BuildTiles/Main/tgshape.cxx index c0731b10..c5d11664 100644 --- a/src/BuildTiles/Main/tgshape.cxx +++ b/src/BuildTiles/Main/tgshape.cxx @@ -103,11 +103,39 @@ std::istream& operator >> ( std::istream& in, TGShape& p) return in; } +void TGShape::LoadFromGzFile(gzFile& fp) +{ + int i, count; + // First, load the clipmask + clip_mask.LoadFromGzFile( fp ); + + // Then load superpolys + sgReadInt( fp, &count ); + for (i=0; i -//#include - -//#include -//#include +#include +#include +#include #include #include @@ -58,6 +56,8 @@ public: void SetMask( TGPolygon mask ); void BuildMask( void ); void IntersectPolys( void ); + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); // Friends for serialization friend std::istream& operator>> ( std::istream&, TGShape& ); diff --git a/src/Lib/Geometry/point3d.hxx b/src/Lib/Geometry/point3d.hxx index 826fdcef..7c6aa86c 100644 --- a/src/Lib/Geometry/point3d.hxx +++ b/src/Lib/Geometry/point3d.hxx @@ -46,6 +46,7 @@ #include +#include //const double fgPoint3_Epsilon = 0.0000001; const double fgPoint3_Epsilon = 0.000001; @@ -173,6 +174,16 @@ inline std::ostream& operator<< ( std::ostream& out, const Point3D& p ) return out; } +inline void sgWritePoint3D ( gzFile fd, const Point3D& var ) { + sgWriteDouble ( fd, 3, var.get_n() ) ; +} + +inline void sgReadPoint3D ( gzFile fd, Point3D& var ) { + double data[3]; + sgReadDouble ( fd, 3, data ); + var = Point3D(data[0], data[1], data[2]); +} + /////////////////////////// // // Point3D Member functions diff --git a/src/Lib/Geometry/tg_nodes.cxx b/src/Lib/Geometry/tg_nodes.cxx index b57c3fa1..6fcbdb94 100644 --- a/src/Lib/Geometry/tg_nodes.cxx +++ b/src/Lib/Geometry/tg_nodes.cxx @@ -3,9 +3,60 @@ #include "tg_nodes.hxx" +// compare node's positions (x, then y) +int compare_position(const TGNode& n1, const TGNode& n2) +{ + Point3D pos1 = n1.GetPosition(); + Point3D pos2 = n2.GetPosition(); + + if ( pos1.x() == pos2.x() ) { + return ( pos1.y() < pos2.y() ); + } else { + return ( pos1.x() < pos2.x() ); + } +} + +int fuzzy_compare_xposition(const TGNode& n1, const TGNode& n2) +{ + Point3D pos1 = n1.GetPosition(); + Point3D pos2 = n2.GetPosition(); + + if ( fabs(pos1.x() - pos2.x()) < 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::find( const Point3D& p ) const { +int TGNodes::sorted_find( const Point3D& 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 Point3D& p ) const { const_node_list_iterator current, last; Point3D pos; int counter = 0; @@ -25,9 +76,45 @@ int TGNodes::find( const Point3D& p ) const { return -1; } -int TGNodes::unique_add( const Point3D& p ) { +#if 0 +void TGNodes::sorted_unique_add( const Point3D& p ) { +# if 0 + TGNode node( p ); + node.SetFixedPosition( false ); + + node_list_iterator idx = std::lower_bound( tg_node_list.begin(), tg_node_list.end(), node, compare_position ); + tg_node_list.insert( idx, node ); +#else + TGNode node( p ); + node.SetFixedPosition( false ); + + node_list_iterator lb, ub, idx; + + // 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; + } + } + } + + // we didn't find an existing node - insert new one in correct order + idx = std::lower_bound( lb, ub, node, compare_position ); + tg_node_list.insert( idx, node ); + +// return std::distance( tg_node_list.begin(), idx ); +#endif +} +#endif + +void TGNodes::linear_unique_add( const Point3D& p ) { node_list_iterator current, last; - int counter = 0; // see if point already exists current = tg_node_list.begin(); @@ -35,11 +122,9 @@ int TGNodes::unique_add( const Point3D& p ) { for ( ; current != last; ++current ) { if ( close_enough_2d(p, (*current).GetPosition() ) ) { - // cout << "found an existing match!" << endl; - return counter; + return; } - ++counter; } TGNode node( p ); @@ -47,13 +132,59 @@ int TGNodes::unique_add( const Point3D& p ) { // add to list tg_node_list.push_back( node ); - - return counter; } -int TGNodes::unique_add_fixed_elevation( const Point3D& p ) { +#if 0 +void TGNodes::sorted_unique_add_fixed_elevation( const Point3D& p ) { +# if 0 + TGNode node( p ); + node.SetFixedPosition(true); + + node_list_iterator idx = std::lower_bound( tg_node_list.begin(), tg_node_list.end(), node, compare_position ); + + if ( idx != tg_node_list.end() ) { + if ( close_enough_2d( p, idx->GetPosition() ) ) { + SG_LOG(SG_GENERAL, SG_ALERT, "AddFixedLocation: node " << p << " exists at " << std::distance(tg_node_list.begin(), idx) ); + idx->SetPosition( p ); + idx->SetFixedPosition( true ); + } else { + tg_node_list.insert( idx, node ); +} + } +#else + TGNode node( p ); + node.SetFixedPosition(true); + + node_list_iterator lb, ub, idx; + + // 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()) ) { + lb->SetPosition( p ); + lb->SetFixedPosition( true ); + +// return std::distance( tg_node_list.begin(), lb ); + return; + } + } + } + + // we didn't find an existing node - insert new one in correct order + idx = std::lower_bound( lb, ub, node, compare_position ); + tg_node_list.insert( idx, node ); + +// return std::distance( tg_node_list.begin(), idx ); +#endif +} +#endif + +void TGNodes::linear_unique_add_fixed_elevation( const Point3D& p ) { node_list_iterator current, last; - int counter = 0; // see if point already exists current = tg_node_list.begin(); @@ -61,16 +192,14 @@ int TGNodes::unique_add_fixed_elevation( const Point3D& p ) { for ( ; current != last; ++current ) { if ( close_enough_2d(p, (*current).GetPosition() ) ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Adding fixed elev node : node already exists at " << counter << " old position is " << (*current).GetPosition() << " new position is " << p ); // Force the match to our position, and mark as fixed (*current).SetPosition( p ); (*current).SetFixedPosition( true ); - return counter; + return; } - ++counter; } TGNode node( p ); @@ -79,7 +208,6 @@ int TGNodes::unique_add_fixed_elevation( const Point3D& p ) { // add to list tg_node_list.push_back( node ); - return counter; } point_list TGNodes::get_geod_nodes( void ) const { @@ -97,6 +225,9 @@ point_list TGNodes::get_geod_nodes( void ) const { return points; } +// 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 point_list TGNodes::get_geod_inside( Point3D min, Point3D max ) const { point_list points; const_node_list_iterator current, last; @@ -260,6 +391,30 @@ std::istream& operator >> ( std::istream& in, TGNode& n ) return in; } +void TGNode::LoadFromGzFile(gzFile& fp) +{ + int i, nCount; + + // Load a tgnode + sgReadPoint3D( fp, position); + CalcWgs84(); + + sgReadPoint3D( fp, normal ); + sgReadInt( fp, (int*)&fixed_position ); + sgReadInt( fp, (int*)&fixed_normal ); + + sgReadInt( fp, &nCount ); + for (i=0; i> ( std::istream& in, TGNodes& ns ) { int i, nCount; + // Load sorted flag + in >> ns.sorted; // Load all tgnodes in >> nCount; @@ -300,10 +477,30 @@ std::istream& operator >> ( std::istream& in, TGNodes& ns ) return in; } +void TGNodes::LoadFromGzFile(gzFile& fp) +{ + int i, nCount; + + // Load sorted flag + sgReadInt( fp, (int*)&sorted ); + + // Load all tgnodes + sgReadInt( fp, &nCount ); + + for (i=0; i +#endif #ifndef __cplusplus # error This library requires C++ #endif +#include #include #include -#include #include +#include + +#include #define FG_PROXIMITY_EPSILON 0.000001 #define FG_COURSE_EPSILON 0.0001 @@ -93,6 +99,8 @@ public: inline void SetNormal( const Point3D& n ) { normal = n; } inline Point3D GetNormal( void ) const { return normal; } + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); // Friends for serialization friend std::istream& operator>> ( std::istream&, TGNode& ); friend std::ostream& operator<< ( std::ostream&, const TGNode& ); @@ -118,35 +126,53 @@ class TGNodes { public: // Constructor and destructor - TGNodes( void ) {} + TGNodes( void ) { + sorted = false; + } ~TGNodes( void ) {} // delete all the data out of node_list - inline void clear() { tg_node_list.clear(); } + inline void clear() { + tg_node_list.clear(); + sorted = 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. - int unique_add( const Point3D& p ); + void unique_add( const Point3D& p ) { + if ( !sorted ) { + linear_unique_add( p ); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); + exit(0); + } + } // 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. - int unique_add_fixed_elevation( const Point3D& p ); - node_list get_fixed_elevation_nodes( void ) const; - - // Add the point with no uniqueness checking - int simple_add( const Point3D& p ); - - // 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. - // Use a course proximity check - int course_add( const Point3D& p ); + void unique_add_fixed_elevation( const Point3D& p ) { + if ( !sorted ) { + linear_unique_add_fixed_elevation( p ); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); + exit(0); + } + } // Find the index of the specified point (compair to the same // tolerance as unique_add(). Returns -1 if not found. - int find( const Point3D& p ) const; + int find( const Point3D& p ) const { + if ( sorted ) { + return sorted_find( p ); + } else { + return linear_find( p ); + } + } -// bool LookupFixedElevation( Point3D p, double* z ); + node_list get_fixed_elevation_nodes( void ) const; + + void SortNodes( void ); void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); } Point3D GetNormal( int idx ) const { return tg_node_list[idx].GetNormal(); } @@ -184,13 +210,21 @@ public: 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::istream& operator>> ( std::istream&, TGNodes& ); friend std::ostream& operator<< ( std::ostream&, const TGNodes& ); private: + void linear_unique_add( const Point3D& p ); + void linear_unique_add_fixed_elevation( const Point3D& p ); + + int sorted_find( const Point3D& p ) const; + int linear_find( const Point3D& p ) const; node_list tg_node_list; + bool sorted; // 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 c14afd5c..a322bf24 100644 --- a/src/Lib/Polygon/polygon.cxx +++ b/src/Lib/Polygon/polygon.cxx @@ -960,10 +960,30 @@ std::ostream& operator << (std::ostream &output, const TGPolygon &poly) return output; } +void TGPolygon::SaveToGzFile(gzFile& fp) +{ + int nContours = poly.size(); + + // Save the number of contours + sgWriteInt( fp, nContours ); + for (int i = 0; i < nContours; i++) { + int nPoints = poly[i].size(); + + // Save number of points in the contour + sgWriteInt( fp, nPoints ); + + // Then save the points + for ( int j = 0; j < nPoints; j++ ) { + sgWritePoint3D( fp, poly[i][j] ); + } + + sgWriteInt( fp, hole_list[i] ); + } +} // Read a polygon from input buffer. std::istream& operator >> (std::istream &input, TGPolygon &poly) { - int nContours = poly.contours(); + int nContours; double x, y, z; // Read the number of contours @@ -991,3 +1011,26 @@ std::istream& operator >> (std::istream &input, TGPolygon &poly) return input; } + +void TGPolygon::LoadFromGzFile(gzFile& fp) +{ + int nContours; + int nPoints; + int hole; + Point3D pt; + + // Save the number of contours + sgReadInt( fp, &nContours ); + for (int i = 0; i < nContours; i++) { + sgReadInt( fp, &nPoints ); + + // Then read the points + for ( int j = 0; j < nPoints; j++ ) { + sgReadPoint3D( fp, pt ); + add_node( i, pt ); + } + + sgReadInt( fp, &hole ); + set_hole_flag( i, hole ); + } +} diff --git a/src/Lib/Polygon/polygon.hxx b/src/Lib/Polygon/polygon.hxx index e143bb04..f77a7af5 100644 --- a/src/Lib/Polygon/polygon.hxx +++ b/src/Lib/Polygon/polygon.hxx @@ -206,6 +206,9 @@ public: // output void write_contour( const int contour, const std::string& file ) const; + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); + // Friends for serialization friend std::istream& operator>> ( std::istream&, TGPolygon& ); friend std::ostream& operator<< ( std::ostream&, const TGPolygon& ); diff --git a/src/Lib/Polygon/superpoly.cxx b/src/Lib/Polygon/superpoly.cxx index 5a7ab783..a380a35d 100644 --- a/src/Lib/Polygon/superpoly.cxx +++ b/src/Lib/Polygon/superpoly.cxx @@ -81,10 +81,39 @@ std::ostream& operator<< ( std::ostream& output, const TGSuperPoly& sp ) } else { output << sp.flag << "\n"; } - + return output; } +void TGSuperPoly::SaveToGzFile(gzFile& fp) +{ + int nFaceNormals; + int nFaceAreas; + + // Save the data + sgWriteString( fp, material.c_str() ); + + poly.SaveToGzFile( fp ); + normals.SaveToGzFile( fp ); + texcoords.SaveToGzFile( fp ); + + tris.SaveToGzFile( fp ); + tri_idxs.SaveToGzFile( fp ); + + nFaceNormals = face_normals.size(); + sgWriteInt( fp, nFaceNormals ); + for ( int i = 0; i < nFaceNormals; i++ ) { + sgWritePoint3D( fp, face_normals[i] ); + } + + nFaceAreas = face_areas.size(); + sgWriteInt( fp, nFaceAreas ); + for ( int i = 0; i < nFaceAreas; i++ ) { + sgWriteDouble( fp, face_areas[i] ); + } + + sgWriteString( fp, flag.c_str() ); +} std::istream& operator>> ( std::istream& input, TGSuperPoly& sp ) { int nFaceNormals; @@ -117,6 +146,47 @@ std::istream& operator>> ( std::istream& input, TGSuperPoly& sp ) return input; } +void TGSuperPoly::LoadFromGzFile(gzFile& fp) +{ + int nFaceNormals; + int nFaceAreas; + Point3D normal; + double area; + char* strbuf; + + // Load the data + sgReadString( fp, &strbuf ); + if ( strbuf ) { + material = strbuf; + delete strbuf; + } + + poly.LoadFromGzFile( fp ); + normals.LoadFromGzFile( fp ); + texcoords.LoadFromGzFile( fp ); + + tris.LoadFromGzFile( fp ); + tri_idxs.LoadFromGzFile( fp ); + + sgReadInt( fp, &nFaceNormals ); + for ( int i = 0; i < nFaceNormals; i++ ) { + sgReadPoint3D( fp, normal ); + face_normals.push_back( normal ); + } + + sgReadInt( fp, &nFaceAreas ); + for ( int i = 0; i < nFaceAreas; i++ ) { + sgReadDouble( fp, &area ); + face_areas.push_back( area ); + } + + sgReadString( fp, &strbuf ); + if ( strbuf ) { + flag = strbuf; + delete strbuf; + } +} + std::ostream& operator<< ( std::ostream& output, const TGPolyNodes& pn ) { int nContours; @@ -137,6 +207,22 @@ std::ostream& operator<< ( std::ostream& output, const TGPolyNodes& pn ) return output; } +void TGPolyNodes::SaveToGzFile(gzFile& fp) +{ + int nContours; + int nPoints; + + // Save the data + nContours = poly.size(); + sgWriteInt( fp, nContours ); + for(int i=0; i> ( std::istream& input, TGPolyNodes& pn ) { @@ -158,4 +244,24 @@ std::istream& operator>> ( std::istream& input, TGPolyNodes& pn ) } return input; +} + +void TGPolyNodes::LoadFromGzFile(gzFile& fp) +{ + int nContours; + int nPoints; + int point; + + // Load the data + sgReadInt( fp, &nContours ); + for( int i=0; i> ( std::istream&, TGPolyNodes& ); friend std::ostream& operator<< ( std::ostream&, const TGPolyNodes& ); @@ -244,6 +247,9 @@ public: // erase the polygon void erase(); + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); + // Friends for serialization friend std::istream& operator>> ( std::istream&, TGSuperPoly& ); friend std::ostream& operator<< ( std::ostream&, const TGSuperPoly& ); diff --git a/src/Lib/Polygon/texparams.cxx b/src/Lib/Polygon/texparams.cxx index c965537a..d3ed98c0 100644 --- a/src/Lib/Polygon/texparams.cxx +++ b/src/Lib/Polygon/texparams.cxx @@ -17,6 +17,19 @@ std::ostream& operator << (std::ostream &output, const TGTexParams &tp) return output; } +void TGTexParams::SaveToGzFile(gzFile& fp) +{ + sgWritePoint3D( fp, ref ); + sgWriteDouble( fp, width ); + sgWriteDouble( fp, length ); + sgWriteDouble( fp, heading ); + + sgWriteDouble( fp, minu ); + sgWriteDouble( fp, maxu ); + sgWriteDouble( fp, minv ); + sgWriteDouble( fp, maxv ); +} + // Read a polygon from input buffer. std::istream& operator >> (std::istream &input, TGTexParams &tp) { @@ -32,4 +45,17 @@ std::istream& operator >> (std::istream &input, TGTexParams &tp) input >> tp.maxv; return input; -} \ No newline at end of file +} + +void TGTexParams::LoadFromGzFile(gzFile& fp) +{ + sgReadPoint3D( fp, ref ); + sgReadDouble( fp, &width ); + sgReadDouble( fp, &length ); + sgReadDouble( fp, &heading ); + + sgReadDouble( fp, &minu ); + sgReadDouble( fp, &maxu ); + sgReadDouble( fp, &minv ); + sgReadDouble( fp, &maxv ); +} diff --git a/src/Lib/Polygon/texparams.hxx b/src/Lib/Polygon/texparams.hxx index 1c53036c..c8e7af15 100644 --- a/src/Lib/Polygon/texparams.hxx +++ b/src/Lib/Polygon/texparams.hxx @@ -144,6 +144,9 @@ public: maxv = x; } + void SaveToGzFile( gzFile& fp ); + void LoadFromGzFile( gzFile& fp ); + // Friends for serialization friend std::istream& operator>> ( std::istream&, TGTexParams& ); friend std::ostream& operator<< ( std::ostream&, const TGTexParams& );