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:
parent
89e69a863f
commit
6edeadd86e
25 changed files with 1010 additions and 1482 deletions
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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 );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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 );
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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, ¢er_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 );
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
262
src/Lib/Polygon/tg_unique_tgnode.hxx
Normal file
262
src/Lib/Polygon/tg_unique_tgnode.hxx
Normal 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 */
|
Loading…
Reference in a new issue