1
0
Fork 0

tile matching phase 1

- 3 stage construct
- insert neighbor vertexes from all sides
This commit is contained in:
Peter Sadrozinski 2012-09-09 10:37:25 -04:00 committed by Christian Schmitt
parent 779db9566b
commit 6a3a57f198
12 changed files with 386 additions and 1185 deletions

View file

@ -5,5 +5,4 @@ include_directories(${PROJECT_SOURCE_DIR}/src/BuildTiles)
add_subdirectory(Osgb36)
add_subdirectory(Parallel)
add_subdirectory(Match)
add_subdirectory(Main)

View file

@ -12,7 +12,6 @@ set_target_properties(tg-construct PROPERTIES
target_link_libraries(tg-construct
Osgb36
Match
Polygon Geometry
Array landcover poly2tri
${GDAL_LIBRARY}

View file

@ -40,11 +40,11 @@
#include <simgear/io/sg_binobj.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/debug/logstream.hxx>
#include <CGAL/Plane_3.h>
#include <Geometry/poly_support.hxx>
#include <Geometry/poly_extra.hxx>
#include <Match/match.hxx>
#include <Osgb36/osgb36.hxx>
#include "construct.hxx"
@ -72,8 +72,6 @@ static const double quarter_cover_size = cover_size * 0.25;
// Constructor
TGConstruct::TGConstruct():
useUKGrid(false),
writeSharedEdges(true),
useOwnSharedEdges(false),
ignoreLandmass(false),
debug_all(false),
ds_id((void*)-1)
@ -92,6 +90,20 @@ TGConstruct::~TGConstruct() {
nodes.clear();
}
// paths
void TGConstruct::set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load ) {
work_base = work;
share_base = share;
output_base = output;
load_dirs = load;
}
void TGConstruct::set_options( bool uk_grid, bool ignore_lm, double n ) {
useUKGrid = uk_grid;
ignoreLandmass = ignore_lm;
nudge = n;
}
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);
@ -195,13 +207,20 @@ bool TGConstruct::IsDebugArea( unsigned int area )
void TGConstruct::WriteDebugShape( const char* layer_name, const TGShape& shape )
{
char name[64];
char feature_name[128];
shape.GetName( name );
ds_id = tgShapefileOpenDatasource( ds_name );
l_id = tgShapefileOpenLayer( ds_id, layer_name );
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, name );
sprintf( feature_name, "%s_clipmask", name );
tgShapefileCreateFeature( ds_id, l_id, shape.clip_mask, feature_name );
for (unsigned int i=0; i<shape.sps.size(); i++) {
sprintf( feature_name, "%s_%d", name, i );
tgShapefileCreateFeature( ds_id, l_id, shape.sps[i].get_poly(), feature_name );
}
// close after each write
ds_id = tgShapefileCloseDatasource( ds_id );
}
@ -239,7 +258,7 @@ void TGConstruct::LoadElevationArray( void ) {
int i;
for ( i = 0; i < (int)load_dirs.size(); ++i ) {
string array_path = get_work_base() + "/" + load_dirs[i] + "/" + base + "/" + bucket.gen_index_str();
string array_path = work_base + "/" + load_dirs[i] + "/" + base + "/" + bucket.gen_index_str();
if ( array.open(array_path) ) {
break;
@ -590,7 +609,7 @@ int TGConstruct::LoadLandclassPolys( void ) {
// load 2D polygons from all directories provided
for ( i = 0; i < (int)load_dirs.size(); ++i ) {
poly_path = get_work_base() + "/" + load_dirs[i] + '/' + base;
poly_path = work_base + "/" + load_dirs[i] + '/' + base;
string tile_str = bucket.gen_index_str();
simgear::Dir d(poly_path);
@ -1158,7 +1177,7 @@ TGPolygon TGConstruct::linear_tex_coords( const TGPolygon& tri, const TGTexParam
// collect custom objects and move to scenery area
void TGConstruct::AddCustomObjects( void ) {
// Create/open the output .stg file for writing
SGPath dest_d(get_output_base().c_str());
SGPath dest_d(output_base.c_str());
dest_d.append(bucket.gen_base_path().c_str());
string dest_dir = dest_d.str_native();
SGPath dest_i(dest_d);
@ -1180,7 +1199,7 @@ void TGConstruct::AddCustomObjects( void ) {
char name[256];
for ( int i = 0; i < (int)load_dirs.size(); ++i ) {
SGPath base(get_work_base().c_str());
SGPath base(work_base.c_str());
base.append(load_dirs[i]);
base.append( bucket.gen_base_path() );
SGPath index(base);
@ -1807,27 +1826,6 @@ void TGConstruct::CalcPointNormals( void )
}
}
void TGConstruct::LoadSharedEdgeData( void )
{
match.load_neighbor_shared( bucket, share_base );
if ( useOwnSharedEdges ) {
match.load_missing_shared( bucket, share_base );
}
match.add_shared_nodes( this );
}
void TGConstruct::SaveSharedEdgeData( void )
{
match.split_tile( bucket, this );
SG_LOG(SG_GENERAL, SG_ALERT, "Tile Split");
if ( writeSharedEdges ) {
SG_LOG(SG_GENERAL, SG_ALERT, "write shared edges");
match.write_shared( bucket, share_base );
}
}
void TGConstruct::TesselatePolys( void )
{
// tesselate the polygons and prepair them for final output
@ -1854,6 +1852,10 @@ void TGConstruct::TesselatePolys( void )
shape+1 << "-" << segment << " of " << (int)polys_clipped.area_size(area) <<
": id = " << id );
if ( IsDebugShape( id ) ) {
SG_LOG( SG_CLIPPER, SG_INFO, std::setprecision(12) << std::fixed << poly );
}
// TGPolygon tri = polygon_tesselate_alt_with_extra( poly, poly_extra, false );
TGPolygon tri = polygon_tesselate_alt_with_extra_cgal( poly, poly_extra, false );
@ -1980,7 +1982,7 @@ void TGConstruct::WriteBtgFile( void )
group_list fans_tc; fans_tc.clear();
string_list fan_materials; fan_materials.clear();
string base = get_output_base();
string base = output_base;
string binname = bucket.gen_index_str();
binname += ".btg";
string txtname = bucket.gen_index_str();
@ -2117,6 +2119,66 @@ void TGConstruct::CalcTextureCoordinates( void )
}
}
void TGConstruct::SaveSharedEdgeData( int stage )
{
string dir;
string file;
switch( stage ) {
case 1:
{
point_list north, south, east, west;
int nCount;
nodes.get_geod_edge( bucket, north, south, east, west );
dir = share_base + "/stage1/" + bucket.gen_base_path();
SGPath sgp( dir );
sgp.append( "dummy" );
sgp.create_dir( 0755 );
file = dir + "/" + bucket.gen_index_str() + "_edges";
std::ofstream ofs_e( file.c_str() );
// first, set the precision
ofs_e << std::setprecision(12);
ofs_e << std::fixed;
// north
nCount = north.size();
ofs_e << nCount << "\n";
for (int i=0; i<nCount; i++) {
ofs_e << north[i];
}
// south
nCount = south.size();
ofs_e << nCount << "\n";
for (int i=0; i<nCount; i++) {
ofs_e << south[i];
}
// east
nCount = east.size();
ofs_e << nCount << "\n";
for (int i=0; i<nCount; i++) {
ofs_e << east[i];
}
// west
nCount = west.size();
ofs_e << nCount << "\n";
for (int i=0; i<nCount; i++) {
ofs_e << west[i];
}
ofs_e.close();
}
break;
}
}
void TGConstruct::SaveToIntermediateFiles( int stage )
{
string dir;
@ -2126,19 +2188,27 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
case 1: // Save the clipped polys and node list
{
dir = share_base + "/stage1/" + bucket.gen_base_path();
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
SGPath sgp( dir );
sgp.append( "dummy" );
sgp.create_dir( 0755 );
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
std::ofstream ofs_cp( file.c_str() );
// first, set the precision
ofs_cp << std::setprecision(15);
ofs_cp << std::fixed;
ofs_cp << polys_clipped;
ofs_cp.close();
file = dir + "/" + bucket.gen_index_str() + "_nodes";
file = dir + "/" + bucket.gen_index_str() + "_nodes";
std::ofstream ofs_n( file.c_str() );
// first, set the precision
ofs_n << std::setprecision(15);
ofs_n << std::fixed;
ofs_n << nodes;
ofs_n.close();
break;
@ -2147,19 +2217,26 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
case 2: // Save the clipped polys and node list
{
dir = share_base + "/stage2/" + bucket.gen_base_path();
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
SGPath sgp( dir );
sgp.append( "dummy" );
sgp.create_dir( 0755 );
file = dir + "/" + bucket.gen_index_str() + "_clipped_polys";
std::ofstream ofs_cp( file.c_str() );
// first, set the precision
ofs_cp << std::setprecision(15);
ofs_cp << std::fixed;
ofs_cp << polys_clipped;
ofs_cp.close();
file = dir + "/" + bucket.gen_index_str() + "_nodes";
std::ofstream ofs_n( file.c_str() );
// first, set the precision
ofs_n << std::setprecision(15);
ofs_n << std::fixed;
ofs_n << nodes;
ofs_n.close();
break;
@ -2167,6 +2244,103 @@ void TGConstruct::SaveToIntermediateFiles( int stage )
}
}
void TGConstruct::LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, point_list& south, point_list& east, point_list& west )
{
string dir;
string file;
Point3D pt;
int nCount;
dir = share_base + "/stage1/" + b.gen_base_path();
file = dir + "/" + b.gen_index_str() + "_edges";
std::ifstream ifs_edges( file.c_str() );
north.clear();
south.clear();
east.clear();
west.clear();
if ( ifs_edges.is_open() ) {
// North
ifs_edges >> nCount;
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " north boundary");
for (int i=0; i<nCount; i++) {
ifs_edges >> pt;
north.push_back(pt);
}
// South
ifs_edges >> nCount;
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " south boundary");
for (int i=0; i<nCount; i++) {
ifs_edges >> pt;
south.push_back(pt);
}
// East
ifs_edges >> nCount;
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " east boundary");
for (int i=0; i<nCount; i++) {
ifs_edges >> pt;
east.push_back(pt);
}
// West
ifs_edges >> nCount;
SG_LOG( SG_CLIPPER, SG_INFO, "loading " << nCount << "Points on " << b.gen_index_str() << " west boundary");
for (int i=0; i<nCount; i++) {
ifs_edges >> pt;
west.push_back(pt);
}
ifs_edges.close();
}
}
void TGConstruct::LoadSharedEdgeData( int stage )
{
switch( stage ) {
case 1:
{
// we need to read just 4 buckets for stage 1 - 1 for each edge
point_list north, south, east, west;
SGBucket nb, sb, eb, wb;
double clon = bucket.get_center_lon();
double clat = bucket.get_center_lat();
// Read North tile and add its southern nodes
nb = sgBucketOffset(clon, clat, 0, 1);
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] );
}
// 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] );
}
// 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] );
}
// 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] );
}
}
break;
}
}
void TGConstruct::LoadFromIntermediateFiles( int stage )
{
string dir;
@ -2253,6 +2427,10 @@ void TGConstruct::ConstructBucketStage1() {
// 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
CleanClippedPolys();
// STEP 6)
// Save the tile boundary info for stage 2 (just x,y coords of points on the boundary)
SaveSharedEdgeData( 1 );
}
void TGConstruct::ConstructBucketStage2() {
@ -2267,16 +2445,13 @@ void TGConstruct::ConstructBucketStage2() {
strcpy( ds_name, "" );
}
// TEMP TEMP TEMP - save in intermediate file...)
// Load grid of elevation data (Array)
// STEP 7)
// Need the array of elevation data for stage 2
LoadElevationArray();
// restore construct from stage1 intermediate files
LoadFromIntermediateFiles( 1 );
// STEP 6)
// Merge in Shared data - should just be x,y nodes on the borders from stage1
LoadSharedEdgeData();
LoadSharedEdgeData( 1 );
// STEP 7)
// Fix T-Junctions by finding nodes that lie close to polygon edges, and
@ -2296,6 +2471,11 @@ void TGConstruct::ConstructBucketStage2() {
// STEP 10)
// Interpolate elevations, and flatten stuff
CalcElevations();
// STEP 11)
// Save the tile boundary info for stage 3
// includes elevation info, and a list of connected triangles
SaveSharedEdgeData( 2 );
}
void TGConstruct::ConstructBucketStage3() {
@ -2310,15 +2490,6 @@ void TGConstruct::ConstructBucketStage3() {
strcpy( ds_name, "" );
}
// TEMP TEMP TEMP )
// Load grid of elevation data (Array)
LoadElevationArray();
// STEP 11)
// Merge in Shared data - nodes on the shared edge should have x,y,z - we'll average the z
// shared edge data nodes also have 1 or 2 connected nodes so we can see their connected faces
//LoadSharedEdgeData();
// STEP 12)
// Generate face_connected list
LookupFacesPerNode();
@ -2344,10 +2515,6 @@ void TGConstruct::ConstructBucketStage3() {
// Calculate Texture Coordinates
CalcTextureCoordinates();
// STEP 15) // only if not stages...
// Write out the shared edge data
SaveSharedEdgeData();
// STEP 16)
// Generate the btg file
WriteBtgFile();

View file

@ -117,27 +117,22 @@ public:
inline std::istream& operator >> ( std::istream& in, TGShape& p)
{
int i, count;
TGSuperPoly sp;
TGTexParams tp;
// First, load the clipmask
SG_LOG(SG_GENERAL, SG_ALERT, "\tshape: clipmask" );
in >> p.clip_mask;
// Then load superpolys
in >> count;
SG_LOG(SG_GENERAL, SG_ALERT, "\tshape: superpoly count " << count );
for (i=0; i<count; i++) {
SG_LOG(SG_GENERAL, SG_ALERT, "\tshape: load superpoly " << i );
TGSuperPoly sp;
in >> sp;
p.sps.push_back( sp );
}
// Then load texparams
in >> count;
SG_LOG(SG_GENERAL, SG_ALERT, "\tshape: texparams count " << count );
for (i=0; i<count; i++) {
SG_LOG(SG_GENERAL, SG_ALERT, "\tshape: load texparam " << i );
TGTexParams tp;
in >> tp;
p.tps.push_back( tp );
}
@ -326,10 +321,8 @@ inline std::istream& operator >> ( std::istream& in, TGLandclass& lc)
// Load all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
in >> count;
SG_LOG(SG_GENERAL, SG_ALERT, "Loading Landclass: area " << i << " size is " << count );
for (j=0; j<count; j++) {
SG_LOG(SG_GENERAL, SG_ALERT, "Loading Landclass: load shape " << j << " of " << count );
TGShape shape;
in >> shape;
@ -345,10 +338,6 @@ inline std::ostream& operator<< ( std::ostream& out, const TGLandclass& lc )
int i, j, count;
TGShape shape;
// first, set the precision
out << std::setprecision(12);
out << std::fixed;
// Save all landclass shapes
for (i=0; i<TG_MAX_AREA_TYPES; i++) {
count = lc.shapes[i].size();
@ -388,18 +377,12 @@ private:
// with the UK grid
bool useUKGrid;
double nudge;
// flag indicating whether this is a rebuild and Shared edge
// data should only be used for fitting, but not rewritten
bool writeSharedEdges;
// flag indicating whether the shared edge data of the
// tile to be built should be used in addition to neighbour data
bool useOwnSharedEdges;
// flag indicating whether to ignore the landmass
bool ignoreLandmass;
// I think we should remove this
double nudge;
// path to the debug shapes
std::string debug_path;
@ -431,7 +414,7 @@ private:
TGNodes nodes;
// SHared Edges match data
TGMatch match;
// TGMatch match;
private:
// Load Data
@ -452,6 +435,11 @@ private:
void LoadSharedEdgeData( void );
void SaveSharedEdgeData( void );
void LoadSharedEdgeData( int stage );
void LoadNeighboorEdgeDataStage1( SGBucket& b, point_list& north, point_list& south, point_list& east, point_list& west );
void SaveSharedEdgeData( int stage );
// Polygon Cleaning
void CleanClippedPolys( void );
void FixTJunctions( void );
@ -523,6 +511,9 @@ public:
inline void set_cover (const std::string &s) { cover = s; }
// paths
void set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load_dirs );
#if 0
inline std::string get_work_base() const { return work_base; }
inline void set_work_base( const std::string s ) { work_base = s; }
inline std::string get_output_base() const { return output_base; }
@ -530,22 +521,21 @@ public:
inline std::string get_share_base() const { return share_base; }
inline void set_share_base( const std::string s ) { share_base = s; }
inline void set_load_dirs( const std::vector<std::string> ld ) { load_dirs = ld; }
#endif
void set_options( bool uk_grid, bool ignore_lm, double n );
#if 0
// UK grid flag
inline bool get_useUKGrid() const { return useUKGrid; }
inline void set_useUKGrid( const bool b ) { useUKGrid = b; }
// Nudge
inline void set_nudge( double n ) { nudge = n; }
// shared edge write flag
inline void set_write_shared_edges( const bool b ) { writeSharedEdges = b; }
// own shared edge use flag
inline void set_use_own_shared_edges( const bool b ) { useOwnSharedEdges = b; }
// ignore landmass flag
inline void set_ignore_landmass( const bool b) { ignoreLandmass = b; }
#endif
// TODO : REMOVE
inline TGNodes* get_nodes() { return &nodes; }

View file

@ -52,9 +52,6 @@
#include <Geometry/poly_support.hxx>
#include <landcover/landcover.hxx>
// TODO : Get rid of match...
#include <Match/match.hxx>
#include "construct.hxx"
#include "usgs.hxx"
@ -147,8 +144,6 @@ static void usage( const string name ) {
SG_LOG(SG_GENERAL, SG_ALERT, " --priorities=<filename>");
SG_LOG(SG_GENERAL, SG_ALERT, " --usgs-map=<filename>");
SG_LOG(SG_GENERAL, SG_ALERT, " --useUKgrid");
SG_LOG(SG_GENERAL, SG_ALERT, " --no-write-shared-edges");
SG_LOG(SG_GENERAL, SG_ALERT, " --use-own-shared-edges");
SG_LOG(SG_GENERAL, SG_ALERT, " --ignore-landmass");
SG_LOG(SG_GENERAL, SG_ALERT, " ] <load directory...>");
exit(-1);
@ -174,17 +169,9 @@ int main(int argc, char **argv) {
// flag indicating whether UK grid should be used for in-UK
// texture coordinate generation
bool useUKgrid = false;
// flag indicating whether this is a rebuild and Shared edge
// data should only be used for fitting, but not rewritten
bool writeSharedEdges = true;
// flag indicating whether the shared edge data of the
// tile to be built should be used in addition to neighbour data
bool useOwnSharedEdges = false;
bool ignoreLandmass = false;
sglog().setLogLevels( SG_ALL, SG_INFO );
// Initialize shapefile support (for debugging)
@ -223,10 +210,6 @@ int main(int argc, char **argv) {
usgs_map_file = arg.substr(11);
} else if (arg.find("--useUKgrid") == 0) {
useUKgrid = true;
} else if (arg.find("--no-write-shared-edges") == 0) {
writeSharedEdges = false;
} else if (arg.find("--use-own-shared-edges") == 0) {
useOwnSharedEdges = true;
} else if (arg.find("--ignore-landmass") == 0) {
ignoreLandmass = true;
} else if (arg.find("--debug-dir=") == 0) {
@ -283,15 +266,8 @@ int main(int argc, char **argv) {
all_stages = new TGConstruct();
all_stages->set_cover( cover );
all_stages->set_work_base( work_dir );
all_stages->set_output_base( output_dir );
all_stages->set_share_base( share_dir );
all_stages->set_load_dirs( load_dirs );
all_stages->set_useUKGrid( useUKgrid );
all_stages->set_write_shared_edges( writeSharedEdges );
all_stages->set_use_own_shared_edges( useOwnSharedEdges );
all_stages->set_ignore_landmass( ignoreLandmass );
all_stages->set_nudge( nudge );
all_stages->set_paths( work_dir, share_dir, output_dir, load_dirs );
all_stages->set_options( useUKgrid, ignoreLandmass, nudge );
all_stages->set_bucket( b );
all_stages->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -316,15 +292,8 @@ int main(int argc, char **argv) {
all_stages = new TGConstruct();
all_stages->set_cover( cover );
all_stages->set_work_base( work_dir );
all_stages->set_output_base( output_dir );
all_stages->set_share_base( share_dir );
all_stages->set_load_dirs( load_dirs );
all_stages->set_useUKGrid( useUKgrid );
all_stages->set_write_shared_edges( writeSharedEdges );
all_stages->set_use_own_shared_edges( useOwnSharedEdges );
all_stages->set_ignore_landmass( ignoreLandmass );
all_stages->set_nudge( nudge );
all_stages->set_paths( work_dir, share_dir, output_dir, load_dirs );
all_stages->set_options( useUKgrid, ignoreLandmass, nudge );
all_stages->set_bucket( b_min );
all_stages->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -341,7 +310,6 @@ int main(int argc, char **argv) {
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy);
// construct stage 1
for ( j = 0; j <= dy; j++ ) {
for ( i = 0; i <= dx; i++ ) {
@ -356,15 +324,8 @@ int main(int argc, char **argv) {
stage1 = new TGConstruct();
stage1->set_cover( cover );
stage1->set_work_base( work_dir );
stage1->set_output_base( output_dir );
stage1->set_share_base( share_dir );
stage1->set_load_dirs( load_dirs );
stage1->set_useUKGrid( useUKgrid );
stage1->set_write_shared_edges( writeSharedEdges );
stage1->set_use_own_shared_edges( useOwnSharedEdges );
stage1->set_ignore_landmass( ignoreLandmass );
stage1->set_nudge( nudge );
stage1->set_paths( work_dir, share_dir, output_dir, load_dirs );
stage1->set_options( useUKgrid, ignoreLandmass, nudge );
stage1->set_bucket( b_cur );
stage1->set_debug( debug_dir, debug_defs );
@ -392,15 +353,8 @@ int main(int argc, char **argv) {
stage2 = new TGConstruct();
stage2->set_cover( cover );
stage2->set_work_base( work_dir );
stage2->set_output_base( output_dir );
stage2->set_share_base( share_dir );
stage2->set_load_dirs( load_dirs );
stage2->set_useUKGrid( useUKgrid );
stage2->set_write_shared_edges( writeSharedEdges );
stage2->set_use_own_shared_edges( useOwnSharedEdges );
stage2->set_ignore_landmass( ignoreLandmass );
stage2->set_nudge( nudge );
stage2->set_paths( work_dir, share_dir, output_dir, load_dirs );
stage2->set_options( useUKgrid, ignoreLandmass, nudge );
stage2->set_bucket( b_cur );
stage2->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -429,15 +383,8 @@ int main(int argc, char **argv) {
stage3 = new TGConstruct();
stage3->set_cover( cover );
stage3->set_work_base( work_dir );
stage3->set_output_base( output_dir );
stage3->set_share_base( share_dir );
stage3->set_load_dirs( load_dirs );
stage3->set_useUKGrid( useUKgrid );
stage3->set_write_shared_edges( writeSharedEdges );
stage3->set_use_own_shared_edges( useOwnSharedEdges );
stage3->set_ignore_landmass( ignoreLandmass );
stage3->set_nudge( nudge );
stage3->set_paths( work_dir, share_dir, output_dir, load_dirs );
stage3->set_options( useUKgrid, ignoreLandmass, nudge );
stage3->set_bucket( b_cur );
stage3->set_debug( debug_dir, debug_area_defs, debug_shape_defs );
@ -460,15 +407,8 @@ int main(int argc, char **argv) {
all_stages = new TGConstruct();
all_stages->set_cover( cover );
all_stages->set_work_base( work_dir );
all_stages->set_output_base( output_dir );
all_stages->set_share_base( share_dir );
all_stages->set_load_dirs( load_dirs );
all_stages->set_useUKGrid( useUKgrid );
all_stages->set_write_shared_edges( writeSharedEdges );
all_stages->set_use_own_shared_edges( useOwnSharedEdges );
all_stages->set_ignore_landmass( ignoreLandmass );
all_stages->set_nudge( nudge );
all_stages->set_paths( work_dir, share_dir, output_dir, load_dirs );
all_stages->set_options( useUKgrid, ignoreLandmass, nudge );
all_stages->set_bucket( b );
all_stages->set_debug( debug_dir, debug_area_defs, debug_shape_defs );

View file

@ -1,5 +0,0 @@
add_library(Match STATIC
match.cxx match.hxx
)

View file

@ -1,874 +0,0 @@
// match.cxx -- Handle details of matching up tile edges
//
// Written by Curtis Olson, started March 1998.
//
// Copyright (C) 1998 - 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: match.cxx,v 1.21 2004-11-19 22:25:49 curt Exp $
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <Geometry/point3d.hxx>
#include <Geometry/tg_nodes.hxx>
#include <Polygon/point2d.hxx>
#include "match.hxx"
#include <Main/construct.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <stdlib.h>
//using std::cout;
//using std::endl;
using std::string;
TGMatch::TGMatch( void ) {
}
TGMatch::~TGMatch( void ) {
}
// scan the specified share file for the specified information
void TGMatch::scan_share_file( const string& dir, const SGBucket& b,
neighbor_type search, neighbor_type dest )
{
string file = dir + "/" + b.gen_base_path() + "/" + b.gen_index_str();
// cout << "reading shared data from " << file << endl;
sg_gzifstream in( file );
if ( !in.is_open() ) {
// cout << "Cannot open file: " << file << endl;
return;
}
// cout << "open successful." << endl;
string target;
if ( search == SW_Corner ) {
target = "sw_node";
} else if ( search == SE_Corner ) {
target = "se_node";
} else if ( search == NE_Corner ) {
target = "ne_node";
} else if ( search == NW_Corner ) {
target = "nw_node";
} else if ( search == NORTH ) {
target = "n_node";
} else if ( search == SOUTH ) {
target = "s_node";
} else if ( search == EAST ) {
target = "e_node";
} else if ( search == WEST ) {
target = "w_node";
}
string key;
Point3D node, normal;
while ( in ) {
in >> key;
in >> node;
if ( key == target ) {
// cout << key << " " << node << endl;
in >> key;
in >> normal;
if ( dest == SW_Corner ) {
sw_node = node;
sw_normal = normal;
sw_flag = true;
} else if ( dest == SE_Corner ) {
se_node = node;
se_normal = normal;
se_flag = true;
} else if ( dest == NE_Corner ) {
ne_node = node;
ne_normal = normal;
ne_flag = true;
} else if ( dest == NW_Corner ) {
nw_node = node;
nw_normal = normal;
nw_flag = true;
} else if ( dest == NORTH ) {
north_nodes.push_back(node);
north_normals.push_back(normal);
north_flag = true;
} else if ( dest == SOUTH ) {
south_nodes.push_back(node);
south_normals.push_back(normal);
south_flag = true;
} else if ( dest == EAST ) {
east_nodes.push_back(node);
east_normals.push_back(normal);
east_flag = true;
} else if ( dest == WEST ) {
west_nodes.push_back(node);
west_normals.push_back(normal);
west_flag = true;
}
} else if ( (target == "n_node") && (key == "n_null") ) {
south_flag = true;
} else if ( (target == "s_node") && (key == "s_null") ) {
north_flag = true;
} else if ( (target == "e_node") && (key == "e_null") ) {
west_flag = true;
} else if ( (target == "w_node") && (key == "w_null") ) {
east_flag = true;
}
}
}
// try to find info for the specified shared component
void TGMatch::load_shared( SGBucket b, string base, neighbor_type n ) {
double clon = b.get_center_lon();
double clat = b.get_center_lat();
SGBucket cb;
if ( n == SW_Corner ) {
// cout << "searching for SW corner data" << endl;
cb = sgBucketOffset(clon, clat, -1, 0);
scan_share_file( base, cb, SE_Corner, n );
cb = sgBucketOffset(clon, clat, -1, -1);
scan_share_file( base, cb, NE_Corner, n );
cb = sgBucketOffset(clon, clat, 0, -1);
scan_share_file( base, cb, NW_Corner, n );
} else if ( n == SE_Corner ) {
// cout << "searching for SE corner data" << endl;
cb = sgBucketOffset(clon, clat, 0, -1);
scan_share_file( base, cb, NE_Corner, n );
cb = sgBucketOffset(clon, clat, 1, -1);
scan_share_file( base, cb, NW_Corner, n );
cb = sgBucketOffset(clon, clat, 1, 0);
scan_share_file( base, cb, SW_Corner, n );
} else if ( n == NE_Corner ) {
// cout << "searching for NE corner data" << endl;
cb = sgBucketOffset(clon, clat, 1, 0);
scan_share_file( base, cb, NW_Corner, n );
cb = sgBucketOffset(clon, clat, 1, 1);
scan_share_file( base, cb, SW_Corner, n );
cb = sgBucketOffset(clon, clat, 0, 1);
scan_share_file( base, cb, SE_Corner, n );
} else if ( n == NW_Corner ) {
// cout << "searching for NW corner data" << endl;
cb = sgBucketOffset(clon, clat, 0, 1);
scan_share_file( base, cb, SW_Corner, n );
cb = sgBucketOffset(clon, clat, -1, 1);
scan_share_file( base, cb, SE_Corner, n );
cb = sgBucketOffset(clon, clat, -1, 0);
scan_share_file( base, cb, NE_Corner, n );
} else if ( n == NORTH ) {
// cout << "searching for NORTH edge data" << endl;
cb = sgBucketOffset(clon, clat, 0, 1);
scan_share_file( base, cb, SOUTH, n );
} else if ( n == SOUTH ) {
// cout << "searching for SOUTH edge data" << endl;
cb = sgBucketOffset(clon, clat, 0, -1);
scan_share_file( base, cb, NORTH, n );
} else if ( n == EAST ) {
// cout << "searching for EAST edge data" << endl;
cb = sgBucketOffset(clon, clat, 1, 0);
scan_share_file( base, cb, WEST, n );
} else if ( n == WEST ) {
// cout << "searching for WEST edge data" << endl;
cb = sgBucketOffset(clon, clat, -1, 0);
scan_share_file( base, cb, EAST, n );
}
}
// load any previously existing shared data from all neighbors (if
// shared data for a component exists set that components flag to true
void TGMatch::load_neighbor_shared( SGBucket b, string share_dir ) {
// cout << "Loading existing shared data from neighbor tiles" << endl;
string base = share_dir + "/";
// start with all flags false
sw_flag = se_flag = ne_flag = nw_flag = false;
north_flag = south_flag = east_flag = west_flag = false;
load_shared( b, base, SW_Corner );
load_shared( b, base, SE_Corner );
load_shared( b, base, NE_Corner );
load_shared( b, base, NW_Corner );
north_nodes.clear();
south_nodes.clear();
east_nodes.clear();
west_nodes.clear();
load_shared( b, base, NORTH );
load_shared( b, base, SOUTH );
load_shared( b, base, EAST );
load_shared( b, base, WEST );
#if 0
cout << "Shared data read in:" << endl;
if ( sw_flag ) {
cout << " sw corner = " << sw_node << endl;
cout << " normal = " << sw_normal << endl;
}
if ( se_flag ) {
cout << " se corner = " << se_node << endl;
cout << " normal = " << se_normal << endl;
}
if ( ne_flag ) {
cout << " ne corner = " << ne_node << endl;
cout << " normal = " << ne_normal << endl;
}
if ( nw_flag ) {
cout << " nw corner = " << nw_node << endl;
cout << " normal = " << nw_normal << endl;
}
if ( north_flag ) {
cout << " north nodes = " << north_nodes.size() << endl;
for ( int i = 0; i < (int)north_nodes.size(); ++i ) {
cout << " " << north_nodes[i] << endl;
}
}
if ( south_flag ) {
cout << " south nodes = " << south_nodes.size() << endl;
for ( int i = 0; i < (int)south_nodes.size(); ++i ) {
cout << " " << south_nodes[i] << endl;
}
}
if ( east_flag ) {
cout << " east nodes = " << east_nodes.size() << endl;
for ( int i = 0; i < (int)east_nodes.size(); ++i ) {
cout << " " << east_nodes[i] << endl;
}
}
if ( west_flag ) {
cout << " west nodes = " << west_nodes.size() << endl;
for ( int i = 0; i < (int)west_nodes.size(); ++i ) {
cout << " " << west_nodes[i] << endl;
}
}
#endif
}
// try to load any missing shared data from our own shared data file
void TGMatch::load_missing_shared( SGBucket b, string share ) {
string base = share + "/";
if ( !nw_flag ) {
scan_share_file( base, b, NW_Corner, NW_Corner );
}
if ( !ne_flag ) {
scan_share_file( base, b, NE_Corner, NE_Corner );
}
if ( !se_flag ) {
scan_share_file( base, b, SE_Corner, SE_Corner );
}
if ( !sw_flag ) {
scan_share_file( base, b, SW_Corner, SW_Corner );
}
if ( !north_flag ) {
scan_share_file( base, b, NORTH, NORTH );
}
if ( !east_flag ) {
scan_share_file( base, b, EAST, EAST );
}
if ( !south_flag ) {
scan_share_file( base, b, SOUTH, SOUTH );
}
if ( !west_flag ) {
scan_share_file( base, b, WEST, WEST );
}
}
// fake a normal for a point which is basically straight up
Point3D tgFakeNormal( const Point3D& p ) {
Point3D radians = Point3D( p.x() * SGD_DEGREES_TO_RADIANS,
p.y() * SGD_DEGREES_TO_RADIANS,
p.z() );
Point3D cart = sgGeodToCart(radians);
double len = Point3D(0.0).distance3D(cart);
// cout << "len = " << len << endl;
cart /= len;
// cout << "new fake normal = " << cart << endl;
return cart;
}
// split up the tile between the shared edge points, normals, and
// segments and the body. This must be done after calling
// load_neighbor_data() and will ignore any shared data from the
// current tile that already exists from a neighbor.
void TGMatch::split_tile( SGBucket b, TGConstruct* c ) {
int i;
//cout << "Spliting tile" << endl;
//cout << " extracting (shared) edge nodes and normals" << endl;
// calculate tile boundaries
point2d min, max;
min.x = b.get_center_lon() - 0.5 * b.get_width();
min.y = b.get_center_lat() - 0.5 * b.get_height();
max.x = b.get_center_lon() + 0.5 * b.get_width();
max.y = b.get_center_lat() + 0.5 * b.get_height();
// defaults "just in case"
if ( ! sw_flag ) {
sw_node = Point3D( min.x, min.y, 0.0 );
sw_normal = tgFakeNormal( sw_node );
}
if ( ! se_flag ) {
se_node = Point3D( max.x, min.y, 0.0 );
se_normal = tgFakeNormal( se_node );
}
if ( ! nw_flag ) {
nw_node = Point3D( min.x, max.y, 0.0 );
nw_normal = tgFakeNormal( nw_node );
}
if ( ! ne_flag ) {
ne_node = Point3D( max.x, max.y, 0.0 );
ne_normal = tgFakeNormal( ne_node );
}
// separate nodes and normals into components
body_nodes.clear();
point_list nodes = c->get_geod_nodes();
point_list point_normals = c->get_point_normals();
SG_LOG(SG_GENERAL, SG_ALERT, "number of geod nodes = " << nodes.size() );
SG_LOG(SG_GENERAL, SG_ALERT, "number of normals = " << point_normals.size() );
for ( i = 0; i < (int)nodes.size(); ++i ) {
Point3D node = nodes[i];
Point3D normal = point_normals[i];
if ( (fabs(node.y() - min.y) < SG_EPSILON) &&
(fabs(node.x() - min.x) < SG_EPSILON) ) {
if ( ! sw_flag ) {
sw_node = node;
sw_normal = normal;
}
} else if ( (fabs(node.y() - min.y) < SG_EPSILON) &&
(fabs(node.x() - max.x) < SG_EPSILON) ) {
if ( ! se_flag ) {
se_node = node;
se_normal = normal;
}
} else if ( (fabs(node.y() - max.y) < SG_EPSILON) &&
(fabs(node.x() - max.x) < SG_EPSILON)) {
if ( ! ne_flag ) {
ne_node = node;
ne_normal = normal;
}
} else if ( (fabs(node.y() - max.y) < SG_EPSILON) &&
(fabs(node.x() - min.x) < SG_EPSILON) ) {
if ( ! nw_flag ) {
nw_node = node;
nw_normal = normal;
}
} else if ( fabs(node.x() - min.x) < SG_EPSILON ) {
if ( ! west_flag ) {
west_nodes.push_back( node );
west_normals.push_back( normal );
}
} else if ( fabs(node.x() - max.x) < SG_EPSILON ) {
if ( ! east_flag ) {
east_nodes.push_back( node );
east_normals.push_back( normal );
}
} else if ( fabs(node.y() - min.y) < SG_EPSILON ) {
if ( ! south_flag ) {
south_nodes.push_back( node );
south_normals.push_back( normal );
}
} else if ( fabs(node.y() - max.y) < SG_EPSILON ) {
if ( ! north_flag ) {
north_nodes.push_back( node );
north_normals.push_back( normal );
}
} else {
body_nodes.push_back( node );
body_normals.push_back( normal );
}
}
#if 0 // UNUSED
// separate area edge segment into components
cout << " extracting (shared) area edge segments" << endl;
TGTriSeg seg;
Point3D p1, p2;
triseg_list seg_list = c.get_tri_segs().get_seg_list();
triseg_list_iterator current = seg_list.begin();
triseg_list_iterator last = seg_list.end();
for ( ; current != last; ++current ) {
seg = *current;
p1 = nodes[ seg.get_n1() ];
p2 = nodes[ seg.get_n2() ];
if ( fabs(p1.y() - p2.y()) < SG_EPSILON ) {
// check if horizontal
if ( fabs(p1.y() - max.y) < SG_EPSILON ) {
north_segs.push_back( seg );
} else if ( fabs(p1.y() - min.y) < SG_EPSILON ) {
south_segs.push_back( seg );
} else {
body_segs.push_back( seg );
}
} else if ( fabs(p1.x() - p2.x()) < SG_EPSILON ) {
// check if vertical
if ( fabs(p1.x() - max.x) < SG_EPSILON ) {
east_segs.push_back( seg );
} else if ( fabs(p1.x() - min.x) < SG_EPSILON ) {
west_segs.push_back( seg );
} else {
body_segs.push_back( seg );
}
} else {
body_segs.push_back( seg );
}
}
if ( !sw_flag ) { cout << " sw corner = " << sw_node << endl; }
if ( !se_flag ) { cout << " se corner = " << se_node << endl; }
if ( !ne_flag ) { cout << " ne corner = " << ne_node << endl; }
if ( !nw_flag ) { cout << " nw corner = " << nw_node << endl; }
/*
if ( !north_flag ) {
cout << " north nodes = " << north_nodes.size() << endl;
for ( i = 0; i < (int)north_nodes.size(); ++i ) {
cout << " " << north_nodes[i] << endl;
}
}
if ( !south_flag ) {
cout << " south nodes = " << south_nodes.size() << endl;
for ( i = 0; i < (int)south_nodes.size(); ++i ) {
cout << " " << south_nodes[i] << endl;
}
}
if ( !east_flag ) {
cout << " east nodes = " << east_nodes.size() << endl;
for ( i = 0; i < (int)east_nodes.size(); ++i ) {
cout << " " << east_nodes[i] << endl;
}
}
if ( !west_flag ) {
cout << " west nodes = " << west_nodes.size() << endl;
for ( i = 0; i < (int)west_nodes.size(); ++i ) {
cout << " " << west_nodes[i] << endl;
}
}
cout << " body nodes = " << body_nodes.size() << endl;
for ( i = 0; i < (int)body_nodes.size(); ++i ) {
cout << " " << body_nodes[i] << endl;
}
*/
#endif
SG_LOG(SG_GENERAL, SG_ALERT, "SPLIT TILE COMPLETE " );
}
// write the new shared edge points, normals, and segments for this
// tile
void TGMatch::write_shared( SGBucket b, string shared ) {
string dir = shared + "/" + b.gen_base_path();
string file = dir + "/" + b.gen_index_str();
SGPath sgp( dir );
sgp.append( "dummy" );
sgp.create_dir( 0755 );
//cout << "shared data will be written to " << file << endl;
#if 0
cout << "FLAGS" << endl;
cout << "=====" << endl;
cout << "sw_flag = " << sw_flag << endl;
cout << "se_flag = " << se_flag << endl;
cout << "ne_flag = " << ne_flag << endl;
cout << "nw_flag = " << nw_flag << endl;
cout << "north_flag = " << north_flag << endl;
cout << "south_flag = " << south_flag << endl;
cout << "east_flag = " << east_flag << endl;
cout << "west_flag = " << west_flag << endl;
#endif
FILE *fp;
if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
// cout << "ERROR: opening " << file << " for writing!" << endl;
exit(-1);
}
/*
* We only write data out for those sides for which the adjacent
* tiles still have to be built.
*
* If we have already read data for a given corner or side, this
* means that the adjacent tile already has been built.
*/
if ( ! sw_flag ) {
fprintf( fp, "sw_node %.10f %.10f %.10f\n",
sw_node.x(), sw_node.y(), sw_node.z() );
fprintf( fp, "sw_normal %.10f %.10f %.10f\n",
sw_normal.x(), sw_normal.y(), sw_normal.z() );
}
if ( ! se_flag ) {
fprintf( fp, "se_node %.10f %.10f %.10f\n",
se_node.x(), se_node.y(), se_node.z() );
fprintf( fp, "se_normal %.10f %.10f %.10f\n",
se_normal.x(), se_normal.y(), se_normal.z() );
}
if ( ! nw_flag ) {
fprintf( fp, "nw_node %.10f %.10f %.10f\n",
nw_node.x(), nw_node.y(), nw_node.z() );
fprintf( fp, "nw_normal %.10f %.10f %.10f\n",
nw_normal.x(), nw_normal.y(), nw_normal.z() );
}
if ( ! ne_flag ) {
fprintf( fp, "ne_node %.10f %.10f %.10f\n",
ne_node.x(), ne_node.y(), ne_node.z() );
fprintf( fp, "ne_normal %.10f %.10f %.10f\n",
ne_normal.x(), ne_normal.y(), ne_normal.z() );
}
if ( ! north_flag ) {
if ( (int)north_nodes.size() == 0 ) {
fprintf( fp, "n_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)north_nodes.size(); ++i ) {
fprintf( fp, "n_node %.10f %.10f %.10f\n",
north_nodes[i].x(), north_nodes[i].y(),
north_nodes[i].z() );
fprintf( fp, "n_normal %.10f %.10f %.10f\n",
north_normals[i].x(), north_normals[i].y(),
north_normals[i].z() );
}
}
}
if ( ! south_flag ) {
if ( (int)south_nodes.size() == 0 ) {
fprintf( fp, "s_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)south_nodes.size(); ++i ) {
fprintf( fp, "s_node %.10f %.10f %.10f\n",
south_nodes[i].x(), south_nodes[i].y(),
south_nodes[i].z() );
fprintf( fp, "s_normal %.10f %.10f %.10f\n",
south_normals[i].x(), south_normals[i].y(),
south_normals[i].z() );
}
}
}
if ( ! east_flag ) {
if ( (int)east_nodes.size() == 0 ) {
fprintf( fp, "e_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)east_nodes.size(); ++i ) {
fprintf( fp, "e_node %.10f %.10f %.10f\n",
east_nodes[i].x(), east_nodes[i].y(),
east_nodes[i].z() );
fprintf( fp, "e_normal %.10f %.10f %.10f\n",
east_normals[i].x(), east_normals[i].y(),
east_normals[i].z() );
}
}
}
if ( ! west_flag ) {
if ( (int)west_nodes.size() == 0 ) {
fprintf( fp, "w_null -999.0 -999.0 -999.0\n" );
} else {
for ( int i = 0; i < (int)west_nodes.size(); ++i ) {
fprintf( fp, "w_node %.10f %.10f %.10f\n",
west_nodes[i].x(), west_nodes[i].y(),
west_nodes[i].z() );
fprintf( fp, "w_normal %.10f %.10f %.10f\n",
west_normals[i].x(), west_normals[i].y(),
west_normals[i].z() );
}
}
}
#if 0 // not needed
point_list nodes = c.get_geod_nodes();
Point3D p1, p2;
for ( int i = 0; i < (int)north_segs.size(); ++i ) {
p1 = nodes[ north_segs[i].get_n1() ];
p2 = nodes[ north_segs[i].get_n2() ];
fprintf( fp, "n_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)south_segs.size(); ++i ) {
p1 = nodes[ south_segs[i].get_n1() ];
p2 = nodes[ south_segs[i].get_n2() ];
fprintf( fp, "s_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)east_segs.size(); ++i ) {
p1 = nodes[ east_segs[i].get_n1() ];
p2 = nodes[ east_segs[i].get_n2() ];
fprintf( fp, "e_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
for ( int i = 0; i < (int)west_segs.size(); ++i ) {
p1 = nodes[ west_segs[i].get_n1() ];
p2 = nodes[ west_segs[i].get_n2() ];
fprintf( fp, "w_seg %.10f %.10f %.10f %.10f\n",
p1.x(), p1.y(), p2.x(), p2.y() );
}
#endif
fclose( fp );
string command = "gzip --force --best " + file;
system(command.c_str());
}
// insert normal into vector, extending it first if needed
void insert_normal( point_list& normals, Point3D n, int i ) {
Point3D empty( 0.0 );
// extend vector if needed
while ( i >= (int)normals.size() ) {
normals.push_back( empty );
}
normals[i] = n;
}
// Just add nodes and normals to the node list
void TGMatch::add_shared_nodes( TGConstruct* c ) {
TGNodes* nodes;
nodes = c->get_nodes();
// cout << " BEFORE ADDING SHARED NODES: " << nodes->size() << endl;
if ( sw_flag ) {
nodes->unique_add_fixed_elevation( sw_node );
}
if ( se_flag ) {
nodes->unique_add_fixed_elevation( se_node );
}
if ( nw_flag ) {
nodes->unique_add_fixed_elevation( nw_node );
}
if ( ne_flag ) {
nodes->unique_add_fixed_elevation( ne_node );
}
if ( north_flag ) {
for (unsigned int i = 0; i < north_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( north_nodes[i] );
}
}
if ( south_flag ) {
for (unsigned int i = 0; i < south_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( south_nodes[i] );
}
}
if ( east_flag ) {
for (unsigned int i = 0; i < east_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( east_nodes[i] );
}
}
if ( west_flag ) {
for (unsigned int i = 0; i < west_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( west_nodes[i] );
}
}
// cout << " AFTER ADDING SHARED NODES: " << nodes->size() << endl;
}
// reassemble the tile pieces (combining the shared data and our own
// data)
void TGMatch::assemble_tile( TGConstruct* c ) {
int i;
TGTriNodes new_nodes;
new_nodes.clear();
point_list new_normals;
new_normals.clear();
TGTriSegments new_segs;
new_segs.clear();
// add the corner points
int sw_index = new_nodes.unique_add( sw_node );
insert_normal( new_normals, sw_normal, sw_index );
int se_index = new_nodes.unique_add( se_node );
insert_normal( new_normals, se_normal, se_index );
int ne_index = new_nodes.unique_add( ne_node );
insert_normal( new_normals, ne_normal, ne_index );
int nw_index = new_nodes.unique_add( nw_node );
insert_normal( new_normals, nw_normal, nw_index );
// cout << "after adding corners:" << endl;
// cout << " new_nodes = " << new_nodes.size() << endl;
// cout << " new normals = " << new_normals.size() << endl;
// add the edge points
int index;
// cout << "Total north nodes = " << north_nodes.size() << endl;
for ( i = 0; i < (int)north_nodes.size(); ++i ) {
// cout << "adding north node " << north_nodes[i] << endl;
index = new_nodes.unique_add( north_nodes[i] );
insert_normal( new_normals, north_normals[i], index );
}
for ( i = 0; i < (int)south_nodes.size(); ++i ) {
index = new_nodes.unique_add( south_nodes[i] );
insert_normal( new_normals, south_normals[i], index );
}
for ( i = 0; i < (int)east_nodes.size(); ++i ) {
index = new_nodes.unique_add( east_nodes[i] );
insert_normal( new_normals, east_normals[i], index );
}
// cout << "Total west nodes = " << west_nodes.size() << endl;
for ( i = 0; i < (int)west_nodes.size(); ++i ) {
// cout << "adding west node " << west_nodes[i] << endl;
index = new_nodes.unique_add( west_nodes[i] );
insert_normal( new_normals, west_normals[i], index );
}
// cout << "after adding edges:" << endl;
// cout << " new_nodes = " << new_nodes.size() << endl;
// cout << " new normals = " << new_normals.size() << endl;
// add the body points
for ( i = 0; i < (int)body_nodes.size(); ++i ) {
index = new_nodes.unique_add( body_nodes[i] );
insert_normal( new_normals, body_normals[i], index );
}
// cout << "after adding body points:" << endl;
// cout << " new_nodes = " << new_nodes.size() << endl;
// cout << " new normals = " << new_normals.size() << endl;
// add the edge segments
new_segs.unique_divide_and_add( new_nodes.get_node_list(),
TGTriSeg(sw_index, se_index, 1) );
new_segs.unique_divide_and_add( new_nodes.get_node_list(),
TGTriSeg(se_index, ne_index, 1) );
new_segs.unique_divide_and_add( new_nodes.get_node_list(),
TGTriSeg(ne_index, nw_index, 1) );
new_segs.unique_divide_and_add( new_nodes.get_node_list(),
TGTriSeg(nw_index, sw_index, 1) );
// cout << "after adding edge segments:" << endl;
// cout << " new_nodes = " << new_nodes.size() << endl;
// cout << " new normals = " << new_normals.size() << endl;
// add the body segments
point_list geod_nodes = c->get_geod_nodes();
TGTriSeg seg;
Point3D p1, p2;
int n1, n2, marker;
triseg_list_iterator current = body_segs.begin();
triseg_list_iterator last = body_segs.end();
for ( ; current != last; ++current ) {
seg = *current;
// get the original points (x,y,z)
p1 = geod_nodes[ seg.get_n1() ];
p2 = geod_nodes[ seg.get_n2() ];
marker = seg.get_boundary_marker();
// make sure these points are in the new node list (and get
// their new index)
n1 = new_nodes.unique_add( p1 );
if ( n1 >= (int)new_normals.size() ) {
// cout << "Adding a segment resulted in a new node, faking a normal"
// << endl;
Point3D fake = tgFakeNormal( p1 );
insert_normal( new_normals, fake, n1 );
}
n2 = new_nodes.unique_add( p2 );
if ( n2 >= (int)new_normals.size() ) {
// cout << "Adding a segment resulted in a new node, faking a normal"
// << endl;
Point3D fake = tgFakeNormal( p2 );
insert_normal( new_normals, fake, n2 );
}
// add the segment using the new indices
new_segs.unique_divide_and_add( new_nodes.get_node_list(),
TGTriSeg(n1, n2, marker) );
}
#if 0 // UNUSED
c.set_tri_nodes( new_nodes );
c.set_point_normals( new_normals );
c.set_tri_segs( new_segs );
cout << "after adding all segments (should be the same):" << endl;
cout << " new_nodes = " << new_nodes.size() << endl;
cout << " new normals = " << new_normals.size() << endl;
#endif
}

View file

@ -1,130 +0,0 @@
// match.hxx -- Class to help match up tile edges
//
// Written by Curtis Olson, started April 1999.
//
// Copyright (C) 1998 - 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: match.hxx,v 1.7 2004-11-19 22:25:49 curt Exp $
#ifndef _MATCH_HXX
#define _MATCH_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <string>
#include <vector>
#include <simgear/compiler.h>
#include <simgear/math/sg_types.hxx>
#include <simgear/bucket/newbucket.hxx>
// TO REMOVE
#include <Geometry/trieles.hxx>
#include <Geometry/trinodes.hxx>
#include <Geometry/trisegs.hxx>
// TO REMOVE
// Forward Declaration
class TGConstruct;
class TGMatch {
private:
// nodes breakdown
Point3D sw_node, se_node, ne_node, nw_node;
point_list north_nodes, south_nodes, east_nodes, west_nodes;
point_list body_nodes;
// normals breakdown
Point3D sw_normal, se_normal, ne_normal, nw_normal;
point_list north_normals, south_normals, east_normals, west_normals;
point_list body_normals;
// flags
// a flag is set if and only if we have read data for the given
// corner or side
bool sw_flag, se_flag, ne_flag, nw_flag;
bool north_flag, south_flag, east_flag, west_flag;
// segment breakdown
triseg_list north_segs, south_segs, east_segs, west_segs;
triseg_list body_segs;
public:
enum neighbor_type {
SW_Corner = 1,
SE_Corner = 2,
NE_Corner = 3,
NW_Corner = 4,
NORTH = 5,
SOUTH = 6,
EAST = 7,
WEST = 8
};
// Constructor
TGMatch( void );
// Destructor
~TGMatch( void );
// load any previously existing shared data from all neighbors (if
// shared data for a component exists set that components flag to
// true
void load_neighbor_shared( SGBucket b, std::string base );
// try to load any missing shared data from our own shared data file
void load_missing_shared( SGBucket b, std::string base );
// scan the specified share file for the specified information
void scan_share_file( const std::string& dir, const SGBucket& b,
neighbor_type search, neighbor_type dest );
// try to find info for the specified shared component
void load_shared( SGBucket b, std::string base, neighbor_type n );
// NEW TILE MATCHING - PRE TRIANGULATION
// Just add nodes and normals to the node list
void add_shared_nodes( TGConstruct* c );
// split up the tile between the shared edge points, normals, and
// segments and the body. This must be done after calling
// load_neighbor_data() and will ignore any shared data from the
// current tile that already exists from a neighbor.
void split_tile( SGBucket b, TGConstruct* c );
// write the new shared edge points, normals, and segments for
// this tile
void write_shared( SGBucket b, std::string base );
// reassemble the tile pieces (combining the shared data and our
// own data)
void assemble_tile( TGConstruct* c );
};
// fake a normal for a point which is basically straight up
Point3D tgFakeNormal( const Point3D& p );
#endif // _MATCH_HXX

View file

@ -1,4 +1,5 @@
#include <simgear/debug/logstream.hxx>
#include <CGAL/Plane_3.h>
#include "tg_nodes.hxx"
@ -119,6 +120,36 @@ point_list TGNodes::get_geod_inside( Point3D min, Point3D max ) const {
return points;
}
void TGNodes::get_geod_edge( SGBucket b, point_list& north, point_list& south, point_list& east, point_list& west ) const {
const_node_list_iterator current, last;
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();
for ( ; current != last; ++current ) {
Point3D pt = (*current).GetPosition();
// may save the same point twice - so we get all the corners
if ( fabs(pt.y() - north_compare) < SG_EPSILON) {
north.push_back( pt );
}
if ( fabs(pt.y() - south_compare) < SG_EPSILON) {
south.push_back( pt );
}
if ( fabs(pt.x() - east_compare) < SG_EPSILON) {
east.push_back( pt );
}
if ( fabs(pt.x() - west_compare) < SG_EPSILON) {
west.push_back( pt );
}
}
}
std::vector< SGVec3d > TGNodes::get_wgs84_nodes_as_SGVec3d( void ) const {
const_node_list_iterator current, last;
std::vector< SGVec3d > points;
@ -201,6 +232,90 @@ void TGNodes::Dump( void ) {
}
}
// input from stream
std::istream& operator >> ( std::istream& in, TGNode& n )
{
int i, nCount;
// Load a tgnode
in >> n.position;
n.CalcWgs84();
in >> n.normal;
in >> n.fixed_position;
in >> n.fixed_normal;
in >> nCount;
for (i=0; i<nCount; i++) {
TGFaceLookup face;
in >> face.area;
in >> face.shape;
in >> face.seg;
in >> face.tri;
n.faces.push_back( face );
}
return in;
}
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;
}
// input from stream
std::istream& operator >> ( std::istream& in, TGNodes& ns )
{
int i, nCount;
// Load all tgnodes
in >> nCount;
for (i=0; i<nCount; i++) {
TGNode node;
in >> node;
ns.tg_node_list.push_back( node );
}
return in;
}
std::ostream& operator<< ( std::ostream& out, const TGNodes& ns )
{
int i, nCount;
// 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;
}
#if 0
bool TGNodes::LookupFixedElevation( Point3D p, double* z )
{

View file

@ -7,6 +7,7 @@
#endif
#include <simgear/compiler.h>
#include <simgear/bucket/newbucket.hxx>
#include <Geometry/point3d.hxx>
#include <simgear/math/sg_types.hxx>
@ -26,6 +27,10 @@ typedef std::vector < TGFaceLookup > TGFaceList;
class TGNode {
public:
TGNode() {
// constructor for serialization only
}
TGNode( Point3D p ) {
position = p;
normal = Point3D();
@ -88,6 +93,10 @@ public:
inline void SetNormal( const Point3D& n ) { normal = n; }
inline Point3D GetNormal( void ) const { return normal; }
// Friends for serialization
friend std::istream& operator>> ( std::istream&, TGNode& );
friend std::ostream& operator<< ( std::ostream&, const TGNode& );
private:
Point3D position;
Point3D normal;
@ -152,7 +161,10 @@ public:
// Find all the nodes within a bounding box
point_list get_geod_inside( Point3D min, Point3D max ) const;
// Find a;; the nodes on the tile edges
void get_geod_edge( SGBucket b, point_list& north, point_list& south, point_list& east, point_list& west ) const;
// return a point list of wgs84 nodes
std::vector< SGVec3d > get_wgs84_nodes_as_SGVec3d() const;
point_list get_wgs84_nodes_as_Point3d() const;
@ -173,6 +185,10 @@ public:
void Dump( void );
// Friends for serialization
friend std::istream& operator>> ( std::istream&, TGNodes& );
friend std::ostream& operator<< ( std::ostream&, const TGNodes& );
private:
node_list tg_node_list;

View file

@ -970,7 +970,6 @@ TGPolygon tgPolygonSimplify(const TGPolygon &poly)
// Send a polygon to standard output.
std::ostream& operator << (std::ostream &output, const TGPolygon &poly)
{
char buff[128];
int nContours = poly.contours();
// Save the number of contours

View file

@ -94,40 +94,25 @@ std::istream& operator>> ( std::istream& input, TGSuperPoly& sp )
// Load the data
input >> sp.material;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: material " << sp.material );
input >> sp.poly;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: poly " << sp.poly );
input >> sp.normals;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: normals " << sp.normals );
input >> sp.texcoords;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: texcoords " << sp.texcoords );
input >> sp.tris;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: tris " << sp.tris );
input >> sp.tri_idxs;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: tri_idxs " << sp.tri_idxs );
input >> nFaceNormals;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: nFaceNormals " << nFaceNormals );
for ( int i = 0; i < nFaceNormals; i++ ) {
input >> normal;
sp.face_normals.push_back(normal);
}
input >> nFaceAreas;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: nFaceAreas " << nFaceAreas );
for ( int i = 0; i < nFaceAreas; i++ ) {
input >> area;
sp.face_areas.push_back(area);
}
input >> sp.flag;
SG_LOG(SG_GENERAL, SG_ALERT, "\t\tsp: flag " << sp.flag );
return input;
}