tgconstruct edge matching with existing terrain
This commit is contained in:
parent
c7c8c0be82
commit
47db776404
11 changed files with 436 additions and 33 deletions
|
@ -47,6 +47,7 @@ static void usage( const string name ) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "[ --output-dir=<directory>");
|
SG_LOG(SG_GENERAL, SG_ALERT, "[ --output-dir=<directory>");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " --work-dir=<directory>");
|
SG_LOG(SG_GENERAL, SG_ALERT, " --work-dir=<directory>");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " --share-dir=<directory>");
|
SG_LOG(SG_GENERAL, SG_ALERT, " --share-dir=<directory>");
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, " --match-dir=<directory>");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " --cover=<path to land-cover raster>");
|
SG_LOG(SG_GENERAL, SG_ALERT, " --cover=<path to land-cover raster>");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " --tile-id=<id>");
|
SG_LOG(SG_GENERAL, SG_ALERT, " --tile-id=<id>");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " --min-lon=<degrees>");
|
SG_LOG(SG_GENERAL, SG_ALERT, " --min-lon=<degrees>");
|
||||||
|
@ -63,10 +64,23 @@ static void usage( const string name ) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveDuplicateBuckets( std::vector<SGBucket>& keep, std::vector<SGBucket>& remove )
|
||||||
|
{
|
||||||
|
for ( unsigned int i=0; i<remove.size(); i++) {
|
||||||
|
for ( unsigned int j=0; j<keep.size(); j++ ) {
|
||||||
|
if ( remove[i] == keep[j] ) {
|
||||||
|
keep.erase( keep.begin()+j );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
string output_dir = ".";
|
string output_dir = ".";
|
||||||
string work_dir = ".";
|
string work_dir = ".";
|
||||||
string share_dir = "";
|
string share_dir = "";
|
||||||
|
string match_dir = "";
|
||||||
string cover = "";
|
string cover = "";
|
||||||
string priorities_file = DEFAULT_PRIORITIES_FILE;
|
string priorities_file = DEFAULT_PRIORITIES_FILE;
|
||||||
string usgs_map_file = DEFAULT_USGS_MAPFILE;
|
string usgs_map_file = DEFAULT_USGS_MAPFILE;
|
||||||
|
@ -97,6 +111,8 @@ int main(int argc, char **argv) {
|
||||||
work_dir = arg.substr(11);
|
work_dir = arg.substr(11);
|
||||||
} else if (arg.find("--share-dir=") == 0) {
|
} else if (arg.find("--share-dir=") == 0) {
|
||||||
share_dir = arg.substr(12);
|
share_dir = arg.substr(12);
|
||||||
|
} else if (arg.find("--match-dir=") == 0) {
|
||||||
|
match_dir = arg.substr(12);
|
||||||
} else if (arg.find("--tile-id=") == 0) {
|
} else if (arg.find("--tile-id=") == 0) {
|
||||||
tile_id = atol(arg.substr(10).c_str());
|
tile_id = atol(arg.substr(10).c_str());
|
||||||
} else if ( arg.find("--min-lon=") == 0 ) {
|
} else if ( arg.find("--min-lon=") == 0 ) {
|
||||||
|
@ -142,6 +158,8 @@ int main(int argc, char **argv) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Output directory is " << output_dir);
|
SG_LOG(SG_GENERAL, SG_ALERT, "Output directory is " << output_dir);
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Working directory is " << work_dir);
|
SG_LOG(SG_GENERAL, SG_ALERT, "Working directory is " << work_dir);
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Shared directory is " << share_dir);
|
SG_LOG(SG_GENERAL, SG_ALERT, "Shared directory is " << share_dir);
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Match directory is " << match_dir);
|
||||||
|
|
||||||
if ( tile_id > 0 ) {
|
if ( tile_id > 0 ) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Tile id is " << tile_id);
|
SG_LOG(SG_GENERAL, SG_ALERT, "Tile id is " << tile_id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,10 +185,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tile work queue
|
// tile work queue
|
||||||
|
std::vector<SGBucket> matchList;
|
||||||
std::vector<SGBucket> bucketList;
|
std::vector<SGBucket> bucketList;
|
||||||
SGLockedQueue<SGBucket> wq;
|
SGLockedQueue<SGBucket> wq;
|
||||||
|
SGMutex filelock;
|
||||||
|
|
||||||
// First generate the workqueue of buckets to construct
|
// First, check if we want to match existing scenery -
|
||||||
|
// if we do, generate a list of buckets outside of the bounding box
|
||||||
if (tile_id == -1) {
|
if (tile_id == -1) {
|
||||||
// build all the tiles in an area
|
// build all the tiles in an area
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Building tile(s) within given bounding box");
|
SG_LOG(SG_GENERAL, SG_ALERT, "Building tile(s) within given bounding box");
|
||||||
|
@ -184,14 +205,37 @@ int main(int argc, char **argv) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
|
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
|
||||||
sgGetBuckets( min, max, bucketList );
|
sgGetBuckets( min, max, bucketList );
|
||||||
}
|
}
|
||||||
|
if ( match_dir != "" ) {
|
||||||
|
b_min = b_min.sibling(-1,-1);
|
||||||
|
b_max = b_max.sibling(1,1);
|
||||||
|
|
||||||
|
sgGetBuckets( b_min.get_center(), b_max.get_center(), matchList );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// construct the specified tile
|
// construct the specified tile
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Building tile " << tile_id);
|
SG_LOG(SG_GENERAL, SG_ALERT, "Building tile " << tile_id);
|
||||||
bucketList.push_back( SGBucket( tile_id ) );
|
bucketList.push_back( SGBucket( tile_id ) );
|
||||||
|
if ( match_dir != "" ) {
|
||||||
|
SGBucket b_min( SGBucket(tile_id).sibling(-1,-1) );
|
||||||
|
SGBucket b_max( SGBucket(tile_id).sibling( 1, 1) );
|
||||||
|
sgGetBuckets( b_min.get_center(), b_max.get_center(), matchList );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( match_dir != "" ) {
|
||||||
|
RemoveDuplicateBuckets( matchList, bucketList );
|
||||||
|
|
||||||
|
// generate the immuatble shared files - when tile matching, we must not
|
||||||
|
// modify shared edges from an immutable file - new tile will collapse
|
||||||
|
// triangles as appropriate.
|
||||||
|
TGConstruct* construct = new TGConstruct( areas, 1, wq, &filelock );
|
||||||
|
//construct->set_cover( cover );
|
||||||
|
construct->set_paths( work_dir, share_dir, match_dir, output_dir, load_dirs );
|
||||||
|
construct->CreateMatchedEdgeFiles( matchList );
|
||||||
|
delete construct;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TGConstruct *> constructs;
|
std::vector<TGConstruct *> constructs;
|
||||||
SGMutex filelock;
|
|
||||||
|
|
||||||
/* fill the workqueue */
|
/* fill the workqueue */
|
||||||
for (unsigned int i=0; i<bucketList.size(); i++) {
|
for (unsigned int i=0; i<bucketList.size(); i++) {
|
||||||
|
@ -202,7 +246,7 @@ int main(int argc, char **argv) {
|
||||||
for (int i=0; i<num_threads; i++) {
|
for (int i=0; i<num_threads; i++) {
|
||||||
TGConstruct* construct = new TGConstruct( areas, 1, wq, &filelock );
|
TGConstruct* construct = new TGConstruct( areas, 1, wq, &filelock );
|
||||||
//construct->set_cover( cover );
|
//construct->set_cover( cover );
|
||||||
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
|
construct->set_paths( work_dir, share_dir, match_dir, output_dir, load_dirs );
|
||||||
construct->set_options( ignoreLandmass, nudge );
|
construct->set_options( ignoreLandmass, nudge );
|
||||||
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||||
constructs.push_back( construct );
|
constructs.push_back( construct );
|
||||||
|
@ -235,7 +279,7 @@ int main(int argc, char **argv) {
|
||||||
for (int i=0; i<num_threads; i++) {
|
for (int i=0; i<num_threads; i++) {
|
||||||
TGConstruct* construct = new TGConstruct( areas, 2, wq, &filelock );
|
TGConstruct* construct = new TGConstruct( areas, 2, wq, &filelock );
|
||||||
//construct->set_cover( cover );
|
//construct->set_cover( cover );
|
||||||
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
|
construct->set_paths( work_dir, share_dir, match_dir, output_dir, load_dirs );
|
||||||
construct->set_options( ignoreLandmass, nudge );
|
construct->set_options( ignoreLandmass, nudge );
|
||||||
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||||
constructs.push_back( construct );
|
constructs.push_back( construct );
|
||||||
|
@ -267,7 +311,7 @@ int main(int argc, char **argv) {
|
||||||
for (int i=0; i<num_threads; i++) {
|
for (int i=0; i<num_threads; i++) {
|
||||||
TGConstruct* construct = new TGConstruct( areas, 3, wq, &filelock );
|
TGConstruct* construct = new TGConstruct( areas, 3, wq, &filelock );
|
||||||
//construct->set_cover( cover );
|
//construct->set_cover( cover );
|
||||||
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
|
construct->set_paths( work_dir, share_dir, match_dir, output_dir, load_dirs );
|
||||||
construct->set_options( ignoreLandmass, nudge );
|
construct->set_options( ignoreLandmass, nudge );
|
||||||
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
construct->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
|
||||||
constructs.push_back( construct );
|
constructs.push_back( construct );
|
||||||
|
|
|
@ -55,9 +55,12 @@ TGConstruct::~TGConstruct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TGConstruct: Setup
|
// TGConstruct: Setup
|
||||||
void TGConstruct::set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load ) {
|
void TGConstruct::set_paths( const std::string work, const std::string share,
|
||||||
|
const std::string match, const std::string output,
|
||||||
|
const std::vector<std::string> load ) {
|
||||||
work_base = work;
|
work_base = work;
|
||||||
share_base = share;
|
share_base = share;
|
||||||
|
match_base = match;
|
||||||
output_base = output;
|
output_base = output;
|
||||||
load_dirs = load;
|
load_dirs = load;
|
||||||
}
|
}
|
||||||
|
@ -93,6 +96,12 @@ void TGConstruct::run()
|
||||||
strcpy( ds_name, "" );
|
strcpy( ds_name, "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( stage == 1 ) {
|
||||||
|
// Matched edge data is generated from a previous scenery build - do this before we
|
||||||
|
// start the current tile - it can mark edges as immutable
|
||||||
|
LoadMatchedEdgeFiles();
|
||||||
|
}
|
||||||
|
|
||||||
if ( stage > 1 ) {
|
if ( stage > 1 ) {
|
||||||
LoadFromIntermediateFiles( stage-1 );
|
LoadFromIntermediateFiles( stage-1 );
|
||||||
LoadSharedEdgeData( stage-1 );
|
LoadSharedEdgeData( stage-1 );
|
||||||
|
|
|
@ -83,7 +83,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
void set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load_dirs );
|
void set_paths( const std::string work, const std::string share, const std::string match,
|
||||||
|
const std::string output, const std::vector<std::string> load_dirs );
|
||||||
void set_options( bool ignore_lm, double n );
|
void set_options( bool ignore_lm, double n );
|
||||||
|
|
||||||
// TODO : REMOVE
|
// TODO : REMOVE
|
||||||
|
@ -98,6 +99,8 @@ public:
|
||||||
// Debug
|
// Debug
|
||||||
void set_debug( std::string path, std::vector<std::string> area_defs, std::vector<std::string> shape_defs );
|
void set_debug( std::string path, std::vector<std::string> area_defs, std::vector<std::string> shape_defs );
|
||||||
|
|
||||||
|
void CreateMatchedEdgeFiles( std::vector<SGBucket>& bucketList );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
|
@ -107,6 +110,10 @@ private:
|
||||||
// Load Data
|
// Load Data
|
||||||
void LoadElevationArray( bool add_nodes );
|
void LoadElevationArray( bool add_nodes );
|
||||||
int LoadLandclassPolys( void );
|
int LoadLandclassPolys( void );
|
||||||
|
bool CheckMatchingNode( SGGeod& node, bool road, bool fixed );
|
||||||
|
|
||||||
|
SGGeod GetNearestNodeLatitude( const SGGeod& node, const std::vector<SGGeod>& selection );
|
||||||
|
SGGeod GetNearestNodeLongitude( const SGGeod& node, const std::vector<SGGeod>& selection );
|
||||||
|
|
||||||
// Clip Data
|
// Clip Data
|
||||||
bool ClipLandclassPolys( void );
|
bool ClipLandclassPolys( void );
|
||||||
|
@ -118,8 +125,11 @@ private:
|
||||||
// Shared edge Matching
|
// Shared edge Matching
|
||||||
void SaveSharedEdgeData( int stage );
|
void SaveSharedEdgeData( int stage );
|
||||||
void LoadSharedEdgeData( int stage );
|
void LoadSharedEdgeData( int stage );
|
||||||
|
void LoadMatchedEdgeFiles();
|
||||||
|
|
||||||
void LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west );
|
void LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west );
|
||||||
|
void LoadNeighboorMatchDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west );
|
||||||
|
|
||||||
void ReadNeighborFaces( gzFile& fp );
|
void ReadNeighborFaces( gzFile& fp );
|
||||||
void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const;
|
void WriteNeighborFaces( gzFile& fp, const SGGeod& pt ) const;
|
||||||
TGNeighborFaces* AddNeighborFaces( const SGGeod& node );
|
TGNeighborFaces* AddNeighborFaces( const SGGeod& node );
|
||||||
|
@ -164,14 +174,16 @@ private:
|
||||||
SGLockedQueue<SGBucket>& workQueue;
|
SGLockedQueue<SGBucket>& workQueue;
|
||||||
unsigned int total_tiles;
|
unsigned int total_tiles;
|
||||||
unsigned int stage;
|
unsigned int stage;
|
||||||
|
std::vector<SGGeod> nm_north, nm_south, nm_east, nm_west;
|
||||||
|
|
||||||
// path to land-cover file (if any)
|
// path to land-cover file (if any)
|
||||||
std::string cover;
|
std::string cover;
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
std::string work_base;
|
std::string work_base;
|
||||||
std::string output_base;
|
|
||||||
std::string share_base;
|
std::string share_base;
|
||||||
|
std::string match_base;
|
||||||
|
std::string output_base;
|
||||||
|
|
||||||
std::vector<std::string> load_dirs;
|
std::vector<std::string> load_dirs;
|
||||||
|
|
||||||
|
|
|
@ -278,6 +278,7 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
|
|
||||||
// Now make sure any newly added intersection nodes are added to the tgnodes
|
// Now make sure any newly added intersection nodes are added to the tgnodes
|
||||||
for (unsigned int area = 0; area < area_defs.size(); area++) {
|
for (unsigned int area = 0; area < area_defs.size(); area++) {
|
||||||
|
bool isRoad = area_defs.is_road_area( area );
|
||||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||||
tgPolygon& poly = polys_clipped.get_poly( area, p );
|
tgPolygon& poly = polys_clipped.get_poly( area, p );
|
||||||
|
|
||||||
|
@ -286,8 +287,12 @@ bool TGConstruct::ClipLandclassPolys( void ) {
|
||||||
for (unsigned int con=0; con < poly.Contours(); con++) {
|
for (unsigned int con=0; con < poly.Contours(); con++) {
|
||||||
for (unsigned int n = 0; n < poly.ContourSize( con ); n++) {
|
for (unsigned int n = 0; n < poly.ContourSize( con ); n++) {
|
||||||
// ensure we have all nodes...
|
// ensure we have all nodes...
|
||||||
TGNode const& node = poly.GetNode( con, n );
|
SGGeod node = poly.GetNode( con, n );
|
||||||
nodes.unique_add( node );
|
if ( CheckMatchingNode( node, isRoad, false ) ) {
|
||||||
|
poly.SetNode( con, n, node );
|
||||||
|
} else {
|
||||||
|
poly.DelNode( con, n );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,10 @@ void TGConstruct::LoadElevationArray( bool add_nodes ) {
|
||||||
|
|
||||||
std::vector<SGGeod> const& fit_list = array.get_fitted_list();
|
std::vector<SGGeod> const& fit_list = array.get_fitted_list();
|
||||||
for (unsigned int i=0; i<fit_list.size(); i++) {
|
for (unsigned int i=0; i<fit_list.size(); i++) {
|
||||||
nodes.unique_add( fit_list[i] );
|
SGGeod node = fit_list[i];
|
||||||
|
if ( CheckMatchingNode( node, false, false ) ) {
|
||||||
|
nodes.unique_add( node );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,23 +84,22 @@ int TGConstruct::LoadLandclassPolys( void ) {
|
||||||
poly.LoadFromGzFile( fp );
|
poly.LoadFromGzFile( fp );
|
||||||
area = area_defs.get_area_priority( poly.GetFlag() );
|
area = area_defs.get_area_priority( poly.GetFlag() );
|
||||||
material = area_defs.get_area_name( area );
|
material = area_defs.get_area_name( area );
|
||||||
|
bool isRoad = area_defs.is_road_area( area );
|
||||||
|
|
||||||
poly.SetMaterial( material );
|
poly.SetMaterial( material );
|
||||||
poly.SetId( cur_poly_id++ );
|
poly.SetId( cur_poly_id++ );
|
||||||
|
|
||||||
if ( poly.Contours() ) {
|
if ( poly.Contours() ) {
|
||||||
polys_in.add_poly( area, poly );
|
|
||||||
total_polys_read++;
|
|
||||||
|
|
||||||
// add the nodes
|
// add the nodes
|
||||||
for (unsigned int j=0; j<poly.Contours(); j++) {
|
for (unsigned int j=0; j<poly.Contours(); j++) {
|
||||||
for (unsigned int k=0; k<poly.ContourSize(j); k++) {
|
for (int k=poly.ContourSize(j)-1; k>= 0; k--) {
|
||||||
SGGeod const& node = poly.GetNode( j, k );
|
SGGeod node = poly.GetNode( j, k );
|
||||||
|
bool isFixed = poly.GetPreserve3D();
|
||||||
|
|
||||||
if ( poly.GetPreserve3D() ) {
|
if ( CheckMatchingNode( node, isRoad, isFixed ) ) {
|
||||||
nodes.unique_add_fixed_elevation( node );
|
poly.SetNode( j, k, node );
|
||||||
} else {
|
} else {
|
||||||
nodes.unique_add( node );
|
poly.DelNode( j, k );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,6 +110,13 @@ int TGConstruct::LoadLandclassPolys( void ) {
|
||||||
|
|
||||||
tgShapefile::FromPolygon( poly, ds_name, layer, material.c_str() );
|
tgShapefile::FromPolygon( poly, ds_name, layer, material.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* make sure we loaded a valid poly */
|
||||||
|
poly = tgPolygon::RemoveBadContours(poly);
|
||||||
|
if ( poly.Contours() ) {
|
||||||
|
polys_in.add_poly( area, poly );
|
||||||
|
total_polys_read++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,3 +130,112 @@ int TGConstruct::LoadLandclassPolys( void ) {
|
||||||
|
|
||||||
return total_polys_read;
|
return total_polys_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TGConstruct::CheckMatchingNode( SGGeod& node, bool road, bool fixed )
|
||||||
|
{
|
||||||
|
bool matched = false;
|
||||||
|
bool added = false;
|
||||||
|
|
||||||
|
if ( fixed ) {
|
||||||
|
node = nodes.unique_add_fixed_elevation( node );
|
||||||
|
added = true;
|
||||||
|
} else {
|
||||||
|
// check mutable edge
|
||||||
|
if ( !nm_north.empty() ) {
|
||||||
|
double north_compare = bucket.get_center_lat() + 0.5 * bucket.get_height();
|
||||||
|
if ( fabs(node.getLatitudeDeg() - north_compare) < SG_EPSILON) {
|
||||||
|
if ( !road ) {
|
||||||
|
// node is on the non_mutable northern border - get closest pt
|
||||||
|
node = GetNearestNodeLongitude( node, nm_north );
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " AddNode: constrained on north border from " << node << " to " << node );
|
||||||
|
added = true;
|
||||||
|
} else {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !added && !matched && !nm_south.empty() ) {
|
||||||
|
double south_compare = bucket.get_center_lat() - 0.5 * bucket.get_height();
|
||||||
|
if ( fabs(node.getLatitudeDeg() - south_compare) < SG_EPSILON) {
|
||||||
|
if ( !road ) {
|
||||||
|
// node is on the non_mutable southern border - get closest pt
|
||||||
|
node = GetNearestNodeLongitude( node, nm_south );
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " AddNode: constrained on south border from " << node << " to " << node );
|
||||||
|
added = true;
|
||||||
|
} else {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !added && !matched && !nm_east.empty() ) {
|
||||||
|
double east_compare = bucket.get_center_lon() + 0.5 * bucket.get_width();
|
||||||
|
if ( fabs(node.getLongitudeDeg() - east_compare) < SG_EPSILON) {
|
||||||
|
if ( !road ) {
|
||||||
|
// node is on the non_mutable eastern border - get closest pt
|
||||||
|
node = GetNearestNodeLatitude( node, nm_east );
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " AddNode: constrained on east border from " << node << " to " << node );
|
||||||
|
added = true;
|
||||||
|
} else {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !added && !matched && !nm_west.empty() ) {
|
||||||
|
double west_compare = bucket.get_center_lon() - 0.5 * bucket.get_width();
|
||||||
|
if ( fabs(node.getLongitudeDeg() - west_compare) < SG_EPSILON) {
|
||||||
|
if ( !road ) {
|
||||||
|
// node is on the non_mutable western border - get closest pt
|
||||||
|
node = GetNearestNodeLatitude( node, nm_west );
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, " AddNode: constrained on west border from " << node << " to " << node );
|
||||||
|
added = true;
|
||||||
|
} else {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!added && !matched) {
|
||||||
|
node = nodes.unique_add( node );
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGGeod TGConstruct::GetNearestNodeLongitude( const SGGeod& node, const std::vector<SGGeod>& selection )
|
||||||
|
{
|
||||||
|
double min_dist = std::numeric_limits<double>::infinity();
|
||||||
|
double cur_dist;
|
||||||
|
unsigned int min_idx = 0;
|
||||||
|
|
||||||
|
for ( unsigned int i=0; i<selection.size(); i++ ) {
|
||||||
|
cur_dist = fabs( node.getLongitudeDeg() - selection[i].getLongitudeDeg() );
|
||||||
|
if ( cur_dist < min_dist ) {
|
||||||
|
min_dist = cur_dist;
|
||||||
|
min_idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selection[min_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
SGGeod TGConstruct::GetNearestNodeLatitude( const SGGeod& node, const std::vector<SGGeod>& selection )
|
||||||
|
{
|
||||||
|
double min_dist = std::numeric_limits<double>::infinity();
|
||||||
|
double cur_dist;
|
||||||
|
unsigned int min_idx = 0;
|
||||||
|
|
||||||
|
for ( unsigned int i=0; i<selection.size(); i++ ) {
|
||||||
|
cur_dist = fabs( node.getLatitudeDeg() - selection[i].getLatitudeDeg() );
|
||||||
|
if ( cur_dist < min_dist ) {
|
||||||
|
min_dist = cur_dist;
|
||||||
|
min_idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selection[min_idx];
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
|
#include <simgear/io/sg_binobj.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/io/lowlevel.hxx>
|
#include <simgear/io/lowlevel.hxx>
|
||||||
|
|
||||||
|
@ -34,6 +35,147 @@
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
void TGConstruct::CreateMatchedEdgeFiles( std::vector<SGBucket>& bucketList )
|
||||||
|
{
|
||||||
|
// todo - add to work queue
|
||||||
|
for ( unsigned int i=0; i<bucketList.size(); i++ ) {
|
||||||
|
SGBucket b = bucketList[i];
|
||||||
|
nodes.clear();
|
||||||
|
|
||||||
|
// load the .btg from the match directory
|
||||||
|
SGPath file = match_base + "/" + b.gen_base_path() + "/" + b.gen_index_str() + ".btg.gz";
|
||||||
|
SGBinObject obj;
|
||||||
|
|
||||||
|
obj.read_bin( file.str() );
|
||||||
|
std::vector<SGVec3d> wgs84_nodes(obj.get_wgs84_nodes() );
|
||||||
|
|
||||||
|
string filepath;
|
||||||
|
std::vector<SGGeod> north, south, east, west;
|
||||||
|
int nCount;
|
||||||
|
|
||||||
|
// read in all of the .btg nodes
|
||||||
|
for ( unsigned int j=0; j<wgs84_nodes.size(); j++ ) {
|
||||||
|
SGGeod pos = SGGeod::fromCart( wgs84_nodes[j] + obj.get_gbs_center() );
|
||||||
|
nodes.unique_add( pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Read " << nodes.size() << " from file " << file.str() );
|
||||||
|
|
||||||
|
nodes.init_spacial_query();
|
||||||
|
nodes.get_geod_edge( b, north, south, east, west );
|
||||||
|
|
||||||
|
filepath = share_base + "/match1/" + b.gen_base_path() + "/" + b.gen_index_str() + "_edges";
|
||||||
|
SGPath file2(filepath);
|
||||||
|
|
||||||
|
lock->lock();
|
||||||
|
|
||||||
|
file2.create_dir( 0755 );
|
||||||
|
|
||||||
|
gzFile fp;
|
||||||
|
if ( (fp = gzopen( filepath.c_str(), "wb9" )) == NULL ) {
|
||||||
|
SG_LOG( SG_GENERAL, SG_INFO, "ERROR: opening " << file.str() << " for writing!" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sgClearWriteError();
|
||||||
|
|
||||||
|
// north
|
||||||
|
nCount = north.size();
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "write " << north.size() << " northern nodes to file " << filepath.c_str() );
|
||||||
|
sgWriteInt( fp, nCount );
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgWriteGeod( fp, north[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// south
|
||||||
|
nCount = south.size();
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "write " << south.size() << " southern nodes to file " << filepath.c_str() );
|
||||||
|
sgWriteInt( fp, nCount );
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgWriteGeod( fp, south[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// east
|
||||||
|
nCount = east.size();
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "write " << east.size() << " eastern nodes to file " << filepath.c_str() );
|
||||||
|
sgWriteInt( fp, nCount );
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgWriteGeod( fp, east[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// west
|
||||||
|
nCount = west.size();
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "write " << west.size() << " western nodes to file " << filepath.c_str() );
|
||||||
|
sgWriteInt( fp, nCount );
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgWriteGeod( fp, west[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
gzclose(fp);
|
||||||
|
|
||||||
|
lock->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TGConstruct::LoadMatchedEdgeFiles()
|
||||||
|
{
|
||||||
|
// try to load matched edges - on successful load, the edge is marked immutable
|
||||||
|
|
||||||
|
// we need to read just 4 buckets for stage 1 - 1 for each edge
|
||||||
|
std::vector<SGGeod> north, south, east, west;
|
||||||
|
SGBucket nb, sb, eb, wb;
|
||||||
|
|
||||||
|
// Read Northern tile and add its southern nodes
|
||||||
|
nb = bucket.sibling(0, 1);
|
||||||
|
LoadNeighboorMatchDataStage1( nb, north, south, east, west );
|
||||||
|
if ( !south.empty() ) {
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Read " << south.size() << " northern matched nodes " );
|
||||||
|
|
||||||
|
// Add southern nodes from northern tile
|
||||||
|
for (unsigned int i=0; i<south.size(); i++) {
|
||||||
|
nodes.unique_add( south[i] );
|
||||||
|
nm_north.push_back( south[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Southern Tile and add its northern nodes
|
||||||
|
sb = bucket.sibling(0, -1);
|
||||||
|
LoadNeighboorMatchDataStage1( sb, north, south, east, west );
|
||||||
|
if ( !north.empty() ) {
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Read " << north.size() << " southern matched nodes " );
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<north.size(); i++) {
|
||||||
|
nodes.unique_add( north[i] );
|
||||||
|
nm_south.push_back( north[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Eastern Tile and add its western nodes
|
||||||
|
eb = bucket.sibling(1, 0);
|
||||||
|
LoadNeighboorMatchDataStage1( eb, north, south, east, west );
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Read " << west.size() << " eastern matched nodes " );
|
||||||
|
|
||||||
|
if ( !west.empty() ) {
|
||||||
|
for (unsigned int i=0; i<west.size(); i++) {
|
||||||
|
nodes.unique_add( west[i] );
|
||||||
|
nm_east.push_back( west[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Western Tile and add its eastern nodes
|
||||||
|
wb = bucket.sibling(-1, 0);
|
||||||
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Read " << east.size() << " western matched nodes " );
|
||||||
|
|
||||||
|
LoadNeighboorMatchDataStage1( wb, north, south, east, west );
|
||||||
|
if ( !east.empty() ) {
|
||||||
|
for (unsigned int i=0; i<east.size(); i++) {
|
||||||
|
nodes.unique_add( east[i] );
|
||||||
|
nm_west.push_back( east[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TGConstruct::SaveSharedEdgeData( int stage )
|
void TGConstruct::SaveSharedEdgeData( int stage )
|
||||||
{
|
{
|
||||||
switch( stage ) {
|
switch( stage ) {
|
||||||
|
@ -527,6 +669,60 @@ void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, std::vector<SGGeod>&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TGConstruct::LoadNeighboorMatchDataStage1( SGBucket& b, std::vector<SGGeod>& north, std::vector<SGGeod>& south, std::vector<SGGeod>& east, std::vector<SGGeod>& west )
|
||||||
|
{
|
||||||
|
string dir;
|
||||||
|
string file;
|
||||||
|
gzFile fp;
|
||||||
|
SGGeod pt;
|
||||||
|
int nCount;
|
||||||
|
|
||||||
|
dir = share_base + "/match1/" + b.gen_base_path();
|
||||||
|
file = dir + "/" + b.gen_index_str() + "_edges";
|
||||||
|
fp = gzopen( file.c_str(), "rb" );
|
||||||
|
|
||||||
|
north.clear();
|
||||||
|
south.clear();
|
||||||
|
east.clear();
|
||||||
|
west.clear();
|
||||||
|
|
||||||
|
if (fp) {
|
||||||
|
// North
|
||||||
|
sgReadInt( fp, &nCount );
|
||||||
|
SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary");
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgReadGeod( fp, pt );
|
||||||
|
north.push_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// South
|
||||||
|
sgReadInt( fp, &nCount );
|
||||||
|
SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " south boundary");
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgReadGeod( fp, pt );
|
||||||
|
south.push_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// East
|
||||||
|
sgReadInt( fp, &nCount );
|
||||||
|
SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " east boundary");
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgReadGeod( fp, pt );
|
||||||
|
east.push_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// West
|
||||||
|
sgReadInt( fp, &nCount );
|
||||||
|
SG_LOG( SG_CLIPPER, SG_DEBUG, "loading " << nCount << "Points on " << b.gen_index_str() << " west boundary");
|
||||||
|
for (int i=0; i<nCount; i++) {
|
||||||
|
sgReadGeod( fp, pt );
|
||||||
|
west.push_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
gzclose( fp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TGConstruct::LoadFromIntermediateFiles( int stage )
|
void TGConstruct::LoadFromIntermediateFiles( int stage )
|
||||||
{
|
{
|
||||||
string dir;
|
string dir;
|
||||||
|
|
|
@ -64,6 +64,7 @@ void TGConstruct::TesselatePolys( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int area = 0; area < area_defs.size(); area++) {
|
for (unsigned int area = 0; area < area_defs.size(); area++) {
|
||||||
|
bool isRoad = area_defs.is_road_area( area );
|
||||||
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
for (unsigned int p = 0; p < polys_clipped.area_size(area); p++ ) {
|
||||||
tgPolygon& poly = polys_clipped.get_poly(area, p );
|
tgPolygon& poly = polys_clipped.get_poly(area, p );
|
||||||
|
|
||||||
|
@ -71,7 +72,13 @@ void TGConstruct::TesselatePolys( void )
|
||||||
for (unsigned int k=0; k < poly.Triangles(); k++) {
|
for (unsigned int k=0; k < poly.Triangles(); k++) {
|
||||||
for (int l = 0; l < 3; l++) {
|
for (int l = 0; l < 3; l++) {
|
||||||
// ensure we have all nodes...
|
// ensure we have all nodes...
|
||||||
nodes.unique_add( poly.GetTriNode( k, l ) );
|
SGGeod node = poly.GetTriNode( k, l );
|
||||||
|
if ( CheckMatchingNode( node, isRoad, false ) ) {
|
||||||
|
nodes.unique_add( node );
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_GENERAL, SG_INFO, "after tesselation, we can't add a node - quit");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,9 @@ public:
|
||||||
void SetNode( unsigned int i, SGGeod n ) {
|
void SetNode( unsigned int i, SGGeod n ) {
|
||||||
node_list[i] = n;
|
node_list[i] = n;
|
||||||
}
|
}
|
||||||
|
void DelNode( unsigned int i ) {
|
||||||
|
node_list.erase( node_list.begin()+i);
|
||||||
|
}
|
||||||
SGGeod GetNode( unsigned int i ) const {
|
SGGeod GetNode( unsigned int i ) const {
|
||||||
return node_list[i];
|
return node_list[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,26 +68,32 @@ public:
|
||||||
|
|
||||||
// Add a point to the point list if it doesn't already exist.
|
// Add a point to the point list if it doesn't already exist.
|
||||||
// Returns the index (starting at zero) of the point in the list.
|
// Returns the index (starting at zero) of the point in the list.
|
||||||
void unique_add( const SGGeod& p ) {
|
SGGeod unique_add( const SGGeod& p ) {
|
||||||
TGNode n(p);
|
TGNode n(p);
|
||||||
n.SetFixedPosition(false);
|
n.SetFixedPosition(false);
|
||||||
tg_node_list.add(n);
|
unsigned idx = tg_node_list.add(n);
|
||||||
kd_tree_valid = false;
|
kd_tree_valid = false;
|
||||||
|
|
||||||
|
return tg_node_list[idx].GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unique_add( const TGNode& n ) {
|
SGGeod unique_add( const TGNode& n ) {
|
||||||
tg_node_list.add(n);
|
unsigned int idx = tg_node_list.add(n);
|
||||||
kd_tree_valid = false;
|
kd_tree_valid = false;
|
||||||
|
|
||||||
|
return tg_node_list[idx].GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a point to the point list if it doesn't already exist
|
// Add a point to the point list if it doesn't already exist
|
||||||
// (checking all three dimensions.) Returns the index (starting
|
// (checking all three dimensions.) Returns the index (starting
|
||||||
// at zero) of the point in the list.
|
// at zero) of the point in the list.
|
||||||
void unique_add_fixed_elevation( const SGGeod& p ) {
|
SGGeod unique_add_fixed_elevation( const SGGeod& p ) {
|
||||||
TGNode n(p);
|
TGNode n(p);
|
||||||
n.SetFixedPosition(true);
|
n.SetFixedPosition(true);
|
||||||
tg_node_list.add(n);
|
unsigned int idx = tg_node_list.add(n);
|
||||||
kd_tree_valid = false;
|
kd_tree_valid = false;
|
||||||
|
|
||||||
|
return tg_node_list[idx].GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index of the specified point (compair to the same
|
// Find the index of the specified point (compair to the same
|
||||||
|
|
|
@ -264,6 +264,9 @@ public:
|
||||||
|
|
||||||
contours[c].AddNode( n );
|
contours[c].AddNode( n );
|
||||||
}
|
}
|
||||||
|
void DelNode( unsigned int c, unsigned int n ) {
|
||||||
|
contours[c].DelNode( n );
|
||||||
|
}
|
||||||
|
|
||||||
tgRectangle GetBoundingBox( void ) const;
|
tgRectangle GetBoundingBox( void ) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue