1
0
Fork 0

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
This commit is contained in:
Peter Sadrozinski 2012-12-02 14:53:21 -05:00
parent 89e69a863f
commit 6edeadd86e
25 changed files with 1010 additions and 1482 deletions

View file

@ -15,8 +15,6 @@ add_executable(tg-construct
tgconstruct_texture.cxx tgconstruct_texture.cxx
tglandclass.cxx tglandclass.cxx
tglandclass.hxx tglandclass.hxx
tgshape.cxx
tgshape.hxx
priorities.cxx priorities.cxx
priorities.hxx priorities.hxx
usgs.cxx usgs.cxx

View file

@ -18,12 +18,6 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. // 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 #ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
@ -184,12 +178,15 @@ int main(int argc, char **argv) {
} else { } else {
SGBucket b_cur; SGBucket b_cur;
int dx, dy, i, j; int dx, dy, i, j;
int total_buckets, cur_bucket;
sgBucketDiff(b_min, b_max, &dx, &dy); sgBucketDiff(b_min, b_max, &dx, &dy);
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries"); SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy); SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy);
// construct stage 1 // construct stage 1
total_buckets = (dx+1) * (dy + 1);
cur_bucket = 0;
for ( j = 0; j <= dy; j++ ) { for ( j = 0; j <= dy; j++ ) {
for ( i = 0; i <= dx; i++ ) { for ( i = 0; i <= dx; i++ ) {
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); 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_bucket( b_cur );
stage1->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); 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->ConstructBucketStage1();
stage1->SaveToIntermediateFiles(1); 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; delete stage1;
} }
} }
// construct stage 2 // construct stage 2
cur_bucket = 0;
for ( j = 0; j <= dy; j++ ) { for ( j = 0; j <= dy; j++ ) {
for ( i = 0; i <= dx; i++ ) { for ( i = 0; i <= dx; i++ ) {
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); 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_bucket( b_cur );
stage2->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); 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->LoadFromIntermediateFiles(1);
stage2->ConstructBucketStage2(); stage2->ConstructBucketStage2();
stage2->SaveToIntermediateFiles(2); stage2->SaveToIntermediateFiles(2);
@ -231,6 +238,7 @@ int main(int argc, char **argv) {
} }
// construct stage 3 // construct stage 3
cur_bucket = 0;
for ( j = 0; j <= dy; j++ ) { for ( j = 0; j <= dy; j++ ) {
for ( i = 0; i <= dx; i++ ) { for ( i = 0; i <= dx; i++ ) {
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j); 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_bucket( b_cur );
stage3->set_debug( debug_dir, debug_area_defs, debug_shape_defs ); 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->LoadFromIntermediateFiles(2);
stage3->ConstructBucketStage3(); stage3->ConstructBucketStage3();

View file

@ -73,9 +73,7 @@ void TGConstruct::set_options( bool ignore_lm, double n ) {
// Also, we are still calculating some thing more than one // Also, we are still calculating some thing more than one
// (like face area - need to move this into superpoly ) // (like face area - need to move this into superpoly )
void TGConstruct::ConstructBucketStage1() { void TGConstruct::ConstructBucketStage1() {
// First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
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() );
/* If we have some debug IDs, create a datasource */ /* If we have some debug IDs, create a datasource */
if ( debug_shapes.size() || debug_all ) { if ( debug_shapes.size() || debug_all ) {
@ -91,6 +89,7 @@ void TGConstruct::ConstructBucketStage1() {
// STEP 2) // STEP 2)
// Clip 2D polygons against one another // Clip 2D polygons against one another
SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass polys" );
if ( LoadLandclassPolys() == 0 ) { if ( LoadLandclassPolys() == 0 ) {
// don't build the tile if there is no 2d data ... it *must* // 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. // be ocean and the sim can build the tile on the fly.
@ -101,16 +100,20 @@ void TGConstruct::ConstructBucketStage1() {
// STEP 3) // STEP 3)
// Load the land use polygons if the --cover option was specified // Load the land use polygons if the --cover option was specified
if ( get_cover().size() > 0 ) { if ( get_cover().size() > 0 ) {
SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass raster" );
load_landcover(); load_landcover();
} }
// STEP 4) // STEP 4)
// Clip the Landclass polygons // Clip the Landclass polygons
SG_LOG(SG_GENERAL, SG_ALERT, " - Clipping landclass polys" );
ClipLandclassPolys(); ClipLandclassPolys();
// STEP 5) // STEP 5)
// Clean the polys - after this, we shouldn't change their shape (other than slightly for // 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 // 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(); CleanClippedPolys();
// STEP 6) // STEP 6)
@ -120,9 +123,7 @@ void TGConstruct::ConstructBucketStage1() {
void TGConstruct::ConstructBucketStage2() { void TGConstruct::ConstructBucketStage2() {
if ( !IsOceanTile() ) { if ( !IsOceanTile() ) {
// First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
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() );
/* If we have some debug IDs, create a datasource */ /* If we have some debug IDs, create a datasource */
if ( debug_shapes.size() || debug_all ) { if ( debug_shapes.size() || debug_all ) {
@ -143,43 +144,43 @@ void TGConstruct::ConstructBucketStage2() {
// STEP 9) // STEP 9)
// Fix T-Junctions by finding nodes that lie close to polygon edges, and // Fix T-Junctions by finding nodes that lie close to polygon edges, and
// inserting them into the edge // inserting them into the edge
SG_LOG(SG_GENERAL, SG_ALERT, " - Fix T-Junctions" );
nodes.init_spacial_query();
FixTJunctions(); FixTJunctions();
// STEP 10) // STEP 10)
// Generate triangles - we can't generate the node-face lookup table // Generate triangles - we can't generate the node-face lookup table
// until all polys are tesselated, as extra nodes can still be generated // until all polys are tesselated, as extra nodes can still be generated
SG_LOG(SG_GENERAL, SG_ALERT, " - Tesselate" );
TesselatePolys(); 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) // STEP 12)
// Generate triangle vertex coordinates to node index lists // Generate triangle vertex coordinates to node index lists
// NOTE: After this point, no new nodes can be added // NOTE: After this point, no new nodes can be added
SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Nodes Per Vertex");
LookupNodesPerVertex(); LookupNodesPerVertex();
// STEP 13) // STEP 13)
// Interpolate elevations, and flatten stuff // Interpolate elevations, and flatten stuff
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Elevation Per Node");
CalcElevations(); CalcElevations();
// STEP 14) // 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(); LookupFacesPerNode();
// STEP 15) // STEP 15)
// Save the tile boundary info for stage 3 // Save the tile boundary info for stage 3
// includes elevation info, and a list of connected triangles // includes elevation info, and a list of connected triangles
nodes.init_spacial_query();
SaveSharedEdgeData( 2 ); SaveSharedEdgeData( 2 );
} }
} }
void TGConstruct::ConstructBucketStage3() { void TGConstruct::ConstructBucketStage3() {
if ( !IsOceanTile() ) { if ( !IsOceanTile() ) {
// First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
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() );
/* If we have some debug IDs, create a datasource */ /* If we have some debug IDs, create a datasource */
if ( debug_shapes.size() || debug_all ) { if ( debug_shapes.size() || debug_all ) {
@ -189,20 +190,26 @@ void TGConstruct::ConstructBucketStage3() {
strcpy( ds_name, "" ); strcpy( ds_name, "" );
} }
SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node (again)");
LookupFacesPerNode();
// STEP 16) // STEP 16)
// Load in the neighbor faces and elevation data // Load in the neighbor faces and elevation data
LoadSharedEdgeDataStage2(); LoadSharedEdgeDataStage2();
// STEP 17) // STEP 17)
// Average out the elevation for nodes on tile boundaries // Average out the elevation for nodes on tile boundaries
SG_LOG(SG_GENERAL, SG_ALERT, " - Average Edge Node Elevations");
AverageEdgeElevations(); AverageEdgeElevations();
// STEP 18) // STEP 18)
// Calculate Face Normals // Calculate Face Normals
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Face Normals");
CalcFaceNormals(); CalcFaceNormals();
// STEP 19) // STEP 19)
// Calculate Point Normals // Calculate Point Normals
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Point Normals");
CalcPointNormals(); CalcPointNormals();
#if 0 #if 0
@ -217,14 +224,17 @@ void TGConstruct::ConstructBucketStage3() {
// STEP 21) // STEP 21)
// Calculate Texture Coordinates // Calculate Texture Coordinates
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Texture Coordinates");
CalcTextureCoordinates(); CalcTextureCoordinates();
// STEP 22) // STEP 22)
// Generate the btg file // Generate the btg file
SG_LOG(SG_GENERAL, SG_ALERT, " - Generate BTG File");
WriteBtgFile(); WriteBtgFile();
// STEP 23) // STEP 23)
// Write Custom objects to .stg file // Write Custom objects to .stg file
SG_LOG(SG_GENERAL, SG_ALERT, " - Generate Custome Objects");
AddCustomObjects(); AddCustomObjects();
} }
} }

View file

@ -38,24 +38,24 @@
#include <landcover/landcover.hxx> #include <landcover/landcover.hxx>
#include "tglandclass.hxx" #include "tglandclass.hxx"
#include "priorities.hxx"
#define FIND_SLIVERS (0) #define FIND_SLIVERS (0)
// Stage2 shared edge data // Stage2 shared edge data
struct TGNeighborFaces { struct TGNeighborFaces {
public: public:
Point3D node; SGGeod node;
double_list elevations; // we'll take the average double_list elevations; // we'll take the average
double_list face_areas; double_list face_areas;
point_list face_normals; std::vector<SGVec3f> face_normals;
}; };
typedef std::vector < TGNeighborFaces > neighbor_face_list; typedef std::vector < TGNeighborFaces > neighbor_face_list;
typedef neighbor_face_list::iterator neighbor_face_list_iterator; typedef neighbor_face_list::iterator neighbor_face_list_iterator;
typedef neighbor_face_list::const_iterator const_neighbor_face_list_iterator; typedef neighbor_face_list::const_iterator const_neighbor_face_list_iterator;
class TGConstruct { class TGConstruct {
private: private:
@ -135,16 +135,15 @@ private:
// Shared edge Matching // Shared edge Matching
void SaveSharedEdgeDataStage2( void ); void SaveSharedEdgeDataStage2( void );
void LoadSharedEdgeDataStage2( void ); void LoadSharedEdgeDataStage2( void );
void WriteSharedEdgeNeighboorFaces( gzFile& fp, Point3D pt );
void LoadSharedEdgeData( int stage ); 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<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west );
void SaveSharedEdgeData( int stage ); void SaveSharedEdgeData( int stage );
void ReadNeighborFaces( gzFile& fp ); void ReadNeighborFaces( gzFile& fp );
void WriteNeighborFaces( gzFile& fp, Point3D pt ); void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const;
TGNeighborFaces* AddNeighborFaces( Point3D node ); TGNeighborFaces* AddNeighborFaces( const SGGeod& node );
TGNeighborFaces* FindNeighborFaces( Point3D node ); TGNeighborFaces* FindNeighborFaces( const SGGeod& node );
// Polygon Cleaning // Polygon Cleaning
void CleanClippedPolys( void ); void CleanClippedPolys( void );
@ -164,9 +163,7 @@ private:
void CalcPointNormals( void ); void CalcPointNormals( void );
void CalcTextureCoordinates( void ); void CalcTextureCoordinates( void );
// Helpers // Helpers
SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ); SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const;
TGPolygon linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp );
TGPolygon area_tex_coords( const TGPolygon& tri );
// Output // Output
void WriteBtgFile( void ); void WriteBtgFile( void );
@ -179,10 +176,6 @@ private:
bool IsDebugShape( unsigned int id ); bool IsDebugShape( unsigned int id );
bool IsDebugArea( unsigned int area ); 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: public:
// Constructor // Constructor
TGConstruct(); TGConstruct();

View file

@ -40,25 +40,25 @@ using std::string;
void TGConstruct::FixTJunctions( void ) { void TGConstruct::FixTJunctions( void ) {
int before, after; int before, after;
std::vector<SGGeod> points; std::vector<SGGeod> points;
nodes.get_geod_nodes( points ); tg::Rectangle bb;
// traverse each poly, and add intermediate nodes // traverse each poly, and add intermediate nodes
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) { 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 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);
tgPolygon current = polys_clipped.get_poly(i, j, k); bb = current.GetBoundingBox();
nodes.get_geod_inside( bb.getMin(), bb.getMax(), points );
before = current.TotalNodes(); before = current.TotalNodes();
current = tgPolygon::AddColinearNodes( current, points ); current = tgPolygon::AddColinearNodes( current, points );
after = current.TotalNodes(); after = current.TotalNodes();
if (before != after) { 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 ); 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 */ /* Save it back */
polys_clipped.set_poly( i, j, k, current ); polys_clipped.set_poly( i, j, current );
}
} }
} }
} }
@ -76,23 +76,7 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l
continue; continue;
} }
for ( unsigned int s = 0; s < clipped.area_size(area) && sliver_list.size(); ++s ) { sliver_list = tgPolygon::MergeSlivers( polys_clipped.get_polys(area), sliver_list );
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
}
}
} }
SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << sliver_list.size() ); 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() { void TGConstruct::CleanClippedPolys() {
// Clean the polys // Clean the polys
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { 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 p = 0; p < polys_clipped.area_size(area); p++ ) {
unsigned int id = polys_clipped.get_shape( area, shape ).id;
// step 1 : snap // step 1 : snap
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { tgPolygon poly = polys_clipped.get_poly(area, p);
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
poly = tgPolygon::Snap(poly, gSnap); poly = tgPolygon::Snap(poly, gSnap);
polys_clipped.set_poly( area, shape, segment, poly );
}
if ( IsDebugShape( id ) ) { if ( IsDebugShape( poly.GetId() ) ) {
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "snapped", "" ); tgPolygon::ToShapefile( poly, ds_name, "snapped", "" );
} }
// step 2 : remove_dups // 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 ); poly = tgPolygon::RemoveDups( poly );
polys_clipped.set_poly( area, shape, segment, poly );
}
if ( IsDebugShape( id ) ) { if ( IsDebugShape( poly.GetId() ) ) {
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_dups", "" ); tgPolygon::ToShapefile( poly, ds_name, "rem_dups", "" );
} }
// step 3 : remove_bad_contours // 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 ); poly = tgPolygon::RemoveBadContours( poly );
polys_clipped.set_poly( area, shape, segment, poly );
if ( IsDebugShape( poly.GetId() ) ) {
tgPolygon::ToShapefile( poly, ds_name, "rem_bcs", "" );
} }
if ( IsDebugShape( id ) ) { polys_clipped.set_poly(area, p, poly);
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
} }
} }
} }
@ -167,10 +129,10 @@ void TGConstruct::AverageEdgeElevations( void )
elevation = elevation / num_elevations; elevation = elevation / num_elevations;
/* Find this node, and update it's elevation */ /* Find this node, and update it's elevation */
int idx = nodes.find( faces.node.toSGGeod() ); int idx = nodes.find( faces.node );
if (idx != -1) { if (idx != -1) {
TGNode node = nodes.get_node( idx ); TGNode const& node = nodes.get_node( idx );
if ( !node.GetFixedPosition() ) { if ( !node.GetFixedPosition() ) {
// set elevation as the average between all tiles that have it // set elevation as the average between all tiles that have it

View file

@ -77,16 +77,16 @@ bool TGConstruct::ClipLandclassPolys( void ) {
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) { for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
if ( is_landmass_area( i ) && !ignoreLandmass ) { if ( is_landmass_area( i ) && !ignoreLandmass ) {
for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) { 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 ) ) { } else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.area_size(i); j++) { 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 ) ) { } else if ( is_island_area( i ) ) {
for (unsigned int j = 0; j < polys_in.area_size(i); j++) { 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 ) { for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
debug_area = IsDebugArea( i ); debug_area = IsDebugArea( i );
for( j = 0; j < (int)polys_in.area_size(i); ++j ) { for( j = 0; j < (int)polys_in.area_size(i); ++j ) {
tgPolygon current = polys_in.get_mask(i, j); tgPolygon& current = polys_in.get_poly(i, j);
debug_shape = IsDebugShape( polys_in.get_shape( i, j ).id ); 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; tmp = current;
@ -122,18 +122,17 @@ bool TGConstruct::ClipLandclassPolys( void ) {
if ( is_water_area( i ) ) { if ( is_water_area( i ) ) {
// clip against island mask // clip against island mask
tmp = tgPolygon::Diff( tmp, island_mask ); tmp = tgPolygon::Diff( tmp, island_mask );
} }
if ( debug_area || debug_shape ) { if ( debug_area || debug_shape ) {
char layer[32]; char layer[32];
char name[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); sprintf(name, "shape %d,%d", i,j);
tgPolygon::ToShapefile( tmp, ds_name, layer, name ); 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 ); accum.ToShapefiles( ds_name, layer );
} }
@ -143,7 +142,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
char layer[32]; char layer[32];
char name[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); sprintf(name, "shape %d,%d", i,j);
tgPolygon::ToShapefile( clipped, ds_name, layer, name ); 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 // add the sliverless result polygon to the clipped polys list
if ( clipped.Contours() > 0 ) { if ( clipped.Contours() > 0 ) {
TGShape shape;
// copy all of the superpolys and texparams // copy all of the superpolys and texparams
shape.SetMask( clipped ); clipped.SetId( polys_in.get_poly( i, j ).GetId() );
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;
// shape.sps.push_back( sp ); // shape.sps.push_back( sp );
polys_clipped.add_shape( i, shape ); polys_clipped.add_poly( i, clipped );
#if 0 #if 0
if ( debug_area || debug_shape ) { if ( debug_area || debug_shape ) {
@ -183,7 +175,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
accum.Add( tmp ); accum.Add( tmp );
if ( debug_area || debug_shape ) { if ( debug_area || debug_shape ) {
char layer[32]; 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 ); accum.ToShapefiles( ds_name, layer );
} }
@ -192,6 +184,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
} }
} }
#if 0
if ( debug_all || debug_shapes.size() || debug_areas.size() ) { if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
// Dump the sliver list // Dump the sliver list
char name[32]; char name[32];
@ -200,6 +193,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
tgContour::ToShapefile( slivers[i], ds_name, "slivers", name ); tgContour::ToShapefile( slivers[i], ds_name, "slivers", name );
} }
} }
#endif
#if FIND_SLIVERS #if FIND_SLIVERS
// Now, merge any slivers with clipped polys // Now, merge any slivers with clipped polys
@ -234,40 +228,23 @@ bool TGConstruct::ClipLandclassPolys( void ) {
#endif #endif
if ( remains.Contours() > 0 ) { if ( remains.Contours() > 0 ) {
TGShape shape; remains.SetMaterial( get_area_name(get_sliver_target_area_type()) );
polys_clipped.add_poly( (int)get_sliver_target_area_type(), remains );
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();
} }
} }
// Now make sure any newly added intersection nodes are added to the tgnodes // 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 area = 0; area < TG_MAX_AREA_TYPES; area++) {
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
for (unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++) { tgPolygon& poly = polys_clipped.get_poly( area, p );
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
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 con=0; con < poly.Contours(); con++) {
for (unsigned int node = 0; node < poly.ContourSize( con ); node++) { for (unsigned int n = 0; n < poly.ContourSize( con ); n++) {
// ensure we have all nodes... // ensure we have all nodes...
nodes.unique_add( poly.GetNode( con, node ) ); TGNode const& node = poly.GetNode( con, n );
} nodes.unique_add( node );
} }
} }
} }

