1
0
Fork 0

Numerous small fixes following code review:

(1) Whitespace use matched better to surrounding code
(2) While(1) in TGArray::rectify_heights replaced with do/while loop
(3) Incorrect interpolation for 2 points fixed in altitude_from_grid
(4) exit(1) replaced with return EXIT_FAILURE in cliff-decode.cxx
This commit is contained in:
James.Hester 2019-01-13 09:59:00 +11:00
parent dfe81ce9fa
commit 3421ce2018
5 changed files with 404 additions and 352 deletions

View file

@ -127,7 +127,7 @@ void TGArray::load_cliffs(const string & height_base)
SGPath b(height_base); SGPath b(height_base);
simgear::Dir d(b.dir()); simgear::Dir d(b.dir());
simgear::PathList files = d.children(simgear::Dir::TYPE_FILE); simgear::PathList files = d.children(simgear::Dir::TYPE_FILE);
BOOST_FOREACH(const SGPath& p, files) { for (const SGPath& p: files) {
if (p.file_base() != b.file_base()) { if (p.file_base() != b.file_base()) {
continue; continue;
} }
@ -425,19 +425,22 @@ double TGArray::closest_nonvoid_elev( double lon, double lat ) const {
} }
} }
//Find and remember all points that are bad because they are
//too close to a cliff
std::vector<int> TGArray::collect_bad_points(const double bad_zone) { std::vector<int> TGArray::collect_bad_points(const double bad_zone) {
//Find and remember all points that are bad because they are
//too close to a cliff
std::vector<int> bad_points; //local to avoid multi-thread issues std::vector<int> bad_points; //local to avoid multi-thread issues
for(int horiz=0;horiz<cols;horiz++) {
for( int horiz=0;horiz<cols;horiz++ ) {
double lon = (originx + col_step*horiz)/3600; double lon = (originx + col_step*horiz)/3600;
for(int vert=0;vert<rows;vert++) { for( int vert=0;vert<rows;vert++ ) {
double lat = (originy + row_step*vert)/3600; double lat = (originy + row_step*vert)/3600;
if(is_near_cliff(lon,lat,bad_zone)) { if( is_near_cliff(lon,lat,bad_zone) ) {
bad_points.push_back(horiz+vert*cols); bad_points.push_back(horiz+vert*cols);
} }
} }
} }
return bad_points; return bad_points;
} }
@ -445,41 +448,45 @@ std::vector<int> TGArray::collect_bad_points(const double bad_zone) {
bool TGArray::is_bad_point(const int xgrid, const int ygrid, const std::vector<int> bad_points) const { bool TGArray::is_bad_point(const int xgrid, const int ygrid, const std::vector<int> bad_points) const {
int grididx; int grididx;
grididx = xgrid+ygrid*cols; grididx = xgrid+ygrid*cols;
auto result = std::find(std::begin(bad_points),std::end(bad_points),grididx); auto result = std::find( std::begin(bad_points),std::end(bad_points),grididx );
if (result != std::end(bad_points)) return true; if ( result != std::end(bad_points) ) return true;
return false; return false;
} }
//This may collide with other threads, but as they will both be writing //This may collide with other threads, but as they will both be writing
//the correct height, this is harmless. //the correct height, this is harmless.
void TGArray::rectify_heights(const double bad_zone) { void TGArray::rectify_heights( const double bad_zone ) {
double new_ht; double new_ht;
std::vector<int> rectified,bad_points; std::vector<int> rectified,bad_points;
bad_points = collect_bad_points(bad_zone); int total_rectified;
while(1) { bad_points = collect_bad_points( bad_zone );
for (auto pt : bad_points) {
do {
for ( auto pt : bad_points ) {
int ygrid = pt/cols; int ygrid = pt/cols;
int xgrid = pt - ygrid*cols; int xgrid = pt - ygrid*cols;
new_ht = rectify_point(xgrid,ygrid,bad_points); new_ht = rectify_point( xgrid,ygrid,bad_points );
if (new_ht > -9999) { if (new_ht > -9999) {
rectified.push_back(pt); rectified.push_back(pt);
set_array_elev(xgrid,ygrid,(int) new_ht); set_array_elev( xgrid,ygrid,(int) new_ht );
} }
} }
SG_LOG(SG_GENERAL, SG_DEBUG, "Rectified " << rectified.size() << " points "); total_rectified = rectified.size();
if(rectified.size()>0) { SG_LOG(SG_GENERAL, SG_DEBUG, "Rectified " << total_rectified << " points ");
for(auto r : rectified) {
bad_points.erase(std::remove(std::begin(bad_points),std::end(bad_points),r)); if( total_rectified > 0 ) {
for( auto r : rectified ) {
bad_points.erase( std::remove( std::begin(bad_points), std::end(bad_points),r) );
} }
rectified.clear(); rectified.clear();
} else { }
if(bad_points.size() > 0) { } while ( total_rectified > 0 );
if( bad_points.size() > 0 ) {
SG_LOG(SG_GENERAL, SG_DEBUG, "Failed to rectify " << bad_points.size() << " points"); SG_LOG(SG_GENERAL, SG_DEBUG, "Failed to rectify " << bad_points.size() << " points");
} }
break; // Cant do any more
}
}
} }
/* If we have cliffs, it is possible that a grid point will be too close /* If we have cliffs, it is possible that a grid point will be too close
@ -496,6 +503,7 @@ through the three known points.
* * * * * *
TODO: Handle points on the boundaries. */ TODO: Handle points on the boundaries. */
double TGArray::rectify_point(const int xgrid, const int ygrid, const std::vector<int> bad_points) const { double TGArray::rectify_point(const int xgrid, const int ygrid, const std::vector<int> bad_points) const {
//xgrid: grid units horizontally //xgrid: grid units horizontally
//ygrid: grid units vertically //ygrid: grid units vertically
@ -508,54 +516,68 @@ double TGArray::rectify_point(const int xgrid, const int ygrid, const std::vecto
int original_height = get_array_elev(xgrid,ygrid); int original_height = get_array_elev(xgrid,ygrid);
centre_long = (originx + col_step*xgrid)/3600; centre_long = (originx + col_step*xgrid)/3600;
centre_lat = (originy + row_step*ygrid)/3600; centre_lat = (originy + row_step*ygrid)/3600;
for (int horiz = -1; horiz <= 1; horiz+=2) {
for ( int horiz = -1; horiz <= 1; horiz+=2 ) {
if (xgrid + horiz >= cols || xgrid + horiz < 0) continue; //edge of bucket if (xgrid + horiz >= cols || xgrid + horiz < 0) continue; //edge of bucket
double test_long = centre_long + (col_step*horiz)/3600; double test_long = centre_long + (col_step*horiz)/3600;
for (int vert = -1; vert <= 1; vert+=2) { for ( int vert = -1; vert <= 1; vert+=2 ) {
if (ygrid + vert >= rows || ygrid + vert < 0) continue; //edge of bucket if (ygrid + vert >= rows || ygrid + vert < 0) continue; //edge of bucket
double test_lat = centre_lat + (row_step*vert)/3600; double test_lat = centre_lat + (row_step*vert)/3600;
if (!is_bad_point(xgrid+horiz,ygrid+vert,bad_points) && //can trust height if ( !is_bad_point( xgrid+horiz,ygrid+vert,bad_points ) && //can trust height
check_points(test_long,test_lat,centre_long,centre_lat)) { //same side check_points( test_long,test_lat,centre_long,centre_lat ) ) { //same side
corners[pt_cnt][0] = horiz; corners[pt_cnt][0] = horiz;
corners[pt_cnt][1] = vert; corners[pt_cnt][1] = vert;
pt_cnt++; pt_cnt++;
} }
} }
} // end of search for corners } // end of search for corners
if (pt_cnt == 0) return -9999; // no corners found if (pt_cnt == 0) return -9999; // no corners found
// Find two points that form a rectangle with a corner // Find two points that form a rectangle with a corner
int pt; int pt;
double height = 0; double height = 0;
for (pt = 0; pt < pt_cnt; pt++) { for ( pt = 0; pt < pt_cnt; pt++ ) {
if (!is_bad_point(xgrid+corners[pt][0],ygrid,bad_points) &&
!is_bad_point(xgrid, ygrid+corners[pt][1],bad_points)) { if ( !is_bad_point( xgrid+corners[pt][0],ygrid,bad_points ) &&
!is_bad_point( xgrid, ygrid+corners[pt][1],bad_points ) ) {
double test_horiz = centre_long + corners[pt][0]*col_step/3600; double test_horiz = centre_long + corners[pt][0]*col_step/3600;
double test_vert = centre_lat + corners[pt][1]*row_step/3600; double test_vert = centre_lat + corners[pt][1]*row_step/3600;
if (check_points(test_horiz,centre_lat,centre_long,centre_lat) &&
check_points(centre_long,test_vert,centre_long,centre_lat)) break; if ( check_points( test_horiz,centre_lat,centre_long,centre_lat ) &&
check_points( centre_long,test_vert,centre_long,centre_lat ) ) break;
} }
} }
if (pt == pt_cnt) { // perhaps we have a concave cliff, just take the if (pt == pt_cnt) {
// perhaps we have a concave cliff, just take the
// average of the known points // average of the known points
double totht = 0; double totht = 0;
for(int pti = 0; pti <pt_cnt; pti++) { for( int pti = 0; pti <pt_cnt; pti++ ) {
totht = totht + get_array_elev(xgrid+corners[pti][0],ygrid+corners[pti][1]); totht = totht + get_array_elev( xgrid+corners[pti][0],ygrid+corners[pti][1] );
} }
height = totht/pt_cnt; height = totht/pt_cnt;
} else { } else {
// We have three points, calculate the height // We have three points, calculate the height
// Set anything very negative to zero // Set anything very negative to zero
double corner = get_array_elev(xgrid+corners[pt][0],ygrid+corners[pt][1]); double corner = get_array_elev( xgrid+corners[pt][0],ygrid+corners[pt][1] );
double horiz = get_array_elev(xgrid,ygrid+corners[pt][1]); double horiz = get_array_elev( xgrid,ygrid+corners[pt][1] );
double vert = get_array_elev(xgrid+corners[pt][0],ygrid); double vert = get_array_elev( xgrid+corners[pt][0],ygrid );
if (corner < -9000) corner = 0; if ( corner < -9000 ) corner = 0;
if (horiz < -9000) horiz = 0; if ( horiz < -9000 ) horiz = 0;
if (vert < -9000) vert = 0; if ( vert < -9000 ) vert = 0;
height = horiz + (vert - corner); height = horiz + ( vert - corner );
} }
SG_LOG(SG_GENERAL, SG_DEBUG, xgrid << "," << ygrid << ": was " << original_height << " , now " << height); SG_LOG(SG_GENERAL, SG_DEBUG, xgrid << "," << ygrid << ": was " << original_height << " , now " << height);
return height; return height;
} }
@ -589,8 +611,6 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
xindex = (int)(xlocal); xindex = (int)(xlocal);
yindex = (int)(ylocal); yindex = (int)(ylocal);
// printf("xindex = %d yindex = %d\n", xindex, yindex);
if ( xindex + 1 == cols ) { if ( xindex + 1 == cols ) {
xindex--; xindex--;
} }
@ -601,7 +621,9 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
if ( (xindex < 0) || (xindex + 1 >= cols) || if ( (xindex < 0) || (xindex + 1 >= cols) ||
(yindex < 0) || (yindex + 1 >= rows) ) { (yindex < 0) || (yindex + 1 >= rows) ) {
SG_LOG(SG_GENERAL, SG_DEBUG, "WARNING: Attempt to interpolate value outside of array!!!" ); SG_LOG(SG_GENERAL, SG_DEBUG, "WARNING: Attempt to interpolate value outside of array!!!" );
return -9999; return -9999;
} }
@ -613,26 +635,28 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
int corners[4][2]; int corners[4][2];
int ccnt = 0; int ccnt = 0;
int missing = -1; //the missing point when 3 available int missing = -1; //the missing point when 3 available
double lon1 = (originx+(xindex*col_step))/3600; double lon1 = (originx+(xindex*col_step))/3600;
double lat1 = (originy+(yindex*row_step))/3600; double lat1 = (originy+(yindex*row_step))/3600;
double lon2 = lon1 + col_step/3600; double lon2 = lon1 + col_step/3600;
double lat2 = lat1 + row_step/3600; double lat2 = lat1 + row_step/3600;
if (check_points(lon1,lat1,londeg,latdeg)) {
if ( check_points(lon1,lat1,londeg,latdeg) ) {
corners[ccnt][0] = xindex; corners[ccnt][0] = xindex;
corners[ccnt][1] = yindex; corners[ccnt][1] = yindex;
ccnt++; ccnt++;
} else missing = 0; } else missing = 0;
if (check_points(lon1,lat2,londeg,latdeg)) { if ( check_points(lon1,lat2,londeg,latdeg) ) {
corners[ccnt][0] = xindex; corners[ccnt][0] = xindex;
corners[ccnt][1] = yindex+1; corners[ccnt][1] = yindex+1;
ccnt++; ccnt++;
} else missing = 1; } else missing = 1;
if (check_points(lon2,lat2,londeg,latdeg)) { if ( check_points(lon2,lat2,londeg,latdeg) ) {
corners[ccnt][0] = xindex+1; corners[ccnt][0] = xindex+1;
corners[ccnt][1] = yindex+1; corners[ccnt][1] = yindex+1;
ccnt++; ccnt++;
} else missing = 2; } else missing = 2;
if (check_points(lon2,lat1,londeg,latdeg)) { if ( check_points(lon2,lat1,londeg,latdeg) ) {
corners[ccnt][0] = xindex+1; corners[ccnt][0] = xindex+1;
corners[ccnt][1] = yindex; corners[ccnt][1] = yindex;
ccnt++; ccnt++;
@ -643,10 +667,13 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
// choose the points so that x2 is the right angle // choose the points so that x2 is the right angle
// and x1-x2 is the x arm of the triangle // and x1-x2 is the x arm of the triangle
// dx,dy are the (positive) distances from the x1 corner // dx,dy are the (positive) distances from the x1 corner
SG_LOG(SG_GENERAL, SG_DEBUG, "3 points, missing #" << missing); SG_LOG(SG_GENERAL, SG_DEBUG, "3 points, missing #" << missing);
dx = xlocal -xindex; dx = xlocal -xindex;
dy = ylocal -yindex; dy = ylocal -yindex;
switch (missing) {
switch ( missing ) {
case 0: //SW corner missing case 0: //SW corner missing
x1 = corners[0][0]; x1 = corners[0][0];
y1 = corners[0][1]; y1 = corners[0][1];
@ -702,6 +729,7 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
// We interpolate on height along x1-x2 and // We interpolate on height along x1-x2 and
// x1 - x3. Then interpolate between these // x1 - x3. Then interpolate between these
// two points along y. // two points along y.
z1 = get_array_elev(x1,y1); z1 = get_array_elev(x1,y1);
z2 = get_array_elev(x2,y2); z2 = get_array_elev(x2,y2);
z3 = get_array_elev(x3,y3); z3 = get_array_elev(x3,y3);
@ -715,6 +743,7 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
} }
break; break;
case 2: //project onto line connecting two points case 2: //project onto line connecting two points
x1 = corners[0][0]; x1 = corners[0][0];
y1 = corners[0][1]; y1 = corners[0][1];
@ -729,10 +758,10 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
dx = xlocal - x1; dx = xlocal - x1;
dy = ylocal - y1; dy = ylocal - y1;
if (x1==x2) { if (x1==x2) {
elev = z1+dy*(z2-z1); elev = z1+dy*(z2-z1)/(y2-y1);
} }
else if (y1==y2) { else if (y1==y2) {
elev = z1+dx*(z2-z1); elev = z1+dx*(z2-z1)/(x2-x1);
} }
else { //diagonal: project onto 45 degree line else { //diagonal: project onto 45 degree line
int comp1 = x2-x1; int comp1 = x2-x1;
@ -742,12 +771,16 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
elev = (z2-z1)*projlen/sqrt(2); elev = (z2-z1)*projlen/sqrt(2);
} }
break; break;
case 1: //only one point found case 1: //only one point found
elev = get_array_elev(corners[0][0],corners[0][1]); elev = get_array_elev( corners[0][0],corners[0][1] );
break; break;
case 0: // all points on wrong side, fall through to normal calc case 0: // all points on wrong side, fall through to normal calc
SG_LOG(SG_GENERAL, SG_WARN, "All elevation grid points on wrong side of cliff for " << std::setprecision(10) << londeg << "," << latdeg ); SG_LOG(SG_GENERAL, SG_WARN, "All elevation grid points on wrong side of cliff for " << std::setprecision(10) << londeg << "," << latdeg );
SG_LOG(SG_GENERAL, SG_WARN, "Grid points ("<< std::setprecision(9) << lon1 << "," << lat1 << "),("<<lon2<<","<<lat2<<")"); SG_LOG(SG_GENERAL, SG_WARN, "Grid points ("<< std::setprecision(9) << lon1 << "," << lat1 << "),("<<lon2<<","<<lat2<<")");
default: // all corners default: // all corners
dx = xlocal - xindex; dx = xlocal - xindex;
dy = ylocal - yindex; dy = ylocal - yindex;
@ -815,32 +848,44 @@ double TGArray::altitude_from_grid( double lon, double lat ) const {
// Check that two points are on the same side of all cliff contours // Check that two points are on the same side of all cliff contours
// Could speed up by checking bounding box first // Could speed up by checking bounding box first
bool TGArray::check_points (const double lon1, const double lat1, const double lon2, const double lat2) const { bool TGArray::check_points( const double lon1, const double lat1, const double lon2, const double lat2 ) const {
if (cliffs_list.size()==0) return true;
if (fabs(lon1-lon2)<SG_EPSILON && fabs(lat1-lat2)<SG_EPSILON) return true; if ( cliffs_list.size()==0 ) return true;
SGGeod pt1 = SGGeod::fromDeg(lon1,lat1);
SGGeod pt2 = SGGeod::fromDeg(lon2,lat2); if ( fabs(lon1-lon2)<SG_EPSILON && fabs(lat1-lat2)<SG_EPSILON ) return true;
SGGeod pt1 = SGGeod::fromDeg( lon1,lat1 );
SGGeod pt2 = SGGeod::fromDeg( lon2,lat2 );
bool same_side = true; bool same_side = true;
for (int i=0;i<cliffs_list.size();i++) {
bool check_result = cliffs_list[i].AreSameSide(pt1,pt2); for ( int i=0;i<cliffs_list.size();i++ ) {
bool check_result = cliffs_list[i].AreSameSide( pt1,pt2 );
if(!check_result) { if(!check_result) {
SG_LOG(SG_GENERAL, SG_DEBUG, "Cliff " << i <<":" <<pt1 << " and " << pt2 << " on opposite sides"); SG_LOG(SG_GENERAL, SG_DEBUG, "Cliff " << i <<":" <<pt1 << " and " << pt2 << " on opposite sides");
same_side = false; same_side = false;
break; break;
} }
} }
return same_side; return same_side;
} }
//Check that a point is more than given distance from any cliff //Check that a point is more than given distance from any cliff
//Could speed up by checking bounding box //Could speed up by checking bounding box
bool TGArray::is_near_cliff(const double lon1, const double lat1, const double bad_zone) const { bool TGArray::is_near_cliff( const double lon1, const double lat1, const double bad_zone ) const {
if (cliffs_list.size()==0) return false; if (cliffs_list.size()==0) return false;
SGGeod pt1 = SGGeod::fromDeg(lon1,lat1); SGGeod pt1 = SGGeod::fromDeg(lon1,lat1);
for (int i=0;i<cliffs_list.size();i++) {
for ( int i=0;i<cliffs_list.size();i++ ) {
double dist = cliffs_list[i].MinDist(pt1); double dist = cliffs_list[i].MinDist(pt1);
if (dist < bad_zone) return true; if (dist < bad_zone) return true;
} }
return false; return false;
} }

View file

@ -11,7 +11,7 @@
#include "tg_misc.hxx" #include "tg_misc.hxx"
tgPolygon tgChopper::Clip( const tgPolygon& subject, tgPolygon tgChopper::Clip( const tgPolygon& subject,
const std::string& type, SGBucket& b) const std::string& type, SGBucket& b )
{ {
tgPolygon base, result; tgPolygon base, result;
@ -21,8 +21,7 @@ tgPolygon tgChopper::Clip( const tgPolygon& subject,
base.AddNode( 0, b.get_corner( SG_BUCKET_NE ) ); base.AddNode( 0, b.get_corner( SG_BUCKET_NE ) );
base.AddNode( 0, b.get_corner( SG_BUCKET_NW ) ); base.AddNode( 0, b.get_corner( SG_BUCKET_NW ) );
result = tgPolygon::Intersect( subject, base); result = tgPolygon::Intersect( subject, base );
// Debug: See if numbers of nodes have changed
if ( result.Contours() > 0 ) { if ( result.Contours() > 0 ) {
if ( subject.GetPreserve3D() ) { if ( subject.GetPreserve3D() ) {
@ -68,7 +67,7 @@ void tgChopper::ClipRow( const tgPolygon& subject, const double& center_lat, con
} }
void tgChopper::Add( const tgPolygon& subject, const std::string& type) void tgChopper::Add( const tgPolygon& subject, const std::string& type )
{ {
// bail out immediately if polygon is empty // bail out immediately if polygon is empty
if ( subject.Contours() == 0 ) if ( subject.Contours() == 0 )
@ -95,7 +94,7 @@ void tgChopper::Add( const tgPolygon& subject, const std::string& type)
// We just have a single row - no need to intersect first // We just have a single row - no need to intersect first
SG_LOG( SG_GENERAL, SG_DEBUG, " UN_CLIPPED row - center lat is " << b_min.get_center_lat() ); SG_LOG( SG_GENERAL, SG_DEBUG, " UN_CLIPPED row - center lat is " << b_min.get_center_lat() );
ClipRow( subject, b_min.get_center_lat(), type); ClipRow( subject, b_min.get_center_lat(), type );
} }
else else
{ {
@ -122,7 +121,7 @@ void tgChopper::Add( const tgPolygon& subject, const std::string& type)
clip_row.AddNode( 0, SGGeod::fromDeg( 180.0, clip_top) ); clip_row.AddNode( 0, SGGeod::fromDeg( 180.0, clip_top) );
clip_row.AddNode( 0, SGGeod::fromDeg(-180.0, clip_top) ); clip_row.AddNode( 0, SGGeod::fromDeg(-180.0, clip_top) );
clipped = tgPolygon::Intersect( subject, clip_row); clipped = tgPolygon::Intersect( subject, clip_row );
if ( clipped.TotalNodes() > 0 ) { if ( clipped.TotalNodes() > 0 ) {
if ( subject.GetPreserve3D() ) { if ( subject.GetPreserve3D() ) {

View file

@ -61,7 +61,7 @@ double tgContour::GetArea( void ) const
SGVec2d a, b; SGVec2d a, b;
unsigned int i, j; unsigned int i, j;
if (node_list.size() ) { if ( node_list.size() ) {
j = node_list.size() - 1; j = node_list.size() - 1;
for (i=0; i<node_list.size(); i++) { for (i=0; i<node_list.size(); i++) {
a = SGGeod_ToSGVec2d( node_list[i] ); a = SGGeod_ToSGVec2d( node_list[i] );
@ -82,29 +82,32 @@ bool tgContour::AreSameSide( const SGGeod& firstpt, const SGGeod& secondpt) cons
double x2 = secondpt.getLatitudeDeg(); double x2 = secondpt.getLatitudeDeg();
double y1 = firstpt.getLongitudeDeg(); double y1 = firstpt.getLongitudeDeg();
double y2 = secondpt.getLongitudeDeg(); double y2 = secondpt.getLongitudeDeg();
//Store differences for later //Store differences for later
double xdif = x2-x1; double xdif = x2-x1;
double ydif = y2-y1; double ydif = y2-y1;
/*We describe a line parametrically: /*We describe a line parametrically:
x1 (x2-x1) x1 (x2-x1)
L = + t L = + t
y1 (y2-y1) y1 (y2-y1)
with u the parametric coefficient for the second line. with u the parametric coefficient for the second line.
Then the line segments intersect if 0 <= t,u <= 1. Then the line segments intersect if 0 <= t,u <= 1.
To determine t and u we use the approach of Goldman ("Graphics To determine t and u we use the approach of Goldman ("Graphics
Gems" as described in Stack Overflow question 563198). Gems" as described in Stack Overflow question 563198).
if r x s = r_x * s_y - r_y * s_x, then if r x s = r_x * s_y - r_y * s_x, then
t = (q - p) x s / (r x s) t = (q - p) x s / (r x s)
and and
u = (q - p) x r / (r x s) u = (q - p) x r / (r x s)
for line 1 = p + t r, line 2 = q + u s for line 1 = p + t r, line 2 = q + u s
*/ */
//Now cycle over all nodes and count how many times we intersect //Now cycle over all nodes and count how many times we intersect
int intersect_ct = 0; int intersect_ct = 0;
if (node_list.size()) { if (node_list.size()) {
@ -117,6 +120,7 @@ for line 1 = p + t r, line 2 = q + u s
double nydif = ny2-ny1; double nydif = ny2-ny1;
double nxdif = nx2-nx1; double nxdif = nx2-nx1;
double denom = xdif*nydif - ydif*nxdif; double denom = xdif*nydif - ydif*nxdif;
if (denom != 0) { //Not parallel if (denom != 0) { //Not parallel
double crossx = nx1-x1; double crossy = ny1-y1; double crossx = nx1-x1; double crossy = ny1-y1;
double t = (crossx*nydif - crossy*nxdif)/denom; double t = (crossx*nydif - crossy*nxdif)/denom;
@ -129,27 +133,31 @@ for line 1 = p + t r, line 2 = q + u s
} }
} }
} }
bool isinter = (intersect_ct%2 == 0); bool isinter = (intersect_ct%2 == 0);
return isinter; return isinter;
} }
double tgContour::MinDist(const SGGeod& probe) const double tgContour::MinDist(const SGGeod& probe) const {
{
SGVec3d probexyz; SGVec3d probexyz;
SGGeodesy::SGGeodToCart(probe,probexyz); SGGeodesy::SGGeodToCart( probe,probexyz );
double mindist = 100000.0; double mindist = 100000.0;
double dist; double dist;
if (node_list.size()) {
if ( node_list.size() ) {
int j = node_list.size() - 1; int j = node_list.size() - 1;
for (int i=0;i<j;i++) { for (int i=0;i<j;i++) {
SGVec3d start,end; SGVec3d start,end;
SGGeodesy::SGGeodToCart(node_list[i],start); SGGeodesy::SGGeodToCart( node_list[i],start );
SGGeodesy::SGGeodToCart(node_list[i+1],end); SGGeodesy::SGGeodToCart( node_list[i+1],end );
SGLineSegment<double> piece = SGLineSegment<double>(start,end); SGLineSegment<double> piece = SGLineSegment<double>(start,end);
dist = distSqr(piece,probexyz); dist = distSqr( piece,probexyz );
if (dist < mindist) mindist = dist; if (dist < mindist) mindist = dist;
} }
} }
return sqrt(mindist); return sqrt(mindist);
} }

View file

@ -137,7 +137,7 @@ tgPolygon tgPolygon::Diff( const tgPolygon& subject, tgPolygon& clip )
} }
//Intersect will keep open paths open //Intersect will keep open paths open
tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip) tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip )
{ {
tgPolygon result; tgPolygon result;
UniqueSGGeodSet all_nodes; UniqueSGGeodSet all_nodes;
@ -162,14 +162,14 @@ tgPolygon tgPolygon::Intersect( const tgPolygon& subject, const tgPolygon& clip)
ClipperLib::Clipper c; ClipperLib::Clipper c;
c.Clear(); c.Clear();
c.AddPaths(clipper_subject, ClipperLib::PolyType::Subject, subject.IsClosed()); c.AddPaths(clipper_subject, ClipperLib::PolyType::Subject, subject.IsClosed() );
c.AddPaths(clipper_clip, ClipperLib::PolyType::Clip, true); c.AddPaths(clipper_clip, ClipperLib::PolyType::Clip, true);
if(subject.IsClosed()) { if(subject.IsClosed()) {
c.Execute(ClipperLib::ClipType::Intersection, clipper_result, ClipperLib::PolyFillType::EvenOdd, ClipperLib::PolyFillType::EvenOdd); c.Execute(ClipperLib::ClipType::Intersection, clipper_result, ClipperLib::PolyFillType::EvenOdd, ClipperLib::PolyFillType::EvenOdd );
result = tgPolygon::FromClipper( clipper_result ); result = tgPolygon::FromClipper( clipper_result );
} }
else { else {
c.Execute(ClipperLib::ClipType::Intersection, clipper_tree_result, ClipperLib::PolyFillType::EvenOdd, ClipperLib::PolyFillType::EvenOdd); c.Execute(ClipperLib::ClipType::Intersection, clipper_tree_result, ClipperLib::PolyFillType::EvenOdd, ClipperLib::PolyFillType::EvenOdd );
result = tgPolygon::FromClipper( clipper_tree_result ); result = tgPolygon::FromClipper( clipper_tree_result );
} }
result = tgPolygon::AddColinearNodes( result, all_nodes ); result = tgPolygon::AddColinearNodes( result, all_nodes );

View file

@ -391,7 +391,7 @@ int main( int argc, char **argv ) {
if( poDS == NULL ) if( poDS == NULL )
{ {
SG_LOG( SG_GENERAL, SG_ALERT, "Failed opening datasource " << datasource ); SG_LOG( SG_GENERAL, SG_ALERT, "Failed opening datasource " << datasource );
exit( 1 ); return EXIT_FAILURE;
} }
SG_LOG( SG_GENERAL, SG_ALERT, "Processing datasource " << datasource ); SG_LOG( SG_GENERAL, SG_ALERT, "Processing datasource " << datasource );
@ -404,7 +404,7 @@ int main( int argc, char **argv ) {
if (poLayer == NULL ) if (poLayer == NULL )
{ {
SG_LOG( SG_GENERAL, SG_ALERT, "Failed opening layer " << argv[i] << " from datasource " << datasource ); SG_LOG( SG_GENERAL, SG_ALERT, "Failed opening layer " << argv[i] << " from datasource " << datasource );
exit( 1 ); return EXIT_FAILURE;
} }
processLayer(poLayer, results ); processLayer(poLayer, results );
} }