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
|
||||
tglandclass.cxx
|
||||
tglandclass.hxx
|
||||
tgshape.cxx
|
||||
tgshape.hxx
|
||||
priorities.cxx
|
||||
priorities.hxx
|
||||
usgs.cxx
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
|
||||
// TODO TODO TODO : Get rid of construct - data hiding is moretrouble than it's worth right now.
|
||||
// constantly needing to call set after every operation....
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
@ -184,12 +178,15 @@ int main(int argc, char **argv) {
|
|||
} else {
|
||||
SGBucket b_cur;
|
||||
int dx, dy, i, j;
|
||||
int total_buckets, cur_bucket;
|
||||
|
||||
sgBucketDiff(b_min, b_max, &dx, &dy);
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy);
|
||||
|
||||
// construct stage 1
|
||||
total_buckets = (dx+1) * (dy + 1);
|
||||
cur_bucket = 0;
|
||||
for ( j = 0; j <= dy; j++ ) {
|
||||
for ( i = 0; i <= dx; i++ ) {
|
||||
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j);
|
||||
|
@ -202,14 +199,23 @@ int main(int argc, char **argv) {
|
|||
stage1->set_bucket( b_cur );
|
||||
stage1->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 1: Construct bucket " << cur_bucket++ << " of " << total_buckets );
|
||||
SGTimeStamp build_start;
|
||||
build_start.stamp();
|
||||
|
||||
stage1->ConstructBucketStage1();
|
||||
stage1->SaveToIntermediateFiles(1);
|
||||
|
||||
SGTimeStamp build_end;
|
||||
build_end.stamp();
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 1: finshed in " << build_end - build_start );
|
||||
delete stage1;
|
||||
}
|
||||
}
|
||||
|
||||
// construct stage 2
|
||||
cur_bucket = 0;
|
||||
for ( j = 0; j <= dy; j++ ) {
|
||||
for ( i = 0; i <= dx; i++ ) {
|
||||
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j);
|
||||
|
@ -222,6 +228,7 @@ int main(int argc, char **argv) {
|
|||
stage2->set_bucket( b_cur );
|
||||
stage2->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 2: Construct bucket " << cur_bucket++ << " of " << total_buckets );
|
||||
stage2->LoadFromIntermediateFiles(1);
|
||||
stage2->ConstructBucketStage2();
|
||||
stage2->SaveToIntermediateFiles(2);
|
||||
|
@ -231,6 +238,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// construct stage 3
|
||||
cur_bucket = 0;
|
||||
for ( j = 0; j <= dy; j++ ) {
|
||||
for ( i = 0; i <= dx; i++ ) {
|
||||
b_cur = sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j);
|
||||
|
@ -243,6 +251,7 @@ int main(int argc, char **argv) {
|
|||
stage3->set_bucket( b_cur );
|
||||
stage3->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "STAGE 3: Construct bucket " << cur_bucket++ << " of " << total_buckets );
|
||||
stage3->LoadFromIntermediateFiles(2);
|
||||
stage3->ConstructBucketStage3();
|
||||
|
||||
|
|
|
@ -73,9 +73,7 @@ void TGConstruct::set_options( bool ignore_lm, double n ) {
|
|||
// Also, we are still calculating some thing more than one
|
||||
// (like face area - need to move this into superpoly )
|
||||
void TGConstruct::ConstructBucketStage1() {
|
||||
// First, set the precision of floating point logging:
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed);
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
|
||||
/* If we have some debug IDs, create a datasource */
|
||||
if ( debug_shapes.size() || debug_all ) {
|
||||
|
@ -91,6 +89,7 @@ void TGConstruct::ConstructBucketStage1() {
|
|||
|
||||
// STEP 2)
|
||||
// Clip 2D polygons against one another
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass polys" );
|
||||
if ( LoadLandclassPolys() == 0 ) {
|
||||
// don't build the tile if there is no 2d data ... it *must*
|
||||
// be ocean and the sim can build the tile on the fly.
|
||||
|
@ -101,16 +100,20 @@ void TGConstruct::ConstructBucketStage1() {
|
|||
// STEP 3)
|
||||
// Load the land use polygons if the --cover option was specified
|
||||
if ( get_cover().size() > 0 ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Loading landclass raster" );
|
||||
load_landcover();
|
||||
}
|
||||
|
||||
// STEP 4)
|
||||
// Clip the Landclass polygons
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Clipping landclass polys" );
|
||||
ClipLandclassPolys();
|
||||
|
||||
// STEP 5)
|
||||
// Clean the polys - after this, we shouldn't change their shape (other than slightly for
|
||||
// fix T-Junctions - as This is the end of the first pass for multicore design
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Cleaning landclass polys" );
|
||||
nodes.init_spacial_query();
|
||||
CleanClippedPolys();
|
||||
|
||||
// STEP 6)
|
||||
|
@ -120,9 +123,7 @@ void TGConstruct::ConstructBucketStage1() {
|
|||
|
||||
void TGConstruct::ConstructBucketStage2() {
|
||||
if ( !IsOceanTile() ) {
|
||||
// First, set the precision of floating point logging:
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed);
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
|
||||
/* If we have some debug IDs, create a datasource */
|
||||
if ( debug_shapes.size() || debug_all ) {
|
||||
|
@ -143,43 +144,43 @@ void TGConstruct::ConstructBucketStage2() {
|
|||
// STEP 9)
|
||||
// Fix T-Junctions by finding nodes that lie close to polygon edges, and
|
||||
// inserting them into the edge
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Fix T-Junctions" );
|
||||
nodes.init_spacial_query();
|
||||
FixTJunctions();
|
||||
|
||||
// STEP 10)
|
||||
// Generate triangles - we can't generate the node-face lookup table
|
||||
// until all polys are tesselated, as extra nodes can still be generated
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Tesselate" );
|
||||
TesselatePolys();
|
||||
|
||||
// STEP 11)
|
||||
// Optimize the node list now since linear add is faster than sorted add.
|
||||
// no more nodes can be added from this point on
|
||||
nodes.SortNodes();
|
||||
|
||||
// STEP 12)
|
||||
// Generate triangle vertex coordinates to node index lists
|
||||
// NOTE: After this point, no new nodes can be added
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Nodes Per Vertex");
|
||||
LookupNodesPerVertex();
|
||||
|
||||
// STEP 13)
|
||||
// Interpolate elevations, and flatten stuff
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Elevation Per Node");
|
||||
CalcElevations();
|
||||
|
||||
// STEP 14)
|
||||
// Generate face_connected list
|
||||
// Generate face_connected list - needed for saving the edge data
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node");
|
||||
LookupFacesPerNode();
|
||||
|
||||
// STEP 15)
|
||||
// Save the tile boundary info for stage 3
|
||||
// includes elevation info, and a list of connected triangles
|
||||
nodes.init_spacial_query();
|
||||
SaveSharedEdgeData( 2 );
|
||||
}
|
||||
}
|
||||
|
||||
void TGConstruct::ConstructBucketStage3() {
|
||||
if ( !IsOceanTile() ) {
|
||||
// First, set the precision of floating point logging:
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed);
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() );
|
||||
|
||||
/* If we have some debug IDs, create a datasource */
|
||||
if ( debug_shapes.size() || debug_all ) {
|
||||
|
@ -189,20 +190,26 @@ void TGConstruct::ConstructBucketStage3() {
|
|||
strcpy( ds_name, "" );
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Lookup Faces Per Node (again)");
|
||||
LookupFacesPerNode();
|
||||
|
||||
// STEP 16)
|
||||
// Load in the neighbor faces and elevation data
|
||||
LoadSharedEdgeDataStage2();
|
||||
|
||||
// STEP 17)
|
||||
// Average out the elevation for nodes on tile boundaries
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Average Edge Node Elevations");
|
||||
AverageEdgeElevations();
|
||||
|
||||
// STEP 18)
|
||||
// Calculate Face Normals
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Face Normals");
|
||||
CalcFaceNormals();
|
||||
|
||||
// STEP 19)
|
||||
// Calculate Point Normals
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Point Normals");
|
||||
CalcPointNormals();
|
||||
|
||||
#if 0
|
||||
|
@ -217,14 +224,17 @@ void TGConstruct::ConstructBucketStage3() {
|
|||
|
||||
// STEP 21)
|
||||
// Calculate Texture Coordinates
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Calculate Texture Coordinates");
|
||||
CalcTextureCoordinates();
|
||||
|
||||
// STEP 22)
|
||||
// Generate the btg file
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Generate BTG File");
|
||||
WriteBtgFile();
|
||||
|
||||
// STEP 23)
|
||||
// Write Custom objects to .stg file
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " - Generate Custome Objects");
|
||||
AddCustomObjects();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,24 +38,24 @@
|
|||
#include <landcover/landcover.hxx>
|
||||
|
||||
#include "tglandclass.hxx"
|
||||
#include "priorities.hxx"
|
||||
|
||||
#define FIND_SLIVERS (0)
|
||||
|
||||
// Stage2 shared edge data
|
||||
struct TGNeighborFaces {
|
||||
public:
|
||||
Point3D node;
|
||||
SGGeod node;
|
||||
|
||||
double_list elevations; // we'll take the average
|
||||
double_list face_areas;
|
||||
point_list face_normals;
|
||||
std::vector<SGVec3f> face_normals;
|
||||
};
|
||||
|
||||
typedef std::vector < TGNeighborFaces > neighbor_face_list;
|
||||
typedef neighbor_face_list::iterator neighbor_face_list_iterator;
|
||||
typedef neighbor_face_list::const_iterator const_neighbor_face_list_iterator;
|
||||
|
||||
|
||||
class TGConstruct {
|
||||
|
||||
private:
|
||||
|
@ -135,16 +135,15 @@ private:
|
|||
// Shared edge Matching
|
||||
void SaveSharedEdgeDataStage2( void );
|
||||
void LoadSharedEdgeDataStage2( void );
|
||||
void WriteSharedEdgeNeighboorFaces( gzFile& fp, Point3D pt );
|
||||
void LoadSharedEdgeData( int stage );
|
||||
void LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, point_list& south, point_list& east, point_list& west );
|
||||
void LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west );
|
||||
|
||||
void SaveSharedEdgeData( int stage );
|
||||
|
||||
void ReadNeighborFaces( gzFile& fp );
|
||||
void WriteNeighborFaces( gzFile& fp, Point3D pt );
|
||||
TGNeighborFaces* AddNeighborFaces( Point3D node );
|
||||
TGNeighborFaces* FindNeighborFaces( Point3D node );
|
||||
void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const;
|
||||
TGNeighborFaces* AddNeighborFaces( const SGGeod& node );
|
||||
TGNeighborFaces* FindNeighborFaces( const SGGeod& node );
|
||||
|
||||
// Polygon Cleaning
|
||||
void CleanClippedPolys( void );
|
||||
|
@ -164,9 +163,7 @@ private:
|
|||
void CalcPointNormals( void );
|
||||
void CalcTextureCoordinates( void );
|
||||
// Helpers
|
||||
SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 );
|
||||
TGPolygon linear_tex_coords( const TGPolygon& tri, const TGTexParams& tp );
|
||||
TGPolygon area_tex_coords( const TGPolygon& tri );
|
||||
SGVec3f calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const;
|
||||
|
||||
// Output
|
||||
void WriteBtgFile( void );
|
||||
|
@ -179,10 +176,6 @@ private:
|
|||
bool IsDebugShape( unsigned int id );
|
||||
bool IsDebugArea( unsigned int area );
|
||||
|
||||
void WriteDebugShape( const char* layer_name, const TGShape& shape );
|
||||
void WriteDebugPoly( const char* layer_name, const char* name, const TGPolygon& poly );
|
||||
void WriteDebugPolys( const char* layer_name, const poly_list& polys );
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
TGConstruct();
|
||||
|
|
|
@ -40,25 +40,25 @@ using std::string;
|
|||
void TGConstruct::FixTJunctions( void ) {
|
||||
int before, after;
|
||||
std::vector<SGGeod> points;
|
||||
nodes.get_geod_nodes( points );
|
||||
tg::Rectangle bb;
|
||||
|
||||
// traverse each poly, and add intermediate nodes
|
||||
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
||||
for( unsigned int j = 0; j < polys_clipped.area_size(i); ++j ) {
|
||||
for( unsigned int k = 0; k < polys_clipped.shape_size(i, j); ++k ) {
|
||||
tgPolygon current = polys_clipped.get_poly(i, j, k);
|
||||
tgPolygon current = polys_clipped.get_poly(i, j);
|
||||
bb = current.GetBoundingBox();
|
||||
nodes.get_geod_inside( bb.getMin(), bb.getMax(), points );
|
||||
|
||||
before = current.TotalNodes();
|
||||
current = tgPolygon::AddColinearNodes( current, points );
|
||||
after = current.TotalNodes();
|
||||
before = current.TotalNodes();
|
||||
current = tgPolygon::AddColinearNodes( current, points );
|
||||
after = current.TotalNodes();
|
||||
|
||||
if (before != after) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << "-" << k << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after );
|
||||
}
|
||||
|
||||
/* Save it back */
|
||||
polys_clipped.set_poly( i, j, k, current );
|
||||
if (before != after) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Fixed T-Junctions in " << get_area_name( (AreaType)i ) << ":" << j+1 << " of " << (int)polys_clipped.area_size(i) << " nodes increased from " << before << " to " << after );
|
||||
}
|
||||
|
||||
/* Save it back */
|
||||
polys_clipped.set_poly( i, j, current );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,23 +76,7 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l
|
|||
continue;
|
||||
}
|
||||
|
||||
for ( unsigned int s = 0; s < clipped.area_size(area) && sliver_list.size(); ++s ) {
|
||||
TGShape shape = clipped.get_shape( area, s );
|
||||
|
||||
unsigned int before = sliver_list.size();
|
||||
sliver_list = tgPolygon::MergeSlivers( shape.polys, sliver_list );
|
||||
unsigned int after = sliver_list.size();
|
||||
|
||||
if (before != after) {
|
||||
shape.BuildMask();
|
||||
|
||||
#if 0
|
||||
if ( IsDebugShape( shape.id ) ) {
|
||||
WriteDebugShape( "with_slivers", shape );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
sliver_list = tgPolygon::MergeSlivers( polys_clipped.get_polys(area), sliver_list );
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " UNMERGED SLIVERS: " << sliver_list.size() );
|
||||
|
@ -101,54 +85,32 @@ void TGConstruct::merge_slivers( TGLandclass& clipped, tgcontour_list& sliver_l
|
|||
}
|
||||
|
||||
void TGConstruct::CleanClippedPolys() {
|
||||
|
||||
// Clean the polys
|
||||
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
||||
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
||||
|
||||
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
// step 1 : snap
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
poly = tgPolygon::Snap(poly, gSnap);
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
tgPolygon poly = polys_clipped.get_poly(area, p);
|
||||
poly = tgPolygon::Snap(poly, gSnap);
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "snapped", "" );
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
tgPolygon::ToShapefile( poly, ds_name, "snapped", "" );
|
||||
}
|
||||
|
||||
// step 2 : remove_dups
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
poly = tgPolygon::RemoveDups( poly );
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
poly = tgPolygon::RemoveDups( poly );
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_dups", "" );
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
tgPolygon::ToShapefile( poly, ds_name, "rem_dups", "" );
|
||||
}
|
||||
|
||||
// step 3 : remove_bad_contours
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
poly = tgPolygon::RemoveBadContours( poly );
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
poly = tgPolygon::RemoveBadContours( poly );
|
||||
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
tgPolygon::ToShapefile( poly, ds_name, "rem_bcs", "" );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "rem_bcs", "" );
|
||||
}
|
||||
|
||||
// todo - add up all segments in a shape for printout
|
||||
#if 0
|
||||
after = poly.total_size();
|
||||
if (before != after) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Cleanined poly " << get_area_name( (AreaType)area ) <<
|
||||
":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " before: " << before << " after: " << after );
|
||||
}
|
||||
#endif
|
||||
|
||||
polys_clipped.set_poly(area, p, poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,10 +129,10 @@ void TGConstruct::AverageEdgeElevations( void )
|
|||
elevation = elevation / num_elevations;
|
||||
|
||||
/* Find this node, and update it's elevation */
|
||||
int idx = nodes.find( faces.node.toSGGeod() );
|
||||
int idx = nodes.find( faces.node );
|
||||
|
||||
if (idx != -1) {
|
||||
TGNode node = nodes.get_node( idx );
|
||||
TGNode const& node = nodes.get_node( idx );
|
||||
|
||||
if ( !node.GetFixedPosition() ) {
|
||||
// set elevation as the average between all tiles that have it
|
||||
|
|
|
@ -77,16 +77,16 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
|
||||
if ( is_landmass_area( i ) && !ignoreLandmass ) {
|
||||
for ( unsigned int j = 0; j < polys_in.area_size(i); ++j ) {
|
||||
land_list.push_back( polys_in.get_mask(i, j) );
|
||||
land_list.push_back( polys_in.get_poly(i, j) );
|
||||
}
|
||||
|
||||
} else if ( is_water_area( i ) ) {
|
||||
for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
|
||||
water_list.push_back( polys_in.get_mask(i, j) );
|
||||
water_list.push_back( polys_in.get_poly(i, j) );
|
||||
}
|
||||
} else if ( is_island_area( i ) ) {
|
||||
for (unsigned int j = 0; j < polys_in.area_size(i); j++) {
|
||||
island_list.push_back( polys_in.get_mask(i, j) );
|
||||
island_list.push_back( polys_in.get_poly(i, j) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,10 +106,10 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
||||
debug_area = IsDebugArea( i );
|
||||
for( j = 0; j < (int)polys_in.area_size(i); ++j ) {
|
||||
tgPolygon current = polys_in.get_mask(i, j);
|
||||
debug_shape = IsDebugShape( polys_in.get_shape( i, j ).id );
|
||||
tgPolygon& current = polys_in.get_poly(i, j);
|
||||
debug_shape = IsDebugShape( polys_in.get_poly( i, j ).GetId() );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_shape( i, j ).id );
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Clipping " << get_area_name( (AreaType)i ) << "(" << i << "):" << j+1 << " of " << polys_in.area_size(i) << " id " << polys_in.get_poly( i, j ).GetId() );
|
||||
|
||||
tmp = current;
|
||||
|
||||
|
@ -122,18 +122,17 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
if ( is_water_area( i ) ) {
|
||||
// clip against island mask
|
||||
tmp = tgPolygon::Diff( tmp, island_mask );
|
||||
|
||||
}
|
||||
|
||||
if ( debug_area || debug_shape ) {
|
||||
char layer[32];
|
||||
char name[32];
|
||||
|
||||
sprintf(layer, "pre_clip_%d", polys_in.get_shape( i, j ).id );
|
||||
sprintf(layer, "pre_clip_%d", polys_in.get_poly( i, j ).GetId() );
|
||||
sprintf(name, "shape %d,%d", i,j);
|
||||
tgPolygon::ToShapefile( tmp, ds_name, layer, name );
|
||||
|
||||
sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id );
|
||||
sprintf(layer, "pre_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() );
|
||||
accum.ToShapefiles( ds_name, layer );
|
||||
}
|
||||
|
||||
|
@ -143,7 +142,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
char layer[32];
|
||||
char name[32];
|
||||
|
||||
sprintf(layer, "post_clip_%d", polys_in.get_shape( i, j ).id );
|
||||
sprintf(layer, "post_clip_%d", polys_in.get_poly( i, j ).GetId() );
|
||||
sprintf(name, "shape %d,%d", i,j);
|
||||
|
||||
tgPolygon::ToShapefile( clipped, ds_name, layer, name );
|
||||
|
@ -159,18 +158,11 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
|
||||
// add the sliverless result polygon to the clipped polys list
|
||||
if ( clipped.Contours() > 0 ) {
|
||||
TGShape shape;
|
||||
|
||||
// copy all of the superpolys and texparams
|
||||
shape.SetMask( clipped );
|
||||
shape.textured = polys_in.get_textured( i, j );
|
||||
shape.id = polys_in.get_shape( i, j ).id;
|
||||
|
||||
shape.area = polys_in.get_shape( i, j ).area;
|
||||
shape.polys = polys_in.get_shape( i, j ).polys;
|
||||
clipped.SetId( polys_in.get_poly( i, j ).GetId() );
|
||||
|
||||
// shape.sps.push_back( sp );
|
||||
polys_clipped.add_shape( i, shape );
|
||||
polys_clipped.add_poly( i, clipped );
|
||||
|
||||
#if 0
|
||||
if ( debug_area || debug_shape ) {
|
||||
|
@ -183,7 +175,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
accum.Add( tmp );
|
||||
if ( debug_area || debug_shape ) {
|
||||
char layer[32];
|
||||
sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_shape( i, j ).id );
|
||||
sprintf(layer, "post_clip_accum_%d_%d", accum_idx, polys_in.get_poly( i, j ).GetId() );
|
||||
|
||||
accum.ToShapefiles( ds_name, layer );
|
||||
}
|
||||
|
@ -192,6 +184,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( debug_all || debug_shapes.size() || debug_areas.size() ) {
|
||||
// Dump the sliver list
|
||||
char name[32];
|
||||
|
@ -200,6 +193,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
tgContour::ToShapefile( slivers[i], ds_name, "slivers", name );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FIND_SLIVERS
|
||||
// Now, merge any slivers with clipped polys
|
||||
|
@ -234,40 +228,23 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
|||
#endif
|
||||
|
||||
if ( remains.Contours() > 0 ) {
|
||||
TGShape shape;
|
||||
|
||||
string material = get_area_name(get_sliver_target_area_type());
|
||||
remains.SetMaterial( material );
|
||||
|
||||
shape.SetMask( remains );
|
||||
shape.textured = false;
|
||||
shape.polys.push_back( remains );
|
||||
|
||||
polys_clipped.add_shape( (int)get_sliver_target_area_type(), shape );
|
||||
}
|
||||
}
|
||||
|
||||
// Once clipping is complete, intersect the individual segments with their clip masks
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Seperating segments from clip mask for " << get_area_name( (AreaType)area ) << ":" << shape+1 << " of " << polys_clipped.area_size(area) );
|
||||
polys_clipped.get_shape(area, shape).IntersectPolys();
|
||||
remains.SetMaterial( get_area_name(get_sliver_target_area_type()) );
|
||||
polys_clipped.add_poly( (int)get_sliver_target_area_type(), remains );
|
||||
}
|
||||
}
|
||||
|
||||
// Now make sure any newly added intersection nodes are added to the tgnodes
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for (unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++) {
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon& poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Collecting nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
|
||||
|
||||
for (unsigned int con=0; con < poly.Contours(); con++) {
|
||||
for (unsigned int node = 0; node < poly.ContourSize( con ); node++) {
|
||||
// ensure we have all nodes...
|
||||
nodes.unique_add( poly.GetNode( con, node ) );
|
||||
}
|
||||
for (unsigned int con=0; con < poly.Contours(); con++) {
|
||||
for (unsigned int n = 0; n < poly.ContourSize( con ); n++) {
|
||||
// ensure we have all nodes...
|
||||
TGNode const& node = poly.GetNode( con, n );
|
||||
nodes.unique_add( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ using std::string;
|
|||
|
||||
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;
|
||||
|
||||
/* Find any ids for our tile */
|
||||
|
@ -131,78 +129,4 @@ bool TGConstruct::IsDebugArea( unsigned int area )
|
|||
}
|
||||
|
||||
return is_debug;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
|
||||
{
|
||||
char name[64];
|
||||
shape.GetName( name );
|
||||
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
tgShapefileCreateFeature( ds_id, l_id, shape.mask, name );
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
}
|
||||
|
||||
void TGConstruct::WriteDebugPoly( const char* layer_name, const char* name, const TGPolygon& poly )
|
||||
{
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
tgShapefileCreateFeature( ds_id, l_id, poly, name );
|
||||
|
||||
// close after each write
|
||||
ds_id = tgShapefileCloseDatasource( ds_id );
|
||||
}
|
||||
|
||||
void TGConstruct::WriteDebugPolys( const char* layer_name, const poly_list& polys )
|
||||
{
|
||||
ds_id = tgShapefileOpenDatasource( ds_name );
|
||||
l_id = tgShapefileOpenLayer( ds_id, layer_name );
|
||||
|
||||
for( unsigned int i=0; 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
|
||||
}
|
|
@ -50,40 +50,16 @@ void TGConstruct::LoadElevationArray( bool add_nodes ) {
|
|||
array.remove_voids( );
|
||||
|
||||
if ( add_nodes ) {
|
||||
point_list corner_list = array.get_corner_list();
|
||||
for (unsigned int i=0; i<corner_list.size(); i++) {
|
||||
nodes.unique_add( corner_list[i].toSGGeod() );
|
||||
point_list corner_list = array.get_corner_list();
|
||||
for (unsigned int i=0; i<corner_list.size(); i++) {
|
||||
nodes.unique_add( corner_list[i].toSGGeod() );
|
||||
}
|
||||
|
||||
point_list fit_list = array.get_fitted_list();
|
||||
for (unsigned int i=0; i<fit_list.size(); i++) {
|
||||
nodes.unique_add( fit_list[i].toSGGeod() );
|
||||
}
|
||||
}
|
||||
|
||||
point_list fit_list = array.get_fitted_list();
|
||||
for (unsigned int i=0; i<fit_list.size(); i++) {
|
||||
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
|
||||
|
@ -92,14 +68,11 @@ static double distanceSphere( const SGGeoc& p1, const SGGeod& p2 ) {
|
|||
void TGConstruct::CalcElevations( void )
|
||||
{
|
||||
std::vector<SGGeod> raw_nodes;
|
||||
SGGeoc p;
|
||||
double e1, e2, e3, min;
|
||||
int n1, n2, n3;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "fixing node heights");
|
||||
|
||||
for (int i = 0; i < (int)nodes.size(); ++i) {
|
||||
TGNode node = nodes.get_node( i );
|
||||
TGNode const& node = nodes.get_node( i );
|
||||
SGGeod pos = node.GetPosition();
|
||||
|
||||
if ( !node.GetFixedPosition() ) {
|
||||
|
@ -113,122 +86,136 @@ void TGConstruct::CalcElevations( void )
|
|||
// now flatten some stuff
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
if ( is_lake_area( (AreaType)area ) ) {
|
||||
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) {
|
||||
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
|
||||
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
min = e1;
|
||||
if ( e2 < min ) { min = e2; }
|
||||
if ( e3 < min ) { min = e3; }
|
||||
|
||||
min = e1;
|
||||
if ( e2 < min ) { min = e2; }
|
||||
if ( e3 < min ) { min = e3; }
|
||||
|
||||
nodes.SetElevation( n1, min );
|
||||
nodes.SetElevation( n2, min );
|
||||
nodes.SetElevation( n3, min );
|
||||
}
|
||||
nodes.SetElevation( n1, min );
|
||||
nodes.SetElevation( n2, min );
|
||||
nodes.SetElevation( n3, min );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_stream_area( (AreaType)area ) ) {
|
||||
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) {
|
||||
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
|
||||
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
min = e1;
|
||||
SGGeod src = raw_nodes[n1];
|
||||
|
||||
min = e1;
|
||||
p = SGGeoc::fromGeod( raw_nodes[n1] );
|
||||
if ( e2 < min ) { min = e2; src = raw_nodes[n2]; }
|
||||
if ( e3 < min ) { min = e3; src = raw_nodes[n3]; }
|
||||
|
||||
if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); }
|
||||
if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); }
|
||||
|
||||
double d1 = distanceSphere( p, raw_nodes[n1] );
|
||||
double d2 = distanceSphere( p, raw_nodes[n2] );
|
||||
double d3 = distanceSphere( p, raw_nodes[n3] );
|
||||
|
||||
double max1 = d1 * 0.20 + min;
|
||||
double max2 = d2 * 0.20 + min;
|
||||
double max3 = d3 * 0.20 + min;
|
||||
|
||||
if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); }
|
||||
if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); }
|
||||
if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); }
|
||||
double d1, d2, d3;
|
||||
if ( min == e1 ) {
|
||||
d1 = 0.0f;
|
||||
} else {
|
||||
d1 = SGGeodesy::distanceM( src, raw_nodes[n1] );
|
||||
}
|
||||
if ( min == e2 ) {
|
||||
d2 = 0.0f;
|
||||
} else {
|
||||
d2 = SGGeodesy::distanceM( src, raw_nodes[n2] );
|
||||
}
|
||||
if ( min == e3 ) {
|
||||
d3 = 0.0f;
|
||||
} else {
|
||||
d3 = SGGeodesy::distanceM( src, raw_nodes[n3] );
|
||||
}
|
||||
|
||||
double max1 = d1 * 0.20 + min;
|
||||
double max2 = d2 * 0.20 + min;
|
||||
double max3 = d3 * 0.20 + min;
|
||||
|
||||
if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); }
|
||||
if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); }
|
||||
if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_road_area( (AreaType)area ) ) {
|
||||
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) {
|
||||
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
|
||||
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
e1 = nodes.get_node(n1).GetPosition().getElevationM();
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
e2 = nodes.get_node(n2).GetPosition().getElevationM();
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
e3 = nodes.get_node(n3).GetPosition().getElevationM();
|
||||
min = e1;
|
||||
SGGeod src = raw_nodes[n1];
|
||||
|
||||
min = e1;
|
||||
p = SGGeoc::fromGeod( raw_nodes[n1] );
|
||||
if ( e2 < min ) { min = e2; src = raw_nodes[n2]; }
|
||||
if ( e3 < min ) { min = e3; src = raw_nodes[n3]; }
|
||||
|
||||
if ( e2 < min ) { min = e2; p = SGGeoc::fromGeod( raw_nodes[n2] ); }
|
||||
if ( e3 < min ) { min = e3; p = SGGeoc::fromGeod( raw_nodes[n3] ); }
|
||||
|
||||
double d1 = distanceSphere( p, raw_nodes[n1] );
|
||||
double d2 = distanceSphere( p, raw_nodes[n2] );
|
||||
double d3 = distanceSphere( p, raw_nodes[n3] );
|
||||
|
||||
double max1 = d1 * 0.30 + min;
|
||||
double max2 = d2 * 0.30 + min;
|
||||
double max3 = d3 * 0.30 + min;
|
||||
|
||||
if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); }
|
||||
if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); }
|
||||
if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); }
|
||||
double d1, d2, d3;
|
||||
if ( min == e1 ) {
|
||||
d1 = 0.0f;
|
||||
} else {
|
||||
d1 = SGGeodesy::distanceM( src, raw_nodes[n1] );
|
||||
}
|
||||
if ( min == e2 ) {
|
||||
d2 = 0.0f;
|
||||
} else {
|
||||
d2 = SGGeodesy::distanceM( src, raw_nodes[n2] );
|
||||
}
|
||||
if ( min == e3 ) {
|
||||
d3 = 0.0f;
|
||||
} else {
|
||||
d3 = SGGeodesy::distanceM( src, raw_nodes[n3] );
|
||||
}
|
||||
|
||||
double max1 = d1 * 0.30 + min;
|
||||
double max2 = d2 * 0.30 + min;
|
||||
double max3 = d3 * 0.30 + min;
|
||||
|
||||
if ( max1 < e1 ) { nodes.SetElevation( n1, max1 ); }
|
||||
if ( max2 < e2 ) { nodes.SetElevation( n2, max2 ); }
|
||||
if ( max3 < e3 ) { nodes.SetElevation( n3, max3 ); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_ocean_area( (AreaType)area ) ) {
|
||||
for (int shape = 0; shape < (int)polys_clipped.area_size(area); ++shape ) {
|
||||
for (int segment = 0; segment < (int)polys_clipped.shape_size(area, shape); ++segment ) {
|
||||
for (int p = 0; p < (int)polys_clipped.area_size(area); ++p ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Flattening " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Flattening " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) );
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
n1 = poly.GetTriIdx( tri, 0 );
|
||||
n2 = poly.GetTriIdx( tri, 1 );
|
||||
n3 = poly.GetTriIdx( tri, 2 );
|
||||
|
||||
nodes.SetElevation( n1, 0.0 );
|
||||
nodes.SetElevation( n2, 0.0 );
|
||||
nodes.SetElevation( n3, 0.0 );
|
||||
}
|
||||
nodes.SetElevation( n1, 0.0 );
|
||||
nodes.SetElevation( n2, 0.0 );
|
||||
nodes.SetElevation( n3, 0.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,27 +34,21 @@
|
|||
// indexes into the node array (cast as unsigned long)
|
||||
void TGConstruct::LookupNodesPerVertex( void )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "LookupNodesPerVertex");
|
||||
|
||||
// for each node, traverse all the triangles - and create face lists
|
||||
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
||||
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly( area, shape, segment );
|
||||
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon& poly = polys_clipped.get_poly( area, p );
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
for (unsigned int vertex = 0; vertex < 3; vertex++) {
|
||||
int idx = nodes.find( poly.GetTriNode( tri, vertex ) );
|
||||
if (idx >= 0) {
|
||||
poly.SetTriIdx( tri, vertex, idx );
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << poly.GetTriNode( tri, vertex ) );
|
||||
exit(0);
|
||||
}
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
for (unsigned int vertex = 0; vertex < 3; vertex++) {
|
||||
int idx = nodes.find( poly.GetTriNode( tri, vertex ) );
|
||||
if (idx >= 0) {
|
||||
poly.SetTriIdx( tri, vertex, idx );
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "didn't find vertex! " << poly.GetTriNode( tri, vertex ) );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,19 +56,15 @@ void TGConstruct::LookupNodesPerVertex( void )
|
|||
|
||||
void TGConstruct::LookupFacesPerNode( void )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "LookupFacesPerNode");
|
||||
|
||||
// Add each face that includes a node to the node's face list
|
||||
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
||||
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon const& poly = polys_clipped.get_poly(area, p );
|
||||
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
int i = poly.GetTriIdx( tri, v );
|
||||
nodes.AddFace( i, area, shape, segment, tri );
|
||||
}
|
||||
for (unsigned int tri=0; tri < poly.Triangles(); tri++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
int i = poly.GetTriIdx( tri, v );
|
||||
nodes.AddFace( i, area, p, tri );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,19 +29,7 @@
|
|||
|
||||
#include "tgconstruct.hxx"
|
||||
|
||||
//using std::string;
|
||||
|
||||
#if 0
|
||||
double TGConstruct::calc_tri_area( int_list& triangle_nodes ) {
|
||||
SGGeod p1 = nodes.get_node( triangle_nodes[0] ).GetPosition();
|
||||
SGGeod p2 = nodes.get_node( triangle_nodes[1] ).GetPosition();
|
||||
SGGeod p3 = nodes.get_node( triangle_nodes[2] ).GetPosition();
|
||||
|
||||
return triangle_area( p1, p2, p3 );
|
||||
}
|
||||
#endif
|
||||
|
||||
SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) {
|
||||
SGVec3f TGConstruct::calc_normal( double area, const SGVec3d& p1, const SGVec3d& p2, const SGVec3d& p3 ) const {
|
||||
SGVec3f v1, v2;
|
||||
SGVec3f normal;
|
||||
|
||||
|
@ -111,11 +99,9 @@ void TGConstruct::CalcFaceNormals( void )
|
|||
nodes.get_geod_nodes( geod_nodes );
|
||||
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << shape+1 << "-" << segment << " of " << polys_in.area_size(area) );
|
||||
calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, shape, segment ) );
|
||||
}
|
||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Calculating face normals for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_in.area_size(area) );
|
||||
calc_normals( geod_nodes, wgs84_nodes, polys_clipped.get_poly( area, p ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,9 +109,7 @@ void TGConstruct::CalcFaceNormals( void )
|
|||
void TGConstruct::CalcPointNormals( void )
|
||||
{
|
||||
// traverse triangle structure building the face normal table
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Calculating point normals: 0%");
|
||||
|
||||
SGVec3d normal;
|
||||
SGVec3f normal;
|
||||
double face_area;
|
||||
|
||||
std::vector<SGVec3d> wgs84_nodes;
|
||||
|
@ -135,15 +119,15 @@ void TGConstruct::CalcPointNormals( void )
|
|||
unsigned int cur_percent = 1;
|
||||
|
||||
for ( unsigned int i = 0; i<nodes.size(); i++ ) {
|
||||
TGNode node = nodes.get_node( i );
|
||||
TGFaceList faces = node.GetFaces();
|
||||
TGNeighborFaces* neighbor_faces = NULL;
|
||||
TGNode const& node = nodes.get_node( i );
|
||||
TGFaceList const& faces = node.GetFaces();
|
||||
TGNeighborFaces const* neighbor_faces = NULL;
|
||||
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 ) {
|
||||
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;
|
||||
cur_percent += 1;
|
||||
}
|
||||
|
@ -151,12 +135,11 @@ void TGConstruct::CalcPointNormals( void )
|
|||
// for each triangle that shares this node
|
||||
for ( unsigned int j = 0; j < faces.size(); ++j ) {
|
||||
unsigned int at = faces[j].area;
|
||||
unsigned int shape = faces[j].shape;
|
||||
unsigned int segment = faces[j].seg;
|
||||
unsigned int poly = faces[j].poly;
|
||||
unsigned int tri = faces[j].tri;
|
||||
|
||||
normal = polys_clipped.get_face_normal( at, shape, segment, tri ).toSGVec3d();
|
||||
face_area = polys_clipped.get_face_area( at, shape, segment, tri );
|
||||
normal = polys_clipped.get_face_normal( at, poly, tri );
|
||||
face_area = polys_clipped.get_face_area( at, poly, tri );
|
||||
|
||||
normal *= face_area; // scale normal weight relative to 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
|
||||
neighbor_faces = FindNeighborFaces( Point3D::fromSGGeod( node.GetPosition() ) );
|
||||
neighbor_faces = FindNeighborFaces( node.GetPosition() );
|
||||
if ( neighbor_faces ) {
|
||||
int num_faces = neighbor_faces->face_areas.size();
|
||||
for ( int j = 0; j < num_faces; j++ ) {
|
||||
normal = neighbor_faces->face_normals[j].toSGVec3d();
|
||||
normal = neighbor_faces->face_normals[j];
|
||||
face_area = neighbor_faces->face_areas[j];
|
||||
|
||||
normal *= face_area;
|
||||
|
@ -178,7 +161,6 @@ void TGConstruct::CalcPointNormals( void )
|
|||
}
|
||||
|
||||
average /= total_area;
|
||||
SGVec3f n = SGVec3f( average.x(), average.y(), average.z() );
|
||||
nodes.SetNormal( i, n );
|
||||
nodes.SetNormal( i, average );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -135,45 +135,35 @@ void TGConstruct::WriteBtgFile( void )
|
|||
int_list pt_n, tri_n, strip_n;
|
||||
int_list tri_tc, strip_tc;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Output triangles" );
|
||||
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
// only tesselate non holes
|
||||
if ( !is_hole_area( area ) ) {
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" <<
|
||||
shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) );
|
||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Ouput nodes for " << get_area_name( (AreaType)area ) << ":" << p+1 << " of " << polys_clipped.area_size(area) );
|
||||
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
string material = polys_clipped.get_material(area, shape, segment);
|
||||
tgPolygon poly = polys_clipped.get_poly(area, p);
|
||||
string material = poly.GetMaterial();
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " num tris " << poly.Triangles() );
|
||||
for (unsigned int k = 0; k < poly.Triangles(); ++k) {
|
||||
tri_v.clear();
|
||||
tri_n.clear();
|
||||
tri_tc.clear();
|
||||
for (int l = 0; l < 3; ++l) {
|
||||
index = poly.GetTriIdx( k, l );
|
||||
tri_v.push_back( index );
|
||||
|
||||
for (unsigned int k = 0; k < poly.Triangles(); ++k) {
|
||||
tri_v.clear();
|
||||
tri_n.clear();
|
||||
tri_tc.clear();
|
||||
for (int l = 0; l < 3; ++l) {
|
||||
index = poly.GetTriIdx( k, l );
|
||||
tri_v.push_back( index );
|
||||
// add the node's normal
|
||||
index = normals.add( nodes.GetNormal( index ) );
|
||||
tri_n.push_back( index );
|
||||
|
||||
// add the node's normal
|
||||
index = normals.add( nodes.GetNormal( index ) );
|
||||
tri_n.push_back( index );
|
||||
|
||||
index = texcoords.add( poly.GetTriTexCoord( k, l ) );
|
||||
tri_tc.push_back( index );
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
tris_n.push_back( tri_n );
|
||||
tris_tc.push_back( tri_tc );
|
||||
|
||||
material = polys_clipped.get_material(area, shape, segment);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Add tri material " << material);
|
||||
|
||||
tri_materials.push_back( material );
|
||||
index = texcoords.add( poly.GetTriTexCoord( k, l ) );
|
||||
tri_tc.push_back( index );
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
tris_n.push_back( tri_n );
|
||||
tris_tc.push_back( tri_tc );
|
||||
|
||||
tri_materials.push_back( material );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,20 +37,6 @@ using std::string;
|
|||
|
||||
static unsigned int cur_poly_id = 0;
|
||||
|
||||
// Add a polygon to the clipper. - only used by load_osgb36_poly - make that function more like ogr load
|
||||
void TGConstruct::add_poly( int area, tgPolygon &poly, string material ) {
|
||||
TGShape shape;
|
||||
|
||||
if ( area < TG_MAX_AREA_TYPES ) {
|
||||
poly.SetMaterial( material );
|
||||
shape.polys.push_back( poly );
|
||||
polys_in.add_shape( area, shape );
|
||||
} else {
|
||||
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " << area);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool TGConstruct::load_poly(const string& path) {
|
||||
bool poly3d = false;
|
||||
bool with_tp = false;
|
||||
|
@ -114,11 +100,11 @@ bool TGConstruct::load_poly(const string& path) {
|
|||
|
||||
|
||||
// Generate a new Shape for the poly
|
||||
TGShape shape;
|
||||
tgPolygon poly;
|
||||
SGGeod p;
|
||||
|
||||
|
||||
for (k=0; k<num_polys;k++) {
|
||||
poly.Erase();
|
||||
|
||||
if ( with_tp ) {
|
||||
in >> x;
|
||||
|
@ -213,24 +199,19 @@ bool TGConstruct::load_poly(const string& path) {
|
|||
poly.SetMaterial( material );
|
||||
|
||||
if ( with_tp ) {
|
||||
shape.textured = true;
|
||||
poly.SetTexMethod( TG_TEX_BY_TPS_CLIPU, -1, 0, 1, 0 );
|
||||
} else {
|
||||
shape.textured = false;
|
||||
poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() );
|
||||
}
|
||||
shape.polys.push_back( poly );
|
||||
|
||||
in >> skipcomment;
|
||||
}
|
||||
|
||||
// Once the full poly is loaded, build the clip mask
|
||||
shape.BuildMask();
|
||||
shape.area = area;
|
||||
shape.id = cur_poly_id++;
|
||||
poly.SetId( cur_poly_id++ );
|
||||
polys_in.add_poly( area, poly );
|
||||
|
||||
polys_in.add_shape( area, shape );
|
||||
|
||||
if ( IsDebugShape( shape.id ) ) {
|
||||
tgPolygon::ToShapefile( shape.mask, ds_name, "loaded", "" );
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
tgPolygon::ToShapefile( poly, ds_name, "loaded", "" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +241,7 @@ int TGConstruct::LoadLandclassPolys( void ) {
|
|||
}
|
||||
|
||||
simgear::PathList files = d.children(simgear::Dir::TYPE_FILE);
|
||||
SG_LOG( SG_CLIPPER, SG_ALERT, files.size() << " Polys in " << d.path() );
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, files.size() << " Polys in " << d.path() );
|
||||
|
||||
BOOST_FOREACH(const SGPath& p, files) {
|
||||
if (p.file_base() != tile_str) {
|
||||
|
@ -274,7 +255,7 @@ int TGConstruct::LoadLandclassPolys( void ) {
|
|||
// skipped!
|
||||
} else {
|
||||
load_poly( p.str() );
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, " Loaded " << p.file());
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " Loaded " << p.file());
|
||||
++count;
|
||||
}
|
||||
} // of directory file children
|
||||
|
|
|
@ -96,7 +96,7 @@ void TGConstruct::SaveSharedEdgeData( int stage )
|
|||
{
|
||||
// for stage 2, we need enough info on a node to average out elevation and
|
||||
// generate a correct normal
|
||||
// we will use the Point3D, as stage1 above, then a point list per node
|
||||
// we will use a geod, as stage1 above, then a geod list per node
|
||||
// to store the neighboors.
|
||||
//
|
||||
// NOTE: Some neighboors (likely 2) are on the shared border.
|
||||
|
@ -110,12 +110,12 @@ void TGConstruct::SaveSharedEdgeData( int stage )
|
|||
}
|
||||
}
|
||||
|
||||
void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
|
||||
void TGConstruct::WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const
|
||||
{
|
||||
// find all neighboors of this point
|
||||
int n = nodes.find( pt.toSGGeod() );
|
||||
TGNode node = nodes.get_node( n );
|
||||
TGFaceList faces = node.GetFaces();
|
||||
int n = nodes.find( pt );
|
||||
TGNode const& node = nodes.get_node( n );
|
||||
TGFaceList const& faces = node.GetFaces();
|
||||
|
||||
// write the number of neighboor faces
|
||||
sgWriteInt( fp, faces.size() );
|
||||
|
@ -123,20 +123,16 @@ void TGConstruct::WriteNeighborFaces( gzFile& fp, Point3D pt )
|
|||
// write out each face normal and size
|
||||
for (unsigned int j=0; j<faces.size(); j++) {
|
||||
// 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();
|
||||
SGGeod p2 = nodes.get_node( poly.GetTriIdx( tri, 1) ).GetPosition();
|
||||
SGGeod p3 = nodes.get_node( poly.GetTriIdx( tri, 2) ).GetPosition();
|
||||
|
||||
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();
|
||||
SGVec3d const& wgs_p1 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
|
||||
SGVec3d const& wgs_p2 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
|
||||
SGVec3d const& wgs_p3 = nodes[ poly.GetTriIdx( tri, 0) ].GetWgs84();
|
||||
|
||||
double face_area = triangle_area( p1, p2, 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;
|
||||
|
||||
|
@ -160,7 +156,7 @@ TGNeighborFaces* TGConstruct::FindNeighborFaces( Point3D node )
|
|||
return faces;
|
||||
}
|
||||
|
||||
TGNeighborFaces* TGConstruct::AddNeighborFaces( Point3D node )
|
||||
TGNeighborFaces* TGConstruct::AddNeighborFaces( const SGGeod& node )
|
||||
{
|
||||
TGNeighborFaces faces;
|
||||
faces.node = node;
|
||||
|
@ -187,14 +183,14 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
|
|||
// look to see if we already have this node
|
||||
// If we do, (it's a corner) add more faces to it.
|
||||
// otherwise, initialize it with our elevation data
|
||||
pFaces = FindNeighborFaces( Point3D::fromSGGeod( node ) );
|
||||
pFaces = FindNeighborFaces( node );
|
||||
if ( !pFaces ) {
|
||||
pFaces = AddNeighborFaces( Point3D::fromSGGeod( node ) );
|
||||
pFaces = AddNeighborFaces( node );
|
||||
|
||||
// new face - let's add our elevation first
|
||||
int idx = nodes.find( node );
|
||||
if (idx >= 0) {
|
||||
TGNode local = nodes.get_node( idx );
|
||||
TGNode const& local = nodes.get_node( idx );
|
||||
pFaces->elevations.push_back( local.GetPosition().getElevationM() );
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +208,7 @@ void TGConstruct::ReadNeighborFaces( gzFile& fp )
|
|||
pFaces->face_areas.push_back( area );
|
||||
|
||||
sgReadVec3( fp, normal );
|
||||
pFaces->face_normals.push_back( Point3D::fromSGVec3( normal ) );
|
||||
pFaces->face_normals.push_back( normal );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +242,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
|
|||
for (int i=0; i<nCount; i++) {
|
||||
// write the 3d point
|
||||
sgWriteGeod( fp, north[i] );
|
||||
WriteNeighborFaces( fp, Point3D::fromSGGeod( north[i] ) );
|
||||
WriteNeighborFaces( fp, north[i] );
|
||||
}
|
||||
gzclose(fp);
|
||||
|
||||
|
@ -262,7 +258,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
|
|||
sgWriteInt( fp, nCount );
|
||||
for (int i=0; i<nCount; i++) {
|
||||
sgWriteGeod( fp, south[i] );
|
||||
WriteNeighborFaces( fp, Point3D::fromSGGeod( south[i] ) );
|
||||
WriteNeighborFaces( fp, south[i] );
|
||||
}
|
||||
gzclose(fp);
|
||||
|
||||
|
@ -278,7 +274,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
|
|||
sgWriteInt( fp, nCount );
|
||||
for (int i=0; i<nCount; i++) {
|
||||
sgWriteGeod( fp, east[i] );
|
||||
WriteNeighborFaces( fp, Point3D::fromSGGeod( east[i] ) );
|
||||
WriteNeighborFaces( fp, east[i] );
|
||||
}
|
||||
gzclose(fp);
|
||||
|
||||
|
@ -294,7 +290,7 @@ void TGConstruct::SaveSharedEdgeDataStage2( void )
|
|||
sgWriteInt( fp, nCount );
|
||||
for (int i=0; i<nCount; i++) {
|
||||
sgWriteGeod( fp, west[i] );
|
||||
WriteNeighborFaces( fp, Point3D::fromSGGeod( west[i] ) );
|
||||
WriteNeighborFaces( fp, west[i] );
|
||||
}
|
||||
gzclose(fp);
|
||||
}
|
||||
|
@ -381,6 +377,7 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
|
|||
gzclose( fp );
|
||||
|
||||
file = dir + "/" + bucket.gen_index_str() + "_nodes";
|
||||
|
||||
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO,"ERROR: opening " << file.c_str() << " for writing!" );
|
||||
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 file;
|
||||
gzFile fp;
|
||||
Point3D pt;
|
||||
SGGeod pt;
|
||||
int nCount;
|
||||
|
||||
dir = share_base + "/stage1/" + b.gen_base_path();
|
||||
|
@ -445,33 +442,33 @@ void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, p
|
|||
if (fp) {
|
||||
// North
|
||||
sgReadInt( fp, &nCount );
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary");
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary");
|
||||
for (int i=0; i<nCount; i++) {
|
||||
sgReadPoint3D( fp, pt );
|
||||
sgReadGeod( fp, pt );
|
||||
north.push_back(pt);
|
||||
}
|
||||
|
||||
// South
|
||||
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++) {
|
||||
sgReadPoint3D( fp, pt );
|
||||
sgReadGeod( fp, pt );
|
||||
south.push_back(pt);
|
||||
}
|
||||
|
||||
// East
|
||||
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++) {
|
||||
sgReadPoint3D( fp, pt );
|
||||
sgReadGeod( fp, pt );
|
||||
east.push_back(pt);
|
||||
}
|
||||
|
||||
// West
|
||||
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++) {
|
||||
sgReadPoint3D( fp, pt );
|
||||
sgReadGeod( fp, pt );
|
||||
west.push_back(pt);
|
||||
}
|
||||
|
||||
|
@ -485,7 +482,7 @@ void TGConstruct::LoadSharedEdgeData( int stage )
|
|||
case 1:
|
||||
{
|
||||
// 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;
|
||||
double clon = bucket.get_center_lon();
|
||||
double clat = bucket.get_center_lat();
|
||||
|
@ -495,28 +492,28 @@ void TGConstruct::LoadSharedEdgeData( int stage )
|
|||
LoadNeighboorEdgeDataStage1( nb, north, south, east, west );
|
||||
// Add southern nodes from northern tile
|
||||
for (unsigned int i=0; i<south.size(); i++) {
|
||||
nodes.unique_add( south[i].toSGGeod() );
|
||||
nodes.unique_add( south[i] );
|
||||
}
|
||||
|
||||
// Read South Tile and add its northern nodes
|
||||
sb = sgBucketOffset(clon, clat, 0, -1);
|
||||
LoadNeighboorEdgeDataStage1( sb, north, south, east, west );
|
||||
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
|
||||
eb = sgBucketOffset(clon, clat, 1, 0);
|
||||
LoadNeighboorEdgeDataStage1( eb, north, south, east, west );
|
||||
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
|
||||
wb = sgBucketOffset(clon, clat, -1, 0);
|
||||
LoadNeighboorEdgeDataStage1( wb, north, south, east, west );
|
||||
for (unsigned int i=0; i<east.size(); i++) {
|
||||
nodes.unique_add( east[i].toSGGeod() );
|
||||
nodes.unique_add( east[i] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -583,4 +580,4 @@ void TGConstruct::LoadFromIntermediateFiles( int stage )
|
|||
if ( !read_ok ) {
|
||||
SetOceanTile();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,16 +25,10 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
//#include <simgear/compiler.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <Geometry/poly_support.hxx>
|
||||
//#include <Geometry/poly_extra.hxx>
|
||||
|
||||
#include "tgconstruct.hxx"
|
||||
|
||||
//using std::string;
|
||||
|
||||
void TGConstruct::TesselatePolys( void )
|
||||
{
|
||||
// tesselate the polygons and prepair them for final output
|
||||
|
@ -42,38 +36,40 @@ void TGConstruct::TesselatePolys( void )
|
|||
SGGeod min, max;
|
||||
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
for (unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
unsigned int id = polys_clipped.get_shape( area, shape ).id;
|
||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, p );
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
tgPolygon::ToShapefile( polys_clipped.get_shape( area, shape ).mask, ds_name, "preteselate", "" );
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
tgPolygon::ToShapefile( poly, ds_name, "preteselate", "" );
|
||||
}
|
||||
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
tg::Rectangle rect = poly.GetBoundingBox();
|
||||
nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra );
|
||||
|
||||
tg::Rectangle rect = poly.GetBoundingBox();
|
||||
nodes.get_geod_inside( rect.getMin(), rect.getMax(), poly_extra );
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||
p+1 << " of " << (int)polys_clipped.area_size(area) << ": id = " << poly.GetId() );
|
||||
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Tesselating " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||
shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) <<
|
||||
": id = " << id );
|
||||
if ( IsDebugShape( poly.GetId() ) ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, poly );
|
||||
}
|
||||
|
||||
if ( IsDebugShape( id ) ) {
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, poly );
|
||||
poly.Tesselate( poly_extra );
|
||||
|
||||
polys_clipped.set_poly( area, p, poly );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++) {
|
||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon& poly = polys_clipped.get_poly(area, p );
|
||||
|
||||
// ensure all added nodes are accounted for
|
||||
for (unsigned int k=0; k < poly.Triangles(); k++) {
|
||||
for (int l = 0; l < 3; l++) {
|
||||
// ensure we have all nodes...
|
||||
nodes.unique_add( poly.GetTriNode( k, l ) );
|
||||
}
|
||||
|
||||
poly.Tesselate( poly_extra );
|
||||
|
||||
// ensure all added nodes are accounted for
|
||||
for (unsigned int k=0; k < poly.Triangles(); k++) {
|
||||
for (int l = 0; l < 3; l++) {
|
||||
// ensure we have all nodes...
|
||||
nodes.unique_add( poly.GetTriNode( k, l ) );
|
||||
}
|
||||
}
|
||||
|
||||
polys_clipped.set_poly( area, shape, segment, poly );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,161 +25,19 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/misc/texcoord.hxx>
|
||||
#include <simgear/debug/logstream.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 )
|
||||
{
|
||||
for ( unsigned int area = 0; area < TG_MAX_AREA_TYPES; area++ ) {
|
||||
for( unsigned int shape = 0; shape < polys_clipped.area_size(area); shape++ ) {
|
||||
for ( unsigned int segment = 0; segment < polys_clipped.shape_size(area, shape); segment++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, shape, segment);
|
||||
SG_LOG( SG_CLIPPER, SG_INFO, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||
shape+1 << "-" << segment << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() );
|
||||
for( unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||
tgPolygon poly = polys_clipped.get_poly(area, p);
|
||||
SG_LOG( SG_CLIPPER, SG_DEBUG, "Texturing " << get_area_name( (AreaType)area ) << "(" << area << "): " <<
|
||||
p+1 << " of " << polys_clipped.area_size(area) << " with " << poly.GetMaterial() );
|
||||
|
||||
if ( polys_clipped.get_textured( area, shape ) ) {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "USE TEXTURE PARAMS for tex coord calculations" );
|
||||
poly.SetTexMethod( TG_TEX_BY_TPS_CLIPUV, -1, -1, 1, 1 );
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "USE SIMGEAR for tex coord calculations" );
|
||||
poly.SetTexMethod( TG_TEX_BY_GEODE, bucket.get_center_lat() );
|
||||
}
|
||||
poly.Texture( );
|
||||
polys_clipped.set_poly(area, shape, segment, poly);
|
||||
}
|
||||
poly.Texture( );
|
||||
polys_clipped.set_poly(area, p, poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ void TGLandclass::clear(void)
|
|||
int 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 );
|
||||
|
||||
for (j=0; j<count; j++) {
|
||||
TGShape shape;
|
||||
tgPolygon poly;
|
||||
|
||||
shape.LoadFromGzFile( fp );
|
||||
shapes[i].push_back( shape );
|
||||
poly.LoadFromGzFile( fp );
|
||||
polys[i].push_back( poly );
|
||||
}
|
||||
}
|
||||
}
|
||||
std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
|
||||
{
|
||||
int i, j, count;
|
||||
TGShape shape;
|
||||
tgPolygon poly;
|
||||
|
||||
// Save all landclass shapes
|
||||
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
|
||||
count = lc.shapes[i].size();
|
||||
count = lc.polys[i].size();
|
||||
out << count << "\n";
|
||||
for (j=0; j<count; j++) {
|
||||
out << lc.shapes[i][j] << " ";
|
||||
out << lc.polys[i][j] << " ";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
@ -78,15 +78,15 @@ std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
|
|||
void TGLandclass::SaveToGzFile(gzFile& fp)
|
||||
{
|
||||
int i, j, count;
|
||||
TGShape shape;
|
||||
tgPolygon shape;
|
||||
|
||||
// Save all landclass shapes
|
||||
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
|
||||
count = shapes[i].size();
|
||||
count = polys[i].size();
|
||||
sgWriteInt( fp, count );
|
||||
|
||||
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/io/lowlevel.hxx>
|
||||
#define TG_MAX_AREA_TYPES 128
|
||||
|
||||
#include "tgshape.hxx"
|
||||
#include <Polygon/polygon.hxx>
|
||||
|
||||
#define TG_MAX_AREA_TYPES 128
|
||||
|
||||
class TGLandclass
|
||||
{
|
||||
|
@ -46,108 +47,50 @@ public:
|
|||
|
||||
inline unsigned int area_size( unsigned int area )
|
||||
{
|
||||
return shapes[area].size();
|
||||
}
|
||||
inline unsigned int shape_size( unsigned int area, unsigned int shape )
|
||||
{
|
||||
return shapes[area][shape].polys.size();
|
||||
return polys[area].size();
|
||||
}
|
||||
|
||||
inline void add_shape( unsigned int area, TGShape shape )
|
||||
inline tgPolygon const& get_poly( unsigned int area, unsigned int poly ) const
|
||||
{
|
||||
shapes[area].push_back( shape );
|
||||
return polys[area][poly];
|
||||
}
|
||||
inline TGShape& get_shape( unsigned int area, unsigned int shape )
|
||||
inline tgPolygon & get_poly( unsigned int area, unsigned int poly )
|
||||
{
|
||||
return shapes[area][shape];
|
||||
return polys[area][poly];
|
||||
}
|
||||
inline void add_poly( unsigned int area, const tgPolygon& p )
|
||||
{
|
||||
polys[area].push_back( p );
|
||||
}
|
||||
inline void set_poly( unsigned int area, unsigned int poly, const tgPolygon& p )
|
||||
{
|
||||
polys[area][poly] = p;
|
||||
}
|
||||
|
||||
inline tgPolygon get_mask( unsigned int area, unsigned int shape )
|
||||
inline tgpolygon_list& get_polys( unsigned int area )
|
||||
{
|
||||
return shapes[area][shape].mask;
|
||||
return polys[area];
|
||||
}
|
||||
inline void set_mask( unsigned int area, unsigned int shape, tgPolygon mask )
|
||||
|
||||
inline const SGVec3f& get_face_normal( unsigned int area, unsigned int poly, unsigned int tri ) const
|
||||
{
|
||||
shapes[area][shape].mask = mask;
|
||||
return polys[area][poly].GetTriFaceNormal( tri );
|
||||
}
|
||||
|
||||
inline bool get_textured( unsigned int area, unsigned int shape )
|
||||
inline double get_face_area( unsigned int area, unsigned int poly, unsigned int tri )
|
||||
{
|
||||
return shapes[area][shape].textured;
|
||||
}
|
||||
inline void set_textured( unsigned int area, unsigned int shape, bool t )
|
||||
{
|
||||
shapes[area][shape].textured = t;
|
||||
return polys[area][poly].GetTriFaceArea( tri );
|
||||
}
|
||||
|
||||
inline tgPolygon& get_poly( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
inline std::string get_material( unsigned int area, unsigned int poly )
|
||||
{
|
||||
return shapes[area][shape].polys[segment];
|
||||
return polys[area][poly].GetMaterial();
|
||||
}
|
||||
inline void set_poly( unsigned int area, unsigned int shape, unsigned int segment, const tgPolygon& sp )
|
||||
inline const tgTexParams& get_texparams( unsigned int area, unsigned int poly )
|
||||
{
|
||||
shapes[area][shape].polys[segment] = sp;
|
||||
return polys[area][poly].GetTexParams();
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline TGPolygon get_tris( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].get_tris();
|
||||
}
|
||||
inline void set_tris( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon tris )
|
||||
{
|
||||
shapes[area][shape].sps[segment].set_tris( tris );
|
||||
}
|
||||
#endif
|
||||
|
||||
inline Point3D get_face_normal( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
|
||||
{
|
||||
return Point3D::fromSGVec3( shapes[area][shape].polys[segment].GetTriFaceNormal( tri ) );
|
||||
}
|
||||
|
||||
inline double get_face_area( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
|
||||
{
|
||||
return shapes[area][shape].polys[segment].GetTriFaceArea( tri );
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline std::string get_flag( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].get_flag();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline std::string get_material( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].polys[segment].GetMaterial();
|
||||
}
|
||||
inline const tgTexParams& get_texparams( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].polys[segment].GetTexParams();
|
||||
}
|
||||
|
||||
/*
|
||||
inline TGPolygon get_texcoords( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].get_texcoords();
|
||||
}
|
||||
inline void set_texcoords( unsigned int area, unsigned int shape, unsigned int segment, TGPolygon tcs )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].set_texcoords( tcs );
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
inline TGPolyNodes get_tri_idxs( unsigned int area, unsigned int shape, unsigned int segment )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].get_tri_idxs();
|
||||
}
|
||||
inline void set_tri_idxs( unsigned int area, unsigned int shape, unsigned int segment, TGPolyNodes tis )
|
||||
{
|
||||
return shapes[area][shape].sps[segment].set_tri_idxs( tis );
|
||||
}
|
||||
*/
|
||||
|
||||
void SaveToGzFile( gzFile& fp );
|
||||
void LoadFromGzFile( gzFile& fp );
|
||||
|
||||
|
@ -155,7 +98,7 @@ public:
|
|||
friend std::ostream& operator<< ( std::ostream&, const TGLandclass& );
|
||||
|
||||
private:
|
||||
shape_list shapes[TG_MAX_AREA_TYPES];
|
||||
tgpolygon_list polys[TG_MAX_AREA_TYPES];
|
||||
};
|
||||
|
||||
#endif // _TGLANDCLASS_HXX
|
||||
|
|
|
@ -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 <CGAL/Plane_3.h>
|
||||
|
||||
#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;
|
||||
|
||||
#define USE_SPACIAL_QUERY
|
||||
|
||||
#ifndef USE_SPACIAL_QUERY
|
||||
|
||||
void TGNodes::init_spacial_query( void )
|
||||
{
|
||||
kd_tree_valid = true;
|
||||
}
|
||||
|
||||
static bool IsWithin( const SGGeod pt, double xmin, double xmax, double ymin, double ymax )
|
||||
{
|
||||
return ( (xmin <= pt.getLongitudeDeg()) && (ymin <= pt.getLatitudeDeg()) &&
|
||||
|
@ -157,41 +28,32 @@ static bool IsAlmostWithin( const SGGeod pt, const SGGeod& min, const SGGeod& ma
|
|||
max.getLatitudeDeg() + fgPoint3_Epsilon ) );
|
||||
}
|
||||
|
||||
void TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& points ) const {
|
||||
const_node_list_iterator current, last;
|
||||
|
||||
// see if point already exists
|
||||
current = tg_node_list.begin();
|
||||
last = tg_node_list.end();
|
||||
|
||||
bool TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<SGGeod>& points ) const {
|
||||
points.clear();
|
||||
for ( ; current != last; ++current ) {
|
||||
SGGeod pt = (*current).GetPosition();
|
||||
for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
|
||||
SGGeod const& pt = tg_node_list[i].GetPosition();
|
||||
|
||||
if ( IsAlmostWithin( pt, min, max ) ) {
|
||||
points.push_back( pt );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TGNodes::get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west ) const {
|
||||
const_node_list_iterator current, last;
|
||||
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();
|
||||
|
||||
// find all points on the edges
|
||||
current = tg_node_list.begin();
|
||||
last = tg_node_list.end();
|
||||
|
||||
north.clear();
|
||||
south.clear();
|
||||
east.clear();
|
||||
west.clear();
|
||||
|
||||
for ( ; current != last; ++current ) {
|
||||
SGGeod pt = (*current).GetPosition();
|
||||
for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
|
||||
SGGeod const& pt = tg_node_list[i].GetPosition();
|
||||
|
||||
// may save the same point twice - so we get all the corners
|
||||
if ( fabs(pt.getLatitudeDeg() - north_compare) < SG_EPSILON) {
|
||||
|
@ -207,36 +69,171 @@ void TGNodes::get_geod_edge( const SGBucket& b, std::vector<SGGeod>& north, std:
|
|||
west.push_back( pt );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// The spacial search utilizes the boost tuple construct.
|
||||
// The k-d tree is generated in two dimensions. and the first element of the tuple is this 2d point
|
||||
// the second element of the tuple is the elevation of this point
|
||||
// Three dimensional queries is a bit overkill, but the code, although faster, is slightly more cumbersome
|
||||
|
||||
// get function for the property map - needed for cgal trait extension
|
||||
My_point_property_map::reference get(My_point_property_map, My_point_property_map::key_type p) {
|
||||
return boost::get<0>(p);
|
||||
}
|
||||
|
||||
// Build the k-d tree
|
||||
void TGNodes::init_spacial_query( void )
|
||||
{
|
||||
tg_kd_tree.clear();
|
||||
|
||||
for(unsigned int i = 0; i < tg_node_list.size(); i++) {
|
||||
// generate the tuple
|
||||
Point pt( tg_node_list[i].GetPosition().getLongitudeDeg(), tg_node_list[i].GetPosition().getLatitudeDeg() );
|
||||
double e( tg_node_list[i].GetPosition().getElevationM() );
|
||||
Point_and_Elevation pande(pt, e);
|
||||
|
||||
// and insert into tree
|
||||
tg_kd_tree.insert( pande );
|
||||
}
|
||||
|
||||
kd_tree_valid = true;
|
||||
}
|
||||
|
||||
// Spacial Queries using CGAL and boost tuple
|
||||
|
||||
// This query finds all nodes within the bounding box
|
||||
bool TGNodes::get_geod_inside( const SGGeod& min, const SGGeod& max, std::vector<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 {
|
||||
const_node_list_iterator current, last;
|
||||
|
||||
current = tg_node_list.begin();
|
||||
last = tg_node_list.end();
|
||||
|
||||
points.clear();
|
||||
for ( ; current != last; ++current ) {
|
||||
points.push_back( (*current).GetWgs84() );
|
||||
for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
|
||||
points.push_back( tg_node_list[i].GetWgs84() );
|
||||
}
|
||||
}
|
||||
|
||||
void TGNodes::get_normals( std::vector<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();
|
||||
for ( ; current != last; ++current ) {
|
||||
normals.push_back( (*current).GetNormal() );
|
||||
for ( unsigned int i = 0; i < tg_node_list.size(); i++ ) {
|
||||
normals.push_back( tg_node_list[i].GetNormal() );
|
||||
}
|
||||
}
|
||||
|
||||
void TGNodes::Dump( void ) {
|
||||
for (unsigned int i=0; i<tg_node_list.size(); i++) {
|
||||
TGNode node = tg_node_list[ i ];
|
||||
TGNode const& node = tg_node_list[ i ];
|
||||
std::string fixed;
|
||||
|
||||
if ( node.GetFixedPosition() ) {
|
||||
|
@ -249,125 +246,18 @@ void TGNodes::Dump( void ) {
|
|||
if ( node.GetFaces().size() ) {
|
||||
TGFaceList faces = node.GetFaces();
|
||||
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;
|
||||
|
||||
// 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 )
|
||||
{
|
||||
int i, nCount;
|
||||
|
||||
// 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;
|
||||
tg_node_list.SaveToGzFile( fp );
|
||||
}
|
||||
|
||||
void TGNode::SaveToGzFile(gzFile& fp)
|
||||
void TGNodes::LoadFromGzFile( 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 );
|
||||
}
|
||||
tg_node_list.LoadFromGzFile( fp );
|
||||
}
|
|
@ -10,176 +10,110 @@
|
|||
#endif
|
||||
|
||||
#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/bucket/newbucket.hxx>
|
||||
//#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/io/lowlevel.hxx>
|
||||
|
||||
#include <Polygon/tg_unique_tgnode.hxx>
|
||||
|
||||
#define FG_PROXIMITY_EPSILON 0.000001
|
||||
#define FG_COURSE_EPSILON 0.0001
|
||||
|
||||
// for each node, we'll need a vector to lookup all triangles the node
|
||||
// is a member of.
|
||||
struct TGFaceLookup {
|
||||
unsigned int area;
|
||||
unsigned int shape;
|
||||
unsigned int seg;
|
||||
unsigned int tri;
|
||||
};
|
||||
typedef std::vector < TGFaceLookup > TGFaceList;
|
||||
|
||||
|
||||
class TGNode {
|
||||
public:
|
||||
TGNode() {
|
||||
// constructor for serialization only
|
||||
}
|
||||
|
||||
TGNode( SGGeod p ) {
|
||||
position = p;
|
||||
CalcWgs84();
|
||||
|
||||
fixed_position = false; // no matter what - don't move x, y, or z (likely a hole around an airport generated ny genapts)
|
||||
fixed_normal = false; // no matter what - don't modify the normal - likely on a normal generated on a shared edge
|
||||
|
||||
faces.clear();
|
||||
}
|
||||
|
||||
inline void SetFixedPosition( bool fix )
|
||||
{
|
||||
if (!fixed_position) {
|
||||
fixed_position = fix;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CalcWgs84()
|
||||
{
|
||||
wgs84 = SGVec3d::fromGeod(position);
|
||||
}
|
||||
|
||||
inline void AddFace( unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
|
||||
{
|
||||
TGFaceLookup face;
|
||||
face.area = area;
|
||||
face.shape = shape;
|
||||
face.seg = segment;
|
||||
face.tri = tri;
|
||||
|
||||
faces.push_back( face );
|
||||
}
|
||||
|
||||
inline TGFaceList GetFaces( void ) const { return faces; }
|
||||
inline bool GetFixedPosition( void ) const { return fixed_position; }
|
||||
inline void SetFixedNormal( bool fix ) { fixed_normal = fix; }
|
||||
inline bool GetFixedNormal( void ) const { return fixed_normal; }
|
||||
inline SGVec3d GetWgs84( void ) const { return wgs84; }
|
||||
|
||||
inline void SetPosition( const SGGeod& p )
|
||||
{
|
||||
if (!fixed_position) {
|
||||
position = p;
|
||||
CalcWgs84();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetElevation( double z )
|
||||
{
|
||||
if (!fixed_position) {
|
||||
position.setElevationM( z );
|
||||
CalcWgs84();
|
||||
}
|
||||
}
|
||||
|
||||
inline SGGeod GetPosition( void ) const { return position; }
|
||||
inline void SetNormal( const SGVec3f& n ) { normal = n; }
|
||||
inline SGVec3f GetNormal( void ) const { return normal; }
|
||||
|
||||
void SaveToGzFile( gzFile& fp );
|
||||
void LoadFromGzFile( gzFile& fp );
|
||||
// Friends for serialization
|
||||
friend std::ostream& operator<< ( std::ostream&, const TGNode& );
|
||||
|
||||
private:
|
||||
SGGeod position;
|
||||
SGVec3f normal;
|
||||
SGVec3d wgs84;
|
||||
|
||||
bool fixed_position;
|
||||
bool fixed_normal;
|
||||
|
||||
TGFaceList faces;
|
||||
};
|
||||
typedef std::vector < TGNode > node_list;
|
||||
typedef node_list::iterator node_list_iterator;
|
||||
typedef node_list::const_iterator const_node_list_iterator;
|
||||
|
||||
/* This class handles ALL of the nodes in a tile : 3d nodes in elevation data, 2d nodes generated from landclass, etc) */
|
||||
class TGNodes {
|
||||
public:
|
||||
|
||||
// Constructor and destructor
|
||||
TGNodes( void ) {
|
||||
sorted = false;
|
||||
TGNodes( void ) {
|
||||
kd_tree_valid = false;
|
||||
}
|
||||
|
||||
~TGNodes( void ) {}
|
||||
|
||||
// delete all the data out of node_list
|
||||
inline void clear() {
|
||||
tg_node_list.clear();
|
||||
sorted = false;
|
||||
kd_tree_valid = false;
|
||||
}
|
||||
|
||||
// Add a point to the point list if it doesn't already exist.
|
||||
// Returns the index (starting at zero) of the point in the list.
|
||||
void unique_add( const SGGeod& p ) {
|
||||
if ( !sorted ) {
|
||||
linear_unique_add( p );
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!");
|
||||
exit(0);
|
||||
}
|
||||
TGNode n(p);
|
||||
n.SetFixedPosition(false);
|
||||
tg_node_list.add(n);
|
||||
kd_tree_valid = false;
|
||||
}
|
||||
|
||||
void unique_add( const TGNode& n ) {
|
||||
tg_node_list.add(n);
|
||||
kd_tree_valid = false;
|
||||
}
|
||||
|
||||
// Add a point to the point list if it doesn't already exist
|
||||
// (checking all three dimensions.) Returns the index (starting
|
||||
// at zero) of the point in the list.
|
||||
void unique_add_fixed_elevation( const SGGeod& p ) {
|
||||
if ( !sorted ) {
|
||||
linear_unique_add_fixed_elevation( p );
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "ADDING NODE AFTER SORT!");
|
||||
exit(0);
|
||||
}
|
||||
TGNode n(p);
|
||||
n.SetFixedPosition(true);
|
||||
tg_node_list.add(n);
|
||||
kd_tree_valid = false;
|
||||
}
|
||||
|
||||
// Find the index of the specified point (compair to the same
|
||||
// tolerance as unique_add(). Returns -1 if not found.
|
||||
int find( const SGGeod& p ) const {
|
||||
if ( sorted ) {
|
||||
return sorted_find( p );
|
||||
} else {
|
||||
return linear_find( p );
|
||||
}
|
||||
TGNode n(p);
|
||||
return tg_node_list.find(n);
|
||||
}
|
||||
|
||||
void SortNodes( void );
|
||||
void init_spacial_query( void );
|
||||
|
||||
void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); }
|
||||
|
||||
SGVec3f GetNormal( int idx ) const { return tg_node_list[idx].GetNormal(); }
|
||||
void SetNormal( int idx, SGVec3f n ) { tg_node_list[idx].SetNormal( n ); }
|
||||
|
||||
// return the master node list
|
||||
inline node_list& get_node_list() { return tg_node_list; }
|
||||
inline const node_list& get_node_list() const { return tg_node_list; }
|
||||
|
||||
// return a point list of geodetic nodes
|
||||
void get_geod_nodes( std::vector<SGGeod>& points ) const;
|
||||
|
||||
// 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
|
||||
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
|
||||
void get_wgs84_nodes( std::vector<SGVec3d>& points ) const;
|
||||
|
@ -187,32 +121,32 @@ public:
|
|||
// return a point list of normals
|
||||
void get_normals( std::vector<SGVec3f>& normals ) const;
|
||||
|
||||
// return the ith point
|
||||
inline TGNode get_node( int i ) const { return tg_node_list[i]; }
|
||||
// return the ith point (constant)
|
||||
inline TGNode const& get_node( int i ) const { return tg_node_list[i]; }
|
||||
inline TGNode& get_node( int i ) { return tg_node_list[i]; }
|
||||
|
||||
inline void AddFace( int i, unsigned int area, unsigned int shape, unsigned int segment, unsigned int tri )
|
||||
TGNode const& operator[]( int index ) const {
|
||||
return tg_node_list[index];
|
||||
}
|
||||
|
||||
|
||||
inline void AddFace( int i, unsigned int area, unsigned int poly, unsigned int tri )
|
||||
{
|
||||
tg_node_list[i].AddFace( area, shape, segment, tri );
|
||||
tg_node_list[i].AddFace( area, poly, tri );
|
||||
}
|
||||
|
||||
// return the size of the node list
|
||||
inline size_t size() const { return tg_node_list.size(); }
|
||||
|
||||
void Dump( void );
|
||||
|
||||
void SaveToGzFile( gzFile& fp );
|
||||
void LoadFromGzFile( gzFile& fp );
|
||||
|
||||
// Friends for serialization
|
||||
friend std::ostream& operator<< ( std::ostream&, const TGNodes& );
|
||||
|
||||
|
||||
private:
|
||||
void linear_unique_add( const SGGeod& p );
|
||||
void linear_unique_add_fixed_elevation( const SGGeod& p );
|
||||
|
||||
int sorted_find( const SGGeod& p ) const;
|
||||
int linear_find( const SGGeod& p ) const;
|
||||
node_list tg_node_list;
|
||||
bool sorted;
|
||||
UniqueTGNodeSet tg_node_list;
|
||||
Tree tg_kd_tree;
|
||||
bool kd_tree_valid;
|
||||
|
||||
// return true of the two points are "close enough" as defined by
|
||||
// FG_PROXIMITY_EPSILON
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <Geometry/trinodes.hxx>
|
||||
|
||||
#include "polygon.hxx"
|
||||
#include "tg_unique_geod.hxx"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define LONG_LONG_MAX LLONG_MAX
|
||||
|
@ -2235,6 +2234,9 @@ tgPolygon tgPolygon::Expand( const tgPolygon& subject, double offset )
|
|||
result.SetMaterial( subject.GetMaterial() );
|
||||
result.SetTexParams( subject.GetTexParams() );
|
||||
|
||||
result.SetMaterial( subject.GetMaterial() );
|
||||
result.SetTexParams( subject.GetTexParams() );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2280,6 +2282,9 @@ tgPolygon tgPolygon::Union( const tgPolygon& subject, tgPolygon& clip )
|
|||
result = tgPolygon::FromClipper( clipper_result );
|
||||
result = tgPolygon::AddColinearNodes( result, all_nodes );
|
||||
|
||||
result.SetMaterial( subject.GetMaterial() );
|
||||
result.SetTexParams( subject.GetTexParams() );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2337,6 +2342,9 @@ tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip )
|
|||
result = tgPolygon::FromClipper( clipper_result );
|
||||
result = tgPolygon::AddColinearNodes( result, all_nodes );
|
||||
|
||||
result.SetMaterial( subject.GetMaterial() );
|
||||
result.SetTexParams( subject.GetTexParams() );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2794,21 +2802,15 @@ void tgPolygon::LoadFromGzFile( gzFile& fp )
|
|||
|
||||
// load the triangles
|
||||
sgReadUInt( fp, &count );
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " load " << count << " triangles" );
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
triangle.LoadFromGzFile( fp );
|
||||
AddTriangle(triangle);
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " load texparams" );
|
||||
|
||||
// Load the tex params
|
||||
tp.LoadFromGzFile( fp );
|
||||
|
||||
// and the rest
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " load material" );
|
||||
|
||||
sgReadString( fp, &strbuff );
|
||||
if ( strbuff ) {
|
||||
material = strbuff;
|
||||
|
@ -3486,28 +3488,19 @@ void tgAccumulator::Add( const tgPolygon& subject )
|
|||
accum.push_back( clipper_subject );
|
||||
}
|
||||
|
||||
std::vector<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 )
|
||||
{
|
||||
// Save the three nodes, and their attributes
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
sgWriteGeod( fp, node_list[i] );
|
||||
sgWriteVec2( fp, tc_list[i] );
|
||||
sgWritedVec3( fp, norm_list[i] );
|
||||
// sgWriteVec2( fp, tc_list[i] );
|
||||
// sgWritedVec3( fp, norm_list[i] ); // not calculated until stage 3
|
||||
sgWriteInt( fp, idx_list[i] );
|
||||
}
|
||||
|
||||
// and the area, and face normal
|
||||
sgWriteVec3( fp, face_normal );
|
||||
sgWriteDouble( fp, face_area );
|
||||
// sgWriteVec3( fp, face_normal ); // not calculated until stage3
|
||||
// sgWriteDouble( fp, face_area ); // not calculated until stage3
|
||||
}
|
||||
|
||||
void tgTriangle::LoadFromGzFile( gzFile& fp )
|
||||
|
@ -3515,57 +3508,76 @@ void tgTriangle::LoadFromGzFile( gzFile& fp )
|
|||
// Load the nodelist
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
sgReadGeod( fp, node_list[i] );
|
||||
sgReadVec2( fp, tc_list[i] );
|
||||
sgReaddVec3( fp, norm_list[i] );
|
||||
// sgReadVec2( fp, tc_list[i] );
|
||||
// sgReaddVec3( fp, norm_list[i] );
|
||||
sgReadInt( fp, &idx_list[i] );
|
||||
}
|
||||
|
||||
// and the area, and face normal
|
||||
sgReadVec3( fp, face_normal );
|
||||
sgReadDouble( fp, &face_area );
|
||||
// sgReadVec3( fp, face_normal );
|
||||
// sgReadDouble( fp, &face_area );
|
||||
}
|
||||
|
||||
void tgTexParams::SaveToGzFile( gzFile& fp )
|
||||
{
|
||||
// Save the parameters
|
||||
sgWriteGeod( fp, ref );
|
||||
|
||||
sgWriteDouble( fp, width );
|
||||
sgWriteDouble( fp, length );
|
||||
sgWriteDouble( fp, heading );
|
||||
|
||||
sgWriteDouble( fp, minu );
|
||||
sgWriteDouble( fp, maxu );
|
||||
sgWriteDouble( fp, minv );
|
||||
sgWriteDouble( fp, maxv );
|
||||
|
||||
sgWriteDouble( fp, min_clipu );
|
||||
sgWriteDouble( fp, max_clipu );
|
||||
sgWriteDouble( fp, min_clipv );
|
||||
sgWriteDouble( fp, max_clipv );
|
||||
|
||||
sgWriteInt( fp, (int)method );
|
||||
|
||||
if ( method == TG_TEX_BY_GEODE ) {
|
||||
sgWriteDouble( fp, center_lat );
|
||||
} else {
|
||||
sgWriteGeod( fp, ref );
|
||||
sgWriteDouble( fp, width );
|
||||
sgWriteDouble( fp, length );
|
||||
sgWriteDouble( fp, heading );
|
||||
|
||||
sgWriteDouble( fp, minu );
|
||||
sgWriteDouble( fp, maxu );
|
||||
sgWriteDouble( fp, minv );
|
||||
sgWriteDouble( fp, maxv );
|
||||
|
||||
if ( (method == TG_TEX_BY_TPS_CLIPU) ||
|
||||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
sgWriteDouble( fp, min_clipu );
|
||||
sgWriteDouble( fp, max_clipu );
|
||||
}
|
||||
|
||||
if ( (method == TG_TEX_BY_TPS_CLIPV) ||
|
||||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
sgWriteDouble( fp, min_clipv );
|
||||
sgWriteDouble( fp, max_clipv );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tgTexParams::LoadFromGzFile( gzFile& fp )
|
||||
{
|
||||
// Load the parameters
|
||||
sgReadGeod( fp, ref );
|
||||
|
||||
sgReadDouble( fp, &width );
|
||||
sgReadDouble( fp, &length );
|
||||
sgReadDouble( fp, &heading );
|
||||
|
||||
sgReadDouble( fp, &minu );
|
||||
sgReadDouble( fp, &maxu );
|
||||
sgReadDouble( fp, &minv );
|
||||
sgReadDouble( fp, &maxv );
|
||||
|
||||
sgReadDouble( fp, &min_clipu );
|
||||
sgReadDouble( fp, &max_clipu );
|
||||
sgReadDouble( fp, &min_clipv );
|
||||
sgReadDouble( fp, &max_clipv );
|
||||
|
||||
sgReadInt( fp, (int*)&method );
|
||||
}
|
||||
|
||||
if ( method == TG_TEX_BY_GEODE ) {
|
||||
sgReadDouble( fp, ¢er_lat );
|
||||
} else {
|
||||
sgReadGeod( fp, ref );
|
||||
sgReadDouble( fp, &width );
|
||||
sgReadDouble( fp, &length );
|
||||
sgReadDouble( fp, &heading );
|
||||
|
||||
sgReadDouble( fp, &minu );
|
||||
sgReadDouble( fp, &maxu );
|
||||
sgReadDouble( fp, &minv );
|
||||
sgReadDouble( fp, &maxv );
|
||||
|
||||
if ( (method == TG_TEX_BY_TPS_CLIPU) ||
|
||||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
sgReadDouble( fp, &min_clipu );
|
||||
sgReadDouble( fp, &max_clipu );
|
||||
}
|
||||
|
||||
if ( (method == TG_TEX_BY_TPS_CLIPV) ||
|
||||
(method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
sgReadDouble( fp, &min_clipv );
|
||||
sgReadDouble( fp, &max_clipv );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -314,6 +314,9 @@ std::ostream &operator<<(std::ostream &output, const TGPolygon &poly);
|
|||
#include <Geometry/trinodes.hxx>
|
||||
#include <Geometry/rectangle.hxx>
|
||||
|
||||
#include "tg_unique_geod.hxx"
|
||||
|
||||
|
||||
// forward declaration
|
||||
class tgPolygon;
|
||||
|
||||
|
@ -352,6 +355,10 @@ public:
|
|||
SGGeod GetNode( unsigned int i ) const {
|
||||
return node_list[i];
|
||||
}
|
||||
SGGeod const& operator[]( int index ) const {
|
||||
return node_list[index];
|
||||
}
|
||||
|
||||
void RemoveNodeAt( unsigned int idx ) {
|
||||
if ( idx < node_list.size() ) {
|
||||
node_list.erase( node_list.begin() + idx );
|
||||
|
@ -423,7 +430,7 @@ public:
|
|||
idx_list.resize( 3, -1 );
|
||||
}
|
||||
|
||||
SGGeod GetNode( unsigned int i ) const {
|
||||
SGGeod const& GetNode( unsigned int i ) const {
|
||||
return node_list[i];
|
||||
}
|
||||
std::vector<SGGeod>& GetNodeList( void ) {
|
||||
|
@ -449,7 +456,7 @@ public:
|
|||
void SetFaceNormal( const SGVec3f& n ) {
|
||||
face_normal = n;
|
||||
};
|
||||
SGVec3f GetFaceNormal( void ) const {
|
||||
SGVec3f const& GetFaceNormal( void ) const {
|
||||
return face_normal;
|
||||
}
|
||||
|
||||
|
@ -527,7 +534,6 @@ typedef void (*tgpolygon_texfunc)(void);
|
|||
class tgPolygon
|
||||
{
|
||||
public:
|
||||
|
||||
void Erase( void ) {
|
||||
contours.clear();
|
||||
triangles.clear();
|
||||
|
@ -539,7 +545,7 @@ public:
|
|||
unsigned int ContourSize( unsigned int c ) const {
|
||||
return contours[c].GetSize();
|
||||
}
|
||||
void AddContour( tgContour contour ) {
|
||||
void AddContour( tgContour const& contour ) {
|
||||
contours.push_back(contour);
|
||||
}
|
||||
tgContour GetContour( unsigned int c ) const {
|
||||
|
@ -551,10 +557,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int TotalNodes( void ) const;
|
||||
SGGeod GetNode( unsigned int c, unsigned int i ) const {
|
||||
return contours[c].GetNode( i );
|
||||
|
||||
SGGeod const& GetNode( unsigned int c, unsigned int i ) const {
|
||||
return contours[c][i];
|
||||
}
|
||||
void SetNode( unsigned int c, unsigned int i, const SGGeod& n ) {
|
||||
contours[c].SetNode( i, n );
|
||||
|
@ -600,7 +606,7 @@ public:
|
|||
void SetTriFaceNormal( unsigned int c, const SGVec3f& n ) {
|
||||
triangles[c].SetFaceNormal( n );
|
||||
}
|
||||
SGVec3f GetTriFaceNormal( unsigned int c ) const {
|
||||
SGVec3f const& GetTriFaceNormal( unsigned int c ) const {
|
||||
return triangles[c].GetFaceNormal();
|
||||
}
|
||||
void SetTriFaceArea( unsigned int c, double a ) {
|
||||
|
@ -610,12 +616,20 @@ public:
|
|||
return triangles[c].GetFaceArea();
|
||||
}
|
||||
|
||||
std::string GetMaterial( void ) const {
|
||||
std::string const& GetMaterial( void ) const {
|
||||
return material;
|
||||
}
|
||||
void SetMaterial( const std::string m ) {
|
||||
void SetMaterial( const std::string& m ) {
|
||||
material = m;
|
||||
}
|
||||
|
||||
unsigned int GetId( void ) const {
|
||||
return id;
|
||||
}
|
||||
void SetId( unsigned int i ) {
|
||||
id = i;
|
||||
}
|
||||
|
||||
void SetTexParams( const SGGeod& ref, double width, double length, double heading ) {
|
||||
tp.ref = ref;
|
||||
tp.width = width;
|
||||
|
@ -650,7 +664,6 @@ public:
|
|||
tp.center_lat = cl;
|
||||
}
|
||||
|
||||
|
||||
void Tesselate( void );
|
||||
void Tesselate( const std::vector<SGGeod>& extra );
|
||||
|
||||
|
@ -708,9 +721,10 @@ private:
|
|||
tgcontour_list contours;
|
||||
tgtriangle_list triangles;
|
||||
|
||||
std::string material;
|
||||
std::string flag; // let's get rid of this....
|
||||
tgTexParams tp;
|
||||
std::string material;
|
||||
std::string flag; // let's get rid of this....
|
||||
unsigned int id; // unique polygon id for debug
|
||||
tgTexParams tp;
|
||||
};
|
||||
|
||||
class tgLight
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#ifndef _TG_UNIQUE_SGGEOD_HXX
|
||||
#define _TG_UNIQUE_SGGEOD_HXX
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
|
||||
|
@ -117,6 +120,18 @@ public:
|
|||
return index;
|
||||
}
|
||||
|
||||
SGGeod const& operator[]( int index ) const {
|
||||
return geod_list[index];
|
||||
}
|
||||
|
||||
SGGeod& operator[]( int index ) {
|
||||
return geod_list[index];
|
||||
}
|
||||
|
||||
size_t size( void ) const {
|
||||
return geod_list.size();
|
||||
}
|
||||
|
||||
std::vector<SGGeod>& get_list( void ) { return geod_list; }
|
||||
void get_node_list();
|
||||
|
||||
|
@ -124,3 +139,5 @@ private:
|
|||
unique_geod_set index_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