View file

@ -35,8 +35,6 @@ using std::string;
void TGConstruct::set_debug( std::string path, std::vector<string> area_defs, std::vector<string> shape_defs ) void TGConstruct::set_debug( std::string path, std::vector<string> area_defs, std::vector<string> shape_defs )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "Set debug Path " << path);
debug_path = path; debug_path = path;
/* Find any ids for our tile */ /* Find any ids for our tile */
@ -132,77 +130,3 @@ bool TGConstruct::IsDebugArea( unsigned int area )
return is_debug; 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; i<polys.size(); i++ ) {
sprintf( feature_name, "poly_%d", i );
tgShapefileCreateFeature( ds_id, l_id, polys[i], feature_name );
}
// close after each write
ds_id = tgShapefileCloseDatasource( ds_id );
}
#endif
// TODO : Add to TGNodes class
#if 0
bool TGNodesSortByLon( const TGNode& n1, const TGNode& n2 )
{
return ( n1.GetPosition().x() < n2.GetPosition().x() );
}
static void dump_lat_nodes( TGConstruct& c, double lat ) {
node_list all_nodes = c.get_nodes()->get_node_list();
node_list sorted_nodes;
for (unsigned int i=0; i<all_nodes.size(); i++) {
if ( fabs( all_nodes[i].GetPosition().y() - lat ) < 0.0000001 ) {
sorted_nodes.push_back( all_nodes[i] );
}
}
sort( sorted_nodes.begin(), sorted_nodes.end(), TGNodesSortByLon );
for (unsigned int i=0; i<sorted_nodes.size(); i++) {
string fixed;
if ( sorted_nodes[i].GetFixedPosition() ) {
fixed = " z is fixed elevation ";
} else {
fixed = " z is interpolated elevation ";
}
SG_LOG(SG_GENERAL, SG_ALERT, "Point[" << i << "] is " << sorted_nodes[i].GetPosition() << fixed );
}
}
#endif

