1
0
Fork 0

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
This commit is contained in:
Peter Sadrozinski 2012-10-17 18:56:54 -04:00
parent b6a4dacf33
commit c336c134bf
18 changed files with 757 additions and 199 deletions

View file

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

View file

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

View file

@ -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<corner_list.size(); i++) {
nodes.unique_add(corner_list[i]);
@ -59,6 +60,7 @@ void TGConstruct::LoadElevationArray( void ) {
nodes.unique_add(fit_list[i]);
}
}
}
static void calc_gc_course_dist( const Point3D& start, const Point3D& dest,
double *course, double *dist ) {
@ -92,6 +94,7 @@ void TGConstruct::CalcElevations( void )
TGPolyNodes tri_nodes;
double e1, e2, e3, min;
int n1, n2, n3;
point_list raw_nodes;
Point3D p;
SG_LOG(SG_GENERAL, SG_ALERT, "fixing node heights");
@ -106,6 +109,7 @@ void TGConstruct::CalcElevations( void )
}
}
raw_nodes = nodes.get_geod_nodes();
// now flatten some stuff
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
if ( is_lake_area( (AreaType)area ) ) {
@ -153,7 +157,6 @@ void TGConstruct::CalcElevations( void )
exit(0);
}
point_list raw_nodes = nodes.get_geod_nodes();
n1 = tri_nodes.get_pt( tri, 0 );
e1 = nodes.get_node(n1).GetPosition().z();
@ -197,7 +200,6 @@ void TGConstruct::CalcElevations( void )
exit(0);
}
point_list raw_nodes = nodes.get_geod_nodes();
n1 = tri_nodes.get_pt( tri, 0 );
e1 = nodes.get_node(n1).GetPosition().z();

View file

@ -34,7 +34,7 @@
// indexes into the node array (cast as unsigned long)
void TGConstruct::LookupNodesPerVertex( void )
{
SG_LOG(SG_GENERAL, SG_ALERT, "LookupNodexPerVertex");
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++ ) {
@ -50,6 +50,7 @@ void TGConstruct::LookupNodesPerVertex( void )
if (idx >= 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);
}
}

View file

