genapt850 optomizations - use hashes for SGGeod, SGVec3f and SGVec2f lists
This commit is contained in:
parent
c9f79718fa
commit
3f072c42f8
16 changed files with 984 additions and 260 deletions
|
@ -8,6 +8,8 @@
|
|||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
@ -18,22 +20,15 @@
|
|||
#include <simgear/misc/texcoord.hxx>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/texparams.hxx>
|
||||
#include <Polygon/superpoly.hxx>
|
||||
#include <Polygon/texparams.hxx>
|
||||
#include <Polygon/chop.hxx>
|
||||
|
||||
#include <Geometry/poly_support.hxx>
|
||||
#include <Geometry/poly_extra.hxx>
|
||||
#include <Polygon/tg_unique_geod.hxx>
|
||||
#include <Polygon/tg_unique_vec3f.hxx>
|
||||
#include <Polygon/tg_unique_vec2f.hxx>
|
||||
|
||||
#include <Output/output.hxx>
|
||||
|
||||
#include "global.hxx"
|
||||
#include "elevations.hxx"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
string SGLOG_GREEN = "\033[0;32m";
|
||||
string SGLOG_NORMAL = "\033[0m";
|
||||
|
||||
|
@ -57,7 +52,7 @@ Airport::Airport( int c, char* def)
|
|||
// we need to tokenize airports, since we can't scanf two strings next to each other...
|
||||
numParams = 0;
|
||||
bool done = false;
|
||||
|
||||
|
||||
while (!done)
|
||||
{
|
||||
// trim leading whitespace
|
||||
|
@ -232,18 +227,29 @@ bool Airport::isDebugFeature( int feat )
|
|||
// TODO : Add somewhere
|
||||
// Determine node elevations of a point_list based on the provided
|
||||
// TGAptSurface. Offset is added to the final elevation
|
||||
static point_list calc_elevations( TGAptSurface &surf,
|
||||
const point_list& geod_nodes,
|
||||
double offset )
|
||||
static std::vector<SGGeod> calc_elevations( TGAptSurface &surf, const std::vector<SGGeod>& geod_nodes, double offset )
|
||||
{
|
||||
std::vector<SGGeod> result = geod_nodes;
|
||||
for ( unsigned int i = 0; i < result.size(); ++i ) {
|
||||
double elev = surf.query( result[i] );
|
||||
result[i].setElevationM( elev + offset );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 1 // unused
|
||||
static point_list calc_elevations( TGAptSurface &surf, const point_list& geod_nodes, double offset )
|
||||
{
|
||||
point_list result = geod_nodes;
|
||||
for ( unsigned int i = 0; i < result.size(); ++i ) {
|
||||
double elev = surf.query( SGGeod::fromDeg( result[i].lon(), result[i].lat()) );
|
||||
double elev = surf.query( SGGeod::fromDeg( result[i].x(), result[i].y() ) );
|
||||
result[i].setelev( elev + offset );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static tgContour calc_elevations( TGAptSurface &surf,
|
||||
const tgContour& geod_nodes,
|
||||
|
@ -308,7 +314,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
// runway lights
|
||||
tglightcontour_list rwy_lights;
|
||||
|
||||
Point3D p;
|
||||
//Point3D p;
|
||||
|
||||
bool make_shapefiles = false;
|
||||
|
||||
|
@ -600,8 +606,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
|
||||
// add segments to polygons to remove any possible "T"
|
||||
// intersections
|
||||
TGTriNodes tmp_pvmt_nodes;
|
||||
TGTriNodes tmp_feat_nodes;
|
||||
//TGTriNodes tmp_pvmt_nodes;
|
||||
//TGTriNodes tmp_feat_nodes;
|
||||
|
||||
UniqueSGGeodSet tmp_pvmt_nodes;
|
||||
UniqueSGGeodSet tmp_feat_nodes;
|
||||
|
||||
// build temporary node list from runways...
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Build Node List " );
|
||||
|
@ -612,7 +621,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < poly.ContourSize( i ); ++j )
|
||||
{
|
||||
tmp_pvmt_nodes.unique_add( Point3D::fromSGGeod( poly.GetNode(i, j) ) );
|
||||
tmp_pvmt_nodes.add( poly.GetNode(i, j) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -625,7 +634,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < poly.ContourSize( i ); ++j )
|
||||
{
|
||||
tmp_pvmt_nodes.unique_add( Point3D::fromSGGeod( poly.GetNode(i, j) ) );
|
||||
tmp_pvmt_nodes.add( poly.GetNode(i, j) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -638,7 +647,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < poly.ContourSize( i ); ++j )
|
||||
{
|
||||
tmp_feat_nodes.unique_add( Point3D::fromSGGeod( poly.GetNode(i, j) ) );
|
||||
tmp_feat_nodes.add( poly.GetNode(i, j) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -648,7 +657,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < base_poly.ContourSize( i ); ++j )
|
||||
{
|
||||
tmp_pvmt_nodes.unique_add( Point3D::fromSGGeod( base_poly.GetNode(i, j) ) );
|
||||
tmp_pvmt_nodes.add( base_poly.GetNode(i, j) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,7 +667,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < divided_base.ContourSize( i ); ++j )
|
||||
{
|
||||
tmp_pvmt_nodes.unique_add( Point3D::fromSGGeod( divided_base.GetNode(i, j) ) );
|
||||
tmp_pvmt_nodes.add( divided_base.GetNode(i, j) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,7 +678,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
for ( unsigned int k = 0; k < rwy_polys.size(); ++k )
|
||||
{
|
||||
tgPolygon poly = rwy_polys[k];
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_pvmt_nodes );
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_pvmt_nodes.get_list() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.TotalNodes());
|
||||
rwy_polys[k] = poly;
|
||||
}
|
||||
|
@ -678,7 +687,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
for ( unsigned int k = 0; k < pvmt_polys.size(); ++k )
|
||||
{
|
||||
tgPolygon poly = pvmt_polys[k];
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_pvmt_nodes );
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_pvmt_nodes.get_list() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.TotalNodes());
|
||||
pvmt_polys[k] = poly;
|
||||
}
|
||||
|
@ -687,7 +696,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
for ( unsigned int k = 0; k < line_polys.size(); ++k )
|
||||
{
|
||||
tgPolygon poly = line_polys[k];
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_feat_nodes );
|
||||
poly = tgPolygon::AddColinearNodes( poly, tmp_feat_nodes.get_list() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.TotalNodes());
|
||||
line_polys[k] = poly;
|
||||
}
|
||||
|
@ -715,7 +724,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
log_time = time(0);
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Finished cleaning polys for " << icao << " at " << my_ctime(log_time) );
|
||||
|
||||
base_poly = tgPolygon::AddColinearNodes( base_poly, tmp_pvmt_nodes );
|
||||
base_poly = tgPolygon::AddColinearNodes( base_poly, tmp_pvmt_nodes.get_list() );
|
||||
base_poly = tgPolygon::Snap( base_poly, gSnap );
|
||||
|
||||
// Finally find slivers in base
|
||||
|
@ -815,11 +824,10 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
|
||||
// traverse the tri list and create ordered node and texture
|
||||
// coordinate lists
|
||||
|
||||
TGTriNodes nodes, normals, texcoords;
|
||||
nodes.clear();
|
||||
normals.clear();
|
||||
texcoords.clear();
|
||||
// start with just nodes
|
||||
UniqueSGGeodSet nodes;
|
||||
UniqueSGVec3fSet normals;
|
||||
UniqueSGVec2fSet texcoords;
|
||||
|
||||
group_list pts_v; pts_v.clear();
|
||||
group_list pts_n; pts_n.clear();
|
||||
|
@ -841,9 +849,8 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
int_list tri_tc, strip_tc;
|
||||
|
||||
// calculate "the" normal for this airport
|
||||
SGVec3d vnt = SGVec3d::fromGeod( base_poly.GetNode(0, 0) );
|
||||
SGVec3f vnt = SGVec3f::fromGeod( base_poly.GetNode(0, 0) );
|
||||
vnt = normalize(vnt);
|
||||
Point3D vn = Point3D::fromSGVec3(vnt);
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Adding runway nodes and normals");
|
||||
for ( unsigned int k = 0; k < rwy_polys.size(); ++k )
|
||||
|
@ -860,17 +867,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
// let's go out on a limb, and assume triangles have 3 points..
|
||||
for ( int j = 0; j < 3; ++j )
|
||||
{
|
||||
p = Point3D::fromSGGeod( rwy_polys[k].GetTriNode( i, j ) );
|
||||
index = nodes.unique_add( p );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "added rwy point " << p << " at " << index );
|
||||
index = nodes.add( rwy_polys[k].GetTriNode( i, j ) );
|
||||
tri_v.push_back( index );
|
||||
|
||||
// use 'the' normal
|
||||
index = normals.unique_add( vn );
|
||||
index = normals.add( vnt );
|
||||
tri_n.push_back( index );
|
||||
|
||||
Point3D tc = Point3D::fromSGVec2( rwy_polys[k].GetTriTexCoord( i, j ) );
|
||||
index = texcoords.unique_add( tc );
|
||||
index = texcoords.add( rwy_polys[k].GetTriTexCoord(i,j) );
|
||||
tri_tc.push_back( index );
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
|
@ -894,17 +898,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
tri_tc.clear();
|
||||
for ( int j = 0; j < 3; ++j )
|
||||
{
|
||||
p = Point3D::fromSGGeod( pvmt_polys[k].GetTriNode( i, j ) );
|
||||
index = nodes.unique_add( p );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "added pvmt point " << p << " at " << index );
|
||||
index = nodes.add( pvmt_polys[k].GetTriNode( i, j ) );
|
||||
tri_v.push_back( index );
|
||||
|
||||
// use 'the' normal
|
||||
index = normals.unique_add( vn );
|
||||
index = normals.add( vnt );
|
||||
tri_n.push_back( index );
|
||||
|
||||
Point3D tc = Point3D::fromSGVec2( pvmt_polys[k].GetTriTexCoord( i, j ) );
|
||||
index = texcoords.unique_add( tc );
|
||||
index = texcoords.add( pvmt_polys[k].GetTriTexCoord(i,j) );
|
||||
tri_tc.push_back( index );
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
|
@ -928,17 +929,14 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
tri_tc.clear();
|
||||
for ( int j = 0; j < 3; ++j )
|
||||
{
|
||||
p = Point3D::fromSGGeod( line_polys[k].GetTriNode( i, j ) );
|
||||
index = nodes.unique_add( p );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "added line point " << p << " at " << index );
|
||||
index = nodes.add( line_polys[k].GetTriNode( i, j ) );
|
||||
tri_v.push_back( index );
|
||||
|
||||
// use 'the' normal
|
||||
index = normals.unique_add( vn );
|
||||
index = normals.add( vnt );
|
||||
tri_n.push_back( index );
|
||||
|
||||
Point3D tc = Point3D::fromSGVec2( line_polys[k].GetTriTexCoord( i, j ) );
|
||||
index = texcoords.unique_add( tc );
|
||||
index = texcoords.add( line_polys[k].GetTriTexCoord(i,j) );
|
||||
tri_tc.push_back( index );
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
|
@ -960,33 +958,25 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
tri_tc.clear();
|
||||
for ( int j = 0; j < 3; ++j )
|
||||
{
|
||||
p = Point3D::fromSGGeod( base_poly.GetTriNode( i, j ) );
|
||||
index = nodes.unique_add( p );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "added base point " << p << " at " << index );
|
||||
index = nodes.add( base_poly.GetTriNode( i, j ) );
|
||||
tri_v.push_back( index );
|
||||
|
||||
index = normals.unique_add( vn );
|
||||
index = normals.add( vnt );
|
||||
tri_n.push_back( index);
|
||||
}
|
||||
tris_v.push_back( tri_v );
|
||||
tris_n.push_back( tri_n );
|
||||
tri_materials.push_back( "Grass" );
|
||||
|
||||
std::vector < SGGeod > geodNodes;
|
||||
for ( unsigned int j = 0; j < nodes.get_node_list().size(); j++ )
|
||||
{
|
||||
Point3D node = nodes.get_node_list()[j];
|
||||
geodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
|
||||
}
|
||||
base_txs.clear();
|
||||
std::vector < SGGeod > geodNodes = nodes.get_list();
|
||||
|
||||
base_txs.clear();
|
||||
base_txs = sgCalcTexCoords( b, geodNodes, tri_v );
|
||||
|
||||
base_tc.clear();
|
||||
for ( unsigned int j = 0; j < base_txs.size(); ++j )
|
||||
{
|
||||
SGVec2f tc = base_txs[j];
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
|
||||
index = texcoords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
|
||||
index = texcoords.add( base_txs[j] );
|
||||
base_tc.push_back( index );
|
||||
}
|
||||
tris_tc.push_back( base_tc );
|
||||
|
@ -999,7 +989,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
{
|
||||
for ( unsigned int j = 0; j < divided_base.ContourSize( i ); ++j )
|
||||
{
|
||||
index = nodes.unique_add( Point3D::fromSGGeod( divided_base.GetNode(i, j) ) );
|
||||
index = nodes.add( divided_base.GetNode(i, j) );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "added base point " << divided_base.GetNode(i, j) << " at " << index );
|
||||
}
|
||||
}
|
||||
|
@ -1013,7 +1003,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " calc average elevation");
|
||||
{
|
||||
point_list dbg = nodes.get_node_list();
|
||||
std::vector < SGGeod > dbg = nodes.get_list();
|
||||
|
||||
// dump the node list
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " node list size is " << dbg.size() );
|
||||
|
@ -1023,7 +1013,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
}
|
||||
}
|
||||
|
||||
double average = tgAverageElevation( root, elev_src, nodes.get_node_list() );
|
||||
double average = tgAverageElevationGeod( root, elev_src, nodes.get_list() );
|
||||
|
||||
// Now build the fitted airport surface ...
|
||||
|
||||
|
@ -1032,28 +1022,28 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
|
||||
SGGeod min_deg = SGGeod::fromDeg(9999.0, 9999.0);
|
||||
SGGeod max_deg = SGGeod::fromDeg(-9999.0, -9999.0);
|
||||
for ( unsigned int j = 0; j < nodes.get_node_list().size(); ++j )
|
||||
for ( unsigned int j = 0; j < nodes.get_list().size(); ++j )
|
||||
{
|
||||
Point3D p = nodes.get_node_list()[j];
|
||||
if ( p.lon() < min_deg.getLongitudeDeg() )
|
||||
SGGeod p = nodes.get_list()[j];
|
||||
if ( p.getLongitudeDeg() < min_deg.getLongitudeDeg() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lon from node " << j << " is " << p.lon() );
|
||||
min_deg.setLongitudeDeg( p.lon() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lon from node " << j << " is " << p.getLongitudeDeg() );
|
||||
min_deg.setLongitudeDeg( p.getLongitudeDeg() );
|
||||
}
|
||||
if ( p.lon() > max_deg.getLongitudeDeg() )
|
||||
if ( p.getLongitudeDeg() > max_deg.getLongitudeDeg() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lon from node " << j << " is " << p.lon() );
|
||||
max_deg.setLongitudeDeg( p.lon() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lon from node " << j << " is " << p.getLongitudeDeg() );
|
||||
max_deg.setLongitudeDeg( p.getLongitudeDeg() );
|
||||
}
|
||||
if ( p.lat() < min_deg.getLatitudeDeg() )
|
||||
if ( p.getLatitudeDeg() < min_deg.getLatitudeDeg() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lat from node " << j << " is " << p.lat() );
|
||||
min_deg.setLatitudeDeg( p.lat() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new min lat from node " << j << " is " << p.getLatitudeDeg() );
|
||||
min_deg.setLatitudeDeg( p.getLatitudeDeg() );
|
||||
}
|
||||
if ( p.lat() > max_deg.getLatitudeDeg() )
|
||||
if ( p.getLatitudeDeg() > max_deg.getLatitudeDeg() )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lat from node " << j << " is " << p.lat() );
|
||||
max_deg.setLatitudeDeg( p.lat() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "new max lat from node " << j << " is " << p.getLatitudeDeg() );
|
||||
max_deg.setLatitudeDeg( p.getLatitudeDeg() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1104,28 +1094,18 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
SG_LOG(SG_GENERAL, SG_DEBUG, " min: " << min_deg );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " max: " << max_deg );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " average: " << average );
|
||||
|
||||
|
||||
tg::Rectangle aptBounds(min_deg, max_deg);
|
||||
|
||||
TGAptSurface apt_surf( root, elev_src, aptBounds, average );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Airport surface created");
|
||||
|
||||
// calculate node elevations
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Computing airport node elevations");
|
||||
point_list geod_nodes = calc_elevations( apt_surf,
|
||||
nodes.get_node_list(),
|
||||
0.0 );
|
||||
divided_base = calc_elevations( apt_surf, divided_base, 0.0 );
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Done with base calc_elevations()");
|
||||
|
||||
|
||||
// add base skirt (to hide potential cracks)
|
||||
// this has to happen after we've calculated the node elevations
|
||||
// but before we convert to wgs84 coordinates
|
||||
|
||||
#if 0 // do we still need a skirt?
|
||||
int uindex, lindex;
|
||||
|
||||
for ( unsigned int i = 0; i < divided_base.Contours(); ++i )
|
||||
{
|
||||
strip_v.clear();
|
||||
|
@ -1133,8 +1113,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
strip_tc.clear();
|
||||
|
||||
// prime the pump ...
|
||||
p = Point3D::fromSGGeod( divided_base.GetNode( i, 0 ) );
|
||||
uindex = nodes.find( p );
|
||||
uindex = nodes.find( divided_base.GetNode( i, 0 ) );
|
||||
if ( uindex >= 0 )
|
||||
{
|
||||
Point3D lower = geod_nodes[uindex] - Point3D(0, 0, 20);
|
||||
|
@ -1222,89 +1201,59 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
base_tc.clear();
|
||||
for ( unsigned int j = 0; j < base_txs.size(); ++j )
|
||||
{
|
||||
SGVec2f tc = base_txs[j];
|
||||
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
|
||||
index = texcoords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
|
||||
index = texcoords.simple_add( base_txs[j] );
|
||||
base_tc.push_back( index );
|
||||
}
|
||||
strips_tc.push_back( base_tc );
|
||||
}
|
||||
#endif
|
||||
|
||||
// add light points
|
||||
superpoly_list tmp_light_list;
|
||||
tmp_light_list.clear();
|
||||
typedef std::map < string, double, std::less<string> > elev_map_type;
|
||||
typedef elev_map_type::const_iterator const_elev_map_iterator;
|
||||
elev_map_type elevation_map;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Computing runway/approach lighting elevations");
|
||||
|
||||
// pass one, calculate raw elevations from Array
|
||||
for ( unsigned int i = 0; i < rwy_lights.size(); ++i )
|
||||
{
|
||||
TGTriNodes light_nodes;
|
||||
light_nodes.clear();
|
||||
point_list lights_v = rwy_lights[i].TempGetPosListAsPoint3D();
|
||||
for ( unsigned int j = 0; j < lights_v.size(); ++j )
|
||||
{
|
||||
p = lights_v[j];
|
||||
index = light_nodes.simple_add( p );
|
||||
for ( unsigned int i = 0; i < rwy_lights.size(); ++i ) {
|
||||
for ( unsigned int j = 0; j < rwy_lights[i].ContourSize(); j++ ) {
|
||||
double light_elevation = calc_elevation( apt_surf, rwy_lights[i].GetNode(j), 0.0 );
|
||||
rwy_lights[i].SetElevation(j, light_elevation);
|
||||
}
|
||||
|
||||
// calculate light node elevations
|
||||
point_list geod_light_nodes = calc_elevations( apt_surf, light_nodes.get_node_list(), 0.0 );
|
||||
TGPolygon p;
|
||||
p.add_contour( geod_light_nodes, 0 );
|
||||
TGSuperPoly s;
|
||||
s.set_poly( p );
|
||||
tmp_light_list.push_back( s );
|
||||
|
||||
string flag = rwy_lights[i].GetFlag();
|
||||
if ( flag != (string)"" )
|
||||
{
|
||||
double max = -9999;
|
||||
const_elev_map_iterator it = elevation_map.find( flag );
|
||||
if ( it != elevation_map.end() )
|
||||
{
|
||||
max = elevation_map[flag];
|
||||
}
|
||||
for ( unsigned int j = 0; j < geod_light_nodes.size(); ++j )
|
||||
{
|
||||
if ( geod_light_nodes[j].z() > max )
|
||||
{
|
||||
max = geod_light_nodes[j].z();
|
||||
}
|
||||
}
|
||||
elevation_map[flag] = max;
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, flag << " max = " << max );
|
||||
}
|
||||
// TODO : It doesn't look like this does anything... got back in history and make sure...
|
||||
//string flag = rwy_lights[i].GetFlag();
|
||||
//if ( flag != (string)"" )
|
||||
//{
|
||||
// SG_LOG(SG_GENERAL, SG_INFO, " flag " << flag);
|
||||
// double max = -9999;
|
||||
// const_elev_map_iterator it = elevation_map.find( flag );
|
||||
// if ( it != elevation_map.end() )
|
||||
// {
|
||||
// max = elevation_map[flag];
|
||||
// }
|
||||
// for ( unsigned int j = 0; j < geod_light_nodes.size(); ++j )
|
||||
// {
|
||||
// if ( geod_light_nodes[j].z() > max )
|
||||
// {
|
||||
// max = geod_light_nodes[j].z();
|
||||
// }
|
||||
// }
|
||||
// elevation_map[flag] = max;
|
||||
// SG_LOG( SG_GENERAL, SG_INFO, " " << flag << " max = " << max );
|
||||
//}
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Done with lighting calc_elevations() num light polys is " << rwy_lights.size() );
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Done with lighting calc_elevations() num light polys is " << rwy_lights.size() );
|
||||
|
||||
// pass two, for each light group check if we need to lift (based
|
||||
// on flag) and do so, then output next structures.
|
||||
for ( unsigned int i = 0; i < rwy_lights.size(); ++i )
|
||||
// for ( unsigned int i = 0; i < rwy_lights.size(); ++i )
|
||||
for ( unsigned int i = 0; i < rwy_lights.size(); ++i )
|
||||
{
|
||||
// tmp_light_list is a parallel structure to rwy_lights
|
||||
point_list geod_light_nodes = tmp_light_list[i].get_poly().get_contour(0);
|
||||
|
||||
// this is a little round about, but what we want to calculate the
|
||||
// light node elevations as ground + an offset so we do them
|
||||
// seperately, then we add them back into nodes to get the index
|
||||
// out, but also add them to geod_nodes to maintain consistancy
|
||||
// between these two lists.
|
||||
point_list light_normals = rwy_lights[i].TempGetNormalListAsPoint3D();
|
||||
pt_v.clear();
|
||||
pt_n.clear();
|
||||
for ( unsigned int j = 0; j < geod_light_nodes.size(); ++j )
|
||||
for ( unsigned int j = 0; j < rwy_lights[i].ContourSize(); ++j )
|
||||
{
|
||||
p = geod_light_nodes[j];
|
||||
index = nodes.simple_add( p );
|
||||
index = nodes.add( rwy_lights[i].GetPosition(j) );
|
||||
pt_v.push_back( index );
|
||||
geod_nodes.push_back( p );
|
||||
|
||||
index = normals.unique_add( light_normals[j] );
|
||||
index = normals.add( rwy_lights[i].GetNormal(j) );
|
||||
pt_n.push_back( index );
|
||||
}
|
||||
pts_v.push_back( pt_v );
|
||||
|
@ -1312,22 +1261,25 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
pt_materials.push_back( rwy_lights[i].GetType() );
|
||||
}
|
||||
|
||||
// calculate node elevations
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Computing airport node elevations");
|
||||
|
||||
std::vector<SGGeod> geod_nodes = calc_elevations( apt_surf, nodes.get_list(), 0.0 );
|
||||
divided_base = calc_elevations( apt_surf, divided_base, 0.0 );
|
||||
|
||||
// calculate wgs84 mapping of nodes
|
||||
std::vector< SGVec3d > wgs84_nodes;
|
||||
std::vector<SGVec3d> wgs84_nodes;
|
||||
for ( unsigned int i = 0; i < geod_nodes.size(); ++i )
|
||||
{
|
||||
SGGeod geod = SGGeod::fromDegM( geod_nodes[i].x(), geod_nodes[i].y(), geod_nodes[i].z() );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "geod pt = " << geod_nodes[i] );
|
||||
SGVec3d cart = SGVec3d::fromGeod(geod);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " cart pt = " << cart );
|
||||
wgs84_nodes.push_back( cart );
|
||||
wgs84_nodes.push_back( SGVec3d::fromGeod(geod_nodes[i]) );
|
||||
}
|
||||
|
||||
SGSphered d;
|
||||
for ( unsigned int i = 0; i < wgs84_nodes.size(); ++i )
|
||||
{
|
||||
d.expandBy(wgs84_nodes[ i ]);
|
||||
}
|
||||
|
||||
|
||||
SGVec3d gbs_center = d.getCenter();
|
||||
double gbs_radius = d.getRadius();
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "gbs center = " << gbs_center);
|
||||
|
@ -1343,27 +1295,12 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src )
|
|||
string objpath = root + "/AirportObj";
|
||||
string name = icao + ".btg";
|
||||
|
||||
std::vector< SGVec3f > normals_3f;
|
||||
for ( unsigned int i = 0; i < normals.get_node_list().size(); i++ )
|
||||
{
|
||||
Point3D node = normals.get_node_list()[i];
|
||||
normals_3f.push_back( node.toSGVec3f() );
|
||||
}
|
||||
|
||||
std::vector< SGVec2f > texcoords_2f;
|
||||
for ( unsigned int i = 0; i < texcoords.get_node_list().size(); i++ )
|
||||
{
|
||||
Point3D node = texcoords.get_node_list()[i];
|
||||
texcoords_2f.push_back( node.toSGVec2f() );
|
||||
}
|
||||
|
||||
SGBinObject obj;
|
||||
|
||||
obj.set_gbs_center( gbs_center );
|
||||
obj.set_gbs_radius( gbs_radius );
|
||||
obj.set_wgs84_nodes( wgs84_nodes );
|
||||
obj.set_normals( normals_3f );
|
||||
obj.set_texcoords( texcoords_2f );
|
||||
obj.set_normals( normals.get_list() );
|
||||
obj.set_texcoords( texcoords.get_list() );
|
||||
obj.set_pts_v( pts_v );
|
||||
obj.set_pts_n( pts_n );
|
||||
obj.set_pt_materials( pt_materials );
|
||||
|
|
|
@ -129,6 +129,98 @@ double tgAverageElevation( const std::string &root, const string_list elev_src,
|
|||
return average;
|
||||
}
|
||||
|
||||
double tgAverageElevationGeod( const std::string &root, const string_list elev_src,
|
||||
const std::vector<SGGeod> points_source )
|
||||
{
|
||||
bool done = false;
|
||||
unsigned int i;
|
||||
TGArray array;
|
||||
|
||||
// make a copy so our routine is non-destructive.
|
||||
std::vector<SGGeod> points = points_source;
|
||||
|
||||
// just bail if no work to do
|
||||
if ( points.size() == 0 ) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// set all elevations to -9999
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
points[i].setElevationM( -9999.0 );
|
||||
}
|
||||
|
||||
while ( !done ) {
|
||||
// find first node with -9999 elevation
|
||||
SGGeod first = SGGeod();
|
||||
bool found_one = false;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
if ( points[i].getElevationM() < -9000.0 && !found_one ) {
|
||||
first = points[i];
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "found first = " << first );
|
||||
|
||||
found_one = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found_one ) {
|
||||
SGBucket b( first );
|
||||
std::string base = b.gen_base_path();
|
||||
|
||||
// try the various elevation sources
|
||||
i = 0;
|
||||
bool found_file = false;
|
||||
while ( !found_file && i < elev_src.size() ) {
|
||||
std::string array_path = root + "/" + elev_src[i] + "/" + base + "/" + b.gen_index_str();
|
||||
|
||||
if ( array.open(array_path) ) {
|
||||
found_file = true;
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Using array_path = " << array_path );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// this will fill in a zero structure if no array data
|
||||
// found/opened
|
||||
array.parse( b );
|
||||
|
||||
// this will do a hasty job of removing voids by inserting
|
||||
// data from the nearest neighbor (sort of)
|
||||
array.remove_voids();
|
||||
|
||||
// update all the non-updated elevations that are inside
|
||||
// this array file
|
||||
double elev;
|
||||
done = true;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
if ( points[i].getElevationM() < -9000.0 ) {
|
||||
done = false;
|
||||
elev = array.altitude_from_grid( points[i].getLongitudeDeg() * 3600.0,
|
||||
points[i].getLatitudeDeg() * 3600.0 );
|
||||
if ( elev > -9000 ) {
|
||||
points[i].setElevationM( elev );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array.close();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// now find the average height of the queried points
|
||||
double total = 0.0;
|
||||
int count = 0;
|
||||
for ( i = 0; i < points.size(); ++i ) {
|
||||
total += points[i].getElevationM();
|
||||
count++;
|
||||
}
|
||||
double average = total / (double) count;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Average surface height of point list = " << average);
|
||||
|
||||
return average;
|
||||
}
|
||||
|
||||
|
||||
// lookup node elevations for each point in the specified simple
|
||||
// matrix. Returns average of all points.
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
double tgAverageElevation( const std::string &root, const string_list elev_src,
|
||||
const point_list points_source );
|
||||
|
||||
// same - with a geod list
|
||||
double tgAverageElevationGeod( const std::string &root, const string_list elev_src,
|
||||
const std::vector<SGGeod> points_source );
|
||||
|
||||
// lookup node elevations for each point in the specified nurbs++
|
||||
// matrix.
|
||||
void tgCalcElevations( const std::string &root, const string_list elev_src, SimpleMatrix &Pts, double average );
|
||||
|
|
|
@ -44,7 +44,7 @@ tglightcontour_list Helipad::gen_helipad_lights(double maxsize) {
|
|||
tglightcontour_list result;
|
||||
|
||||
// Vector calculation
|
||||
SGVec3d vec = normalize(SGVec3d::fromGeod(GetLoc()));
|
||||
SGVec3f vec = normalize(SGVec3f::fromGeod(GetLoc()));
|
||||
|
||||
// Create yellow edge lights, 5m spacing
|
||||
tgContour area = gen_helipad_area_w_extend(0.0, 0.0);
|
||||
|
|
|
@ -34,7 +34,7 @@ using std::string;
|
|||
|
||||
// calculate the runway light direction vector. We take both runway
|
||||
// ends to get the direction of the runway.
|
||||
SGVec3d Runway::gen_runway_light_vector( float angle, bool recip ) {
|
||||
SGVec3f Runway::gen_runway_light_vector( float angle, bool recip ) {
|
||||
SGVec3f cart1, cart2;
|
||||
if ( !recip ) {
|
||||
cart1 = normalize(SGVec3f::fromGeod(GetStart()));
|
||||
|
@ -49,7 +49,7 @@ SGVec3d Runway::gen_runway_light_vector( float angle, bool recip ) {
|
|||
SGQuatf rotation = SGQuatf::fromAngleAxisDeg(angle, horizontal);
|
||||
SGVec3f light_vec = rotation.transform(runway_vec);
|
||||
|
||||
return (SGVec3d)light_vec;
|
||||
return light_vec;
|
||||
}
|
||||
|
||||
// generate runway edge lighting
|
||||
|
@ -68,7 +68,7 @@ tglightcontour_list Runway::gen_runway_edge_lights( bool recip )
|
|||
double step = dist / divs;
|
||||
SGGeod pt1, pt2;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
if ( recip ) {
|
||||
length_hdg = SGMiscd::normalizePeriodic(0, 360, rwy.heading + 180.0);
|
||||
|
@ -165,8 +165,8 @@ tglightcontour_list Runway::gen_runway_threshold_lights( const int kind, bool re
|
|||
ref2 = GetStart();
|
||||
}
|
||||
|
||||
SGVec3d normal1 = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3d normal2 = gen_runway_light_vector( 3.0, !recip );
|
||||
SGVec3f normal1 = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal2 = gen_runway_light_vector( 3.0, !recip );
|
||||
|
||||
double left_hdg = SGMiscd::normalizePeriodic(0, 360, length_hdg - 90.0);
|
||||
int divs = (int)(rwy.width + 4) / 3.0;
|
||||
|
@ -244,7 +244,7 @@ tglightcontour_list Runway::gen_runway_center_line_lights( bool recip )
|
|||
tgLightContour r_lights;
|
||||
tglightcontour_list result;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
SGGeod pt1, pt2;
|
||||
double length_hdg;
|
||||
|
@ -301,7 +301,7 @@ tgLightContour Runway::gen_touchdown_zone_lights( bool recip )
|
|||
{
|
||||
tgLightContour lights;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
// determine the start point.
|
||||
SGGeod ref;
|
||||
|
@ -360,11 +360,11 @@ tgLightContour Runway::gen_reil( const int kind, bool recip )
|
|||
{
|
||||
tgLightContour lights;
|
||||
string flag = rwy.rwnum[get_thresh0(recip)];
|
||||
SGVec3d normal;
|
||||
SGVec3f normal;
|
||||
|
||||
if (kind == 1) {
|
||||
// omnidirectional lights
|
||||
normal = normalize(SGVec3d::fromGeod(GetStart()));
|
||||
normal = normalize(SGVec3f::fromGeod(GetStart()));
|
||||
} else {
|
||||
// unidirectional lights
|
||||
normal = gen_runway_light_vector( 10, recip );
|
||||
|
@ -405,7 +405,7 @@ tglightcontour_list Runway::gen_calvert( const string &kind, bool recip )
|
|||
int i, j;
|
||||
string flag;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
// Generate long center bar of lights
|
||||
// determine the start point.
|
||||
|
@ -583,7 +583,7 @@ tglightcontour_list Runway::gen_alsf( const string &kind, bool recip )
|
|||
int i;
|
||||
string flag;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
// Generate long center bar of lights
|
||||
// determine the start point.
|
||||
|
@ -848,12 +848,12 @@ tgLightContour Runway::gen_odals( const int kind, bool recip )
|
|||
|
||||
int i;
|
||||
string material;
|
||||
SGVec3d normal;
|
||||
SGVec3f normal;
|
||||
|
||||
if (kind == 0) {
|
||||
// ODALS lighting is omni-directional, but we generate a normal as
|
||||
// a placeholder to keep everything happy.
|
||||
normal = normalize(SGVec3d::fromGeod(GetStart()));
|
||||
normal = normalize(SGVec3f::fromGeod(GetStart()));
|
||||
material = "RWY_ODALS_LIGHTS";
|
||||
} else {
|
||||
// RAIL lights are directional
|
||||
|
@ -906,7 +906,7 @@ tglightcontour_list Runway::gen_ssalx( const string& kind, bool recip )
|
|||
int i;
|
||||
string flag;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGGeod ref_save, pt;
|
||||
|
||||
// Generate long center bar of lights (every 200')
|
||||
|
@ -1023,7 +1023,7 @@ tglightcontour_list Runway::gen_malsx( const string& kind, bool recip )
|
|||
int i;
|
||||
string flag;
|
||||
|
||||
SGVec3d normal = gen_runway_light_vector( 3.0, recip );
|
||||
SGVec3f normal = gen_runway_light_vector( 3.0, recip );
|
||||
|
||||
// Generate long center bar of lights (every 60m)
|
||||
// determine the start point.
|
||||
|
|
|
@ -750,17 +750,17 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
|
|||
tmp = SGGeodesy::direct( prev_outer, heading, cur_light_dist );
|
||||
}
|
||||
|
||||
SGVec3d vec;
|
||||
SGVec3f vec;
|
||||
if ( !directional_light )
|
||||
{
|
||||
// calculate the omnidirectional normal
|
||||
vec = normalize(SGVec3d::fromGeod(tmp));
|
||||
vec = normalize(SGVec3f::fromGeod(tmp));
|
||||
} else
|
||||
{
|
||||
// calculate the directional normal
|
||||
double heading_vec = SGMiscd::normalizePeriodic( 0, 360, heading + 90.0 );
|
||||
SGVec3d cart1 = SGVec3d::fromGeod(tmp);
|
||||
SGVec3d cart2 = SGVec3d::fromGeod( SGGeodesy::direct( tmp, heading_vec, 10 ) );
|
||||
SGVec3f cart1 = SGVec3f::fromGeod(tmp);
|
||||
SGVec3f cart2 = SGVec3f::fromGeod( SGGeodesy::direct( tmp, heading_vec, 10 ) );
|
||||
vec = normalize(cart2 - cart1);
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
string airportareadir=work_dir+"/AirportArea";
|
||||
|
||||
// check for output redirect
|
||||
if ( redirect_port >= 0 ) {
|
||||
|
||||
|
@ -307,25 +309,37 @@ int main(int argc, char **argv)
|
|||
} else {
|
||||
// this is the main program -
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Launch command was " << argv[0] );
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Run genapts with " << num_threads << " threads" );
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Input file = " << input_file);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Terrain sources = ");
|
||||
for ( unsigned int i = 0; i < elev_src.size(); ++i ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " " << work_dir << "/" << elev_src[i] );
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Work directory = " << work_dir);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Nudge = " << nudge);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Longitude = " << min.getLongitudeDeg() << ':' << max.getLongitudeDeg());
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Latitude = " << min.getLatitudeDeg() << ':' << max.getLatitudeDeg());
|
||||
|
||||
if (!max.isValid() || !min.isValid())
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Bad longitude or latitude");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make work directory
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Creating AirportArea directory");
|
||||
|
||||
SGPath sgp( airportareadir );
|
||||
sgp.append( "dummy" );
|
||||
sgp.create_dir( 0755 );
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Run genapts with " << num_threads << " threads" );
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Input file = " << input_file);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Terrain sources = ");
|
||||
for ( unsigned int i = 0; i < elev_src.size(); ++i )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " " << work_dir << "/" << elev_src[i] );
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Work directory = " << work_dir);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Nudge = " << nudge);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Longitude = " << min.getLongitudeDeg() << ':' << max.getLongitudeDeg());
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Latitude = " << min.getLatitudeDeg() << ':' << max.getLatitudeDeg());
|
||||
string command = argv[0];
|
||||
string lastaptfile = work_dir+"/last_apt";
|
||||
|
||||
if (!max.isValid() || !min.isValid())
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Bad longitude or latitude");
|
||||
exit(1);
|
||||
}
|
||||
// initialize persistant polygon counter
|
||||
string counter_file = airportareadir+"/poly_counter";
|
||||
tgPolygon_index_init( counter_file );
|
||||
|
||||
tg::Rectangle boundingBox(min, max);
|
||||
boundingBox.sanify();
|
||||
|
@ -343,21 +357,6 @@ int main(int argc, char **argv)
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
// make work directory
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Creating AirportArea directory");
|
||||
|
||||
string airportareadir=work_dir+"/AirportArea";
|
||||
SGPath sgp( airportareadir );
|
||||
sgp.append( "dummy" );
|
||||
sgp.create_dir( 0755 );
|
||||
|
||||
string command = argv[0];
|
||||
string lastaptfile = work_dir+"/last_apt";
|
||||
|
||||
// initialize persistant polygon counter
|
||||
string counter_file = airportareadir+"/poly_counter";
|
||||
tgPolygon_index_init( counter_file );
|
||||
|
||||
// Initialize shapefile support (for debugging)
|
||||
tgShapefileInit();
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ void LightingObj::BuildBtg( tglightcontour_list& lights )
|
|||
// Calculate the light normal with the help of a second point
|
||||
// in the object heading direction.
|
||||
// SimGear takes care of the glideslope angle calculation from the normal
|
||||
SGVec3d cart1 = SGVec3d::fromGeod(SGGeodesy::direct( ref, heading, 10));
|
||||
SGVec3d cart2 = SGVec3d::fromGeod(ref);
|
||||
SGVec3d normal = normalize(cart2 - cart1);
|
||||
SGVec3f cart1 = SGVec3f::fromGeod(SGGeodesy::direct( ref, heading, 10));
|
||||
SGVec3f cart2 = SGVec3f::fromGeod(ref);
|
||||
SGVec3f normal = normalize(cart2 - cart1);
|
||||
|
||||
// We know our normal, now create the lights
|
||||
SGGeod pt1;
|
||||
|
|
|
@ -164,7 +164,7 @@ private:
|
|||
return (rwy.threshold[get_thresh0(recip)] > 60.0) ? true : false;
|
||||
}
|
||||
|
||||
SGVec3d gen_runway_light_vector( float angle, bool recip );
|
||||
SGVec3f gen_runway_light_vector( float angle, bool recip );
|
||||
tglightcontour_list gen_runway_edge_lights( bool recip );
|
||||
tglightcontour_list gen_runway_threshold_lights( const int kind, bool recip );
|
||||
tglightcontour_list gen_runway_center_line_lights( bool recip );
|
||||
|
|
|
@ -810,7 +810,7 @@ long Scheduler::FindAirport( string icao )
|
|||
|
||||
void Scheduler::RetryAirport( AirportInfo* pai )
|
||||
{
|
||||
retryList.push_back( *pai );
|
||||
// retryList.push_back( *pai );
|
||||
}
|
||||
|
||||
bool Scheduler::AddAirports( long start_pos, tg::Rectangle* boundingBox )
|
||||
|
|
|
@ -1176,6 +1176,87 @@ bool FindIntermediateNode( const SGGeod& start, const SGGeod& end,
|
|||
return found_node;
|
||||
}
|
||||
|
||||
bool FindIntermediateNode( const SGGeod& start, const SGGeod& end,
|
||||
const std::vector<SGGeod>& nodes, SGGeod& result,
|
||||
double bbEpsilon, double errEpsilon )
|
||||
{
|
||||
bool found_node = false;
|
||||
double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min;
|
||||
|
||||
SGGeod p0 = start;
|
||||
SGGeod p1 = end;
|
||||
|
||||
double xdist = fabs(p0.getLongitudeDeg() - p1.getLongitudeDeg());
|
||||
double ydist = fabs(p0.getLatitudeDeg() - p1.getLatitudeDeg());
|
||||
|
||||
x_err_min = xdist + 1.0;
|
||||
y_err_min = ydist + 1.0;
|
||||
|
||||
if ( xdist > ydist ) {
|
||||
// sort these in a sensible order
|
||||
SGGeod p_min, p_max;
|
||||
if ( p0.getLongitudeDeg() < p1.getLongitudeDeg() ) {
|
||||
p_min = p0;
|
||||
p_max = p1;
|
||||
} else {
|
||||
p_min = p1;
|
||||
p_max = p0;
|
||||
}
|
||||
|
||||
m = (p_min.getLatitudeDeg() - p_max.getLatitudeDeg()) / (p_min.getLongitudeDeg() - p_max.getLongitudeDeg());
|
||||
b = p_max.getLatitudeDeg() - m * p_max.getLongitudeDeg();
|
||||
|
||||
for ( int i = 0; i < (int)nodes.size(); ++i ) {
|
||||
// cout << i << endl;
|
||||
SGGeod current = nodes[i];
|
||||
|
||||
if ( (current.getLongitudeDeg() > (p_min.getLongitudeDeg() + (bbEpsilon))) && (current.getLongitudeDeg() < (p_max.getLongitudeDeg() - (bbEpsilon))) ) {
|
||||
y_err = fabs(current.getLatitudeDeg() - (m * current.getLongitudeDeg() + b));
|
||||
|
||||
if ( y_err < errEpsilon ) {
|
||||
found_node = true;
|
||||
if ( y_err < y_err_min ) {
|
||||
result = current;
|
||||
y_err_min = y_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// sort these in a sensible order
|
||||
SGGeod p_min, p_max;
|
||||
if ( p0.getLatitudeDeg() < p1.getLatitudeDeg() ) {
|
||||
p_min = p0;
|
||||
p_max = p1;
|
||||
} else {
|
||||
p_min = p1;
|
||||
p_max = p0;
|
||||
}
|
||||
|
||||
m1 = (p_min.getLongitudeDeg() - p_max.getLongitudeDeg()) / (p_min.getLatitudeDeg() - p_max.getLatitudeDeg());
|
||||
b1 = p_max.getLongitudeDeg() - m1 * p_max.getLatitudeDeg();
|
||||
|
||||
for ( int i = 0; i < (int)nodes.size(); ++i ) {
|
||||
SGGeod current = nodes[i];
|
||||
|
||||
if ( (current.getLatitudeDeg() > (p_min.getLatitudeDeg() + (bbEpsilon))) && (current.getLatitudeDeg() < (p_max.getLatitudeDeg() - (bbEpsilon))) ) {
|
||||
|
||||
x_err = fabs(current.getLongitudeDeg() - (m1 * current.getLatitudeDeg() + b1));
|
||||
|
||||
if ( x_err < errEpsilon ) {
|
||||
found_node = true;
|
||||
if ( x_err < x_err_min ) {
|
||||
result = current;
|
||||
x_err_min = x_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_node;
|
||||
}
|
||||
|
||||
void AddIntermediateNodes( const SGGeod& p0, const SGGeod& p1, point_list& tmp_nodes, tgContour& result, double bbEpsilon, double errEpsilon )
|
||||
{
|
||||
SGGeod new_pt;
|
||||
|
@ -1194,6 +1275,24 @@ void AddIntermediateNodes( const SGGeod& p0, const SGGeod& p1, point_list& tmp_n
|
|||
}
|
||||
}
|
||||
|
||||
void AddIntermediateNodes( const SGGeod& p0, const SGGeod& p1, std::vector<SGGeod>& nodes, tgContour& result, double bbEpsilon, double errEpsilon )
|
||||
{
|
||||
SGGeod new_pt;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_BULK, " " << p0 << " <==> " << p1 );
|
||||
|
||||
bool found_extra = FindIntermediateNode( p0, p1, nodes, new_pt, bbEpsilon, errEpsilon );
|
||||
|
||||
if ( found_extra ) {
|
||||
AddIntermediateNodes( p0, new_pt, nodes, result, bbEpsilon, errEpsilon );
|
||||
|
||||
result.AddNode( new_pt );
|
||||
SG_LOG(SG_GENERAL, SG_BULK, " adding = " << new_pt);
|
||||
|
||||
AddIntermediateNodes( new_pt, p1, nodes, result, bbEpsilon, errEpsilon );
|
||||
}
|
||||
}
|
||||
|
||||
#define CLIPPER_FIXEDPT (10000000000000000)
|
||||
#define CLIPPER_FIXED1M ( 90090)
|
||||
|
||||
|
@ -1821,6 +1920,37 @@ tgContour tgContour::AddColinearNodes( const tgContour& subject, TGTriNodes node
|
|||
return result;
|
||||
}
|
||||
|
||||
tgContour tgContour::AddColinearNodes( const tgContour& subject, std::vector<SGGeod>& nodes )
|
||||
{
|
||||
SGGeod p0, p1;
|
||||
tgContour result;
|
||||
|
||||
for ( unsigned int n = 0; n < subject.GetSize()-1; n++ ) {
|
||||
p0 = subject.GetNode( n );
|
||||
p1 = subject.GetNode( n+1 );
|
||||
|
||||
// add start of segment
|
||||
result.AddNode( p0 );
|
||||
|
||||
// add intermediate points
|
||||
AddIntermediateNodes( p0, p1, nodes, result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||
}
|
||||
|
||||
p0 = subject.GetNode( subject.GetSize() - 1 );
|
||||
p1 = subject.GetNode( 0 );
|
||||
|
||||
// add start of segment
|
||||
result.AddNode( p0 );
|
||||
|
||||
// add intermediate points
|
||||
AddIntermediateNodes( p0, p1, nodes, result, SG_EPSILON*10, SG_EPSILON*4 );
|
||||
|
||||
// maintain original hole flag setting
|
||||
result.SetHole( subject.GetHole() );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<< ( std::ostream& output, const tgContour& subject )
|
||||
{
|
||||
// Save the data
|
||||
|
@ -2379,6 +2509,20 @@ tgPolygon tgPolygon::AddColinearNodes( const tgPolygon& subject, TGTriNodes& nod
|
|||
return result;
|
||||
}
|
||||
|
||||
tgPolygon tgPolygon::AddColinearNodes( const tgPolygon& subject, std::vector<SGGeod>& nodes )
|
||||
{
|
||||
tgPolygon result;
|
||||
|
||||
result.SetMaterial( subject.GetMaterial() );
|
||||
result.SetTexParams( subject.GetTexParams() );
|
||||
|
||||
for ( unsigned int c = 0; c < subject.Contours(); c++ ) {
|
||||
result.AddContour( tgContour::AddColinearNodes( subject.GetContour(c), nodes ) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void tgPolygon::InheritElevations( const tgPolygon& source )
|
||||
{
|
||||
TGTriNodes nodes;
|
||||
|
@ -2441,9 +2585,9 @@ void tgPolygon::InheritElevations( const tgPolygon& source )
|
|||
void tgPolygon::Texture( void )
|
||||
{
|
||||
SGGeod p;
|
||||
SGVec2d t;
|
||||
SGVec2f t;
|
||||
double x, y;
|
||||
double tx, ty;
|
||||
float tx, ty;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Texture Poly with material " << material << " method " << tp.method << " tpref " << tp.ref << " heading " << tp.heading );
|
||||
|
||||
|
@ -2491,29 +2635,29 @@ void tgPolygon::Texture( void )
|
|||
//
|
||||
// 4. Map x, y point into texture coordinates
|
||||
//
|
||||
double tmp;
|
||||
float tmp;
|
||||
|
||||
tmp = x / tp.width;
|
||||
tx = tmp * (tp.maxu - tp.minu) + tp.minu;
|
||||
tmp = (float)x / (float)tp.width;
|
||||
tx = tmp * (float)(tp.maxu - tp.minu) + (float)tp.minu;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ")");
|
||||
|
||||
// clip u?
|
||||
if ( (tp.method == TG_TEX_BY_TPS_CLIPU) || (tp.method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
if ( tx < tp.min_clipu ) { tx = tp.min_clipu; }
|
||||
if ( tx > tp.max_clipu ) { tx = tp.max_clipu; }
|
||||
if ( tx < (float)tp.min_clipu ) { tx = (float)tp.min_clipu; }
|
||||
if ( tx > (float)tp.max_clipu ) { tx = (float)tp.max_clipu; }
|
||||
}
|
||||
|
||||
tmp = y / tp.length;
|
||||
ty = tmp * (tp.maxv - tp.minv) + tp.minv;
|
||||
tmp = (float)y / (float)tp.length;
|
||||
ty = tmp * (float)(tp.maxv - tp.minv) + (float)tp.minv;
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << ty << ")");
|
||||
|
||||
// clip v?
|
||||
if ( (tp.method == TG_TEX_BY_TPS_CLIPV) || (tp.method == TG_TEX_BY_TPS_CLIPUV) ) {
|
||||
if ( ty < tp.min_clipv ) { ty = tp.min_clipv; }
|
||||
if ( ty > tp.max_clipv ) { ty = tp.max_clipv; }
|
||||
if ( ty < (float)tp.min_clipv ) { ty = (float)tp.min_clipv; }
|
||||
if ( ty > (float)tp.max_clipv ) { ty = (float)tp.max_clipv; }
|
||||
}
|
||||
|
||||
t = SGVec2d( tx, ty );
|
||||
t = SGVec2f( tx, ty );
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, " (" << tx << ", " << ty << ")");
|
||||
|
||||
triangles[i].SetTexCoord( j, t );
|
||||
|
|
|
@ -379,6 +379,7 @@ public:
|
|||
static void AddToAccumulator( const tgContour& subject );
|
||||
|
||||
static tgContour AddColinearNodes( const tgContour& subject, TGTriNodes nodes );
|
||||
static tgContour AddColinearNodes( const tgContour& subject, std::vector<SGGeod>& nodes );
|
||||
|
||||
// conversions
|
||||
static ClipperLib::Polygon ToClipper( const tgContour& subject );
|
||||
|
@ -406,7 +407,7 @@ public:
|
|||
node_list.push_back( p1 );
|
||||
node_list.push_back( p2 );
|
||||
|
||||
tc_list.resize( 3, SGVec2d(0.0, 0.0) );
|
||||
tc_list.resize( 3, SGVec2f(0.0, 0.0) );
|
||||
norm_list.resize( 3, SGVec3d(0.0, 0.0, 0.0) );
|
||||
idx_list.resize( 3, -1 );
|
||||
}
|
||||
|
@ -414,10 +415,10 @@ public:
|
|||
SGGeod GetNode( unsigned int i ) const {
|
||||
return node_list[i];
|
||||
}
|
||||
SGVec2d GetTexCoord( unsigned int i ) const {
|
||||
SGVec2f GetTexCoord( unsigned int i ) const {
|
||||
return tc_list[i];
|
||||
}
|
||||
void SetTexCoord( unsigned int i, const SGVec2d tc ) {
|
||||
void SetTexCoord( unsigned int i, const SGVec2f tc ) {
|
||||
tc_list[i] = tc;
|
||||
}
|
||||
|
||||
|
@ -426,7 +427,7 @@ public:
|
|||
|
||||
private:
|
||||
std::vector<SGGeod> node_list;
|
||||
std::vector<SGVec2d> tc_list;
|
||||
std::vector<SGVec2f> tc_list;
|
||||
std::vector<SGVec3d> norm_list;
|
||||
std::vector<int> idx_list;
|
||||
|
||||
|
@ -512,7 +513,7 @@ public:
|
|||
void SetNode( unsigned int c, unsigned int i, const SGGeod& n ) {
|
||||
contours[c].SetNode( i, n );
|
||||
}
|
||||
|
||||
|
||||
void AddNode( unsigned int c, const SGGeod& n ) {
|
||||
// Make sure we have contour c. If we don't add it
|
||||
while( contours.size() < c+1 ) {
|
||||
|
@ -538,7 +539,7 @@ public:
|
|||
SGGeod GetTriNode( unsigned int c, unsigned int i ) const {
|
||||
return triangles[c].GetNode( i );
|
||||
}
|
||||
SGVec2d GetTriTexCoord( unsigned int c, unsigned int i ) const {
|
||||
SGVec2f GetTriTexCoord( unsigned int c, unsigned int i ) const {
|
||||
return triangles[c].GetTexCoord( i );
|
||||
}
|
||||
|
||||
|
@ -622,6 +623,7 @@ public:
|
|||
static void Tesselate( const tgPolygon& subject );
|
||||
|
||||
static tgPolygon AddColinearNodes( const tgPolygon& subject, TGTriNodes& nodes );
|
||||
static tgPolygon AddColinearNodes( const tgPolygon& subject, std::vector<SGGeod>& nodes );
|
||||
|
||||
static void RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers );
|
||||
static void MergeSlivers( tgpolygon_list& subjects, tgcontour_list& slivers );
|
||||
|
@ -645,7 +647,7 @@ class tgLight
|
|||
{
|
||||
public:
|
||||
SGGeod pos;
|
||||
SGVec3d norm;
|
||||
SGVec3f norm;
|
||||
};
|
||||
|
||||
typedef std::vector <tgLight> tglight_list;
|
||||
|
@ -659,17 +661,29 @@ public:
|
|||
return lights.size();
|
||||
}
|
||||
|
||||
void AddLight( SGGeod p, SGVec3d n ) {
|
||||
void AddLight( SGGeod p, SGVec3f n ) {
|
||||
tgLight light;
|
||||
light.pos = p;
|
||||
light.norm = n;
|
||||
lights.push_back(light);
|
||||
}
|
||||
|
||||
void SetElevation( unsigned int i, double elev ) {
|
||||
lights[i].pos.setElevationM( elev );
|
||||
}
|
||||
|
||||
SGGeod GetNode( unsigned int i ) const {
|
||||
return lights[i].pos;
|
||||
}
|
||||
|
||||
SGGeod GetPosition( unsigned int i ) const {
|
||||
return lights[i].pos;
|
||||
}
|
||||
|
||||
SGVec3f GetNormal( unsigned int i ) const {
|
||||
return lights[i].norm;
|
||||
}
|
||||
|
||||
std::string GetFlag( void ) const {
|
||||
return flag;
|
||||
}
|
||||
|
@ -695,6 +709,16 @@ public:
|
|||
return p3dlist;
|
||||
}
|
||||
|
||||
std::vector<SGGeod> GetPositionList( void ) {
|
||||
std::vector<SGGeod> positions;
|
||||
|
||||
for (unsigned int i=0; i<lights.size(); i++) {
|
||||
positions.push_back( lights[i].pos );
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
point_list TempGetNormalListAsPoint3D( void ) {
|
||||
point_list p3dlist;
|
||||
|
||||
|
@ -704,6 +728,17 @@ public:
|
|||
|
||||
return p3dlist;
|
||||
}
|
||||
|
||||
std::vector<SGVec3f> GetNormalList( void ) {
|
||||
std::vector<SGVec3f> normals;
|
||||
|
||||
for (unsigned int i=0; i<lights.size(); i++) {
|
||||
normals.push_back( lights[i].norm );
|
||||
}
|
||||
|
||||
return normals;
|
||||
}
|
||||
|
||||
// END TEMP TEMP TEMP
|
||||
|
||||
// Friend for output
|
||||
|
|
128
src/Lib/Polygon/tg_unique_geod.hxx
Normal file
128
src/Lib/Polygon/tg_unique_geod.hxx
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
|
||||
// Implement Unique SGGeod 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 ) )
|
||||
|
||||
class SGGeodIndex {
|
||||
public:
|
||||
SGGeodIndex( 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)( round(geod.getLongitudeDeg() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[1] = (unsigned long long)( 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;
|
||||
}
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_ALERT, " GetHash x: " << raw_pt[0] << " y: " << raw_pt[1] << " = " << hash );
|
||||
}
|
||||
|
||||
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 SGGeodIndex& a, const SGGeodIndex& b);
|
||||
friend std::ostream& operator<< ( std::ostream&, const SGGeodIndex& );
|
||||
|
||||
private:
|
||||
SGGeod geod;
|
||||
std::size_t hash;
|
||||
unsigned int ordered_index;
|
||||
};
|
||||
|
||||
inline bool operator == (const SGGeodIndex& a, const SGGeodIndex& b) {
|
||||
return (( fabs(a.geod.getLongitudeDeg() - b.geod.getLongitudeDeg()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.geod.getLatitudeDeg() - b.geod.getLatitudeDeg()) < PROXIMITY_EPSILON ));
|
||||
}
|
||||
|
||||
struct SGGeodIndexHash : std::unary_function<SGGeodIndex, std::size_t>
|
||||
{
|
||||
std::size_t operator()(SGGeodIndex const& gi) const {
|
||||
return gi.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::unordered_set<SGGeodIndex, SGGeodIndexHash> unique_geod_set;
|
||||
typedef unique_geod_set::iterator unique_geod_set_iterator;
|
||||
typedef unique_geod_set::const_iterator const_unique_geod_set_iterator;
|
||||
|
||||
class UniqueSGGeodSet {
|
||||
public:
|
||||
UniqueSGGeodSet() {}
|
||||
|
||||
unsigned int add( const SGGeod& g );
|
||||
int find( const SGGeod& g ) const;
|
||||
std::vector<SGGeod>& get_list( void ) { return geod_list; }
|
||||
void get_node_list();
|
||||
|
||||
private:
|
||||
unique_geod_set index_list;
|
||||
std::vector<SGGeod> geod_list;
|
||||
};
|
||||
|
||||
unsigned int UniqueSGGeodSet::add( const SGGeod& g ) {
|
||||
unique_geod_set_iterator it;
|
||||
SGGeodIndex lookup( g );
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it == index_list.end() ) {
|
||||
lookup.SetOrderedIndex( geod_list.size() );
|
||||
index_list.insert( lookup );
|
||||
|
||||
geod_list.push_back(g);
|
||||
} else {
|
||||
lookup = *it;
|
||||
}
|
||||
|
||||
return lookup.GetOrderedIndex();
|
||||
}
|
||||
|
||||
|
||||
int UniqueSGGeodSet::find( const SGGeod& g ) const {
|
||||
unique_geod_set_iterator it;
|
||||
SGGeodIndex lookup( g );
|
||||
int index = -1;
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it != index_list.end() ) {
|
||||
index = it->GetOrderedIndex();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
127
src/Lib/Polygon/tg_unique_vec2f.hxx
Normal file
127
src/Lib/Polygon/tg_unique_vec2f.hxx
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
|
||||
// Implement Unique SGVec2f 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 ) )
|
||||
|
||||
class SGVec2fIndex {
|
||||
public:
|
||||
SGVec2fIndex( SGVec2f v ) {
|
||||
vec = v;
|
||||
|
||||
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)( round(vec.x() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[1] = (unsigned long long)( round(vec.y() * 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;
|
||||
}
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_ALERT, " GetHash x: " << raw_pt[0] << " y: " << raw_pt[1] << " = " << hash );
|
||||
}
|
||||
|
||||
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 SGVec2fIndex& a, const SGVec2fIndex& b);
|
||||
friend std::ostream& operator<< ( std::ostream&, const SGVec2fIndex& );
|
||||
|
||||
private:
|
||||
SGVec2f vec;
|
||||
std::size_t hash;
|
||||
unsigned int ordered_index;
|
||||
};
|
||||
|
||||
inline bool operator == (const SGVec2fIndex& a, const SGVec2fIndex& b) {
|
||||
return (( fabs(a.vec.x() - b.vec.x()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.vec.y() - b.vec.y()) < PROXIMITY_EPSILON ));
|
||||
}
|
||||
|
||||
struct SGVec2fIndexHash : std::unary_function<SGVec2fIndex, std::size_t>
|
||||
{
|
||||
std::size_t operator()(SGVec2fIndex const& vi) const {
|
||||
return vi.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::unordered_set<SGVec2fIndex, SGVec2fIndexHash> unique_vec2f_set;
|
||||
typedef unique_vec2f_set::iterator unique_vec2f_set_iterator;
|
||||
typedef unique_vec2f_set::const_iterator const_unique_vec2f_set_iterator;
|
||||
|
||||
class UniqueSGVec2fSet {
|
||||
public:
|
||||
UniqueSGVec2fSet() {}
|
||||
|
||||
unsigned int add( const SGVec2f& v );
|
||||
int find( const SGVec2f& v ) const;
|
||||
std::vector<SGVec2f>& get_list( void ) { return vector_list; }
|
||||
|
||||
private:
|
||||
unique_vec2f_set index_list;
|
||||
std::vector<SGVec2f> vector_list;
|
||||
};
|
||||
|
||||
unsigned int UniqueSGVec2fSet::add( const SGVec2f& v ) {
|
||||
unique_vec2f_set_iterator it;
|
||||
SGVec2fIndex lookup( v );
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it == index_list.end() ) {
|
||||
lookup.SetOrderedIndex( vector_list.size() );
|
||||
index_list.insert( lookup );
|
||||
|
||||
vector_list.push_back(v);
|
||||
} else {
|
||||
lookup = *it;
|
||||
}
|
||||
|
||||
return lookup.GetOrderedIndex();
|
||||
}
|
||||
|
||||
|
||||
int UniqueSGVec2fSet::find( const SGVec2f& v ) const {
|
||||
unique_vec2f_set_iterator it;
|
||||
SGVec2fIndex lookup( v );
|
||||
int index = -1;
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it != index_list.end() ) {
|
||||
index = it->GetOrderedIndex();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
129
src/Lib/Polygon/tg_unique_vec3d.hxx
Normal file
129
src/Lib/Polygon/tg_unique_vec3d.hxx
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
|
||||
// Implement Unique SGVec3d 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 ) )
|
||||
|
||||
class SGVec3dIndex {
|
||||
public:
|
||||
SGVec3dIndex( SGVec3d v ) {
|
||||
vec = v;
|
||||
|
||||
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[3];
|
||||
raw_pt[0] = (unsigned long long)( round(vec.x() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[1] = (unsigned long long)( round(vec.y() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[2] = (unsigned long long)( round(vec.z() * 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;
|
||||
}
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_ALERT, " GetHash x: " << raw_pt[0] << " y: " << raw_pt[1] << " = " << hash );
|
||||
}
|
||||
|
||||
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 SGVec3dIndex& a, const SGVec3dIndex& b);
|
||||
friend std::ostream& operator<< ( std::ostream&, const SGVec3dIndex& );
|
||||
|
||||
private:
|
||||
SGVec3d vec;
|
||||
std::size_t hash;
|
||||
unsigned int ordered_index;
|
||||
};
|
||||
|
||||
inline bool operator == (const SGVec3dIndex& a, const SGVec3dIndex& b) {
|
||||
return (( fabs(a.vec.x() - b.vec.x()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.vec.y() - b.vec.y()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.vec.z() - b.vec.z()) < PROXIMITY_EPSILON ));
|
||||
}
|
||||
|
||||
struct SGVec3dIndexHash : std::unary_function<SGVec3dIndex, std::size_t>
|
||||
{
|
||||
std::size_t operator()(SGVec3dIndex const& vi) const {
|
||||
return vi.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::unordered_set<SGVec3dIndex, SGVec3dIndexHash> unique_vec3d_set;
|
||||
typedef unique_vec3d_set::iterator unique_vec3d_set_iterator;
|
||||
typedef unique_vec3d_set::const_iterator const_unique_vec3d_set_iterator;
|
||||
|
||||
class UniqueSGVec3dSet {
|
||||
public:
|
||||
UniqueSGVec3dSet() {}
|
||||
|
||||
unsigned int add( const SGVec3d& v );
|
||||
int find( const SGVec3d& v ) const;
|
||||
std::vector<SGVec3d>& get_list( void ) { return vector_list; }
|
||||
|
||||
private:
|
||||
unique_vec3d_set index_list;
|
||||
std::vector<SGVec3d> vector_list;
|
||||
};
|
||||
|
||||
unsigned int UniqueSGVec3dSet::add( const SGVec3d& v ) {
|
||||
unique_vec3d_set_iterator it;
|
||||
SGVec3dIndex lookup( v );
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it == index_list.end() ) {
|
||||
lookup.SetOrderedIndex( vector_list.size() );
|
||||
index_list.insert( lookup );
|
||||
|
||||
vector_list.push_back(v);
|
||||
} else {
|
||||
lookup = *it;
|
||||
}
|
||||
|
||||
return lookup.GetOrderedIndex();
|
||||
}
|
||||
|
||||
|
||||
int UniqueSGVec3dSet::find( const SGVec3d& v ) const {
|
||||
unique_vec3d_set_iterator it;
|
||||
SGVec3dIndex lookup( v );
|
||||
int index = -1;
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it != index_list.end() ) {
|
||||
index = it->GetOrderedIndex();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
129
src/Lib/Polygon/tg_unique_vec3f.hxx
Normal file
129
src/Lib/Polygon/tg_unique_vec3f.hxx
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
|
||||
// Implement Unique SGVec3f 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 ) )
|
||||
|
||||
class SGVec3fIndex {
|
||||
public:
|
||||
SGVec3fIndex( SGVec3f v ) {
|
||||
vec = v;
|
||||
|
||||
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[3];
|
||||
raw_pt[0] = (unsigned long long)( round(vec.x() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[1] = (unsigned long long)( round(vec.y() * PROXIMITY_MULTIPLIER) );
|
||||
raw_pt[2] = (unsigned long long)( round(vec.z() * 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;
|
||||
}
|
||||
|
||||
// SG_LOG(SG_GENERAL, SG_ALERT, " GetHash x: " << raw_pt[0] << " y: " << raw_pt[1] << " = " << hash );
|
||||
}
|
||||
|
||||
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 SGVec3fIndex& a, const SGVec3fIndex& b);
|
||||
friend std::ostream& operator<< ( std::ostream&, const SGVec3fIndex& );
|
||||
|
||||
private:
|
||||
SGVec3f vec;
|
||||
std::size_t hash;
|
||||
unsigned int ordered_index;
|
||||
};
|
||||
|
||||
inline bool operator == (const SGVec3fIndex& a, const SGVec3fIndex& b) {
|
||||
return (( fabs(a.vec.x() - b.vec.x()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.vec.y() - b.vec.y()) < PROXIMITY_EPSILON ) &&
|
||||
( fabs(a.vec.z() - b.vec.z()) < PROXIMITY_EPSILON ));
|
||||
}
|
||||
|
||||
struct SGVec3fIndexHash : std::unary_function<SGVec3fIndex, std::size_t>
|
||||
{
|
||||
std::size_t operator()(SGVec3fIndex const& vi) const {
|
||||
return vi.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::unordered_set<SGVec3fIndex, SGVec3fIndexHash> unique_vec3f_set;
|
||||
typedef unique_vec3f_set::iterator unique_vec3f_set_iterator;
|
||||
typedef unique_vec3f_set::const_iterator const_unique_vec3f_set_iterator;
|
||||
|
||||
class UniqueSGVec3fSet {
|
||||
public:
|
||||
UniqueSGVec3fSet() {}
|
||||
|
||||
unsigned int add( const SGVec3f& v );
|
||||
int find( const SGVec3f& v ) const;
|
||||
std::vector<SGVec3f>& get_list( void ) { return vector_list; }
|
||||
|
||||
private:
|
||||
unique_vec3f_set index_list;
|
||||
std::vector<SGVec3f> vector_list;
|
||||
};
|
||||
|
||||
unsigned int UniqueSGVec3fSet::add( const SGVec3f& v ) {
|
||||
unique_vec3f_set_iterator it;
|
||||
SGVec3fIndex lookup( v );
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it == index_list.end() ) {
|
||||
lookup.SetOrderedIndex( vector_list.size() );
|
||||
index_list.insert( lookup );
|
||||
|
||||
vector_list.push_back(v);
|
||||
} else {
|
||||
lookup = *it;
|
||||
}
|
||||
|
||||
return lookup.GetOrderedIndex();
|
||||
}
|
||||
|
||||
|
||||
int UniqueSGVec3fSet::find( const SGVec3f& v ) const {
|
||||
unique_vec3f_set_iterator it;
|
||||
SGVec3fIndex lookup( v );
|
||||
int index = -1;
|
||||
|
||||
it = index_list.find( lookup );
|
||||
if ( it != index_list.end() ) {
|
||||
index = it->GetOrderedIndex();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
Loading…
Add table
Reference in a new issue