View file

@ -59,31 +59,7 @@ void TGConstruct::LoadElevationArray( bool add_nodes ) {
for (unsigned int i=0; i<fit_list.size(); i++) { for (unsigned int i=0; i<fit_list.size(); i++) {
nodes.unique_add( fit_list[i].toSGGeod() ); nodes.unique_add( fit_list[i].toSGGeod() );
} }
} }
}
static void calc_gc_course_dist( const Point3D& start, const Point3D& dest,
double *course, double *dist ) {
SGGeoc gs = start.toSGGeoc();
SGGeoc gd = dest.toSGGeoc();
*course = SGGeoc::courseRad(gs, gd);
*dist = SGGeoc::distanceM(gs, gd);
}
// calculate spherical distance between two points (lon, lat specified
// in degrees, result returned in meters)
static double distanceSphere( const SGGeoc& p1, const SGGeod& p2 ) {
Point3D r1( p1.getLongitudeRad(),
p1.getLatitudeRad(),
p1.getRadiusM() );
Point3D r2( p2.getLongitudeRad(),
p2.getLatitudeRad(),
p2.getElevationM() );
double course, dist_m;
calc_gc_course_dist( r1, r2, &course, &dist_m );
return dist_m;
} }
// fix the elevations of the geodetic nodes // fix the elevations of the geodetic nodes
@ -92,14 +68,11 @@ static double distanceSphere( const SGGeoc& p1, const SGGeod& p2 ) {
void TGConstruct::CalcElevations( void ) void TGConstruct::CalcElevations( void )
{ {
std::vector<SGGeod> raw_nodes; std::vector<SGGeod> raw_nodes;
SGGeoc p;
double e1, e2, e3, min; double e1, e2, e3, min;
int n1, n2, n3; int n1, n2, n3;
SG_LOG(SG_GENERAL, SG_ALERT, "fixing node heights");
for (int i = 0; i < (int)nodes.size(); ++i) { 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(); SGGeod pos = node.GetPosition();
if ( !node.GetFixedPosition() ) { if ( !node.GetFixedPosition() ) {
@ -113,11 +86,9 @@ void TGConstruct::CalcElevations( void )
// now flatten some stuff // now flatten some stuff
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
if ( is_lake_area( (AreaType)area ) ) { if ( is_lake_area( (AreaType)area ) ) {
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { 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++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
n1 = poly.GetTriIdx( tri, 0 ); n1 = poly.GetTriIdx( tri, 0 );
@ -137,14 +108,11 @@ void TGConstruct::CalcElevations( void )
} }
} }
} }
}
if ( is_stream_area( (AreaType)area ) ) { if ( is_stream_area( (AreaType)area ) ) {
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { 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++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
n1 = poly.GetTriIdx( tri, 0 ); n1 = poly.GetTriIdx( tri, 0 );
@ -155,14 +123,27 @@ void TGConstruct::CalcElevations( void )
e3 = nodes.get_node(n3).GetPosition().getElevationM(); e3 = nodes.get_node(n3).GetPosition().getElevationM();
min = e1; min = e1;
p = SGGeoc::fromGeod( raw_nodes[n1] ); SGGeod src = raw_nodes[n1];
if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); } if ( e2 < min ) { min = e2; src = raw_nodes[n2]; }
if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); } if ( e3 < min ) { min = e3; src = raw_nodes[n3]; }
double d1 = distanceSphere( p, raw_nodes[n1] ); double d1, d2, d3;
double d2 = distanceSphere( p, raw_nodes[n2] ); if ( min == e1 ) {
double d3 = distanceSphere( p, raw_nodes[n3] ); 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 max1 = d1 * 0.20 + min;
double max2 = d2 * 0.20 + min; double max2 = d2 * 0.20 + min;
@ -174,14 +155,11 @@ void TGConstruct::CalcElevations( void )
} }
} }
} }
}
if ( is_road_area( (AreaType)area ) ) { if ( is_road_area( (AreaType)area ) ) {
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { 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++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
n1 = poly.GetTriIdx( tri, 0 ); n1 = poly.GetTriIdx( tri, 0 );
@ -192,14 +170,27 @@ void TGConstruct::CalcElevations( void )
e3 = nodes.get_node(n3).GetPosition().getElevationM(); e3 = nodes.get_node(n3).GetPosition().getElevationM();
min = e1; min = e1;
p = SGGeoc::fromGeod( raw_nodes[n1] ); SGGeod src = raw_nodes[n1];
if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); } if ( e2 < min ) { min = e2; src = raw_nodes[n2]; }
if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); } if ( e3 < min ) { min = e3; src = raw_nodes[n3]; }
double d1 = distanceSphere( p, raw_nodes[n1] ); double d1, d2, d3;
double d2 = distanceSphere( p, raw_nodes[n2] ); if ( min == e1 ) {
double d3 = distanceSphere( p, raw_nodes[n3] ); 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 max1 = d1 * 0.30 + min;
double max2 = d2 * 0.30 + min; double max2 = d2 * 0.30 + min;
@ -211,14 +202,11 @@ void TGConstruct::CalcElevations( void )
} }
} }
} }
}
if ( is_ocean_area( (AreaType)area ) ) { if ( is_ocean_area( (AreaType)area ) ) {
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) { for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) { 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++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
n1 = poly.GetTriIdx( tri, 0 ); n1 = poly.GetTriIdx( tri, 0 );
@ -232,5 +220,4 @@ void TGConstruct::CalcElevations( void )
} }
} }
} }
}
} }

View file

@ -34,13 +34,10 @@
// indexes into the node array (cast as unsigned long) // indexes into the node array (cast as unsigned long)
void TGConstruct::LookupNodesPerVertex( void ) void TGConstruct::LookupNodesPerVertex( void )
{ {
SG_LOG(SG_GENERAL, SG_ALERT, "LookupNodesPerVertex");
// for each node, traverse all the triangles - and create face lists // 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 area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { tgPolygon& poly = polys_clipped.get_poly( area, p );
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
for (unsigned int vertex = 0; vertex < 3; vertex++) { for (unsigned int vertex = 0; vertex < 3; vertex++) {
@ -53,28 +50,21 @@ void TGConstruct::LookupNodesPerVertex( void )
} }
} }
} }
polys_clipped.set_poly( area, shape, segment, poly );
}
} }
} }
} }
void TGConstruct::LookupFacesPerNode( 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 // 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 area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { tgPolygon const& poly = polys_clipped.get_poly(area, p );
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
for (unsigned int tri=0; tri < poly.Triangles(); tri++) { for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
for (int v = 0; v < 3; v++) { for (int v = 0; v < 3; v++) {
int i = poly.GetTriIdx( tri, v ); int i = poly.GetTriIdx( tri, v );
nodes.AddFace( i, area, shape, segment, tri ); nodes.AddFace( i, area, p, tri );
}
} }
} }
} }

View file

@ -29,19 +29,7 @@
#include "tgconstruct.hxx" #include "tgconstruct.hxx"
//using std::string; SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const {
#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 v1, v2; SGVec3f v1, v2;
SGVec3f normal; SGVec3f normal;
@ -111,11 +99,9 @@ void TGConstruct::CalcFaceNormals( void )
nodes.get_geod_nodes( geod_nodes ); nodes.get_geod_nodes( geod_nodes );
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { 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 p = 0; p < polys_clipped.area_size(area); p++ ) {
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { SG_LOG( SG_CLIPPER, SG_DEBUG, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_in.area_size(area) );
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, p ) );
calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, shape, segment ) );
}
} }
} }
} }
@ -123,9 +109,7 @@ void TGConstruct::CalcFaceNormals( void )
void TGConstruct::CalcPointNormals( void ) void TGConstruct::CalcPointNormals( void )
{ {
// traverse triangle structure building the face normal table // traverse triangle structure building the face normal table
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals: 0%"); SGVec3f normal;
SGVec3d normal;
double face_area; double face_area;
std::vector<SGVec3d> wgs84_nodes; std::vector<SGVec3d> wgs84_nodes;
@ -135,15 +119,15 @@ void TGConstruct::CalcPointNormals( void )
unsigned int cur_percent = 1; unsigned int cur_percent = 1;
for ( unsigned int i = 0; i<nodes.size(); i++ ) { for ( unsigned int i = 0; i<nodes.size(); i++ ) {
TGNode node = nodes.get_node( i ); TGNode const& node = nodes.get_node( i );
TGFaceList faces = node.GetFaces(); TGFaceList const& faces = node.GetFaces();
TGNeighborFaces* neighbor_faces = NULL; TGNeighborFaces const* neighbor_faces = NULL;
double total_area = 0.0; double total_area = 0.0;
SGVec3d average( 0.0, 0.0, 0.0 ); SGVec3f average( 0.0, 0.0, 0.0 );
if ( i == one_percent ) { if ( i == one_percent ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals: " << cur_percent << "%" ); SG_LOG(SG_GENERAL, SG_DEBUG, "Calculating point normals: " << cur_percent << "%" );
one_percent += nodes.size() / 100; one_percent += nodes.size() / 100;
cur_percent += 1; cur_percent += 1;
} }
@ -151,12 +135,11 @@ void TGConstruct::CalcPointNormals( void )
// for each triangle that shares this node // for each triangle that shares this node
for ( unsigned int j = 0; j < faces.size(); ++j ) { for ( unsigned int j = 0; j < faces.size(); ++j ) {
unsigned int at = faces[j].area; unsigned int at = faces[j].area;
unsigned int shape = faces[j].shape; unsigned int poly = faces[j].poly;
unsigned int segment = faces[j].seg;
unsigned int tri = faces[j].tri; unsigned int tri = faces[j].tri;
normal = polys_clipped.get_face_normal( at, shape, segment, tri ).toSGVec3d(); normal = polys_clipped.get_face_normal( at, poly, tri );
face_area = polys_clipped.get_face_area( at, shape, segment, tri ); face_area = polys_clipped.get_face_area( at, poly, tri );
normal *= face_area; // scale normal weight relative to area normal *= face_area; // scale normal weight relative to area
total_area += face_area; total_area += face_area;
@ -164,11 +147,11 @@ void TGConstruct::CalcPointNormals( void )
} }
// if this node exists in the shared edge db, add the faces from the neighbooring tile // if this node exists in the shared edge db, add the faces from the neighbooring tile
neighbor_faces = FindNeighborFaces( Point3D::fromSGGeod( node.GetPosition() ) ); neighbor_faces = FindNeighborFaces( node.GetPosition() );
if ( neighbor_faces ) { if ( neighbor_faces ) {
int num_faces = neighbor_faces->face_areas.size(); int num_faces = neighbor_faces->face_areas.size();
for ( int j = 0; j < num_faces; j++ ) { 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]; face_area = neighbor_faces->face_areas[j];
normal *= face_area; normal *= face_area;
@ -178,7 +161,6 @@ void TGConstruct::CalcPointNormals( void )
} }
average /= total_area; average /= total_area;
SGVec3f n = SGVec3f( average.x(), average.y(), average.z() ); nodes.SetNormal( i, average );
nodes.SetNormal( i, n );
} }
} }

