1
0
Fork 0

checkpoint1

- all polys triangulated individually
- shared edge loading should be working, but there are still issues.
This commit is contained in:
Peter Sadrozinski 2012-07-08 18:26:21 -04:00 committed by Christian Schmitt
parent 3f996495c6
commit e6ac493395
14 changed files with 2159 additions and 1004 deletions

View file

@ -41,11 +41,8 @@
#include <stdlib.h> #include <stdlib.h>
using std::cout;
using std::endl;
using std::string; using std::string;
#define MASK_CLIP 1 #define MASK_CLIP 1
@ -65,9 +62,9 @@ TGClipper::~TGClipper() {
// Initialize the clipper (empty all the polygon buckets.) // Initialize the clipper (empty all the polygon buckets.)
bool TGClipper::init() { bool TGClipper::init() {
for ( int i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
polys_in.polys[i].clear(); polys_in.superpolys[i].clear();
} }
fixed_elevations.clear(); nodes.clear();
return true; return true;
} }
@ -109,21 +106,19 @@ bool TGClipper::load_polys(const string& path) {
poly3d = false; poly3d = false;
poly_name = first_line; poly_name = first_line;
} }
cout << "poly name = " << poly_name << endl; SG_LOG( SG_CLIPPER, SG_INFO, "poly name = " << poly_name);
poly_type = get_area_type( poly_name ); poly_type = get_area_type( poly_name );
cout << "poly type (int) = " << (int)poly_type << endl; SG_LOG( SG_CLIPPER, SG_INFO, "poly type (int) = " << (int)poly_type);
in >> contours; in >> contours;
cout << "num contours = " << contours << endl; SG_LOG( SG_CLIPPER, SG_INFO, "num contours = " << contours);
poly.erase(); poly.erase();
for ( i = 0; i < contours; ++i ) { for ( i = 0; i < contours; ++i ) {
in >> count; in >> count;
// cout << "Contour = " << i << " size = " << count << endl;
if ( count < 3 ) { if ( count < 3 ) {
SG_LOG( SG_CLIPPER, SG_ALERT, SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon with less than 3 data points." );
"Polygon with less than 3 data points." );
exit(-1); exit(-1);
} }
@ -138,8 +133,11 @@ bool TGClipper::load_polys(const string& path) {
} }
p = Point3D(startx+nudge, starty+nudge, startz); p = Point3D(startx+nudge, starty+nudge, startz);
poly.add_node( i, p ); poly.add_node( i, p );
if ( poly3d ) { if ( poly3d ) {
fixed_elevations.unique_add( p ); nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
} }
for ( j = 1; j < count - 1; ++j ) { for ( j = 1; j < count - 1; ++j ) {
@ -153,7 +151,9 @@ bool TGClipper::load_polys(const string& path) {
p = Point3D( x+nudge, y+nudge, z ); p = Point3D( x+nudge, y+nudge, z );
poly.add_node( i, p ); poly.add_node( i, p );
if ( poly3d ) { if ( poly3d ) {
fixed_elevations.unique_add( p ); nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
} }
} }
@ -165,25 +165,25 @@ bool TGClipper::load_polys(const string& path) {
lastz = -9999.0; lastz = -9999.0;
} }
if ( (fabs(startx - lastx) < SG_EPSILON) if ( (fabs(startx - lastx) < SG_EPSILON) &&
&& (fabs(starty - lasty) < SG_EPSILON) (fabs(starty - lasty) < SG_EPSILON) &&
&& (fabs(startz - lastz) < SG_EPSILON) ) { (fabs(startz - lastz) < SG_EPSILON) ) {
// last point same as first, discard // last point same as first, discard
} else { } else {
p = Point3D( lastx+nudge, lasty+nudge, lastz ); p = Point3D( lastx+nudge, lasty+nudge, lastz );
poly.add_node( i, p ); poly.add_node( i, p );
if ( poly3d ) { if ( poly3d ) {
fixed_elevations.unique_add( p ); nodes.unique_add_fixed_elevation( p );
} else {
nodes.unique_add( p );
} }
} }
} }
int area = (int)poly_type; int area = (int)poly_type;
string material = get_area_name( area );
add_poly(area, poly); add_poly(area, poly, material);
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
in >> skipcomment; in >> skipcomment;
} }
@ -195,7 +195,6 @@ bool TGClipper::load_polys(const string& path) {
// Load a polygon definition file containing osgb36 Eastings and Northings // Load a polygon definition file containing osgb36 Eastings and Northings
// and convert them to WGS84 Latitude and Longitude // and convert them to WGS84 Latitude and Longitude
bool TGClipper::load_osgb36_polys(const string& path) { bool TGClipper::load_osgb36_polys(const string& path) {
// cout << "Loading osgb36 poly\n";
string poly_name; string poly_name;
AreaType poly_type; AreaType poly_type;
int contours, count, i, j; int contours, count, i, j;
@ -211,9 +210,6 @@ bool TGClipper::load_osgb36_polys(const string& path) {
exit(-1); exit(-1);
} }
// gpc_polygon *poly = new gpc_polygon;
// poly->num_contours = 0;
// poly->contour = NULL;
TGPolygon poly; TGPolygon poly;
Point3D p; Point3D p;
@ -221,11 +217,11 @@ bool TGClipper::load_osgb36_polys(const string& path) {
in >> skipcomment; in >> skipcomment;
while ( !in.eof() ) { while ( !in.eof() ) {
in >> poly_name; in >> poly_name;
cout << "poly name = " << poly_name << endl; SG_LOG( SG_CLIPPER, SG_INFO, "poly name = " << poly_name);
poly_type = get_area_type( poly_name ); poly_type = get_area_type( poly_name );
cout << "poly type (int) = " << (int)poly_type << endl; SG_LOG( SG_CLIPPER, SG_INFO, "poly type (int) = " << (int)poly_type);
in >> contours; in >> contours;
cout << "num contours = " << contours << endl; SG_LOG( SG_CLIPPER, SG_INFO, "num contours = " << contours);
poly.erase(); poly.erase();
@ -233,8 +229,7 @@ bool TGClipper::load_osgb36_polys(const string& path) {
in >> count; in >> count;
if ( count < 3 ) { if ( count < 3 ) {
SG_LOG( SG_CLIPPER, SG_ALERT, SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon with less than 3 data points." );
"Polygon with less than 3 data points." );
exit(-1); exit(-1);
} }
@ -249,8 +244,9 @@ bool TGClipper::load_osgb36_polys(const string& path) {
p = OSGB36ToWGS84(OSRef); p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p ); poly.add_node( i, p );
SG_LOG( SG_CLIPPER, SG_BULK, "0 = " nodes.unique_add( p );
<< startx << ", " << starty );
SG_LOG( SG_CLIPPER, SG_BULK, "0 = " << startx << ", " << starty );
for ( j = 1; j < count - 1; ++j ) { for ( j = 1; j < count - 1; ++j ) {
in >> x; in >> x;
@ -259,33 +255,30 @@ bool TGClipper::load_osgb36_polys(const string& path) {
p = OSGB36ToWGS84(OSRef); p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p ); poly.add_node( i, p );
nodes.unique_add( p );
SG_LOG( SG_CLIPPER, SG_BULK, j << " = " << x << ", " << y ); SG_LOG( SG_CLIPPER, SG_BULK, j << " = " << x << ", " << y );
} }
in >> lastx; in >> lastx;
in >> lasty; in >> lasty;
if ( (fabs(startx - lastx) < SG_EPSILON) if ( (fabs(startx - lastx) < SG_EPSILON) &&
&& (fabs(starty - lasty) < SG_EPSILON) ) { (fabs(starty - lasty) < SG_EPSILON) ) {
// last point same as first, discard // last point same as first, discard
} else { } else {
OSRef = Point3D( lastx, lasty, -9999.0 ); OSRef = Point3D( lastx, lasty, -9999.0 );
p = OSGB36ToWGS84(OSRef); p = OSGB36ToWGS84(OSRef);
poly.add_node( i, p ); poly.add_node( i, p );
SG_LOG( SG_CLIPPER, SG_BULK, count - 1 << " = " nodes.unique_add( p );
<< lastx << ", " << lasty ); SG_LOG( SG_CLIPPER, SG_BULK, count - 1 << " = " << lastx << ", " << lasty );
} }
// gpc_add_contour( poly, &v_list, hole_flag );
} }
int area = (int)poly_type; int area = (int)poly_type;
string material = get_area_name( area );
add_poly( area, poly); add_poly(area, poly, material);
// FILE *ofp= fopen("outfile", "w");
// gpc_write_polygon(ofp, &polys.landuse);
in >> skipcomment; in >> skipcomment;
} }
@ -294,13 +287,17 @@ bool TGClipper::load_osgb36_polys(const string& path) {
} }
// Add a polygon to the clipper. // Add a polygon to the clipper.
void TGClipper::add_poly( int area, const TGPolygon &poly ) void TGClipper::add_poly( int area, const TGPolygon &poly, string material )
{ {
TGSuperPoly sp;
if ( area < TG_MAX_AREA_TYPES ) { if ( area < TG_MAX_AREA_TYPES ) {
polys_in.polys[area].push_back(poly); sp.set_poly( poly );
sp.set_material( material );
polys_in.superpolys[area].push_back(sp);
} else { } else {
SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " SG_LOG( SG_CLIPPER, SG_ALERT, "Polygon type out of range = " << area);
<< area);
exit(-1); exit(-1);
} }
} }
@ -310,9 +307,6 @@ void TGClipper::add_poly( int area, const TGPolygon &poly )
void TGClipper::move_slivers( TGPolygon& in, TGPolygon& out ) { void TGClipper::move_slivers( TGPolygon& in, TGPolygon& out ) {
// traverse each contour of the polygon and attempt to identify // traverse each contour of the polygon and attempt to identify
// likely slivers // likely slivers
// cout << "Begin move slivers" << endl;
int i; int i;
out.erase(); out.erase();
@ -328,20 +322,11 @@ void TGClipper::move_slivers( TGPolygon& in, TGPolygon& out ) {
// process contours in reverse order so deleting a contour doesn't // process contours in reverse order so deleting a contour doesn't
// foul up our sequence // foul up our sequence
for ( i = in.contours() - 1; i >= 0; --i ) { for ( i = in.contours() - 1; i >= 0; --i ) {
// cout << "contour " << i << endl;
min_angle = in.minangle_contour( i ); min_angle = in.minangle_contour( i );
area = in.area_contour( i ); area = in.area_contour( i );
/* cout << " min_angle (rad) = "
<< min_angle << endl;
cout << " min_angle (deg) = "
<< min_angle * 180.0 / SGD_PI << endl;
cout << " area = " << area << endl; */
if ( ((min_angle < angle_cutoff) && (area < area_cutoff)) || if ( ((min_angle < angle_cutoff) && (area < area_cutoff)) ||
( area < area_cutoff / 10.0) ) ( area < area_cutoff / 10.0) ) {
{
// cout << " WE THINK IT'S A SLIVER!" << endl; // cout << " WE THINK IT'S A SLIVER!" << endl;
// check if this is a hole // check if this is a hole
@ -373,7 +358,7 @@ void TGClipper::merge_slivers( TGPolyList& clipped, TGPolygon& slivers ) {
point_list contour; point_list contour;
int original_contours, result_contours; int original_contours, result_contours;
bool done; bool done;
int area, i, j, k; int area, i, j;
for ( i = 0; i < slivers.contours(); ++i ) { for ( i = 0; i < slivers.contours(); ++i ) {
// cout << "Merging sliver = " << i << endl; // cout << "Merging sliver = " << i << endl;
@ -393,39 +378,21 @@ void TGClipper::merge_slivers( TGPolyList& clipped, TGPolygon& slivers ) {
// cout << " testing area = " << area << " with " // cout << " testing area = " << area << " with "
// << clipped.polys[area].size() << " polys" << endl; // << clipped.polys[area].size() << " polys" << endl;
for ( j = 0; for ( j = 0; j < (int)clipped.superpolys[area].size() && !done; ++j ) {
j < (int)clipped.polys[area].size() && !done;
++j )
{
// cout << " polygon = " << j << endl; // cout << " polygon = " << j << endl;
poly = clipped.superpolys[area][j].get_poly();
poly = clipped.polys[area][j];
original_contours = poly.contours(); original_contours = poly.contours();
result = tgPolygonUnion( poly, sliver ); result = tgPolygonUnion( poly, sliver );
result_contours = result.contours(); result_contours = result.contours();
if ( original_contours == result_contours ) { if ( original_contours == result_contours ) {
// cout << " FOUND a poly to merge the sliver with" << endl; // cout << " FOUND a poly to merge the sliver with" << endl;
clipped.polys[area][j] = result; clipped.superpolys[area][j].set_poly( result );
done = true; done = true;
// poly.write("orig");
// sliver.write("sliver");
// result.write("result");
// cout << "press return: ";
// string input;
// cin >> input;
//} else {
// cout << " poly not a match" << endl;
// cout << " original = " << original_contours
// << " result = " << result_contours << endl;
// cout << " sliver = " << endl;
// for ( k = 0; k < (int)contour.size(); ++k ) {
// cout << " " << contour[k].x() << ", "
// << contour[k].y() << endl;
// }
} }
} }
} }
if ( !done ) { if ( !done ) {
// cout << "no suitable polys found for sliver merge" << endl; // cout << "no suitable polys found for sliver merge" << endl;
} }
@ -439,22 +406,31 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
TGPolygon accum, tmp; TGPolygon accum, tmp;
TGPolygon slivers, remains; TGPolygon slivers, remains;
int i, j; int i, j;
Point3D p;
// gpcpoly_iterator current, last;
SG_LOG( SG_CLIPPER, SG_INFO, "Running master clipper" ); SG_LOG( SG_CLIPPER, SG_INFO, "Running master clipper" );
SG_LOG( SG_CLIPPER, SG_INFO, " (" << min.x << "," << min.y << ") (" << max.x << "," << max.y << ")" );
accum.erase(); accum.erase();
cout << " (" << min.x << "," << min.y << ") (" // set up clipping tile : and remember to add the nodes!
<< max.x << "," << max.y << ")" << endl;
// set up clipping tile
polys_in.safety_base.erase(); polys_in.safety_base.erase();
polys_in.safety_base.add_node( 0, Point3D(min.x, min.y, -9999.0) );
polys_in.safety_base.add_node( 0, Point3D(max.x, min.y, -9999.0) ); p = Point3D(min.x, min.y, -9999.0);
polys_in.safety_base.add_node( 0, Point3D(max.x, max.y, -9999.0) ); polys_in.safety_base.add_node( 0, p );
polys_in.safety_base.add_node( 0, Point3D(min.x, max.y, -9999.0) ); nodes.unique_add( p );
p = Point3D(max.x, min.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
p = Point3D(max.x, max.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
p = Point3D(min.x, max.y, -9999.0);
polys_in.safety_base.add_node( 0, p );
nodes.unique_add( p );
// set up land mask, we clip most things to this since it is our // set up land mask, we clip most things to this since it is our
// best representation of land vs. ocean. If we have other less // best representation of land vs. ocean. If we have other less
@ -467,31 +443,26 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
island_mask.erase(); island_mask.erase();
for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) { for ( i = 0; i < TG_MAX_AREA_TYPES; i++ ) {
if ( is_landmass_area( i ) && !m_ignore_landmass ) { if ( is_landmass_area( i ) && !m_ignore_landmass ) {
for ( unsigned j = 0; j < (int)polys_in.polys[i].size(); ++j ) { for ( unsigned int j = 0; j < polys_in.superpolys[i].size(); ++j ) {
land_mask = land_mask = tgPolygonUnion( land_mask, polys_in.superpolys[i][j].get_poly() );
tgPolygonUnion( land_mask, polys_in.polys[i][j] );
} }
} else if ( is_water_area( i ) ) { } else if ( is_water_area( i ) ) {
for (unsigned int j = 0; j < polys_in.polys[i].size(); j++) { for (unsigned int j = 0; j < polys_in.superpolys[i].size(); j++) {
water_mask = water_mask = tgPolygonUnion( water_mask, polys_in.superpolys[i][j].get_poly() );
tgPolygonUnion( water_mask, polys_in.polys[i][j] );
} }
} else if ( is_island_area( i ) ) { } else if ( is_island_area( i ) ) {
for (unsigned int j = 0; j < polys_in.polys[i].size(); j++) { for (unsigned int j = 0; j < polys_in.superpolys[i].size(); j++) {
island_mask = island_mask = tgPolygonUnion( island_mask, polys_in.superpolys[i][j].get_poly() );
tgPolygonUnion( island_mask, polys_in.polys[i][j] );
} }
} }
} }
// process polygons in priority order // process polygons in priority order
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
cout << "num polys of type (" << i << ") = " SG_LOG( SG_CLIPPER, SG_INFO, "num polys of type (" << i << ") = " << polys_in.superpolys[i].size() );
<< polys_in.polys[i].size() << endl; for( j = 0; j < (int)polys_in.superpolys[i].size(); ++j ) {
for( j = 0; j < (int)polys_in.polys[i].size(); ++j ) { TGPolygon current = polys_in.superpolys[i][j].get_poly();
TGPolygon current = polys_in.polys[i][j]; SG_LOG( SG_CLIPPER, SG_INFO, get_area_name( (AreaType)i ) << " = " << current.contours() );
SG_LOG( SG_CLIPPER, SG_INFO, get_area_name( (AreaType)i )
<< " = " << current.contours() );
tmp = current; tmp = current;
@ -545,14 +516,12 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
// add the sliverless result polygon (from after the // add the sliverless result polygon (from after the
// move_slivers) to the clipped polys list // move_slivers) to the clipped polys list
if ( result_diff.contours() > 0 ) { if ( result_diff.contours() > 0 ) {
polys_clipped.polys[i].push_back(result_diff); TGSuperPoly sp;
string material = get_area_name( (AreaType)i );
// static int count = 0; sp.set_material( material );
// cout << "Writing clipped polygon to next-result" << count sp.set_poly( result_diff );
// << endl; polys_clipped.superpolys[i].push_back( sp );
// char filename[256];
// sprintf(filename, "next-result-%02d-%02d", i, count++);
// result_diff.write(filename);
} }
} }
accum = result_union; accum = result_union;
@ -582,31 +551,17 @@ bool TGClipper::clip_all(const point2d& min, const point2d& max) {
} }
if ( remains.contours() > 0 ) { if ( remains.contours() > 0 ) {
polys_clipped.polys[(int)get_sliver_target_area_type()].push_back(remains); TGSuperPoly sp;
} string material = get_area_name(get_sliver_target_area_type());
}
#if 0 sp.set_material( material );
FILE *ofp; sp.set_poly( remains );
// tmp output accum polys_clipped.superpolys[(int)get_sliver_target_area_type()].push_back(sp);
if ( accum.num_contours ) {
ofp = fopen("accum", "w");
gpc_write_polygon(ofp, 1, &accum);
fclose(ofp);
} }
// tmp output safety_base
if ( remains->num_contours ) {
ofp= fopen("remains", "w");
gpc_write_polygon(ofp, 1, remains);
fclose(ofp);
} }
#endif
SG_LOG( SG_CLIPPER, SG_INFO, " master clipper finished." ); SG_LOG( SG_CLIPPER, SG_INFO, " master clipper finished." );
return true; return true;
} }

View file

@ -35,8 +35,10 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <Geometry/trinodes.hxx> //#include <Geometry/trinodes.hxx>
#include <Polygon/polygon.hxx> #include <Geometry/tg_nodes.hxx>
#include <Polygon/superpoly.hxx>
#include <Polygon/texparams.hxx>
#include <Polygon/point2d.hxx> #include <Polygon/point2d.hxx>
#include <string> #include <string>
@ -49,18 +51,21 @@
class TGPolyList class TGPolyList
{ {
public: public:
poly_list polys[TG_MAX_AREA_TYPES]; superpoly_list superpolys[TG_MAX_AREA_TYPES];
texparams_list texparams[TG_MAX_AREA_TYPES];
TGPolygon safety_base; TGPolygon safety_base;
}; };
class TGClipper class TGClipper
{ {
private: private:
TGPolyList polys_in, polys_clipped; TGPolyList polys_in, polys_clipped;
TGTriNodes fixed_elevations; //TGTriNodes fixed_elevations;
TGNodes nodes;
public: public:
@ -80,7 +85,7 @@ public:
bool load_osgb36_polys(const std::string& path); bool load_osgb36_polys(const std::string& path);
// Add a polygon. // Add a polygon.
void add_poly(int area, const TGPolygon &poly); void add_poly(int area, const TGPolygon &poly, std::string material);
// Remove any slivers from in polygon and move them to out // Remove any slivers from in polygon and move them to out
// polygon. // polygon.
@ -99,7 +104,9 @@ public:
inline TGPolyList get_polys_clipped() const { return polys_clipped; } inline TGPolyList get_polys_clipped() const { return polys_clipped; }
// Return the fixed elevation points list // Return the fixed elevation points list
inline TGTriNodes get_fixed_elevations() const { return fixed_elevations; } inline TGNodes get_nodes() const { return nodes; }
inline node_list get_fixed_elevations_nodes() { return nodes.get_fixed_elevation_nodes(); }
double nudge; double nudge;

View file

@ -28,6 +28,7 @@
#include <simgear/io/sg_binobj.hxx> #include <simgear/io/sg_binobj.hxx>
#include <simgear/math/SGGeometry.hxx> #include <simgear/math/SGGeometry.hxx>
#include <simgear/misc/texcoord.hxx> #include <simgear/misc/texcoord.hxx>
#include <simgear/debug/logstream.hxx>
#include <Output/output.hxx> #include <Output/output.hxx>
#include <Clipper/priorities.hxx> #include <Clipper/priorities.hxx>
@ -49,7 +50,7 @@ void TGGenOutput::calc_gbs( TGConstruct& c ) {
gbs_center = SGVec3d::fromGeod( c.get_bucket().get_center() ); gbs_center = SGVec3d::fromGeod( c.get_bucket().get_center() );
double dist_squared, radius_squared = 0; double dist_squared, radius_squared = 0;
for ( int i = 0; i < wgs84_nodes.size(); ++i ) { for ( unsigned int i = 0; i < wgs84_nodes.size(); ++i ) {
dist_squared = distSqr(gbs_center, wgs84_nodes[i].toSGVec3d()); dist_squared = distSqr(gbs_center, wgs84_nodes[i].toSGVec3d());
if ( dist_squared > radius_squared ) { if ( dist_squared > radius_squared ) {
radius_squared = dist_squared; radius_squared = dist_squared;
@ -58,126 +59,44 @@ void TGGenOutput::calc_gbs( TGConstruct& c ) {
gbs_radius = sqrt(radius_squared); gbs_radius = sqrt(radius_squared);
} }
#if 0
#define FG_STANDARD_TEXTURE_DIMENSION 1000.0 // meters
// traverse the specified fan and attempt to calculate "none
// stretching" texture coordinates
int_list TGGenOutput::calc_tex_coords( TGConstruct& c, point_list geod_nodes,
int_list fan )
{
// cout << "calculating texture coordinates for a specific fan of size = "
// << fan.size() << endl;
SGBucket b = c.get_bucket();
double clat = b.get_center_lat();
double clat_rad = clat * SGD_DEGREES_TO_RADIANS;
double cos_lat = cos( clat_rad );
double local_radius = cos_lat * SG_EQUATORIAL_RADIUS_M;
double local_perimeter = 2.0 * local_radius * SGD_PI;
double degree_width = local_perimeter / 360.0;
// cout << "clat = " << clat << endl;
// cout << "clat (radians) = " << clat_rad << endl;
// cout << "cos(lat) = " << cos_lat << endl;
// cout << "local_radius = " << local_radius << endl;
// cout << "local_perimeter = " << local_perimeter << endl;
// cout << "degree_width = " << degree_width << endl;
double perimeter = 2.0 * SG_EQUATORIAL_RADIUS_M * SG_DPI;
double degree_height = perimeter / 360.0;
// cout << "degree_height = " << degree_height << endl;
// find min/max of fan
Point3D min, max, p, t;
bool first = true;
for ( int i = 0; i < (int)fan.size(); ++i ) {
p = geod_nodes[ fan[i] ];
t.setx( p.x() * ( degree_width / FG_STANDARD_TEXTURE_DIMENSION ) );
t.sety( p.y() * ( degree_height / FG_STANDARD_TEXTURE_DIMENSION ) );
if ( first ) {
min = max = t;
first = false;
} else {
if ( t.x() < min.x() ) {
min.setx( t.x() );
}
if ( t.y() < min.y() ) {
min.sety( t.y() );
}
if ( t.x() > max.x() ) {
max.setx( t.x() );
}
if ( t.y() > max.y() ) {
max.sety( t.y() );
}
}
}
min.setx( (double)( (int)min.x() - 1 ) );
min.sety( (double)( (int)min.y() - 1 ) );
// cout << "found min = " << min << endl;
// generate tex_list
Point3D shifted_t;
int index;
int_list tex;
tex.clear();
for ( int i = 0; i < (int)fan.size(); ++i ) {
p = geod_nodes[ fan[i] ];
t.setx( p.x() * ( degree_width / FG_STANDARD_TEXTURE_DIMENSION ) );
t.sety( p.y() * ( degree_height / FG_STANDARD_TEXTURE_DIMENSION ) );
shifted_t = t - min;
if ( shifted_t.x() < SG_EPSILON ) {
shifted_t.setx( 0.0 );
}
if ( shifted_t.y() < SG_EPSILON ) {
shifted_t.sety( 0.0 );
}
shifted_t.setz( 0.0 );
// cout << "shifted_t = " << shifted_t << endl;
index = tex_coords.unique_add( shifted_t );
tex.push_back( index );
}
return tex;
}
#endif
// build the necessary output structures based on the triangulation // build the necessary output structures based on the triangulation
// data // data
int TGGenOutput::build( TGConstruct& c ) { int TGGenOutput::build_fans( TGConstruct& c ) {
int i, j, k; // TGTriNodes trinodes = c.get_tri_nodes();
TGNodes* nodes = c.get_nodes();
TGTriNodes trinodes = c.get_tri_nodes(); string tile_id = c.get_bucket().gen_index_str();
// copy the geodetic node list into this class // copy the geodetic node list into this class
geod_nodes = trinodes.get_node_list(); geod_nodes = nodes->get_geod_nodes();
// copy the triangle list into this class // copy the triangle list into this class
tri_elements = c.get_tri_elements(); tri_elements = c.get_tri_elements();
// build the trifan list // build the trifan list
cout << "total triangles = " << tri_elements.size() << endl; cout << "total triangles = " << tri_elements.size() << endl;
TGGenFans f; TGGenFans f;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
// Sort the triangles by area type
// TODO: Need to sort on Material type - going to make the attribute an index
// into an array of texparams / material names
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
triele_list area_tris; triele_list area_tris;
area_tris.erase( area_tris.begin(), area_tris.end() ); area_tris.erase( area_tris.begin(), area_tris.end() );
const_triele_list_iterator t_current = tri_elements.begin(); const_triele_list_iterator t_current = tri_elements.begin();
const_triele_list_iterator t_last = tri_elements.end(); const_triele_list_iterator t_last = tri_elements.end();
for ( ; t_current != t_last; ++t_current ) { for ( ; t_current != t_last; ++t_current ) {
if ( (int)t_current->get_attribute() == i ) { if ( t_current->get_attribute() == i ) {
area_tris.push_back( *t_current ); area_tris.push_back( *t_current );
} }
} }
if ( (int)area_tris.size() > 0 ) { if ( (int)area_tris.size() > 0 ) {
cout << "generating fans for area = " << i << endl; cout << "generating fans for area = " << i << endl;
fans[i] = f.greedy_build( area_tris ); primitives[i] = f.greedy_build( area_tris );
} }
} }
@ -187,16 +106,16 @@ int TGGenOutput::build( TGConstruct& c ) {
cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl; cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl;
tex_coords.clear(); tex_coords.clear();
std::vector < SGGeod > convGeodNodes; std::vector < SGGeod > convGeodNodes;
for ( k = 0; k < geod_nodes.size(); k++ ) { for ( unsigned int k = 0; k < geod_nodes.size(); k++ ) {
Point3D node = geod_nodes[k]; Point3D node = geod_nodes[k];
convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) ); convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
} }
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
// cout << " area = " << i << endl; // cout << " area = " << i << endl;
for ( j = 0; j < (int)fans[i].size(); ++j ) { for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
// int_list t_list = calc_tex_coords( c, geod_nodes, fans[i][j] ); SG_LOG( SG_CLIPPER, SG_INFO, tile_id << ": Texturing " << get_area_name( (AreaType)i ) << " primitive " << j+1 << " of " << primitives[i].size() );
// cout << fans[i][j].size() << " === "
// << t_list.size() << endl;
SGBucket b = c.get_bucket(); SGBucket b = c.get_bucket();
Point3D ourPosition; Point3D ourPosition;
@ -205,19 +124,20 @@ int TGGenOutput::build( TGConstruct& c ) {
int_list ti_list; int_list ti_list;
ti_list.clear(); ti_list.clear();
//dcl - here read the flag to check if we are building UK grid //dcl - here read the flag to check if we are building UK grid
//If so - check if the bucket is within the UK lat & lon //If so - check if the bucket is within the UK lat & lon
if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) { if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) {
point_list tp_list; point_list tp_list;
tp_list = UK_calc_tex_coords( b, geod_nodes, fans[i][j], 1.0 ); tp_list = UK_calc_tex_coords( b, geod_nodes, primitives[i][j], 1.0 );
for ( k = 0; k < (int)tp_list.size(); ++k ) { for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
// cout << " tc = " << tp_list[k] << endl; // cout << " tc = " << tp_list[k] << endl;
int index = tex_coords.simple_add( tp_list[k] ); int index = tex_coords.simple_add( tp_list[k] );
ti_list.push_back( index ); ti_list.push_back( index );
} }
} else { } else {
std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, fans[i][j] ); std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, primitives[i][j] );
for ( k = 0; k < (int)tp_list.size(); ++k ) { for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
SGVec2f tc = tp_list[k]; SGVec2f tc = tp_list[k];
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc); // SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) ); int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
@ -237,21 +157,132 @@ int TGGenOutput::build( TGConstruct& c ) {
} }
static opt_list tgGenTris( const triele_list tris ) {
triele_list remaining = tris;
opt_list tri_lists;
int_list tri;
tri_lists.clear();
for ( unsigned int i = 0; i < tris.size(); ++i ) {
tri.clear();
tri.push_back( tris[i].get_n1() );
tri.push_back( tris[i].get_n2() );
tri.push_back( tris[i].get_n3() );
tri_lists.push_back( tri );
}
return tri_lists;
}
int TGGenOutput::build_tris( TGConstruct& c ) {
// TGTriNodes trinodes = c.get_tri_nodes();
TGNodes* nodes = c.get_nodes();
string tile_id = c.get_bucket().gen_index_str();
// copy the geodetic node list into this class
geod_nodes = nodes->get_geod_nodes();
// copy the triangle list into this class
tri_elements = c.get_tri_elements();
// build the trifan list
cout << "total triangles = " << tri_elements.size() << endl;
// Sort the triangles by area type
// TODO: Need to sort on Material type - going to make the attribute an index
// into an array of texparams / material names
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
triele_list area_tris;
area_tris.erase( area_tris.begin(), area_tris.end() );
const_triele_list_iterator t_current = tri_elements.begin();
const_triele_list_iterator t_last = tri_elements.end();
for ( ; t_current != t_last; ++t_current ) {
if ( t_current->get_attribute() == i ) {
area_tris.push_back( *t_current );
}
}
if ( area_tris.size() > 0 ) {
cout << "generating tris for area = " << i << endl;
primitives[i] = tgGenTris( area_tris );
}
}
// build the texture coordinate list and make a parallel structure
// to the fan list for pointers into the texture list
cout << "calculating texture coordinates" << endl;
cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl;
tex_coords.clear();
std::vector < SGGeod > convGeodNodes;
for ( unsigned int k = 0; k < geod_nodes.size(); k++ ) {
Point3D node = geod_nodes[k];
convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
}
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
// cout << " area = " << i << endl;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
SG_LOG( SG_CLIPPER, SG_INFO, tile_id << ": Texturing " << get_area_name( (AreaType)i ) << " primitive " << j+1 << " of " << primitives[i].size() );
SGBucket b = c.get_bucket();
Point3D ourPosition;
ourPosition.setlon(b.get_chunk_lon());
ourPosition.setlat(b.get_chunk_lat());
int_list ti_list;
ti_list.clear();
//dcl - here read the flag to check if we are building UK grid
//If so - check if the bucket is within the UK lat & lon
if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) {
point_list tp_list;
tp_list = UK_calc_tex_coords( b, geod_nodes, primitives[i][j], 1.0 );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
// cout << " tc = " << tp_list[k] << endl;
int index = tex_coords.simple_add( tp_list[k] );
ti_list.push_back( index );
}
} else {
std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, primitives[i][j] );
for ( unsigned int k = 0; k < tp_list.size(); ++k ) {
SGVec2f tc = tp_list[k];
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
ti_list.push_back( index );
}
}
textures[i].push_back( ti_list );
}
}
// calculate the global bounding sphere
calc_gbs( c );
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
return 1;
}
// calculate the bounding sphere for a list of triangle faces // calculate the bounding sphere for a list of triangle faces
void TGGenOutput::calc_group_bounding_sphere( TGConstruct& c, void TGGenOutput::calc_group_bounding_sphere( TGConstruct& c,
const opt_list& fans, const opt_list& primitives,
Point3D *center, double *radius ) Point3D *center, double *radius )
{ {
cout << "calculate group bounding sphere for " << fans.size() << " fans." cout << "calculate group bounding sphere for " << primitives.size() << " primitives." << endl;
<< endl;
point_list wgs84_nodes = c.get_wgs84_nodes(); point_list wgs84_nodes = c.get_wgs84_nodes();
// generate a list of unique points from the triangle list // generate a list of unique points from the triangle list
TGTriNodes nodes; TGTriNodes nodes;
const_opt_list_iterator f_current = fans.begin(); const_opt_list_iterator f_current = primitives.begin();
const_opt_list_iterator f_last = fans.end(); const_opt_list_iterator f_last = primitives.end();
for ( ; f_current != f_last; ++f_current ) { for ( ; f_current != f_last; ++f_current ) {
const_int_list_iterator i_current = f_current->begin(); const_int_list_iterator i_current = f_current->begin();
const_int_list_iterator i_last = f_current->end(); const_int_list_iterator i_last = f_current->end();
@ -325,130 +356,8 @@ void TGGenOutput::calc_bounding_sphere( TGConstruct& c, const TGTriEle& t,
*radius = sqrt(max_squared); *radius = sqrt(max_squared);
} }
// write out the fgfs scenery file (using fans)
#if 0 int TGGenOutput::write_fans( TGConstruct &c ) {
// write out the fgfs scenery file
int TGGenOutput::write_orig( TGConstruct &c ) {
Point3D p;
int i;
string base = c.get_output_base();
SGBucket b = c.get_bucket();
string dir = base + b.gen_base_path();
#ifdef _MSC_VER
fg_mkdir( dir.c_str() );
#else
string command = "mkdir -p " + dir;
system(command.c_str());
#endif
string file = dir + "/" + b.gen_index_str();
cout << "Output file = " << file << endl;
FILE *fp;
if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
cout << "ERROR: opening " << file << " for writing!" << endl;
exit(-1);
}
// write headers
fprintf(fp, "# FGFS Scenery\n");
fprintf(fp, "# Version %s\n", FG_SCENERY_FILE_FORMAT);
time_t calendar_time = time(NULL);
struct tm *local_tm;
local_tm = localtime( &calendar_time );
char time_str[256];
strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
fprintf(fp, "# Created %s\n", time_str );
fprintf(fp, "\n");
// write global bounding sphere
fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
fprintf(fp, "\n");
// write nodes
point_list wgs84_nodes = c.get_wgs84_nodes();
cout << "writing nodes = " << wgs84_nodes.size() << endl;
fprintf(fp, "# vertex list\n");
const_point_list_iterator w_current = wgs84_nodes.begin();
const_point_list_iterator w_last = wgs84_nodes.end();
for ( ; w_current != w_last; ++w_current ) {
p = *w_current - gbs_center;
fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
}
fprintf(fp, "\n");
// write vertex normals
point_list point_normals = c.get_point_normals();
cout << "writing normals = " << point_normals.size() << endl;
fprintf(fp, "# vertex normal list\n");
const_point_list_iterator n_current = point_normals.begin();
const_point_list_iterator n_last = point_normals.end();
for ( ; n_current != n_last; ++n_current ) {
p = *n_current;
fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
}
fprintf(fp, "\n");
// write texture coordinates
point_list tex_coord_list = tex_coords.get_node_list();
fprintf(fp, "# texture coordinate list\n");
for ( i = 0; i < (int)tex_coord_list.size(); ++i ) {
p = tex_coord_list[i];
fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y());
}
fprintf(fp, "\n");
// write triangles (grouped by type for now)
Point3D center;
double radius;
fprintf(fp, "# triangle groups\n");
fprintf(fp, "\n");
int total_tris = 0;
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( (int)fans[i].size() > 0 ) {
string attr_name = get_area_name( (AreaType)i );
calc_group_bounding_sphere( c, fans[i], &center, &radius );
cout << "writing " << (int)fans[i].size() << " fans for "
<< attr_name << endl;
fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
center.x(), center.y(), center.z(), radius);
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
fprintf( fp, "tf" );
total_tris += fans[i][j].size() - 2;
for ( int k = 0; k < (int)fans[i][j].size(); ++k ) {
fprintf( fp, " %d/%d", fans[i][j][k], textures[i][j][k] );
}
fprintf( fp, "\n" );
}
fprintf( fp, "\n" );
}
}
cout << "wrote " << total_tris << " tris to output file" << endl;
fclose(fp);
command = "gzip --force --best " + file;
system(command.c_str());
return 1;
}
#endif
// write out the fgfs scenery file
int TGGenOutput::write( TGConstruct &c ) {
int i;
// Assemble all the data into the final format // Assemble all the data into the final format
SGBucket b = c.get_bucket(); SGBucket b = c.get_bucket();
@ -457,12 +366,12 @@ int TGGenOutput::write( TGConstruct &c ) {
name += ".btg"; name += ".btg";
std::vector< SGVec3d > wgs84_nodes; std::vector< SGVec3d > wgs84_nodes;
for ( i = 0; i < c.get_wgs84_nodes().size(); i++ ) { for ( unsigned int i = 0; i < c.get_wgs84_nodes().size(); i++ ) {
Point3D node = c.get_wgs84_nodes()[i]; Point3D node = c.get_wgs84_nodes()[i];
wgs84_nodes.push_back( node.toSGVec3d() ); wgs84_nodes.push_back( node.toSGVec3d() );
} }
std::vector< SGVec3f > normals; std::vector< SGVec3f > normals;
for ( i = 0; i < c.get_point_normals().size(); i++ ) { for ( unsigned int i = 0; i < c.get_point_normals().size(); i++ ) {
Point3D node = c.get_point_normals()[i]; Point3D node = c.get_point_normals()[i];
normals.push_back( node.toSGVec3f() ); normals.push_back( node.toSGVec3f() );
} }
@ -472,7 +381,7 @@ int TGGenOutput::write( TGConstruct &c ) {
printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z()); printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
} */ } */
std::vector< SGVec2f > texcoords; std::vector< SGVec2f > texcoords;
for ( i = 0; i < tex_coords.get_node_list().size(); i++ ) { for ( unsigned int i = 0; i < tex_coords.get_node_list().size(); i++ ) {
Point3D node = tex_coords.get_node_list()[i]; Point3D node = tex_coords.get_node_list()[i];
texcoords.push_back( node.toSGVec2f() ); texcoords.push_back( node.toSGVec2f() );
} }
@ -487,17 +396,16 @@ int TGGenOutput::write( TGConstruct &c ) {
group_list fans_v; group_list fans_tc; string_list fan_materials; group_list fans_v; group_list fans_tc; string_list fan_materials;
fans_v.clear(); fans_tc.clear(); fan_materials.clear(); fans_v.clear(); fans_tc.clear(); fan_materials.clear();
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( (int)fans[i].size() > 0 ) { if ( primitives[i].size() > 0 ) {
cout << "creating " << fans[i].size() << " fans of type " cout << "creating " << primitives[i].size() << " fans of type " << i << endl;
<< i << endl;
string attr_name = get_area_name( (AreaType)i ); string attr_name = get_area_name( (AreaType)i );
int_list vs, tcs; int_list vs, tcs;
for ( int j = 0; j < (int)fans[i].size(); ++j ) { for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
vs.clear(); tcs.clear(); vs.clear(); tcs.clear();
for ( int k = 0; k < (int)fans[i][j].size(); ++k ) { for ( unsigned int k = 0; k < primitives[i][j].size(); ++k ) {
vs.push_back( fans[i][j][k] ); vs.push_back( primitives[i][j][k] );
tcs.push_back( textures[i][j][k] ); tcs.push_back( textures[i][j][k] );
} }
fans_v.push_back( vs ); fans_v.push_back( vs );
@ -529,4 +437,83 @@ int TGGenOutput::write( TGConstruct &c ) {
return 1; return 1;
} }
// write out the fgfs scenery file (using tris)
int TGGenOutput::write_tris( TGConstruct &c ) {
// Assemble all the data into the final format
SGBucket b = c.get_bucket();
string base = c.get_output_base();
string name = b.gen_index_str();
name += ".btg";
std::vector< SGVec3d > wgs84_nodes;
for ( unsigned int i = 0; i < c.get_wgs84_nodes().size(); i++ ) {
Point3D node = c.get_wgs84_nodes()[i];
wgs84_nodes.push_back( node.toSGVec3d() );
}
std::vector< SGVec3f > normals;
for ( unsigned int i = 0; i < c.get_point_normals().size(); i++ ) {
Point3D node = c.get_point_normals()[i];
normals.push_back( node.toSGVec3f() );
}
cout << "dumping normals = " << normals.size() << endl;
/* for ( i = 0; i < (int)normals.size(); ++i ) {
Point3D p = normals[i];
printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
} */
std::vector< SGVec2f > texcoords;
for ( unsigned int i = 0; i < tex_coords.get_node_list().size(); i++ ) {
Point3D node = tex_coords.get_node_list()[i];
texcoords.push_back( node.toSGVec2f() );
}
// allocate and initialize triangle group structures
group_list tris_v; group_list tris_tc; string_list tri_materials;
tris_v.clear(); tris_tc.clear(); tri_materials.clear();
group_list strips_v; group_list strips_tc; string_list strip_materials;
strips_v.clear(); strips_tc.clear(); strip_materials.clear();
group_list fans_v; group_list fans_tc; string_list fan_materials;
fans_v.clear(); fans_tc.clear(); fan_materials.clear();
for ( unsigned int i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
if ( primitives[i].size() > 0 ) {
cout << "creating " << primitives[i].size() << " tris of type " << i << endl;
string attr_name = get_area_name( (AreaType)i );
int_list vs, tcs;
for ( unsigned int j = 0; j < primitives[i].size(); ++j ) {
vs.clear(); tcs.clear();
for ( unsigned int k = 0; k < primitives[i][j].size(); ++k ) {
vs.push_back( primitives[i][j][k] );
tcs.push_back( textures[i][j][k] );
}
tris_v.push_back( vs );
tris_tc.push_back( tcs );
tri_materials.push_back( attr_name );
}
}
}
SGBinObject obj;
obj.set_gbs_center( gbs_center );
obj.set_gbs_radius( gbs_radius );
obj.set_wgs84_nodes( wgs84_nodes );
obj.set_normals( normals );
obj.set_texcoords( texcoords );
obj.set_tris_v( tris_v );
obj.set_tris_tc( tris_tc );
obj.set_tri_materials( tri_materials );
obj.set_strips_v( strips_v );
obj.set_strips_tc( strips_tc );
obj.set_strip_materials( strip_materials );
obj.set_fans_v( fans_v );
obj.set_fans_tc( fans_tc );
obj.set_fan_materials( fan_materials );
obj.write_bin( base, name, b );
return 1;
}

View file

@ -59,8 +59,8 @@ private:
// texture coordinates // texture coordinates
TGTriNodes tex_coords; TGTriNodes tex_coords;
// fan list // fan / triangle list
opt_list fans[TG_MAX_AREA_TYPES]; opt_list primitives[TG_MAX_AREA_TYPES];
// textures pointer list // textures pointer list
tex_list textures[TG_MAX_AREA_TYPES]; tex_list textures[TG_MAX_AREA_TYPES];
@ -93,10 +93,12 @@ public:
// build the necessary output structures based on the // build the necessary output structures based on the
// triangulation data // triangulation data
int build( TGConstruct& c ); int build_fans( TGConstruct& c );
int build_tris( TGConstruct& c );
// write out the fgfs scenery file // write out the fgfs scenery file
int write( TGConstruct &c ); int write_fans( TGConstruct &c );
int write_tris( TGConstruct &c );
}; };

View file

@ -92,10 +92,11 @@ private:
// Fixed elevations (from polygon input data with z values // Fixed elevations (from polygon input data with z values
// pre-specified) // pre-specified)
TGTriNodes fixed_elevations; node_list fixed_elevations;
// raw node list (after triangulation) // raw node list (after triangulation)
TGTriNodes tri_nodes; TGTriNodes tri_nodes;
TGNodes nodes;
// node list in geodetic coords (with fixed elevation) // node list in geodetic coords (with fixed elevation)
point_list geod_nodes; point_list geod_nodes;
@ -115,10 +116,6 @@ private:
// face normal list (for flat shading) // face normal list (for flat shading)
point_list face_normals; point_list face_normals;
// normal list (for each point) in cart coords (for smooth
// shading)
point_list point_normals;
public: public:
// Constructor // Constructor
@ -167,33 +164,32 @@ public:
inline TGPolyList get_clipped_polys() const { return clipped_polys; } inline TGPolyList get_clipped_polys() const { return clipped_polys; }
inline void set_clipped_polys( TGPolyList p ) { clipped_polys = p; } inline void set_clipped_polys( TGPolyList p ) { clipped_polys = p; }
// Fixed elevations (from polygon input data with z values // Fixed elevations (from polygon input data with z values pre-specified)
// pre-specified) inline node_list get_fixed_elevations() const { return nodes.get_fixed_elevation_nodes(); }
inline TGTriNodes get_fixed_elevations() const { return fixed_elevations; }
inline void set_fixed_elevations( TGTriNodes n ) { fixed_elevations = n; }
// node list (after triangulation) // node list (after triangulation) : No need - we won't add nodes....
inline TGTriNodes get_tri_nodes() const { return tri_nodes; } // inline TGTriNodes get_tri_nodes() const { return tri_nodes; }
inline void set_tri_nodes( TGTriNodes n ) { tri_nodes = n; } // inline void set_tri_nodes( TGTriNodes n ) { tri_nodes = n; }
// triangle elements (after triangulation) inline TGNodes* get_nodes() { return &nodes; }
inline void set_nodes( TGNodes n ) { nodes = n; }
// triangle elements (after triangulation) : No need - will be in the triangulated polygons
inline triele_list get_tri_elements() const { return tri_elements; } inline triele_list get_tri_elements() const { return tri_elements; }
inline void set_tri_elements( triele_list e ) { tri_elements = e; } inline void set_tri_elements( triele_list e ) { tri_elements = e; }
inline void set_tri_attribute( int num, AreaType a ) { inline void set_tri_attribute( int num, AreaType a ) { tri_elements[num].set_attribute( a ); }
tri_elements[num].set_attribute( a );
}
// edge segments (after triangulation) // edge segments (after triangulation) : Same as above
inline TGTriSegments get_tri_segs() const { return tri_segs; } inline TGTriSegments get_tri_segs() const { return tri_segs; }
inline void set_tri_segs( TGTriSegments s ) { tri_segs = s; } inline void set_tri_segs( TGTriSegments s ) { tri_segs = s; }
// node list in geodetic coords (with fixed elevation) // node list in geodetic coords (with fixed elevation)
inline point_list get_geod_nodes() const { return geod_nodes; } inline point_list get_geod_nodes() const { return nodes.get_geod_nodes(); }
inline void set_geod_nodes( point_list n ) { geod_nodes = n; } // inline void set_geod_nodes( point_list n ) { geod_nodes = n; }
// node list in cartesian coords (wgs84 model) // node list in cartesian coords (wgs84 model)
inline point_list get_wgs84_nodes() const { return wgs84_nodes; } inline point_list get_wgs84_nodes() const { return nodes.get_wgs84_nodes_as_Point3d(); }
inline void set_wgs84_nodes( point_list n ) { wgs84_nodes = n; } // inline void set_wgs84_nodes( point_list n ) { wgs84_nodes = n; }
// for each node, a list of triangle indices that contain this node // for each node, a list of triangle indices that contain this node
inline belongs_to_list get_reverse_ele_lookup() const { inline belongs_to_list get_reverse_ele_lookup() const {
@ -209,8 +205,7 @@ public:
// normal list (for each point) in cart coords (for smooth // normal list (for each point) in cart coords (for smooth
// shading) // shading)
inline point_list get_point_normals() const { return point_normals; } inline point_list get_point_normals() const { return nodes.get_normals(); }
inline void set_point_normals( point_list n ) { point_normals = n; }
}; };

File diff suppressed because it is too large Load diff

View file

@ -27,9 +27,11 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <Geometry/point3d.hxx> #include <Geometry/point3d.hxx>
#include <Geometry/tg_nodes.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sgstream.hxx> #include <simgear/misc/sgstream.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include "match.hxx" #include "match.hxx"
@ -369,6 +371,9 @@ void TGMatch::split_tile( TGConstruct& c ) {
point_list nodes = c.get_geod_nodes(); point_list nodes = c.get_geod_nodes();
point_list point_normals = c.get_point_normals(); point_list point_normals = c.get_point_normals();
SG_LOG(SG_GENERAL, SG_ALERT, "number of geod nodes = " << nodes.size() );
SG_LOG(SG_GENERAL, SG_ALERT, "number of normals = " << point_normals.size() );
for ( i = 0; i < (int)nodes.size(); ++i ) { for ( i = 0; i < (int)nodes.size(); ++i ) {
Point3D node = nodes[i]; Point3D node = nodes[i];
Point3D normal = point_normals[i]; Point3D normal = point_normals[i];
@ -423,6 +428,7 @@ void TGMatch::split_tile( TGConstruct& c ) {
} }
} }
#if 0 // UNUSED
// separate area edge segment into components // separate area edge segment into components
cout << " extracting (shared) area edge segments" << endl; cout << " extracting (shared) area edge segments" << endl;
@ -494,6 +500,10 @@ void TGMatch::split_tile( TGConstruct& c ) {
cout << " " << body_nodes[i] << endl; cout << " " << body_nodes[i] << endl;
} }
*/ */
#endif
SG_LOG(SG_GENERAL, SG_ALERT, "SPLIT TILE COMPLETE " );
} }
@ -677,6 +687,55 @@ void insert_normal( point_list& normals, Point3D n, int i ) {
normals[i] = n; normals[i] = n;
} }
// Just add nodes and normals to the node list
void TGMatch::add_shared_nodes( TGConstruct& c ) {
TGNodes* nodes;
nodes = c.get_nodes();
cout << " BEFORE ADDING SHARED NODES: " << nodes->size() << endl;
if ( sw_flag ) {
nodes->unique_add_fixed_elevation( sw_node );
}
if ( se_flag ) {
nodes->unique_add_fixed_elevation( se_node );
}
if ( nw_flag ) {
nodes->unique_add_fixed_elevation( nw_node );
}
if ( ne_flag ) {
nodes->unique_add_fixed_elevation( ne_node );
}
if ( north_flag ) {
for (unsigned int i = 0; i < north_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( north_nodes[i] );
}
}
if ( south_flag ) {
for (unsigned int i = 0; i < south_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( south_nodes[i] );
}
}
if ( east_flag ) {
for (unsigned int i = 0; i < east_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( east_nodes[i] );
}
}
if ( west_flag ) {
for (unsigned int i = 0; i < west_nodes.size(); i++) {
nodes->unique_add_fixed_elevation( west_nodes[i] );
}
}
cout << " AFTER ADDING SHARED NODES: " << nodes->size() << endl;
}
// reassemble the tile pieces (combining the shared data and our own // reassemble the tile pieces (combining the shared data and our own
// data) // data)
@ -805,6 +864,7 @@ void TGMatch::assemble_tile( TGConstruct& c ) {
TGTriSeg(n1, n2, marker) ); TGTriSeg(n1, n2, marker) );
} }
#if 0 // UNUSED
c.set_tri_nodes( new_nodes ); c.set_tri_nodes( new_nodes );
c.set_point_normals( new_normals ); c.set_point_normals( new_normals );
c.set_tri_segs( new_segs ); c.set_tri_segs( new_segs );
@ -812,5 +872,6 @@ void TGMatch::assemble_tile( TGConstruct& c ) {
cout << "after adding all segments (should be the same):" << endl; cout << "after adding all segments (should be the same):" << endl;
cout << " new_nodes = " << new_nodes.size() << endl; cout << " new_nodes = " << new_nodes.size() << endl;
cout << " new normals = " << new_normals.size() << endl; cout << " new normals = " << new_normals.size() << endl;
#endif
} }