@ -28,6 +28,7 @@
#include <simgear/misc/sg_dir.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/io/lowlevel.hxx>
#include <Geometry/poly_support.hxx>
@ -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<nCount; i++) {
ofs_e << north[i];
sgWritePoint3D( fp, north[i] );
}
// south
nCount = south.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << south[i];
sgWritePoint3D( fp, south[i] );
}
// east
nCount = east.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << east[i];
sgWritePoint3D( fp, east[i] );
}
// west
nCount = west.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << west[i];
sgWritePoint3D( fp, west[i] );
}
ofs_e.close();
gzclose(fp);
}
break;
@ -111,7 +110,7 @@ void TGConstruct::SaveSharedEdgeData( int stage )
}
}
void TGConstruct::WriteNeighborFaces( std::ofstream& ofs_e, Point3D pt )
void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
{
// find all neighboors of this point
int n = nodes.find( pt );
@ -119,7 +118,7 @@ void TGConstruct::WriteNeighborFaces( std::ofstream& ofs_e, Point3D pt )
TGFaceList faces = node.GetFaces();
// write the number of neighboor faces
ofs_e << faces.size() << "\n";
sgWriteInt( fp, faces.size() );
// write out each face normal and size
for (unsigned int j=0; j<faces.size(); j++) {
@ -142,11 +141,10 @@ void TGConstruct::WriteNeighborFaces( std::ofstream& ofs_e, Point3D pt )
double face_area = triangle_area( p1, p2, p3 );
Point3D face_normal = Point3D::fromSGVec3( calc_normal( face_area, wgs_p1, wgs_p2, wgs_p3 ) );
ofs_e << face_area << " ";
ofs_e << face_normal;
sgWriteDouble( fp, face_area );
sgWritePoint3D( fp, face_normal );
}
}
ofs_e << "\n";
}
TGNeighborFaces* TGConstruct::FindNeighborFaces( Point3D node )
@ -173,19 +171,19 @@ TGNeighborFaces* TGConstruct::AddNeighborFaces( Point3D node )
return &neighbor_faces[neighbor_faces.size()-1];
}
void TGConstruct::ReadNeighborFaces( std::ifstream& in )
void TGConstruct::ReadNeighborFaces( gzFile& fp )
{
int count;
// read the count
in >> count;
sgReadInt( fp, &count );
for (int i=0; i<count; i++) {
TGNeighborFaces* pFaces;
Point3D node;
int num_faces;
in >> 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<num_faces; j++)
{
double area;
Point3D normal;
in >> 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; i++) {
// write the 3d point
ofs_e << north[i];
WriteNeighborFaces( ofs_e, north[i] );
sgWritePoint3D( fp, north[i] );
WriteNeighborFaces( fp, north[i] );
}
ofs_e.close();
gzclose(fp);
// south edge
file = dir + "/" + bucket.gen_index_str() + "_south_edge";
ofs_e.open( file.c_str() );
ofs_e << std::setprecision(12);
ofs_e << std::fixed;
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
nCount = south.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << south[i];
WriteNeighborFaces( ofs_e, south[i] );
sgWritePoint3D( fp, south[i] );
WriteNeighborFaces( fp, south[i] );
}
ofs_e.close();
gzclose(fp);
// east edge
file = dir + "/" + bucket.gen_index_str() + "_east_edge";
ofs_e.open( file.c_str() );
ofs_e << std::setprecision(12);
ofs_e << std::fixed;
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
nCount = east.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << east[i];
WriteNeighborFaces( ofs_e, east[i] );
sgWritePoint3D( fp, east[i] );
WriteNeighborFaces( fp, east[i] );
}
ofs_e.close();
gzclose(fp);
// west egde
file = dir + "/" + bucket.gen_index_str() + "_west_edge";
ofs_e.open( file.c_str() );
ofs_e << std::setprecision(12);
ofs_e << std::fixed;
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
nCount = west.size();
ofs_e << nCount << "\n";
sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) {
ofs_e << west[i];
WriteNeighborFaces( ofs_e, west[i] );
sgWritePoint3D( fp, west[i] );
WriteNeighborFaces( fp, west[i] );
}
ofs_e.close();
gzclose(fp);
}
void TGConstruct::LoadSharedEdgeDataStage2( void )
{
string dir;
string file;
std::ifstream ifs_edge;
double clon = bucket.get_center_lon();
double clat = bucket.get_center_lat();
gzFile fp;
SGBucket b;
// Read Northern tile and add its southern node faces
b = sgBucketOffset(clon, clat, 0, 1);
dir = share_base + "/stage2/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_south_edge";
ifs_edge.open( file.c_str() );
if ( ifs_edge.is_open() ) {
ReadNeighborFaces( ifs_edge );
fp = gzopen( file.c_str(), "rb" );
if (fp) {
sgClearReadError();
ReadNeighborFaces( fp );
gzclose( fp );
}
ifs_edge.close();
// Read Southern tile and add its northern node faces
b = sgBucketOffset(clon, clat, 0, -1);
dir = share_base + "/stage2/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_north_edge";
ifs_edge.open( file.c_str() );
if ( ifs_edge.is_open() ) {
ReadNeighborFaces( ifs_edge );
fp = gzopen( file.c_str(), "rb" );
if (fp) {
sgClearReadError();
ReadNeighborFaces( fp );
gzclose( fp );
}
ifs_edge.close();
// Read Eastern tile and add its western node faces
b = sgBucketOffset(clon, clat, 1, 0);
dir = share_base + "/stage2/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_west_edge";
ifs_edge.open( file.c_str() );
if ( ifs_edge.is_open() ) {
ReadNeighborFaces( ifs_edge );
fp = gzopen( file.c_str(), "rb" );
if (fp) {
sgClearReadError();
ReadNeighborFaces( fp );
gzclose( fp );
}
ifs_edge.close();
// Read Western tile and add its eastern node faces
b = sgBucketOffset(clon, clat, -1, 0);
dir = share_base + "/stage2/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_east_edge";
ifs_edge.open( file.c_str() );
if ( ifs_edge.is_open() ) {
ReadNeighborFaces( ifs_edge );
fp = gzopen( file.c_str(), "rb" );
if (fp) {
sgClearReadError();
ReadNeighborFaces( fp );
gzclose( fp );
}
ifs_edge.close();
}
@ -350,6 +360,7 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
{
string dir;
string file;
gzFile fp;
switch( stage ) {
case 1: // Save the clipped polys and node list
@ -363,22 +374,22 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
sgp.create_dir( 0755 );
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
std::ofstream ofs_cp( file.c_str() );
// first, set the precision
ofs_cp << std::setprecision(15);
ofs_cp << std::fixed;
ofs_cp << polys_clipped;
ofs_cp.close();
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
polys_clipped.SaveToGzFile( fp );
gzclose( fp );
file = dir + "/" + bucket.gen_index_str() + "_nodes";
std::ofstream ofs_n( file.c_str() );
// first, set the precision
ofs_n << std::setprecision(15);
ofs_n << std::fixed;
ofs_n << nodes;
ofs_n.close();
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
nodes.SaveToGzFile( fp );
gzclose( fp );
}
break;
@ -394,22 +405,22 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
sgp.create_dir( 0755 );
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
std::ofstream ofs_cp( file.c_str() );
// first, set the precision
ofs_cp << std::setprecision(15);
ofs_cp << std::fixed;
ofs_cp << polys_clipped;
ofs_cp.close();
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
polys_clipped.SaveToGzFile( fp );
gzclose( fp );
file = dir + "/" + bucket.gen_index_str() + "_nodes";
std::ofstream ofs_n( file.c_str() );
// first, set the precision
ofs_n << std::setprecision(15);
ofs_n << std::fixed;
ofs_n << nodes;
ofs_n.close();
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return;
}
sgClearWriteError();
nodes.SaveToGzFile( fp );
gzclose( fp );
}
break;
}
@ -420,52 +431,53 @@ void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, p
{
string dir;
string file;
gzFile fp;
Point3D pt;
int nCount;
dir = share_base + "/stage1/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_edges";
std::ifstream ifs_edges( file.c_str() );
fp = gzopen( file.c_str(), "rb" );
north.clear();
south.clear();
east.clear();
west.clear();
if ( ifs_edges.is_open() ) {
if (fp) {
// North
ifs_edges >> 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<nCount; i++) {
ifs_edges >> 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<nCount; i++) {
ifs_edges >> 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<nCount; i++) {
ifs_edges >> 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<nCount; i++) {
ifs_edges >> 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;
}

View file

@ -31,6 +31,7 @@
#endif
#include "tglandclass.hxx"
#include <simgear/io/lowlevel.hxx>
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<TG_MAX_AREA_TYPES; i++) {
sgReadInt( fp, &count );
for (j=0; j<count; j++) {
TGShape shape;
shape.LoadFromGzFile( fp );
shapes[i].push_back( shape );
}
}
}
std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
{
int i, j, count;
@ -78,3 +95,18 @@ std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
return out;
}
void TGLandclass::SaveToGzFile(gzFile& fp)
{
int i, j, count;
TGShape shape;
// Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
count = shapes[i].size();
sgWriteInt( fp, count );
for (j=0; j<count; j++) {
shapes[i][j].SaveToGzFile( fp );
}
}
}

View file

@ -33,6 +33,8 @@
# error This library requires C++
#endif
#include <simgear/math/sg_types.hxx>
#include <simgear/io/lowlevel.hxx>
#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& );

View file

@ -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<count; i++) {
TGSuperPoly sp;
sp.LoadFromGzFile( fp );
sps.push_back( sp );
}
// Then load texparams
sgReadInt( fp, &count );
for (i=0; i<count; i++) {
TGTexParams tp;
tp.LoadFromGzFile( fp );
tps.push_back( tp );
}
// Load the id, area type and textured flag
sgReadUInt( fp, &id );
sgReadInt( fp, (int*)&area );
sgReadInt( fp, (int*)&textured );
}
std::ostream& operator<< ( std::ostream& out, const TGShape& p )
{
int i, count;
TGSuperPoly sp;
TGTexParams tp;
// TGSuperPoly sp;
// TGTexParams tp;
// First, save the clipmask
out << p.clip_mask;
@ -133,3 +161,30 @@ std::ostream& operator<< ( std::ostream& out, const TGShape& p )
return out;
}
void TGShape::SaveToGzFile(gzFile& fp)
{
int i, count;
// First, load the clipmask
clip_mask.SaveToGzFile( fp );
// Then save superpolys
count = sps.size();
sgWriteInt( fp, count );
for (i=0; i<count; i++) {
sps[i].SaveToGzFile( fp );
}
// Then save texparams
count = tps.size();
sgWriteInt( fp, count );
for (i=0; i<count; i++) {
tps[i].SaveToGzFile( fp );
}
// Save the id, area type and textured flag
sgWriteUInt( fp, id );
sgWriteInt( fp, (int)area );
sgWriteInt( fp, (int)textured );
}