View file

@ -135,20 +135,14 @@ void TGConstruct::WriteBtgFile( void )
int_list pt_n, tri_n, strip_n; int_list pt_n, tri_n, strip_n;
int_list tri_tc, strip_tc; 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++) { for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
// only tesselate non holes // only tesselate non holes
if ( !is_hole_area( area ) ) { if ( !is_hole_area( area ) ) {
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) { for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { SG_LOG( SG_CLIPPER, SG_DEBUG, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
SG_LOG( SG_CLIPPER, SG_INFO, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" <<
shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
tgPolygon poly = polys_clipped.get_poly(area, shape, segment); tgPolygon poly = polys_clipped.get_poly(area, p);
string material = polys_clipped.get_material(area, shape, segment); string material = poly.GetMaterial();
SG_LOG(SG_GENERAL, SG_INFO, " num tris " << poly.Triangles() );
for (unsigned int k = 0; k < poly.Triangles(); ++k) { for (unsigned int k = 0; k < poly.Triangles(); ++k) {
tri_v.clear(); tri_v.clear();
@ -169,15 +163,11 @@ void TGConstruct::WriteBtgFile( void )
tris_n.push_back( tri_n ); tris_n.push_back( tri_n );
tris_tc.push_back( tri_tc ); 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 ); tri_materials.push_back( material );
} }
} }
} }
} }
}
std::vector< SGVec3d > wgs84_nodes; std::vector< SGVec3d > wgs84_nodes;
nodes.get_wgs84_nodes( wgs84_nodes ); nodes.get_wgs84_nodes( wgs84_nodes );

View file

@ -37,20 +37,6 @@ using std::string;
static unsigned int cur_poly_id = 0; 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 TGConstruct::load_poly(const string& path) {
bool poly3d = false; bool poly3d = false;
bool with_tp = false; bool with_tp = false;
@ -114,11 +100,11 @@ bool TGConstruct::load_poly(const string& path) {
// Generate a new Shape for the poly // Generate a new Shape for the poly
TGShape shape;
tgPolygon poly; tgPolygon poly;
SGGeod p; SGGeod p;
for (k=0; k<num_polys;k++) { for (k=0; k<num_polys;k++) {
poly.Erase();
if ( with_tp ) { if ( with_tp ) {
in >> x; in >> x;
@ -213,24 +199,19 @@ bool TGConstruct::load_poly(const string& path) {
poly.SetMaterial( material ); poly.SetMaterial( material );
if ( with_tp ) { if ( with_tp ) {
shape.textured = true; poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, -1, 0, 1, 0 );
} else { } else {
shape.textured = false; poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() );
} }
shape.polys.push_back( poly );
in >> skipcomment; in >> skipcomment;
poly.SetId( cur_poly_id++ );
polys_in.add_poly( area, poly );
if ( IsDebugShape( poly.GetId() ) ) {
tgPolygon::ToShapefile( poly, ds_name, "loaded", "" );
} }
// Once the full poly is loaded, build the clip mask
shape.BuildMask();
shape.area = area;
shape.id = cur_poly_id++;
polys_in.add_shape( area, shape );
if ( IsDebugShape( shape.id ) ) {
tgPolygon::ToShapefile( shape.mask, ds_name, "loaded", "" );
} }
} }
@ -260,7 +241,7 @@ int TGConstruct::LoadLandclassPolys( void ) {
} }
simgear::PathList files = d.children(simgear::Dir::TYPE_FILE); 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) { BOOST_FOREACH(const SGPath& p, files) {
if (p.file_base() != tile_str) { if (p.file_base() != tile_str) {
@ -274,7 +255,7 @@ int TGConstruct::LoadLandclassPolys( void ) {
// skipped! // skipped!
} else { } else {
load_poly( p.str() ); load_poly( p.str() );
SG_LOG(SG_GENERAL, SG_ALERT, " Loaded " << p.file()); SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file());
++count; ++count;
} }
} // of directory file children } // of directory file children

View file

@ -96,7 +96,7 @@ void TGConstruct::SaveSharedEdgeData( int stage )
{ {
// for stage 2, we need enough info on a node to average out elevation and // for stage 2, we need enough info on a node to average out elevation and
// generate a correct normal // 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. // to store the neighboors.
// //
// NOTE: Some neighboors (likely 2) are on the shared border. // 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 // find all neighboors of this point
int n = nodes.find( pt.toSGGeod() ); int n = nodes.find( pt );
TGNode node = nodes.get_node( n ); TGNode const& node = nodes.get_node( n );
TGFaceList faces = node.GetFaces(); TGFaceList const& faces = node.GetFaces();
// write the number of neighboor faces // write the number of neighboor faces
sgWriteInt( fp, faces.size() ); sgWriteInt( fp, faces.size() );
@ -123,20 +123,16 @@ void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
// write out each face normal and size // write out each face normal and size
for (unsigned int j=0; j<faces.size(); j++) { for (unsigned int j=0; j<faces.size(); j++) {
// for each connected face, get the nodes // for each connected face, get the nodes
unsigned int at = faces[j].area;
unsigned int shape = faces[j].shape;
unsigned int segment = faces[j].seg;
unsigned int tri = faces[j].tri; unsigned int tri = faces[j].tri;
tgPolygon const& poly = polys_clipped.get_poly( faces[j].area, faces[j].poly );
tgPolygon poly = polys_clipped.get_poly( at, shape, segment ); SGGeod const& p1 = nodes[ poly.GetTriIdx( tri, 0) ].GetPosition();
SGGeod const& p2 = nodes[ poly.GetTriIdx( tri, 1) ].GetPosition();
SGGeod const& p3 = nodes[ poly.GetTriIdx( tri, 2) ].GetPosition();
SGGeod p1 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetPosition(); SGVec3d const& wgs_p1 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
SGGeod p2 = nodes.get_node( poly.GetTriIdx( tri, 1) ).GetPosition(); SGVec3d const& wgs_p2 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
SGGeod p3 = nodes.get_node( poly.GetTriIdx( tri, 2) ).GetPosition(); SGVec3d const& wgs_p3 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
SGVec3d wgs_p1 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
SGVec3d wgs_p2 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
SGVec3d wgs_p3 = nodes.get_node( poly.GetTriIdx( tri, 0) ).GetWgs84();
double face_area = triangle_area( p1, p2, p3 ); double face_area = triangle_area( p1, p2, p3 );
SGVec3f face_normal = calc_normal( face_area, wgs_p1, wgs_p2, wgs_p3 ); SGVec3f face_normal = calc_normal( face_area, wgs_p1, wgs_p2, wgs_p3 );
@ -146,7 +142,7 @@ void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
} }
} }
TGNeighborFaces* TGConstruct::FindNeighborFaces( Point3D node ) TGNeighborFaces* TGConstruct::FindNeighborFaces( const SGGeod& node )
{ {
TGNeighborFaces* faces = NULL; TGNeighborFaces* faces = NULL;
@ -160,7 +156,7 @@ TGNeighborFaces* TGConstruct::FindNeighborFaces( Point3D node )
return faces; return faces;
} }
TGNeighborFaces* TGConstruct::AddNeighborFaces( Point3D node ) TGNeighborFaces* TGConstruct::AddNeighborFaces( const SGGeod& node )
{ {
TGNeighborFaces faces; TGNeighborFaces faces;
faces.node = node; faces.node = node;
@ -187,14 +183,14 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
// look to see if we already have this node // look to see if we already have this node
// If we do, (it's a corner) add more faces to it. // If we do, (it's a corner) add more faces to it.
// otherwise, initialize it with our elevation data // otherwise, initialize it with our elevation data
pFaces = FindNeighborFaces( Point3D::fromSGGeod( node ) ); pFaces = FindNeighborFaces( node );
if ( !pFaces ) { if ( !pFaces ) {
pFaces = AddNeighborFaces( Point3D::fromSGGeod( node ) ); pFaces = AddNeighborFaces( node );
// new face - let's add our elevation first // new face - let's add our elevation first
int idx = nodes.find( node ); int idx = nodes.find( node );
if (idx >= 0) { if (idx >= 0) {
TGNode local = nodes.get_node( idx ); TGNode const& local = nodes.get_node( idx );
pFaces->elevations.push_back( local.GetPosition().getElevationM() ); pFaces->elevations.push_back( local.GetPosition().getElevationM() );
} }
} }
@ -212,7 +208,7 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
pFaces->face_areas.push_back( area ); pFaces->face_areas.push_back( area );
sgReadVec3( fp, normal ); 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<nCount; i++) { for (int i=0; i<nCount; i++) {
// write the 3d point // write the 3d point
sgWriteGeod( fp, north[i] ); sgWriteGeod( fp, north[i] );
WriteNeighborFaces( fp, Point3D::fromSGGeod( north[i] ) ); WriteNeighborFaces( fp, north[i] );
} }
gzclose(fp); gzclose(fp);
@ -262,7 +258,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
sgWriteInt( fp, nCount ); sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgWriteGeod( fp, south[i] ); sgWriteGeod( fp, south[i] );
WriteNeighborFaces( fp, Point3D::fromSGGeod( south[i] ) ); WriteNeighborFaces( fp, south[i] );
} }
gzclose(fp); gzclose(fp);
@ -278,7 +274,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
sgWriteInt( fp, nCount ); sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgWriteGeod( fp, east[i] ); sgWriteGeod( fp, east[i] );
WriteNeighborFaces( fp, Point3D::fromSGGeod( east[i] ) ); WriteNeighborFaces( fp, east[i] );
} }
gzclose(fp); gzclose(fp);
@ -294,7 +290,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
sgWriteInt( fp, nCount ); sgWriteInt( fp, nCount );
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgWriteGeod( fp, west[i] ); sgWriteGeod( fp, west[i] );
WriteNeighborFaces( fp, Point3D::fromSGGeod( west[i] ) ); WriteNeighborFaces( fp, west[i] );
} }
gzclose(fp); gzclose(fp);
} }
@ -381,6 +377,7 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
gzclose( fp ); gzclose( fp );
file = dir + "/" + bucket.gen_index_str() + "_nodes"; file = dir + "/" + bucket.gen_index_str() + "_nodes";
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) { if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" ); SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
return; return;
@ -425,12 +422,12 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
} }
} }
void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, point_list& south, point_list& east, point_list& west ) void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west )
{ {
string dir; string dir;
string file; string file;
gzFile fp; gzFile fp;
Point3D pt; SGGeod pt;
int nCount; int nCount;
dir = share_base + "/stage1/" + b.gen_base_path(); dir = share_base + "/stage1/" + b.gen_base_path();
@ -445,33 +442,33 @@ void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, p
if (fp) { if (fp) {
// North // North
sgReadInt( fp, &nCount ); 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<nCount; i++) { for (int i=0; i<nCount; i++) {
sgReadPoint3D( fp, pt ); sgReadGeod( fp, pt );
north.push_back(pt); north.push_back(pt);
} }
// South // South
sgReadInt( fp, &nCount ); sgReadInt( fp, &nCount );
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " south boundary"); SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " south boundary");
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgReadPoint3D( fp, pt ); sgReadGeod( fp, pt );
south.push_back(pt); south.push_back(pt);
} }
// East // East
sgReadInt( fp, &nCount ); sgReadInt( fp, &nCount );
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " east boundary"); SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " east boundary");
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgReadPoint3D( fp, pt ); sgReadGeod( fp, pt );
east.push_back(pt); east.push_back(pt);
} }
// West // West
sgReadInt( fp, &nCount ); sgReadInt( fp, &nCount );
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " west boundary"); SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " west boundary");
for (int i=0; i<nCount; i++) { for (int i=0; i<nCount; i++) {
sgReadPoint3D( fp, pt ); sgReadGeod( fp, pt );
west.push_back(pt); west.push_back(pt);
} }
@ -485,7 +482,7 @@ void TGConstruct::LoadSharedEdgeData( int stage )
case 1: case 1:
{ {
// we need to read just 4 buckets for stage 1 - 1 for each edge // we need to read just 4 buckets for stage 1 - 1 for each edge
point_list north, south, east, west; std::vector<SGGeod> north, south, east, west;
SGBucket nb, sb, eb, wb; SGBucket nb, sb, eb, wb;
double clon = bucket.get_center_lon(); double clon = bucket.get_center_lon();
double clat = bucket.get_center_lat(); double clat = bucket.get_center_lat();
@ -495,28 +492,28 @@ void TGConstruct::LoadSharedEdgeData( int stage )
LoadNeighboorEdgeDataStage1( nb, north, south, east, west ); LoadNeighboorEdgeDataStage1( nb, north, south, east, west );
// Add southern nodes from northern tile // Add southern nodes from northern tile
for (unsigned int i=0; i<south.size(); i++) { for (unsigned int i=0; i<south.size(); i++) {
nodes.unique_add( south[i].toSGGeod() ); nodes.unique_add( south[i] );
} }
// Read South Tile and add its northern nodes // Read South Tile and add its northern nodes
sb = sgBucketOffset(clon, clat, 0, -1); sb = sgBucketOffset(clon, clat, 0, -1);
LoadNeighboorEdgeDataStage1( sb, north, south, east, west ); LoadNeighboorEdgeDataStage1( sb, north, south, east, west );
for (unsigned int i=0; i<north.size(); i++) { for (unsigned int i=0; i<north.size(); i++) {
nodes.unique_add( north[i].toSGGeod() ); nodes.unique_add( north[i] );
} }
// Read East Tile and add its western nodes // Read East Tile and add its western nodes
eb = sgBucketOffset(clon, clat, 1, 0); eb = sgBucketOffset(clon, clat, 1, 0);
LoadNeighboorEdgeDataStage1( eb, north, south, east, west ); LoadNeighboorEdgeDataStage1( eb, north, south, east, west );
for (unsigned int i=0; i<west.size(); i++) { for (unsigned int i=0; i<west.size(); i++) {
nodes.unique_add( west[i].toSGGeod() ); nodes.unique_add( west[i] );
} }
// Read West Tile and add its eastern nodes // Read West Tile and add its eastern nodes
wb = sgBucketOffset(clon, clat, -1, 0); wb = sgBucketOffset(clon, clat, -1, 0);
LoadNeighboorEdgeDataStage1( wb, north, south, east, west ); LoadNeighboorEdgeDataStage1( wb, north, south, east, west );
for (unsigned int i=0; i<east.size(); i++) { for (unsigned int i=0; i<east.size(); i++) {
nodes.unique_add( east[i].toSGGeod() ); nodes.unique_add( east[i] );
} }
} }
break; break;

