1
0
Fork 0

genapt850 optomizations - use hashes for SGGeod, SGVec3f and SGVec2f lists

This commit is contained in:
Peter Sadrozinski 2012-11-18 12:57:25 -05:00
parent c9f79718fa
commit 3f072c42f8
16 changed files with 984 additions and 260 deletions

View file

@ -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 );

View file

@ -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.

View file

@ -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 );

View file

@ -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);

View file

@ -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.

View file

@ -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);
}

View file

@ -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();

View file

@ -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;

View file

@ -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 );

View file

@ -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 )

View file

@ -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 );

View file

@ -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

View 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;
}

View 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;
}

View 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;
}

View 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;
}