View file

@ -95,6 +95,10 @@ public:
// try to find info for the specified shared component // try to find info for the specified shared component
void load_shared( const TGConstruct& c, neighbor_type n ); void load_shared( const TGConstruct& c, neighbor_type n );
// NEW TILE MATCHING - PRE TRIANGULATION
// Just add nodes and normals to the node list
void add_shared_nodes( TGConstruct& c );
// split up the tile between the shared edge points, normals, and // split up the tile between the shared edge points, normals, and
// segments and the body. This must be done after calling // segments and the body. This must be done after calling
// load_neighbor_data() and will ignore any shared data from the // load_neighbor_data() and will ignore any shared data from the

View file

@ -24,6 +24,7 @@
#include <Geometry/poly_support.hxx> #include <Geometry/poly_support.hxx>
#include <Polygon/polygon.hxx> #include <Polygon/polygon.hxx>
#include <Polygon/superpoly.hxx>
#include <TriangleJRS/tri_support.h> #include <TriangleJRS/tri_support.h>
#include "triangle.hxx" #include "triangle.hxx"
@ -75,8 +76,9 @@ TGTriangle::build( const point_list& corner_list,
} }
// next process the polygons // next process the polygons
TGSuperPoly sp;
TGPolygon gpc_poly; TGPolygon gpc_poly;
const_poly_list_iterator current, last; const_superpoly_list_iterator current, last;
// process polygons in priority order // process polygons in priority order
cout << "prepairing node list and polygons" << endl; cout << "prepairing node list and polygons" << endl;
@ -84,16 +86,15 @@ TGTriangle::build( const point_list& corner_list,
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) { for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
polylist[i].clear(); polylist[i].clear();
cout << "area type = " << i << " polys = " << gpc_polys.polys[i].size() cout << "area type = " << i << " polys = " << gpc_polys.superpolys[i].size() << endl;
<< endl;
debug_counter = 0; debug_counter = 0;
current = gpc_polys.polys[i].begin(); current = gpc_polys.superpolys[i].begin();
last = gpc_polys.polys[i].end(); last = gpc_polys.superpolys[i].end();
for ( ; current != last; ++current ) { for ( ; current != last; ++current ) {
gpc_poly = *current; sp = *current;
gpc_poly = sp.get_poly();
cout << "processing a polygon, contours = " // cout << "processing a polygon, contours = " << gpc_poly.contours() << endl;
<< gpc_poly.contours() << endl;
if (gpc_poly.contours() <= 0 ) { if (gpc_poly.contours() <= 0 ) {
cout << "FATAL ERROR! no contours in this polygon" << endl; cout << "FATAL ERROR! no contours in this polygon" << endl;
@ -102,9 +103,7 @@ TGTriangle::build( const point_list& corner_list,
int j; int j;
for ( j = 0; j < gpc_poly.contours(); ++j ) { for ( j = 0; j < gpc_poly.contours(); ++j ) {
cout << " processing contour = " << j << ", nodes = " // cout << " processing contour = " << j << ", nodes = " << gpc_poly.contour_size( j ) << ", hole = " << gpc_poly.get_hole_flag( j ) << endl;
<< gpc_poly.contour_size( j ) << ", hole = "
<< gpc_poly.get_hole_flag( j ) << endl;
/* /*
char junkn[256]; char junkn[256];
@ -149,8 +148,7 @@ TGTriangle::build( const point_list& corner_list,
gpc_poly = remove_bad_contours( gpc_poly ); gpc_poly = remove_bad_contours( gpc_poly );
gpc_poly = remove_cycles( gpc_poly ); gpc_poly = remove_cycles( gpc_poly );
cout << "after sanity checks, contours = " // cout << "after sanity checks, contours = " << gpc_poly.contours() << endl;
<< gpc_poly.contours() << endl;
/* /*
for ( j = 0; j < gpc_poly.contours(); ++j ) { for ( j = 0; j < gpc_poly.contours(); ++j ) {
@ -162,9 +160,9 @@ TGTriangle::build( const point_list& corner_list,
} }
*/ */
cout << "before calc_points_inside()" << endl; // cout << "before calc_points_inside()" << endl;
calc_points_inside( gpc_poly ); calc_points_inside( gpc_poly );
cout << "after calc_points_inside()" << endl; // cout << "after calc_points_inside()" << endl;
#if 0 #if 0
// old way // old way
@ -240,8 +238,7 @@ TGTriangle::build( const point_list& corner_list,
// process each polygon in list // process each polygon in list
for ( ; tp_current != tp_last; ++tp_current ) { for ( ; tp_current != tp_last; ++tp_current ) {
poly = *tp_current; poly = *tp_current;
cout << " processing a polygon with contours = " // cout << " processing a polygon with contours = " << poly.contours() << endl;
<< poly.contours() << endl;
for ( int j = 0; j < (int)poly.contours(); ++j) { for ( int j = 0; j < (int)poly.contours(); ++j) {
for ( int k = 0; k < (int)(poly.contour_size(j) - 1); ++k ) { for ( int k = 0; k < (int)(poly.contour_size(j) - 1); ++k ) {
p1 = poly.get_pt( j, k ); p1 = poly.get_pt( j, k );
@ -280,14 +277,15 @@ TGTriangle::build( const point_list& corner_list,
return 0; return 0;
} }
// populate this class based on the specified gpc_polys list // populate this class based on the specified gpc_polys list
int TGTriangle::rebuild( TGConstruct& c ) { int TGTriangle::rebuild( TGConstruct& c ) {
in_nodes.clear(); in_nodes.clear();
in_segs.clear(); in_segs.clear();
#if 0
in_nodes = c.get_tri_nodes(); in_nodes = c.get_tri_nodes();
in_segs = c.get_tri_segs(); in_segs = c.get_tri_segs();
#endif
return 0; return 0;
} }
@ -307,8 +305,12 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
int counter; int counter;
int i, j; int i, j;
// point list // point list
point_list node_list = in_nodes.get_node_list(); point_list node_list = in_nodes.get_node_list();
cout << "TRIANGULATE : NUMBER OF INPUT NODES: " << node_list.size() << endl;
in.numberofpoints = node_list.size(); in.numberofpoints = node_list.size();
in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL)); in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
@ -465,6 +467,7 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
// use a quality value of 10 (q10) meaning no interior // use a quality value of 10 (q10) meaning no interior
// triangle angles less than 10 degrees // triangle angles less than 10 degrees
// tri_options = "pczAen"; // tri_options = "pczAen";
#if 0
if ( angle < 0.00001 ) { if ( angle < 0.00001 ) {
tri_options = "pczAen"; tri_options = "pczAen";
} else { } else {
@ -474,6 +477,13 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
tri_options += angle_str; tri_options += angle_str;
tri_options += "Aen"; tri_options += "Aen";
} }
#else
// TEST TEST TEST : NO ADDING POINTS
tri_options = "pzenYYQ";
#endif
// // string tri_options = "pzAen"; // // string tri_options = "pzAen";
// // string tri_options = "pczq15S400Aen"; // // string tri_options = "pczq15S400Aen";
} else if ( pass == 2 ) { } else if ( pass == 2 ) {
@ -495,6 +505,8 @@ int TGTriangle::run_triangulate( double angle, const int pass ) {
// now copy the results back into the corresponding TGTriangle // now copy the results back into the corresponding TGTriangle
// structures // structures
cout << "TRIANGULATE : NUMBER OF OUTPUT NODES: " << out.numberofpoints << endl;
// nodes // nodes
out_nodes.clear(); out_nodes.clear();
for ( i = 0; i < out.numberofpoints; ++i ) { for ( i = 0; i < out.numberofpoints; ++i ) {

View file

@ -8,6 +8,7 @@ add_library(Geometry STATIC
poly_support.cxx poly_support.cxx
poly_extra.cxx poly_extra.cxx
rectangle.cxx rectangle.cxx
tg_nodes.cxx
trinodes.cxx trinodes.cxx
trisegs.cxx trisegs.cxx
util.cxx util.cxx
@ -17,6 +18,7 @@ add_library(Geometry STATIC
poly_support.hxx poly_support.hxx
poly_extra.hxx poly_extra.hxx
rectangle.hxx rectangle.hxx
tg_nodes.hxx
trinodes.hxx trinodes.hxx
trisegs.hxx trisegs.hxx
util.hxx util.hxx

View file

@ -114,4 +114,67 @@ TGPolygon add_nodes_to_poly( const TGPolygon& poly,
return result; return result;
} }
// Divide segment if there are other existing points on it, return the
// new polygon
void add_intermediate_tgnodes( int contour, const Point3D& start,
const Point3D& end, const TGNodes* nodes,
TGPolygon *result )
{
point_list points = nodes->get_geod_nodes();
SG_LOG(SG_GENERAL, SG_DEBUG, " add_intermediate_nodes()");
char buf[200];
snprintf(buf, 199, " %.7f %.7f %.7f <=> %.7f %.7f %.7f\n",
start.x(), start.y(), start.z(), end.x(), end.y(), end.z() );
SG_LOG(SG_GENERAL, SG_DEBUG, buf);
Point3D new_pt;
bool found_extra = find_intermediate_node( start, end, points, &new_pt );
if ( found_extra ) {
SG_LOG(SG_GENERAL, SG_DEBUG, "dividing " << start << " " << new_pt << " " << end);
add_intermediate_tgnodes( contour, start, new_pt, nodes, result );
result->add_node( contour, new_pt );
SG_LOG(SG_GENERAL, SG_INFO, " added = " << new_pt);
add_intermediate_tgnodes( contour, new_pt, end, nodes, result );
}
}
TGPolygon add_tgnodes_to_poly( const TGPolygon& poly,
const TGNodes* nodes ) {
TGPolygon result; result.erase();
Point3D p0, p1;
SG_LOG(SG_GENERAL, SG_DEBUG, "add_nodes_to_poly");
for ( int i = 0; i < poly.contours(); ++i ) {
SG_LOG(SG_GENERAL, SG_DEBUG, "contour = " << i);
for ( int j = 0; j < poly.contour_size(i) - 1; ++j ) {
p0 = poly.get_pt( i, j );
p1 = poly.get_pt( i, j + 1 );
// add start of segment
result.add_node( i, p0 );
// add intermediate points
add_intermediate_tgnodes( i, p0, p1, nodes, &result );
// end of segment is beginning of next segment
}
p0 = poly.get_pt( i, poly.contour_size(i) - 1 );
p1 = poly.get_pt( i, 0 );
// add start of segment
result.add_node( i, p0 );
// add intermediate points
add_intermediate_tgnodes( i, p0, p1, nodes, &result );
// maintain original hole flag setting
result.set_hole_flag( i, poly.get_hole_flag( i ) );
}
return result;
}

View file

@ -29,6 +29,8 @@
#include <Geometry/point3d.hxx> #include <Geometry/point3d.hxx>
#include <Geometry/trinodes.hxx> #include <Geometry/trinodes.hxx>
#include <Geometry/tg_nodes.hxx>
#include <Polygon/polygon.hxx> #include <Polygon/polygon.hxx>
@ -46,5 +48,8 @@ void add_intermediate_nodes( int contour, const Point3D& start,
TGPolygon add_nodes_to_poly( const TGPolygon& poly, TGPolygon add_nodes_to_poly( const TGPolygon& poly,
const TGTriNodes& tmp_nodes ); const TGTriNodes& tmp_nodes );
TGPolygon add_tgnodes_to_poly( const TGPolygon& poly,
const TGNodes* nodes );
#endif // _POLY_EXTRA_HXX #endif // _POLY_EXTRA_HXX

View file

@ -0,0 +1,185 @@
#include <simgear/debug/logstream.hxx>
#include "tg_nodes.hxx"
// Find the index of the specified point (compair to the same
// tolerance as unique_add(). Returns -1 if not found.
int TGNodes::find( const Point3D& p ) const {
const_node_list_iterator current, last;
Point3D pos;
int counter = 0;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
pos = current->GetPosition();
if ( close_enough_2d(p, pos ) ) {
return counter;
}
++counter;
}
return -1;
}
int TGNodes::unique_add( const Point3D& p ) {
node_list_iterator current, last;
int counter = 0;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
if ( close_enough_3d(p, (*current).GetPosition() ) ) {
// cout << "found an existing match!" << endl;
return counter;
}
++counter;
}
TGNode node( p );
node.SetFixedPosition( false );
// add to list
tg_node_list.push_back( node );
return counter;
}
int TGNodes::unique_add_fixed_elevation( const Point3D& p ) {
node_list_iterator current, last;
int counter = 0;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
if ( close_enough_3d(p, (*current).GetPosition() ) ) {
SG_LOG(SG_GENERAL, SG_ALERT, "Adding fixed elev node : node already exists at " << counter << " old position is " << (*current).GetPosition() << " new position is " << p );
// Force the match to our position, and mark as fixed
(*current).SetPosition( p );
(*current).SetFixedPosition( true );
return counter;
}
++counter;
}
TGNode node( p );
node.SetFixedPosition( true );
// add to list
tg_node_list.push_back( node );
return counter;
}
point_list TGNodes::get_geod_nodes( void ) const {
point_list points;
const_node_list_iterator current, last;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
points.push_back( (*current).GetPosition() );
}
return points;
}
std::vector< SGVec3d > TGNodes::get_wgs84_nodes_as_SGVec3d( void ) const {
std::vector< SGVec3d > points;
Point3D pos;
const_node_list_iterator current, last;
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
pos = (*current).GetPosition();
SGGeod geod = SGGeod::fromDegM( pos.x(), pos.y(), pos.z() );
SGVec3d cart = SGVec3d::fromGeod(geod);
points.push_back( cart );
}
return points;
}
point_list TGNodes::get_wgs84_nodes_as_Point3d( void ) const {
point_list points;
Point3D pos;
const_node_list_iterator current, last;
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
pos = (*current).GetPosition();
SGGeod geod = SGGeod::fromDegM( pos.x(), pos.y(), pos.z() );
SGVec3d cart = SGVec3d::fromGeod(geod);
points.push_back( Point3D::fromSGVec3( cart ) );
}
return points;
}
node_list TGNodes::get_fixed_elevation_nodes( void ) const {
node_list fixed_elev;
const_node_list_iterator current, last;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
if ( (*current).GetFixedPosition() ) {
fixed_elev.push_back( (*current) );
}
}
return fixed_elev;
}
point_list TGNodes::get_normals( void ) const {
point_list points;
const_node_list_iterator current, last;
// see if point already exists
current = tg_node_list.begin();
last = tg_node_list.end();
for ( ; current != last; ++current ) {
points.push_back( (*current).GetNormal() );
}
return points;
}
bool TGNodes::LookupFixedElevation( Point3D p, double* z )
{
int index = find( p );
bool found = false;
if (index >= 0) {
TGNode node = tg_node_list[index];
if ( node.GetFixedPosition() ) {
*z = tg_node_list[index].GetPosition().z();
found = true;
}
}
return found;
}

View file

@ -0,0 +1,192 @@
#ifndef _TG_NODES_HXX
#define _TG_NODES_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include <Geometry/point3d.hxx>
#include <simgear/math/sg_types.hxx>
#define FG_PROXIMITY_EPSILON 0.000001
#define FG_COURSE_EPSILON 0.0001
typedef std::vector < unsigned int > TGIdxList;
class TGNode {
public:
TGNode( Point3D p ) {
position = p;
normal = Point3D();
fixed_position = false; // no matter what - don't move x, y, or z (likely a hole around an airport generated ny genapts)
fixed_normal = false; // no matter what - don't modify the normal - likely on a normal generated on a shared edge
faces.clear();
neighbors.clear();
}
inline void SetFixedPosition( bool fix )
{
if (!fixed_position) {
fixed_position = fix;
}
}
inline bool GetFixedPosition( void ) const { return fixed_position; }
inline void SetFixedNormal( bool fix ) { fixed_normal = fix; }
inline bool GetFixedNormal( void ) const { return fixed_normal; }
inline void SetPosition( const Point3D& p )
{
if (!fixed_position) {
position = p;
}
}
inline void SetElevation( double z )
{
if (!fixed_position) {
position.setelev( z );
}
}
inline Point3D GetPosition( void ) const { return position; }
inline void SetNormal( const Point3D& n ) { normal = n; }
inline Point3D GetNormal( void ) const { return normal; }
private:
Point3D position;
Point3D normal;
bool fixed_position;
bool fixed_normal;
TGIdxList faces;
TGIdxList neighbors;
};
typedef std::vector < TGNode > node_list;
typedef node_list::iterator node_list_iterator;
typedef node_list::const_iterator const_node_list_iterator;
/* This class handles ALL of the nodes in a tile : 3d nodes in elevation data, 2d nodes generated from landclass, etc) */
class TGNodes {
public:
// Constructor and destructor
TGNodes( void ) {}
~TGNodes( void ) {}
// delete all the data out of node_list
inline void clear() { tg_node_list.clear(); }
// Add a point to the point list if it doesn't already exist.
// Returns the index (starting at zero) of the point in the list.
int unique_add( const Point3D& p );
// Add a point to the point list if it doesn't already exist
// (checking all three dimensions.) Returns the index (starting
// at zero) of the point in the list.
int unique_add_fixed_elevation( const Point3D& p );
node_list get_fixed_elevation_nodes( void ) const;
// Add the point with no uniqueness checking
int simple_add( const Point3D& p );
// Add a point to the point list if it doesn't already exist.
// Returns the index (starting at zero) of the point in the list.
// Use a course proximity check
int course_add( const Point3D& p );
// Find the index of the specified point (compair to the same
// tolerance as unique_add(). Returns -1 if not found.
int find( const Point3D& p ) const;
bool LookupFixedElevation( Point3D p, double* z );
void SetElevation( int idx, double z ) { tg_node_list[idx].SetElevation( z ); }
// return the master node list
inline node_list& get_node_list() { return tg_node_list; }
inline const node_list& get_node_list() const { return tg_node_list; }
// return a point list of geodetic nodes
point_list get_geod_nodes() const;
// return a point list of wgs84 nodes
std::vector< SGVec3d > get_wgs84_nodes_as_SGVec3d() const;
point_list get_wgs84_nodes_as_Point3d() const;
// return a point list of normals
point_list get_normals() const;
// return the ith point
inline TGNode get_node( int i ) const { return tg_node_list[i]; }
// return the size of the node list
inline size_t size() const { return tg_node_list.size(); }
private:
node_list tg_node_list;
// return true of the two points are "close enough" as defined by
// FG_PROXIMITY_EPSILON
bool close_enough_2d( const Point3D& p1, const Point3D& p2 ) const;
// return true of the two points are "close enough" as defined by
// FG_PROXIMITY_EPSILON
bool close_enough_3d( const Point3D& p1, const Point3D& p2 ) const;
// return true of the two points are "close enough" as defined by
// FG_COURSE_EPSILON
bool course_close_enough( const Point3D& p1, const Point3D& p2 );
};
// return true of the two points are "close enough" as defined by
// FG_PROXIMITY_EPSILON checking just x and y dimensions
inline bool TGNodes::close_enough_2d( const Point3D& p1, const Point3D& p2 )
const
{
if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
return true;
} else {
return false;
}
}
// return true of the two points are "close enough" as defined by
// FG_PROXIMITY_EPSILON check all three dimensions
inline bool TGNodes::close_enough_3d( const Point3D& p1, const Point3D& p2 )
const
{
if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) &&
( fabs(p1.z() - p2.z()) < FG_PROXIMITY_EPSILON ) ) {
return true;
} else {
return false;
}
}
// return true of the two points are "close enough" as defined by
// FG_COURSE_EPSILON
inline bool TGNodes::course_close_enough( const Point3D& p1, const Point3D& p2 )
{
if ( ( fabs(p1.x() - p2.x()) < FG_COURSE_EPSILON ) &&
( fabs(p1.y() - p2.y()) < FG_COURSE_EPSILON ) ) {
return true;
} else {
return false;
}
}
#endif // _TG_NODES_HXX