View file

@ -25,16 +25,10 @@
# include <config.h> # include <config.h>
#endif #endif
//#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <Geometry/poly_support.hxx>
//#include <Geometry/poly_extra.hxx>
#include "tgconstruct.hxx" #include "tgconstruct.hxx"
//using std::string;
void TGConstruct::TesselatePolys( void ) void TGConstruct::TesselatePolys( void )
{ {
// tesselate the polygons and prepair them for final output // tesselate the polygons and prepair them for final output
@ -42,29 +36,34 @@ void TGConstruct::TesselatePolys( void )
SGGeod min, max; SGGeod min, max;
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) { 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 p = 0; p < polys_clipped.area_size(area); p++ ) {
unsigned int id = polys_clipped.get_shape( area, shape ).id; tgPolygon poly = polys_clipped.get_poly(area, p );
if ( IsDebugShape( id ) ) { if ( IsDebugShape( poly.GetId() ) ) {
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "preteselate", "" ); 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(); tg::Rectangle rect = poly.GetBoundingBox();
nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra ); nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra );
SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " << SG_LOG( SG_CLIPPER, SG_DEBUG, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) << p+1 << " of " << (int)polys_clipped.area_size(area) << ": id = " << poly.GetId() );
": id = " << id );
if ( IsDebugShape( id ) ) { if ( IsDebugShape( poly.GetId() ) ) {
SG_LOG( SG_CLIPPER, SG_INFO, poly ); SG_LOG( SG_CLIPPER, SG_INFO, poly );
} }
poly.Tesselate( poly_extra ); 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 // ensure all added nodes are accounted for
for (unsigned int k=0; k < poly.Triangles(); k++) { for (unsigned int k=0; k < poly.Triangles(); k++) {
for (int l = 0; l < 3; l++) { for (int l = 0; l < 3; l++) {
@ -72,9 +71,6 @@ void TGConstruct::TesselatePolys( void )
nodes.unique_add( poly.GetTriNode( k, l ) ); nodes.unique_add( poly.GetTriNode( k, l ) );
} }
} }
polys_clipped.set_poly( area, shape, segment, poly );
}
} }
} }
} }

View file

@ -25,161 +25,19 @@
# include <config.h> # include <config.h>
#endif #endif
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/texcoord.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include "tgconstruct.hxx" #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<tri.contours(); c++)
{
// get the points, and calculate the elevations
point_list nodes = tri.get_contour(c);
std::vector< SGGeod > 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 ) void TGConstruct::CalcTextureCoordinates( void )
{ {
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) { 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 p = 0; p < polys_clipped.area_size(area); p++ ) {
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) { tgPolygon poly = polys_clipped.get_poly(area, p);
tgPolygon poly = polys_clipped.get_poly(area, shape, segment); SG_LOG( SG_CLIPPER, SG_DEBUG, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
SG_LOG( SG_CLIPPER, SG_INFO, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " << p+1 << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() );
shape+1 << "-" << segment << " 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( ); poly.Texture( );
polys_clipped.set_poly(area, shape, segment, poly); polys_clipped.set_poly(area, p, poly);
}
} }
} }
} }

View file

@ -38,7 +38,7 @@ void TGLandclass::clear(void)
int i; int i;
for (i=0; i<TG_MAX_AREA_TYPES; i++) { for (i=0; i<TG_MAX_AREA_TYPES; i++) {
shapes[i].clear(); polys[i].clear();
} }
} }
@ -51,24 +51,24 @@ void TGLandclass::LoadFromGzFile(gzFile& fp)
sgReadInt( fp, &count ); sgReadInt( fp, &count );
for (j=0; j<count; j++) { for (j=0; j<count; j++) {
TGShape shape; tgPolygon poly;
shape.LoadFromGzFile( fp ); poly.LoadFromGzFile( fp );
shapes[i].push_back( shape ); polys[i].push_back( poly );
} }
} }
} }
std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc ) std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
{ {
int i, j, count; int i, j, count;
TGShape shape; tgPolygon poly;
// Save all landclass shapes // Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) { for (i=0; i<TG_MAX_AREA_TYPES; i++) {
count = lc.shapes[i].size(); count = lc.polys[i].size();
out << count << "\n"; out << count << "\n";
for (j=0; j<count; j++) { for (j=0; j<count; j++) {
out << lc.shapes[i][j] << " "; out << lc.polys[i][j] << " ";
} }
out << "\n"; out << "\n";
} }
@ -78,15 +78,15 @@ std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
void TGLandclass::SaveToGzFile(gzFile& fp) void TGLandclass::SaveToGzFile(gzFile& fp)
{ {
int i, j, count; int i, j, count;
TGShape shape; tgPolygon shape;
// Save all landclass shapes // Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) { for (i=0; i<TG_MAX_AREA_TYPES; i++) {
count = shapes[i].size(); count = polys[i].size();
sgWriteInt( fp, count ); sgWriteInt( fp, count );
for (j=0; j<count; j++) { for (j=0; j<count; j++) {
shapes[i][j].SaveToGzFile( fp ); polys[i][j].SaveToGzFile( fp );
} }
} }
} }

View file