View file

@ -33,11 +33,9 @@
#define TG_MAX_AREA_TYPES 128
//#include <string>
//#include <vector>
//#include <simgear/compiler.h>
//#include <simgear/debug/logstream.hxx>
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/io/lowlevel.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
@ -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& );

View file

@ -46,6 +46,7 @@
#include <simgear/math/SGMath.hxx>
#include <simgear/io/lowlevel.hxx>
//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

View file

@ -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<nCount; i++) {
TGFaceLookup face;
sgReadUInt( fp, &face.area );
sgReadUInt( fp, &face.shape );
sgReadUInt( fp, &face.seg );
sgReadUInt( fp, &face.tri );
faces.push_back( face );
}
}
std::ostream& operator<< ( std::ostream& out, const TGNode& n )
{
int i, nCount;
@ -282,11 +437,33 @@ std::ostream& operator<< ( std::ostream& out, const TGNode& n )
return out;
}
void TGNode::SaveToGzFile(gzFile& fp)
{
int i, nCount;
// Save a tgnode
sgWritePoint3D( fp, position );
sgWritePoint3D( fp, normal );
sgWriteInt( fp, (int)fixed_position );
sgWriteInt( fp, (int)fixed_normal );
nCount = faces.size();
sgWriteInt( fp, nCount );
for (i=0; i<nCount; i++) {
sgWriteUInt( fp, faces[i].area );
sgWriteUInt( fp, faces[i].shape );
sgWriteUInt( fp, faces[i].seg );
sgWriteUInt( fp, faces[i].tri );
}
}
// input from stream
std::istream& operator >> ( 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<nCount; i++) {
TGNode node;
node.LoadFromGzFile( fp );
tg_node_list.push_back( node );
}
}
std::ostream& operator<< ( std::ostream& out, const TGNodes& ns )
{
int i, nCount;
// Save sorted flag
out << ns.sorted << "\n";
// Save all tgnodes
nCount = ns.tg_node_list.size();
out << nCount << "\n";
@ -315,6 +512,21 @@ std::ostream& operator<< ( std::ostream& out, const TGNodes& ns )
return out;
}
void TGNodes::SaveToGzFile(gzFile& fp)
{
int i, nCount;
// Save sorted flag
sgWriteInt( fp, (int)sorted );
// Save all tgnodes
nCount = tg_node_list.size();
sgWriteInt( fp, nCount );
for (i=0; i<nCount; i++) {
tg_node_list[i].SaveToGzFile( fp );
}
}
#if 0
bool TGNodes::LookupFixedElevation( Point3D p, double* z )

