handle.
private:
+ // minimum interior angle for triangulation
+ string angle;
+
// paths
string work_base;
string output_base;
// Destructor
~FGConstruct();
+ // minimum interior angle for triangulation
+ inline string get_angle() const { return angle; }
+ inline void set_angle( const string s ) { angle = s; }
+
// paths
inline string get_work_base() const { return work_base; }
inline void set_work_base( const string s ) { work_base = s; }
cout << "done building node list and polygons" << endl;
cout << "ready to do triangulation" << endl;
- t.run_triangulate( 1 );
+ t.run_triangulate( c.get_angle(), 1 );
cout << "finished triangulation" << endl;
}
cout << "done re building node list and polygons" << endl;
cout << "ready to do second triangulation" << endl;
- t.run_triangulate( 2 );
+ t.run_triangulate( c.get_angle(), 2 );
cout << "finished second triangulation" << endl;
}
// display usage and exit
void usage( const string name ) {
cout << "Usage: " << name
- << " <work_base> <output_base> tile_id" << endl;
+ << " <min_tri_angle> <work_base> <output_base> tile_id" << endl;
cout << "Usage: " << name
- << " <work_base> <output_base> center_lon center_lat xdist ydist"
+ << " <min_tri_angle> <work_base> <output_base> center_lon center_lat xdist ydist"
<< endl;
exit(-1);
}
fglog().setLogLevels( FG_ALL, FG_DEBUG );
- if ( argc < 3 ) {
+ if ( argc < 4 ) {
usage( argv[0] );
}
// main construction data management class
FGConstruct c;
- c.set_work_base( argv[1] );
- c.set_output_base( argv[2] );
+ c.set_angle( argv[1] );
+ c.set_work_base( argv[2] );
+ c.set_output_base( argv[3] );
c.set_min_nodes( 50 );
c.set_max_nodes( (int)(FG_MAX_NODES * 0.8) );
// lon = -76.201239; lat = 36.894606; // KORF (Norfolk, Virginia)
// lon = -147.166; lat = 60.9925; // Hale-bop test
- if ( argc == 4 ) {
+ if ( argc == 5 ) {
// construct a specific tile and exit
- long index = atoi( argv[3] );
+ long index = atoi( argv[4] );
FGBucket b( index );
c.set_bucket( b );
construct_tile( c );
- } else if ( argc == 7 ) {
+ } else if ( argc == 8 ) {
// build all the tiles in an area
- lon = atof( argv[3] );
- lat = atof( argv[4] );
- double xdist = atof( argv[5] );
- double ydist = atof( argv[6] );
+ lon = atof( argv[4] );
+ lat = atof( argv[5] );
+ double xdist = atof( argv[6] );
+ double ydist = atof( argv[7] );
double min_x = lon - xdist;
double min_y = lat - ydist;
// successfully
bool construct_tile( const string& work_base, const string& output_base,
const FGBucket& b, const string& result_file ) {
- string command = "../Main/construct " + work_base + " " + output_base + " "
- + b.gen_index_str() + " > " + result_file + " 2>&1";
- cout << command << endl;
-
- system( command.c_str() );
-
- FILE *fp = fopen( result_file.c_str(), "r" );
- char line[256];
- while ( fgets( line, 256, fp ) != NULL ) {
- string line_str = line;
- line_str = line_str.substr(0, line_str.length() - 1);
- cout << line_str << endl;
- if ( line_str == "[Finished successfully]" ) {
- fclose(fp);
- return true;
+ double angle = 10.0;
+ bool still_trying = true;
+
+ while ( still_trying ) {
+ still_trying = false;
+ char angle_str[256];
+ sprintf(angle_str, "%.0f", angle);
+ string command = "../Main/construct ";
+ command += angle_str;
+ command += " " + work_base + " " + output_base + " "
+ + b.gen_index_str() + " > " + result_file + " 2>&1";
+ cout << command << endl;
+
+ system( command.c_str() );
+
+ FILE *fp = fopen( result_file.c_str(), "r" );
+ char line[256];
+ while ( fgets( line, 256, fp ) != NULL ) {
+ string line_str = line;
+ line_str = line_str.substr(0, line_str.length() - 1);
+ cout << line_str << endl;
+ if ( line_str == "[Finished successfully]" ) {
+ fclose(fp);
+ return true;
+ } else if ( line_str == "Error: Ran out of precision at" ) {
+ if ( angle > 9.0 ) {
+ angle = 5.0;
+ still_trying = true;
+ } else if ( angle > 4.0 ) {
+ angle = 0.0;
+ still_trying = true;
+ }
+ }
}
+ fclose(fp);
}
-
- fclose(fp);
return false;
}
// generates extra nodes for a better triangulation. 2 = second pass
// after split/reassem where we don't want any extra nodes generated.
-int FGTriangle::run_triangulate( int pass ) {
+int FGTriangle::run_triangulate( const string& angle, const int pass ) {
FGPolygon poly;
Point3D p;
struct triangulateio in, out, vorout;
// use a quality value of 10 (q10) meaning no interior
// triangle angles less than 10 degrees
// tri_options = "pczAen";
- tri_options = "pczq10Aen";
+ if ( angle == "0" ) {
+ tri_options = "pczAen";
+ } else {
+ tri_options = "pczq" + angle + "Aen";
+ }
// // string tri_options = "pzAen";
// // string tri_options = "pczq15S400Aen";
} else if ( pass == 2 ) {
// generates extra nodes for a better triangulation. 2 = second
// pass after split/reassem where we don't want any extra nodes
// generated.
- int run_triangulate( int pass );
+ int run_triangulate( const string& angle, const int pass );
inline FGTriNodes get_out_nodes() const { return out_nodes; }
inline size_t get_out_nodes_size() const { return out_nodes.size(); }
#include <Main/construct_types.hxx>
-#define FG_PROXIMITY_EPSILON 0.000001
+#define FG_PROXIMITY_EPSILON 0.00002
#define FG_COURSE_EPSILON 0.0003
// cout << s.get_n1() << "," << s.get_n2() << endl;
+ // check if segment has duplicated endpoints
+ if ( s.get_n1() == s.get_n2() ) {
+ cout << "WARNING: ignoring null segment with the same "
+ << "point for both endpoints" << endl;
+ return -1;
+ }
+
// check if segment already exists
current = seg_list.begin();
last = seg_list.end();
bool found_extra = false;
int extra_index = 0;
int counter;
- double m, b, y_err, x_err;
+ double m, m1, b, b1, y_err, x_err, y_err_min, x_err_min;
const_point_list_iterator current, last;
// bool temp = false;
// temp = true;
// }
- if ( fabs(p0.x() - p1.x()) > 3 * FG_EPSILON ) {
+ double xdist = fabs(p0.x() - p1.x());
+ double ydist = fabs(p0.y() - p1.y());
+ x_err_min = xdist + 1.0;
+ y_err_min = ydist + 1.0;
+
+ if ( xdist > ydist ) {
// use y = mx + b
// sort these in a sensible order
y_err = fabs(current->y() - (m * current->x() + b));
- if ( y_err < 20 * FG_EPSILON ) {
- // cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
- // cout << p0 << " < " << *current << " < "
- // << p1 << endl;
+ if ( y_err < FG_PROXIMITY_EPSILON ) {
+ cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
+ cout << p0 << " < " << *current << " < "
+ << p1 << endl;
found_extra = true;
- extra_index = counter;
- break;
+ if ( y_err < y_err_min ) {
+ extra_index = counter;
+ y_err_min = y_err;
+ }
}
}
++counter;
}
} else {
- // use x = constant
-
- // cout << "FOUND VERTICLE SEGMENT" << endl;
+ // use x = m1 * y + b1
- // sort these in a sensable order
+ // sort these in a sensible order
if ( p0.y() > p1.y() ) {
Point3D tmp = p0;
p0 = p1;
p1 = tmp;
}
- // cout << " p0 = " << p0 << " p1 = " << p1 << endl;
+ m1 = (p0.x() - p1.x()) / (p0.y() - p1.y());
+ b1 = p1.x() - m1 * p1.y();
+
+ // bool temp = true;
+ // if ( temp ) {
+ // cout << "xdist = " << xdist << " ydist = " << ydist << endl;
+ // cout << " p0 = " << p0 << " p1 = " << p1 << endl;
+ // cout << " m1 = " << m1 << " b1 = " << b1 << endl;
+ // }
+
+ // cout << " should = 0 = " << fabs(p0.x() - (m1 * p0.y() + b1)) << endl;;
+ // cout << " should = 0 = " << fabs(p1.x() - (m1 * p1.y() + b1)) << endl;;
current = nodes.begin();
last = nodes.end();
counter = 0;
for ( ; current != last; ++current ) {
- // cout << counter << endl;
- if ( (current->y() > (p0.y() + FG_EPSILON))
+ if ( (current->y() > (p0.y() + FG_EPSILON))
&& (current->y() < (p1.y() - FG_EPSILON)) ) {
- x_err = fabs(current->x() - p0.x());
- // cout << " found a potential point, x err = "
- // << x_err << endl;
- if ( x_err < 20 * FG_EPSILON ) {
- // cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
- // cout << p0 << " < " << *current << " < "
- // << p1 << endl;
+
+ x_err = fabs(current->x() - (m1 * current->y() + b1));
+
+ // if ( temp ) {
+ // cout << " (" << counter << ") x_err = " << x_err << endl;
+ // }
+
+ if ( x_err < FG_PROXIMITY_EPSILON ) {
+ cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
+ cout << p0 << " < " << *current << " < "
+ << p1 << endl;
found_extra = true;
- extra_index = counter;
- break;
+ if ( x_err < x_err_min ) {
+ extra_index = counter;
+ x_err_min = x_err;
+ }
}
}
++counter;
if ( found_extra ) {
// recurse with two sub segments
- // cout << "dividing " << s.get_n1() << " " << extra_index
- // << " " << s.get_n2() << endl;
+ cout << "dividing " << s.get_n1() << " " << extra_index
+ << " " << s.get_n2() << endl;
unique_divide_and_add( nodes, FGTriSeg( s.get_n1(), extra_index ) );
unique_divide_and_add( nodes, FGTriSeg( extra_index, s.get_n2() ) );
} else {