@ -35,9 +35,10 @@
#include <simgear/math/sg_types.hxx> #include <simgear/math/sg_types.hxx>
#include <simgear/io/lowlevel.hxx> #include <simgear/io/lowlevel.hxx>
#define TG_MAX_AREA_TYPES 128
#include "tgshape.hxx" #include <Polygon/polygon.hxx>
#define TG_MAX_AREA_TYPES 128
class TGLandclass class TGLandclass
{ {
@ -46,107 +47,49 @@ public:
inline unsigned int area_size( unsigned int area ) inline unsigned int area_size( unsigned int area )
{ {
return shapes[area].size(); return polys[area].size();
}
inline unsigned int shape_size( unsigned int area, unsigned int shape )
{
return shapes[area][shape].polys.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 )
{
shapes[area][shape].mask = mask;
} }
inline bool get_textured( unsigned int area, unsigned int shape ) inline const SGVec3f& get_face_normal( unsigned int area, unsigned int poly, unsigned int tri ) const
{ {
return shapes[area][shape].textured; return polys[area][poly].GetTriFaceNormal( tri );
}
inline void set_textured( unsigned int area, unsigned int shape, bool t )
{
shapes[area][shape].textured = t;
} }
inline tgPolygon& get_poly( unsigned int area, unsigned int shape, unsigned int segment ) inline double get_face_area( unsigned int area, unsigned int poly, unsigned int tri )
{ {
return shapes[area][shape].polys[segment]; return polys[area][poly].GetTriFaceArea( tri );
}
inline void set_poly( unsigned int area, unsigned int shape, unsigned int segment, const tgPolygon& sp )
{
shapes[area][shape].polys[segment] = sp;
} }
#if 0 inline std::string get_material( unsigned int area, unsigned int poly )
inline TGPolygon get_tris( unsigned int area, unsigned int shape, unsigned int segment )
{ {
return shapes[area][shape].sps[segment].get_tris(); return polys[area][poly].GetMaterial();
} }
inline void set_tris( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon tris ) inline const tgTexParams& get_texparams( unsigned int area, unsigned int poly )
{ {
shapes[area][shape].sps[segment].set_tris( tris ); return polys[area][poly].GetTexParams();
} }
#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 SaveToGzFile( gzFile& fp );
void LoadFromGzFile( gzFile& fp ); void LoadFromGzFile( gzFile& fp );
@ -155,7 +98,7 @@ public:
friend std::ostream& operator<< ( std::ostream&, const TGLandclass& ); friend std::ostream& operator<< ( std::ostream&, const TGLandclass& );
private: private:
shape_list shapes[TG_MAX_AREA_TYPES]; tgpolygon_list polys[TG_MAX_AREA_TYPES];
}; };
#endif // _TGLANDCLASS_HXX #endif // _TGLANDCLASS_HXX

View file

@ -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 <config.h>
#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<polys.size(); i++)
{
SG_LOG(SG_GENERAL, SG_INFO, " before is " << polys[i].GetMaterial() );
polys[i] = tgPolygon::Intersect( polys[i], mask );
SG_LOG(SG_GENERAL, SG_INFO, " after is " << polys[i].GetMaterial() );
}
} else {
std::string material = polys[0].GetMaterial();
tgTexParams tp = polys[0].GetTexParams();
polys[0] = mask;
polys[0].SetMaterial( material );
polys[0].SetTexParams( tp );
}
}
void TGShape::LoadFromGzFile(gzFile& fp)
{
int i, count;
// First, load the clipmask
SG_LOG(SG_GENERAL, SG_INFO, " load mask" );
mask.LoadFromGzFile( fp );
SG_LOG(SG_GENERAL, SG_INFO, " done" );
// Then load individual polys
sgReadInt( fp, &count );
for (i=0; i<count; i++) {
tgPolygon poly;
poly.LoadFromGzFile( fp );
polys.push_back( poly );
}
// 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;
// First, save the clipmask
out << p.mask;
// Then save superpolys
count = p.polys.size();
out << count << "\n";
for (i=0; i<count; i++) {
out << p.polys[i];
}
// Save the id, area type and textured flag
out << p.id << " ";
out << p.area << " ";
out << p.textured << "\n";
return out;
}
void TGShape::SaveToGzFile(gzFile& fp)
{
int i, count;
// First, save the clipmask
mask.SaveToGzFile( fp );
// Then save superpolys
count = polys.size();
sgWriteInt( fp, count );
for (i=0; i<count; i++) {
polys[i].SaveToGzFile( fp );
}
// Save the id, area type and textured flag
sgWriteUInt( fp, id );
sgWriteInt( fp, (int)area );
sgWriteInt( fp, (int)textured );
}

View file

@ -1,69 +0,0 @@
// TGShape.hxx -- 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.hxx,v 1.13 2004-11-19 22:25:49 curt Exp $
#ifndef _TGSHAPE_HXX
#define _TGSHAPE_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#define TG_MAX_AREA_TYPES 128
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/io/lowlevel.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
#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

View file

@ -1,146 +1,17 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <CGAL/Plane_3.h>
#include "tg_nodes.hxx" #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<SGGeod>& 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; 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 ) static bool IsWithin( const SGGeod pt, double xmin, double xmax, double ymin, double ymax )
{ {
return ( (xmin <= pt.getLongitudeDeg()) && (ymin <= pt.getLatitudeDeg()) && 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 ) ); max.getLatitudeDeg() + fgPoint3_Epsilon ) );
} }
void TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& points ) const { bool TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& 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(); points.clear();
for ( ; current != last; ++current ) { for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
SGGeod pt = (*current).GetPosition(); SGGeod const& pt = tg_node_list[i].GetPosition();
if ( IsAlmostWithin( pt, min, max ) ) { if ( IsAlmostWithin( pt, min, max ) ) {
points.push_back( pt ); points.push_back( pt );
} }
} }
return true;
} }
void TGNodes::get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west ) const { bool TGNodes::get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west ) const {
const_node_list_iterator current, last;
double north_compare = b.get_center_lat() + 0.5 * b.get_height(); 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 south_compare = b.get_center_lat() - 0.5 * b.get_height();
double east_compare = b.get_center_lon() + 0.5 * b.get_width(); double east_compare = b.get_center_lon() + 0.5 * b.get_width();
double west_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(); north.clear();
south.clear(); south.clear();
east.clear(); east.clear();
west.clear(); west.clear();
for ( ; current != last; ++current ) { for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
SGGeod pt = (*current).GetPosition(); SGGeod const& pt = tg_node_list[i].GetPosition();
// may save the same point twice - so we get all the corners // may save the same point twice - so we get all the corners
if ( fabs(pt.getLatitudeDeg() - north_compare) < SG_EPSILON) { if ( fabs(pt.getLatitudeDeg() - north_compare) < SG_EPSILON) {
@ -207,36 +69,171 @@ void TGNodes::get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std:
west.push_back( pt ); 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<SGGeod>& 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<Point_and_Elevation> result;
std::list<Point_and_Elevation>::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<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& 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<Point_and_Elevation> result;
std::list<Point_and_Elevation>::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<SGGeod>& 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<SGVec3d>& points ) const { void TGNodes::get_wgs84_nodes( std::vector<SGVec3d>& points ) const {
const_node_list_iterator current, last;
current = tg_node_list.begin();
last = tg_node_list.end();
points.clear(); points.clear();
for ( ; current != last; ++current ) { for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
points.push_back( (*current).GetWgs84() ); points.push_back( tg_node_list[i].GetWgs84() );
} }
} }
void TGNodes::get_normals( std::vector<SGVec3f>& normals ) const { void TGNodes::get_normals( std::vector<SGVec3f>& 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(); normals.clear();
for ( ; current != last; ++current ) { for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
normals.push_back( (*current).GetNormal() ); normals.push_back( tg_node_list[i].GetNormal() );
} }
} }
void TGNodes::Dump( void ) { void TGNodes::Dump( void ) {
for (unsigned int i=0; i<tg_node_list.size(); i++) { for (unsigned int i=0; i<tg_node_list.size(); i++) {
TGNode node = tg_node_list[ i ]; TGNode const& node = tg_node_list[ i ];
std::string fixed; std::string fixed;
if ( node.GetFixedPosition() ) { if ( node.GetFixedPosition() ) {
@ -249,125 +246,18 @@ void TGNodes::Dump( void ) {
if ( node.GetFaces().size() ) { if ( node.GetFaces().size() ) {
TGFaceList faces = node.GetFaces(); TGFaceList faces = node.GetFaces();
for (unsigned int j=0; j<faces.size(); j++) { for (unsigned int j=0; j<faces.size(); j++) {
SG_LOG(SG_GENERAL, SG_ALERT, "\tface " << faces[j].area << "," << faces[j].shape << "," << faces[j].seg << "," << faces[j].tri ); SG_LOG(SG_GENERAL, SG_ALERT, "\tface " << faces[j].area << "," << faces[j].poly << "," << faces[j].tri );
} }
} }
} }
} }
void TGNode::LoadFromGzFile(gzFile& fp) void TGNodes::SaveToGzFile( gzFile& fp )
{ {
int i, nCount; tg_node_list.SaveToGzFile( fp );
// Load a tgnode
sgReadGeod( fp, position);
CalcWgs84();
sgReadVec3( 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 )
void TGNodes::LoadFromGzFile( gzFile& fp )
{ {
int i, nCount; tg_node_list.LoadFromGzFile( fp );
// Save a tgnode
out << n.position;
out << n.normal;
out << n.fixed_position << " ";
out << n.fixed_normal << "\n";
nCount = n.faces.size();
out << nCount << "\n";
for (i=0; i<nCount; i++) {
out << n.faces[i].area << " ";
out << n.faces[i].shape << " ";
out << n.faces[i].seg << " ";
out << n.faces[i].tri << "\n";
}
return out;
}
void TGNode::SaveToGzFile(gzFile& fp)
{
int i, nCount;
// Save a tgnode
sgWriteGeod( fp, position );
sgWriteVec3( 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 );
}
}
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";
for (i=0; i<nCount; i++) {
out << ns.tg_node_list[i];
}
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 );
}
} }

View file

@ -10,108 +10,47 @@
#endif #endif
#include <cstdlib> #include <cstdlib>
#include <CGAL/Simple_cartesian.h>
//#include <CGAL/Cartesian.h>
//#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Kd_tree.h>
#include <CGAL/algorithm.h>
#include <CGAL/Fuzzy_iso_box.h>
#include <CGAL/Search_traits_2.h>
#include <CGAL/Search_traits_adapter.h> /* Just use two dimensional lookup - elevation is a trait */
#include <boost/iterator/zip_iterator.hpp>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point;
typedef boost::tuple<Point, double> 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<Kernel> Traits;
typedef CGAL::Search_traits_2<Kernel> Traits_base;
typedef CGAL::Search_traits_adapter<Point_and_Elevation, My_point_property_map, Traits_base> Traits;
typedef CGAL::Fuzzy_iso_box<Traits> Fuzzy_bb;
typedef CGAL::Kd_tree<Traits> Tree;
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
//#include <simgear/math/sg_types.hxx>
#include <simgear/io/lowlevel.hxx> #include <simgear/io/lowlevel.hxx>
#include <Polygon/tg_unique_tgnode.hxx>
#define FG_PROXIMITY_EPSILON 0.000001 #define FG_PROXIMITY_EPSILON 0.000001
#define FG_COURSE_EPSILON 0.0001 #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) */ /* This class handles ALL of the nodes in a tile : 3d nodes in elevation data, 2d nodes generated from landclass, etc) */
class TGNodes { class TGNodes {
@ -119,67 +58,62 @@ public:
// Constructor and destructor // Constructor and destructor
TGNodes( void ) { TGNodes( void ) {
sorted = false; kd_tree_valid = false;
} }
~TGNodes( void ) {} ~TGNodes( void ) {}
// delete all the data out of node_list // delete all the data out of node_list
inline void clear() { inline void clear() {
tg_node_list.clear(); kd_tree_valid = false;
sorted = false;
} }
// Add a point to the point list if it doesn't already exist. // 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. // Returns the index (starting at zero) of the point in the list.
void unique_add( const SGGeod& p ) { void unique_add( const SGGeod& p ) {
if ( !sorted ) { TGNode n(p);
linear_unique_add( p ); n.SetFixedPosition(false);
} else { tg_node_list.add(n);
SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); kd_tree_valid = false;
exit(0);
} }
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 // Add a point to the point list if it doesn't already exist
// (checking all three dimensions.) Returns the index (starting // (checking all three dimensions.) Returns the index (starting
// at zero) of the point in the list. // at zero) of the point in the list.
void unique_add_fixed_elevation( const SGGeod& p ) { void unique_add_fixed_elevation( const SGGeod& p ) {
if ( !sorted ) { TGNode n(p);
linear_unique_add_fixed_elevation( p ); n.SetFixedPosition(true);
} else { tg_node_list.add(n);
SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!"); kd_tree_valid = false;
exit(0);
}
} }
// Find the index of the specified point (compair to the same // Find the index of the specified point (compair to the same
// tolerance as unique_add(). Returns -1 if not found. // tolerance as unique_add(). Returns -1 if not found.
int find( const SGGeod& p ) const { int find( const SGGeod& p ) const {
if ( sorted ) { TGNode n(p);
return sorted_find( p ); return tg_node_list.find(n);
} else {
return linear_find( p );
}
} }
void SortNodes( void ); void init_spacial_query( void );
void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); } void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); }
SGVec3f GetNormal( int idx ) const { return tg_node_list[idx].GetNormal(); } SGVec3f GetNormal( int idx ) const { return tg_node_list[idx].GetNormal(); }
void SetNormal( int idx, SGVec3f n ) { tg_node_list[idx].SetNormal( n ); } 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 // return a point list of geodetic nodes
void get_geod_nodes( std::vector<SGGeod>& points ) const; void get_geod_nodes( std::vector<SGGeod>& points ) const;
// Find all the nodes within a bounding box // Find all the nodes within a bounding box
void get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& points ) const; bool get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& points ) const;
// Find a;; the nodes on the tile edges // Find a;; the nodes on the tile edges
void get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west ) const; bool get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west ) const;
// return a point list of wgs84 nodes // return a point list of wgs84 nodes
void get_wgs84_nodes( std::vector<SGVec3d>& points ) const; void get_wgs84_nodes( std::vector<SGVec3d>& points ) const;
@ -187,32 +121,32 @@ public:
// return a point list of normals // return a point list of normals
void get_normals( std::vector<SGVec3f>& normals ) const; void get_normals( std::vector<SGVec3f>& normals ) const;
// return the ith point // return the ith point (constant)
inline TGNode get_node( int i ) const { return tg_node_list[i]; } 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 // return the size of the node list
inline size_t size() const { return tg_node_list.size(); } inline size_t size() const { return tg_node_list.size(); }
void Dump( void ); void Dump( void );
void SaveToGzFile( gzFile& fp ); void SaveToGzFile( gzFile& fp );
void LoadFromGzFile( gzFile& fp ); void LoadFromGzFile( gzFile& fp );
// Friends for serialization
friend std::ostream& operator<< ( std::ostream&, const TGNodes& );
private: private:
void linear_unique_add( const SGGeod& p ); UniqueTGNodeSet tg_node_list;
void linear_unique_add_fixed_elevation( const SGGeod& p ); Tree tg_kd_tree;
bool kd_tree_valid;
int sorted_find( const SGGeod& p ) const;
int linear_find( const SGGeod& p ) const;
node_list tg_node_list;
bool sorted;
// return true of the two points are "close enough" as defined by // return true of the two points are "close enough" as defined by
// FG_PROXIMITY_EPSILON // FG_PROXIMITY_EPSILON