View file

@ -1,15 +1,21 @@
#ifndef _TG_NODES_HXX
#define _TG_NODES_HXX
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef __cplusplus
# error This library requires C++
#endif
#include <cstdlib>
#include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx>
#include <Geometry/point3d.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/io/lowlevel.hxx>
#include <Geometry/point3d.hxx>
#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

View file

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

View file

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

View file

@ -85,6 +85,35 @@ std::ostream& operator<< ( std::ostream& output, const TGSuperPoly& sp )
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<nContours; i++) {
nPoints = poly[i].size();
sgWriteInt( fp, nPoints );
for (int j=0; j<nPoints; j++) {
sgWriteInt( fp, poly[i][j] );
}
}
}
std::istream& operator>> ( std::istream& input, TGPolyNodes& pn )
{
@ -159,3 +245,23 @@ 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<nContours; i++ ) {
int_list points;
sgReadInt( fp, &nPoints );
for (int j=0; j<nPoints; j++) {
sgReadInt( fp, &point );
points.push_back( point );
}
poly.push_back( points );
}
}

View file

@ -120,6 +120,9 @@ public:
poly[contour][i] = n;
}
void SaveToGzFile( gzFile& fp );
void LoadFromGzFile( gzFile& fp );
// Friends for serialization
friend std::istream& operator>> ( 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& );

View file

@ -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)
{
@ -33,3 +46,16 @@ std::istream& operator >> (std::istream &input, TGTexParams &tp)
return input;
}
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 );
}

View file

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