View file

@ -36,7 +36,6 @@
#include <Geometry/trinodes.hxx> #include <Geometry/trinodes.hxx>
#include "polygon.hxx" #include "polygon.hxx"
#include "tg_unique_geod.hxx"
#ifdef _MSC_VER #ifdef _MSC_VER
# define LONG_LONG_MAX LLONG_MAX # define LONG_LONG_MAX LLONG_MAX
@ -2235,6 +2234,9 @@ tgPolygon tgPolygon::Expand( const tgPolygon& subject, double offset )
result.SetMaterial( subject.GetMaterial() ); result.SetMaterial( subject.GetMaterial() );
result.SetTexParams( subject.GetTexParams() ); result.SetTexParams( subject.GetTexParams() );
result.SetMaterial( subject.GetMaterial() );
result.SetTexParams( subject.GetTexParams() );
return result; return result;
} }
@ -2280,6 +2282,9 @@ tgPolygon tgPolygon::Union( const tgPolygon& subject, tgPolygon& clip )
result = tgPolygon::FromClipper( clipper_result ); result = tgPolygon::FromClipper( clipper_result );
result = tgPolygon::AddColinearNodes( result, all_nodes ); result = tgPolygon::AddColinearNodes( result, all_nodes );
result.SetMaterial( subject.GetMaterial() );
result.SetTexParams( subject.GetTexParams() );
return result; return result;
} }
@ -2337,6 +2342,9 @@ tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip )
result = tgPolygon::FromClipper( clipper_result ); result = tgPolygon::FromClipper( clipper_result );
result = tgPolygon::AddColinearNodes( result, all_nodes ); result = tgPolygon::AddColinearNodes( result, all_nodes );
result.SetMaterial( subject.GetMaterial() );
result.SetTexParams( subject.GetTexParams() );
return result; return result;
} }
@ -2794,21 +2802,15 @@ void tgPolygon::LoadFromGzFile( gzFile& fp )
// load the triangles // load the triangles
sgReadUInt( fp, &count ); sgReadUInt( fp, &count );
SG_LOG(SG_GENERAL, SG_INFO, " load " << count << " triangles" );
for (unsigned int i = 0; i < count; i++) { for (unsigned int i = 0; i < count; i++) {
triangle.LoadFromGzFile( fp ); triangle.LoadFromGzFile( fp );
AddTriangle(triangle); AddTriangle(triangle);
} }
SG_LOG(SG_GENERAL, SG_INFO, " load texparams" );
// Load the tex params // Load the tex params
tp.LoadFromGzFile( fp ); tp.LoadFromGzFile( fp );
// and the rest // and the rest
SG_LOG(SG_GENERAL, SG_INFO, " load material" );
sgReadString( fp, &strbuff ); sgReadString( fp, &strbuff );
if ( strbuff ) { if ( strbuff ) {
material = strbuff; material = strbuff;
@ -3486,28 +3488,19 @@ void tgAccumulator::Add( const tgPolygon& subject )
accum.push_back( clipper_subject ); accum.push_back( clipper_subject );
} }
std::vector<SGGeod> node_list;
std::vector<SGVec2f> tc_list;
std::vector<SGVec3d> norm_list;
std::vector<int> idx_list;
SGVec3f face_normal;
double face_area;
void tgTriangle::SaveToGzFile( gzFile& fp ) void tgTriangle::SaveToGzFile( gzFile& fp )
{ {
// Save the three nodes, and their attributes // Save the three nodes, and their attributes
for (unsigned int i = 0; i < 3; i++) { for (unsigned int i = 0; i < 3; i++) {
sgWriteGeod( fp, node_list[i] ); sgWriteGeod( fp, node_list[i] );
sgWriteVec2( fp, tc_list[i] ); // sgWriteVec2( fp, tc_list[i] );
sgWritedVec3( fp, norm_list[i] ); // sgWritedVec3( fp, norm_list[i] ); // not calculated until stage 3
sgWriteInt( fp, idx_list[i] ); sgWriteInt( fp, idx_list[i] );
} }
// and the area, and face normal // and the area, and face normal
sgWriteVec3( fp, face_normal ); // sgWriteVec3( fp, face_normal ); // not calculated until stage3
sgWriteDouble( fp, face_area ); // sgWriteDouble( fp, face_area ); // not calculated until stage3
} }
void tgTriangle::LoadFromGzFile( gzFile& fp ) void tgTriangle::LoadFromGzFile( gzFile& fp )
@ -3515,21 +3508,25 @@ void tgTriangle::LoadFromGzFile( gzFile& fp )
// Load the nodelist // Load the nodelist
for (unsigned int i = 0; i < 3; i++) { for (unsigned int i = 0; i < 3; i++) {
sgReadGeod( fp, node_list[i] ); sgReadGeod( fp, node_list[i] );
sgReadVec2( fp, tc_list[i] ); // sgReadVec2( fp, tc_list[i] );
sgReaddVec3( fp, norm_list[i] ); // sgReaddVec3( fp, norm_list[i] );
sgReadInt( fp, &idx_list[i] ); sgReadInt( fp, &idx_list[i] );
} }
// and the area, and face normal // and the area, and face normal
sgReadVec3( fp, face_normal ); // sgReadVec3( fp, face_normal );
sgReadDouble( fp, &face_area ); // sgReadDouble( fp, &face_area );
} }
void tgTexParams::SaveToGzFile( gzFile& fp ) void tgTexParams::SaveToGzFile( gzFile& fp )
{ {
// Save the parameters // Save the parameters
sgWriteGeod( fp, ref ); sgWriteInt( fp, (int)method );
if ( method == TG_TEX_BY_GEODE ) {
sgWriteDouble( fp, center_lat );
} else {
sgWriteGeod( fp, ref );
sgWriteDouble( fp, width ); sgWriteDouble( fp, width );
sgWriteDouble( fp, length ); sgWriteDouble( fp, length );
sgWriteDouble( fp, heading ); sgWriteDouble( fp, heading );
@ -3539,19 +3536,29 @@ void tgTexParams::SaveToGzFile( gzFile& fp )
sgWriteDouble( fp, minv ); sgWriteDouble( fp, minv );
sgWriteDouble( fp, maxv ); sgWriteDouble( fp, maxv );
if ( (method == TG_TEX_BY_TPS_CLIPU) ||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
sgWriteDouble( fp, min_clipu ); sgWriteDouble( fp, min_clipu );
sgWriteDouble( fp, max_clipu ); sgWriteDouble( fp, max_clipu );
}
if ( (method == TG_TEX_BY_TPS_CLIPV) ||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
sgWriteDouble( fp, min_clipv ); sgWriteDouble( fp, min_clipv );
sgWriteDouble( fp, max_clipv ); sgWriteDouble( fp, max_clipv );
}
sgWriteInt( fp, (int)method ); }
} }
void tgTexParams::LoadFromGzFile( gzFile& fp ) void tgTexParams::LoadFromGzFile( gzFile& fp )
{ {
// Load the parameters // Load the parameters
sgReadGeod( fp, ref ); sgReadInt( fp, (int*)&method );
if ( method == TG_TEX_BY_GEODE ) {
sgReadDouble( fp, &center_lat );
} else {
sgReadGeod( fp, ref );
sgReadDouble( fp, &width ); sgReadDouble( fp, &width );
sgReadDouble( fp, &length ); sgReadDouble( fp, &length );
sgReadDouble( fp, &heading ); sgReadDouble( fp, &heading );
@ -3561,11 +3568,16 @@ void tgTexParams::LoadFromGzFile( gzFile& fp )
sgReadDouble( fp, &minv ); sgReadDouble( fp, &minv );
sgReadDouble( fp, &maxv ); sgReadDouble( fp, &maxv );
if ( (method == TG_TEX_BY_TPS_CLIPU) ||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
sgReadDouble( fp, &min_clipu ); sgReadDouble( fp, &min_clipu );
sgReadDouble( fp, &max_clipu ); sgReadDouble( fp, &max_clipu );
}
if ( (method == TG_TEX_BY_TPS_CLIPV) ||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
sgReadDouble( fp, &min_clipv ); sgReadDouble( fp, &min_clipv );
sgReadDouble( fp, &max_clipv ); sgReadDouble( fp, &max_clipv );
}
sgReadInt( fp, (int*)&method ); }
} }

View file

@ -314,6 +314,9 @@ std::ostream &operator<<(std::ostream &output, const TGPolygon &poly);
#include <Geometry/trinodes.hxx> #include <Geometry/trinodes.hxx>
#include <Geometry/rectangle.hxx> #include <Geometry/rectangle.hxx>
#include "tg_unique_geod.hxx"
// forward declaration // forward declaration
class tgPolygon; class tgPolygon;
@ -352,6 +355,10 @@ public:
SGGeod GetNode( unsigned int i ) const { SGGeod GetNode( unsigned int i ) const {
return node_list[i]; return node_list[i];
} }
SGGeod const& operator[]( int index ) const {
return node_list[index];
}
void RemoveNodeAt( unsigned int idx ) { void RemoveNodeAt( unsigned int idx ) {
if ( idx < node_list.size() ) { if ( idx < node_list.size() ) {
node_list.erase( node_list.begin() + idx ); node_list.erase( node_list.begin() + idx );
@ -423,7 +430,7 @@ public:
idx_list.resize( 3, -1 ); idx_list.resize( 3, -1 );
} }
SGGeod GetNode( unsigned int i ) const { SGGeod const& GetNode( unsigned int i ) const {
return node_list[i]; return node_list[i];
} }
std::vector<SGGeod>& GetNodeList( void ) { std::vector<SGGeod>& GetNodeList( void ) {
@ -449,7 +456,7 @@ public:
void SetFaceNormal( const SGVec3f& n ) { void SetFaceNormal( const SGVec3f& n ) {
face_normal = n; face_normal = n;
}; };
SGVec3f GetFaceNormal( void ) const { SGVec3f const& GetFaceNormal( void ) const {
return face_normal; return face_normal;
} }
@ -527,7 +534,6 @@ typedef void (*tgpolygon_texfunc)(void);
class tgPolygon class tgPolygon
{ {
public: public:
void Erase( void ) { void Erase( void ) {
contours.clear(); contours.clear();
triangles.clear(); triangles.clear();
@ -539,7 +545,7 @@ public:
unsigned int ContourSize( unsigned int c ) const { unsigned int ContourSize( unsigned int c ) const {
return contours[c].GetSize(); return contours[c].GetSize();
} }
void AddContour( tgContour contour ) { void AddContour( tgContour const& contour ) {
contours.push_back(contour); contours.push_back(contour);
} }
tgContour GetContour( unsigned int c ) const { tgContour GetContour( unsigned int c ) const {
@ -551,10 +557,10 @@ public:
} }
} }
unsigned int TotalNodes( void ) const; 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 ) { void SetNode( unsigned int c, unsigned int i, const SGGeod& n ) {
contours[c].SetNode( i, n ); contours[c].SetNode( i, n );
@ -600,7 +606,7 @@ public:
void SetTriFaceNormal( unsigned int c, const SGVec3f& n ) { void SetTriFaceNormal( unsigned int c, const SGVec3f& n ) {
triangles[c].SetFaceNormal( n ); triangles[c].SetFaceNormal( n );
} }
SGVec3f GetTriFaceNormal( unsigned int c ) const { SGVec3f const& GetTriFaceNormal( unsigned int c ) const {
return triangles[c].GetFaceNormal(); return triangles[c].GetFaceNormal();
} }
void SetTriFaceArea( unsigned int c, double a ) { void SetTriFaceArea( unsigned int c, double a ) {
@ -610,12 +616,20 @@ public:
return triangles[c].GetFaceArea(); return triangles[c].GetFaceArea();
} }
std::string GetMaterial( void ) const { std::string const& GetMaterial( void ) const {
return material; return material;
} }
void SetMaterial( const std::string m ) { void SetMaterial( const std::string& m ) {
material = 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 ) { void SetTexParams( const SGGeod& ref, double width, double length, double heading ) {
tp.ref = ref; tp.ref = ref;
tp.width = width; tp.width = width;
@ -650,7 +664,6 @@ public:
tp.center_lat = cl; tp.center_lat = cl;
} }
void Tesselate( void ); void Tesselate( void );
void Tesselate( const std::vector<SGGeod>& extra ); void Tesselate( const std::vector<SGGeod>& extra );
@ -710,6 +723,7 @@ private:
std::string material; std::string material;
std::string flag; // let's get rid of this.... std::string flag; // let's get rid of this....
unsigned int id; // unique polygon id for debug
tgTexParams tp; tgTexParams tp;
}; };

View file

@ -1,3 +1,6 @@
#ifndef _TG_UNIQUE_SGGEOD_HXX
#define _TG_UNIQUE_SGGEOD_HXX
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <simgear/math/SGMisc.hxx> #include <simgear/math/SGMisc.hxx>
@ -117,6 +120,18 @@ public:
return index; 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<SGGeod>& get_list( void ) { return geod_list; } std::vector<SGGeod>& get_list( void ) { return geod_list; }
void get_node_list(); void get_node_list();
@ -124,3 +139,5 @@ private:
unique_geod_set index_list; unique_geod_set index_list;
std::vector<SGGeod> geod_list; std::vector<SGGeod> geod_list;
}; };
#endif /* _TG_UNIQUE_SGGEOD_HXX */

View file

@ -0,0 +1,262 @@
#ifndef _TG_UNIQUE_TGNODE_HXX
#define _TG_UNIQUE_TGNODE_HXX
#include <boost/unordered_set.hpp>
#include <boost/concept_check.hpp>
#include <simgear/math/SGGeod.hxx>
#include <simgear/math/SGMisc.hxx>
// 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<double>::round(geod.getLongitudeDeg() * PROXIMITY_MULTIPLIER) );
raw_pt[1] = (unsigned long long)( SGMisc<double>::round(geod.getLatitudeDeg() * PROXIMITY_MULTIPLIER) );
unsigned char* it = (unsigned char*)raw_pt;
for ( unsigned i=0; i<sizeof( raw_pt ); i++ ) {
hash = hash ^ *it++;
hash = hash * FNV_prime;
}
}
inline void SetOrderedIndex( unsigned int i ) { ordered_index = i; }
inline unsigned int GetOrderedIndex( void ) const { return ordered_index; }
inline std::size_t GetHash( void ) const { return hash; }
friend bool operator == (const TGNodeIndex& a, const TGNodeIndex& b);
friend std::ostream& operator<< ( std::ostream&, const TGNodeIndex& );
private:
SGGeod geod;
std::size_t hash;
unsigned int ordered_index;
};
inline bool operator == (const TGNodeIndex& a, const TGNodeIndex& b) {
return (( fabs(a.geod.getLongitudeDeg() - b.geod.getLongitudeDeg()) < PROXIMITY_EPSILON ) &&
( fabs(a.geod.getLatitudeDeg() - b.geod.getLatitudeDeg()) < PROXIMITY_EPSILON ));
}
struct TGNodeIndexHash : std::unary_function<TGNodeIndex, std::size_t>
{
std::size_t operator()(TGNodeIndex const& gi) const {
return gi.GetHash();
}
};
typedef boost::unordered_set<TGNodeIndex, TGNodeIndexHash> 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<TGNode>& 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.size(); i++) {
node_list[i].SaveToGzFile( fp );
}
}
void LoadFromGzFile( gzFile& fp ) {
unsigned int count;
sgReadUInt( fp, &count );
for (unsigned int i=0; i<count; i++) {
TGNode node;
node.LoadFromGzFile( fp );
add( node );
}
}
private:
unique_tgnode_set index_list;
std::vector<TGNode> node_list;
};
#endif /* _TG_UNIQUE_TGNODE_HXX */