2021-09-21 22:25:16 +08:00
/**
* @ defgroup TIN
*
* @ brief Generation of a Triangular Irregular Network ( TIN ) from a dense DEM grid .
*
* @ author Yi Zhang
* @ date 2021 - 09 - 16
*/
# ifndef _TIN_DELAUNAY_H
# define _TIN_DELAUNAY_H
# include "cmath"
# include "vector"
# include "algorithm"
# define ZERO 1e-5
// Start vertex definition
struct vertex2dc
{
unsigned int id ; // index of the vertex
double x , y ; // position of the vertex
double elev ; // elevation at the vertex
vertex2dc ( ) : x ( NAN ) , y ( NAN ) , elev ( NAN ) , id ( 0 ) { }
vertex2dc ( double inx , double iny , double inelev , unsigned int inid ) { set ( inx , iny , inelev , inid ) ; }
void set ( double inx , double iny , double inelev , unsigned int inid )
{
x = inx ; y = iny ; elev = inelev ; id = inid ;
return ;
}
} ;
bool operator = = ( const vertex2dc & a , const vertex2dc & b ) // overload the == operator for vertex2dc type
{
if ( fabs ( a . x - b . x ) < = ZERO & & fabs ( a . y - b . y ) < = ZERO )
{
return true ;
}
return false ;
}
bool is_collinear ( vertex2dc * a_ptr , vertex2dc * b_ptr , vertex2dc * c_ptr ) // Test if the three points are on the same line
{
// | (y3− y1)(x2− x1)− (y2− y1)(x3− x1)|
if ( fabs ( ( c_ptr - > y - a_ptr - > y ) * ( b_ptr - > x - a_ptr - > x ) - ( b_ptr - > y - a_ptr - > y ) * ( c_ptr - > x - a_ptr - > x ) ) < = ZERO )
{
return true ;
}
return false ;
}
// End vertex definition
2021-09-22 16:36:30 +08:00
// Start edge definition
struct edge
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
vertex2dc * vert [ 2 ] ; // vertex of the edge
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
edge ( ) { vert [ 0 ] = vert [ 1 ] = nullptr ; }
edge ( vertex2dc * v0ptr , vertex2dc * v1ptr ) { set ( v0ptr , v1ptr ) ; }
void set ( vertex2dc * v0ptr , vertex2dc * v1ptr )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
vert [ 0 ] = v0ptr ; vert [ 1 ] = v1ptr ;
2021-09-21 22:25:16 +08:00
return ;
}
} ;
2021-09-22 16:36:30 +08:00
bool operator = = ( const edge & a , const edge & b ) // overload the == operator for edge type
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
if ( ( a . vert [ 0 ] = = b . vert [ 0 ] & & a . vert [ 1 ] = = b . vert [ 1 ] ) | |
( a . vert [ 0 ] = = b . vert [ 1 ] & & a . vert [ 1 ] = = b . vert [ 0 ] ) )
{
return true ;
}
2021-09-21 22:25:16 +08:00
return false ;
}
2021-09-22 16:36:30 +08:00
// End edge definition
// Start triangle definition
struct dem_point ;
2021-09-21 22:25:16 +08:00
struct triangle
{
vertex2dc * vert [ 3 ] ; // vertex of the triangle
double cx , cy ; // center of the triangle's circumcircle
double cr ; // radius of the circumcircle
2021-09-22 16:36:30 +08:00
std : : vector < dem_point * > circum_dem ;
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
triangle ( ) { vert [ 0 ] = vert [ 1 ] = vert [ 2 ] = nullptr ; }
2021-09-21 22:25:16 +08:00
triangle ( vertex2dc * v0ptr , vertex2dc * v1ptr , vertex2dc * v2ptr ) { set ( v0ptr , v1ptr , v2ptr ) ; }
void set ( vertex2dc * v0ptr , vertex2dc * v1ptr , vertex2dc * v2ptr )
{
vert [ 0 ] = v0ptr ; vert [ 1 ] = v1ptr ; vert [ 2 ] = v2ptr ;
2021-09-22 16:36:30 +08:00
double s = 0.5 / ( ( vert [ 1 ] - > x - vert [ 0 ] - > x ) * ( vert [ 2 ] - > y - vert [ 0 ] - > y ) - ( vert [ 1 ] - > y - vert [ 0 ] - > y ) * ( vert [ 2 ] - > x - vert [ 0 ] - > x ) ) ;
double m = vert [ 1 ] - > x * vert [ 1 ] - > x - vert [ 0 ] - > x * vert [ 0 ] - > x + vert [ 1 ] - > y * vert [ 1 ] - > y - vert [ 0 ] - > y * vert [ 0 ] - > y ;
double u = vert [ 2 ] - > x * vert [ 2 ] - > x - vert [ 0 ] - > x * vert [ 0 ] - > x + vert [ 2 ] - > y * vert [ 2 ] - > y - vert [ 0 ] - > y * vert [ 0 ] - > y ;
cx = ( ( vert [ 2 ] - > y - vert [ 0 ] - > y ) * m + ( vert [ 0 ] - > y - vert [ 1 ] - > y ) * u ) * s ;
cy = ( ( vert [ 0 ] - > x - vert [ 2 ] - > x ) * m + ( vert [ 1 ] - > x - vert [ 0 ] - > x ) * u ) * s ;
cr = ( vert [ 0 ] - > x - cx ) * ( vert [ 0 ] - > x - cx ) + ( vert [ 0 ] - > y - cy ) * ( vert [ 0 ] - > y - cy ) ; // not need to sqrt() here
2021-09-21 22:25:16 +08:00
return ;
}
bool bound_location ( double inx , double iny ) // Test if the location is inside the triangle
{
double l1x , l1y , l2x , l2y ;
for ( int i = 0 ; i < 3 ; i + + )
{
l1x = vert [ ( i + 1 ) % 3 ] - > x - vert [ i ] - > x ;
l1y = vert [ ( i + 1 ) % 3 ] - > y - vert [ i ] - > y ;
l2x = inx - vert [ i ] - > x ;
l2y = iny - vert [ i ] - > y ;
if ( ( l1x * l2y - l1y * l2x ) < 0 ) // This condition includes points on the triangle's edge
{
return false ;
}
}
return true ;
}
double interpolate ( double inx , double iny ) // Interpolate the elevation of the given location inside the triangle
{
double a1 = 0.5 * ( ( vert [ 1 ] - > x - inx ) * ( vert [ 2 ] - > y - iny ) - ( vert [ 1 ] - > y - iny ) * ( vert [ 2 ] - > x - inx ) ) ;
double a2 = 0.5 * ( ( vert [ 2 ] - > x - inx ) * ( vert [ 0 ] - > y - iny ) - ( vert [ 2 ] - > y - iny ) * ( vert [ 0 ] - > x - inx ) ) ;
double a3 = 0.5 * ( ( vert [ 0 ] - > x - inx ) * ( vert [ 1 ] - > y - iny ) - ( vert [ 0 ] - > y - iny ) * ( vert [ 1 ] - > x - inx ) ) ;
return ( a1 * vert [ 0 ] - > elev + a2 * vert [ 1 ] - > elev + a3 * vert [ 2 ] - > elev ) / ( a1 + a2 + a3 ) ;
}
} ;
2021-09-22 16:36:30 +08:00
// End triangle definition
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
// Start DEM definition
struct dem_point
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
double x , y ; // position of the DEM location
double elev ; // elevation at the DEM location
double err ; // error of the TIN with respect to the elevation
triangle * host ; // host triangle of the DEM location
std : : vector < triangle * > circum_host ; // triangles which circumcircles include the location
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
dem_point ( ) : x ( NAN ) , y ( NAN ) , elev ( NAN ) , host ( nullptr ) { }
dem_point ( double inx , double iny , double inelev ) { set ( inx , iny , inelev ) ; }
void set ( double inx , double iny , double inelev )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
x = inx ; y = iny ; elev = inelev ; host = nullptr ;
return ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
} ;
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
bool compare_dem_point ( dem_point * a , dem_point * b )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
if ( a - > err > b - > err ) return true ;
return false ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
// End DEM definition
2021-09-21 22:25:16 +08:00
/**
* @ brief Generate the TIN from the DEM grid
*
* @ param [ in ] dem Input DEM grid ( Ordered from lower left corner to the upper right corner )
* @ param [ in ] xmin The minimal coordinate of the DEM grid on the x - axis
* @ param [ in ] xmax The maximal coordinate of the DEM grid on the x - axis
* @ param [ in ] ymin The minimal coordinate of the DEM grid on the y - axis
* @ param [ in ] ymax The maximal coordinate of the DEM grid on the y - axis
* @ param [ in ] dx Data spacing of the DEM grid on the x - axis
* @ param [ in ] dy Data spacing of the DEM grid on the y - axis
* @ param out_verts The output vector of vertex ' s pointers . The user need to destroy the memories allocated by the function before destroy the vector
* @ param out_tris The output vector of triangle ' s pointers . The user need to destroy the memories allocated by the function before destroy the vector
* @ param [ in ] maxi_err Threshold to quit the algorithm . The default is 1e-0
* @ param [ in ] err_records If this pointer is not NULL , record maximal error values after each insertion of vertex .
*/
void dem2tin ( const std : : vector < double > & dem , double xmin , double xmax , double ymin , double ymax ,
double dx , double dy , std : : vector < vertex2dc * > & out_verts , std : : vector < triangle * > & out_tris ,
double maxi_err = 1e-0 , std : : vector < double > * err_records = nullptr )
{
if ( ! out_verts . empty ( ) ) out_verts . clear ( ) ;
if ( ! out_tris . empty ( ) ) out_tris . clear ( ) ;
if ( err_records ! = nullptr & & ! err_records - > empty ( ) ) err_records - > clear ( ) ;
if ( dx < = 0.0 | | dy < = 0.0 | | maxi_err < = 0.0 ) return ;
if ( xmin > = xmax | | ymin > = ymax | | ( xmin + dx ) > xmax | | ( ymin + dy ) > ymax ) return ;
int xnum = round ( ( xmax - xmin ) / dx ) + 1 ;
int ynum = round ( ( ymax - ymin ) / dy ) + 1 ;
if ( dem . size ( ) ! = xnum * ynum ) return ;
// Prepare the DEM points
2021-09-22 16:36:30 +08:00
dem_point * tmp_dem = nullptr ; ;
std : : vector < dem_point * > dem_grid ( xnum * ynum ) ;
2021-09-21 22:25:16 +08:00
std : : vector < dem_point * > : : iterator d_iter ;
2021-09-22 16:36:30 +08:00
for ( int i = 0 ; i < ynum ; + + i )
{
for ( int j = 0 ; j < xnum ; + + j )
{
dem_grid [ j + i * xnum ] = new dem_point ( xmin + dx * j , ymin + dy * i , dem [ j + i * xnum ] ) ;
}
}
2021-09-21 22:25:16 +08:00
vertex2dc * tmp_vert = nullptr ;
2021-09-22 16:36:30 +08:00
tmp_vert = new vertex2dc ( xmin , ymin , dem_grid [ 0 ] - > elev , out_verts . size ( ) ) ; // lower left corner
2021-09-21 22:25:16 +08:00
out_verts . push_back ( tmp_vert ) ;
2021-09-22 16:36:30 +08:00
d_iter = dem_grid . begin ( ) ;
tmp_dem = * d_iter ; delete tmp_dem ;
dem_grid . erase ( d_iter ) ;
tmp_vert = new vertex2dc ( xmax , ymin , dem_grid [ xnum - 2 ] - > elev , out_verts . size ( ) ) ; // lower right corner. Note the first location is already erased
2021-09-21 22:25:16 +08:00
out_verts . push_back ( tmp_vert ) ;
2021-09-22 16:36:30 +08:00
d_iter = dem_grid . begin ( ) + ( xnum - 2 ) ;
tmp_dem = * d_iter ; delete tmp_dem ;
dem_grid . erase ( d_iter ) ;
tmp_vert = new vertex2dc ( xmax , ymax , dem_grid [ xnum * ynum - 3 ] - > elev , out_verts . size ( ) ) ; // upper right corner. Note the first two locations are already erased
2021-09-21 22:25:16 +08:00
out_verts . push_back ( tmp_vert ) ;
2021-09-22 16:36:30 +08:00
d_iter = dem_grid . begin ( ) + ( xnum * ynum - 3 ) ;
tmp_dem = * d_iter ; delete tmp_dem ;
dem_grid . erase ( d_iter ) ;
tmp_vert = new vertex2dc ( xmin , ymax , dem_grid [ xnum * ( ynum - 1 ) - 2 ] - > elev , out_verts . size ( ) ) ; // upper left corner. Note the first two locations are already erased
2021-09-21 22:25:16 +08:00
out_verts . push_back ( tmp_vert ) ;
2021-09-22 16:36:30 +08:00
d_iter = dem_grid . begin ( ) + ( xnum * ( ynum - 1 ) - 2 ) ;
tmp_dem = * d_iter ; delete tmp_dem ;
dem_grid . erase ( d_iter ) ;
triangle * tmp_tri = nullptr ;
std : : vector < triangle * > cnst_tri , new_tri ;
2021-09-21 22:25:16 +08:00
std : : vector < triangle * > : : iterator t_iter ;
if ( ! is_collinear ( out_verts [ 0 ] , out_verts [ 1 ] , out_verts [ 2 ] ) ) // Do not create triangle if the vertexes are collinear
{
tmp_tri = new triangle ( out_verts [ 0 ] , out_verts [ 1 ] , out_verts [ 2 ] ) ; // order the vertex anti-clock wise
2021-09-22 16:36:30 +08:00
out_tris . push_back ( tmp_tri ) ;
2021-09-21 22:25:16 +08:00
}
if ( ! is_collinear ( out_verts [ 0 ] , out_verts [ 2 ] , out_verts [ 3 ] ) )
{
tmp_tri = new triangle ( out_verts [ 0 ] , out_verts [ 2 ] , out_verts [ 3 ] ) ; // order the vertex anti-clock wise
2021-09-22 16:36:30 +08:00
out_tris . push_back ( tmp_tri ) ;
2021-09-21 22:25:16 +08:00
}
// Find host triangle for all DEM locations
2021-09-22 16:36:30 +08:00
for ( int i = 0 ; i < dem_grid . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
for ( int t = 0 ; t < out_tris . size ( ) ; + + t )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
if ( out_tris [ t ] - > bound_location ( dem_grid [ i ] - > x , dem_grid [ i ] - > y ) )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
dem_grid [ i ] - > host = out_tris [ t ] ;
break ; // already found, no need to search more
2021-09-21 22:25:16 +08:00
}
}
}
2021-09-22 16:36:30 +08:00
// Find circum_host triangles for all DEM locations
double dist ;
for ( int i = 0 ; i < dem_grid . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
for ( int t = 0 ; t < out_tris . size ( ) ; + + t )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
dist = ( out_tris [ t ] - > cx - dem_grid [ i ] - > x ) * ( out_tris [ t ] - > cx - dem_grid [ i ] - > x )
+ ( out_tris [ t ] - > cy - dem_grid [ i ] - > y ) * ( out_tris [ t ] - > cy - dem_grid [ i ] - > y ) ;
if ( ( dist - out_tris [ t ] - > cr ) < = ZERO ) // Points on the circumcircle are also included
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
dem_grid [ i ] - > circum_host . push_back ( out_tris [ t ] ) ;
out_tris [ t ] - > circum_dem . push_back ( dem_grid [ i ] ) ;
// no beak here. There might be more than one triangle's circumcircle includes the DEM location
2021-09-21 22:25:16 +08:00
}
}
2021-09-22 16:36:30 +08:00
}
// loop all DEM data to find the location with maximal error
for ( int i = 0 ; i < dem_grid . size ( ) ; + + i )
{
dem_grid [ i ] - > err = fabs ( dem_grid [ i ] - > host - > interpolate ( dem_grid [ i ] - > x , dem_grid [ i ] - > y ) - dem_grid [ i ] - > elev ) ;
}
// Sort dem_grid in the desceding order with respect to the error
std : : sort ( dem_grid . begin ( ) , dem_grid . end ( ) , compare_dem_point ) ;
bool removed ;
edge tmp_edge ;
std : : vector < edge > cnst_edge ;
std : : vector < edge > : : iterator e_iter ;
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
while ( dem_grid [ 0 ] - > err > = maxi_err ) // quit til the threshold is meet
{
if ( err_records ! = nullptr )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
err_records - > push_back ( dem_grid [ 0 ] - > err ) ;
2021-09-21 22:25:16 +08:00
}
// create a new vertex
2021-09-22 16:36:30 +08:00
tmp_vert = new vertex2dc ( dem_grid [ 0 ] - > x , dem_grid [ 0 ] - > y , dem_grid [ 0 ] - > elev , out_verts . size ( ) ) ;
2021-09-21 22:25:16 +08:00
out_verts . push_back ( tmp_vert ) ;
2021-09-22 16:36:30 +08:00
// Move triangles which circumcircles include the new vertex to the cnst_tri and remove it from out_tris
cnst_tri . clear ( ) ;
for ( int i = 0 ; i < dem_grid [ 0 ] - > circum_host . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
cnst_tri . push_back ( dem_grid [ 0 ] - > circum_host [ i ] ) ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
2021-09-21 22:25:16 +08:00
{
for ( t_iter = out_tris . begin ( ) ; t_iter ! = out_tris . end ( ) ; )
{
2021-09-22 16:36:30 +08:00
tmp_tri = * t_iter ;
if ( cnst_tri [ c ] = = tmp_tri )
2021-09-21 22:25:16 +08:00
{
t_iter = out_tris . erase ( t_iter ) ;
2021-09-22 16:36:30 +08:00
break ; // no need to search more
2021-09-21 22:25:16 +08:00
}
else t_iter + + ;
}
2021-09-22 16:36:30 +08:00
}
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
// remove cnst_tri from its circumed DEM's circum triangle list
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
{
for ( int i = 0 ; i < cnst_tri [ c ] - > circum_dem . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
tmp_dem = cnst_tri [ c ] - > circum_dem [ i ] ;
for ( t_iter = tmp_dem - > circum_host . begin ( ) ; t_iter ! = tmp_dem - > circum_host . end ( ) ; )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
if ( cnst_tri [ c ] = = * t_iter )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
t_iter = tmp_dem - > circum_host . erase ( t_iter ) ;
2021-09-21 22:25:16 +08:00
break ;
}
2021-09-22 16:36:30 +08:00
else t_iter + + ;
2021-09-21 22:25:16 +08:00
}
}
2021-09-22 16:36:30 +08:00
}
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
// remove dem_grid[0] from its circumed triangle's circum DEM list
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
{
for ( d_iter = cnst_tri [ c ] - > circum_dem . begin ( ) ; d_iter ! = cnst_tri [ c ] - > circum_dem . end ( ) ; )
2021-09-22 11:41:57 +08:00
{
2021-09-22 16:36:30 +08:00
if ( dem_grid [ 0 ] = = * d_iter )
2021-09-22 11:41:57 +08:00
{
2021-09-22 16:36:30 +08:00
d_iter = cnst_tri [ c ] - > circum_dem . erase ( d_iter ) ;
break ;
2021-09-22 11:41:57 +08:00
}
2021-09-22 16:36:30 +08:00
else d_iter + + ;
2021-09-22 11:41:57 +08:00
}
2021-09-22 16:36:30 +08:00
}
2021-09-22 11:41:57 +08:00
2021-09-22 16:36:30 +08:00
// clear host and circumcircle triangles for the used DEM location
d_iter = dem_grid . begin ( ) ;
tmp_dem = * d_iter ; tmp_dem - > circum_host . clear ( ) ; delete tmp_dem ;
dem_grid . erase ( d_iter ) ;
2021-09-21 22:25:16 +08:00
2021-09-22 16:36:30 +08:00
// loop to remove duplicate edges
cnst_edge . clear ( ) ;
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
for ( int e = 0 ; e < 3 ; + + e )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
tmp_edge . set ( cnst_tri [ c ] - > vert [ e ] , cnst_tri [ c ] - > vert [ ( e + 1 ) % 3 ] ) ;
removed = false ;
for ( e_iter = cnst_edge . begin ( ) ; e_iter ! = cnst_edge . end ( ) ; )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
if ( tmp_edge = = * e_iter ) // duplicate edge, remove from cnst_edge
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
e_iter = cnst_edge . erase ( e_iter ) ;
removed = true ;
break ; // no need to search more
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
else e_iter + + ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
if ( ! removed ) // not a duplicate edge, add to the cnst_edge
2021-09-22 11:41:57 +08:00
{
2021-09-22 16:36:30 +08:00
cnst_edge . push_back ( tmp_edge ) ;
2021-09-22 11:41:57 +08:00
}
}
2021-09-22 16:36:30 +08:00
}
2021-09-22 11:41:57 +08:00
2021-09-22 16:36:30 +08:00
// construct new triangles and add to out_tris
new_tri . clear ( ) ;
for ( int c = 0 ; c < cnst_edge . size ( ) ; + + c )
{
if ( ! is_collinear ( cnst_edge [ c ] . vert [ 0 ] , cnst_edge [ c ] . vert [ 1 ] , tmp_vert ) ) // Do not create triangle if the vertexes are collinear
{
tmp_tri = new triangle ( cnst_edge [ c ] . vert [ 0 ] , cnst_edge [ c ] . vert [ 1 ] , tmp_vert ) ; // order the vertex anti-clock wise
out_tris . push_back ( tmp_tri ) ;
new_tri . push_back ( tmp_tri ) ;
}
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
// loop all DEM data to update host triangles
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
for ( int i = 0 ; i < cnst_tri [ c ] - > circum_dem . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
tmp_dem = cnst_tri [ c ] - > circum_dem [ i ] ;
for ( int n = 0 ; n < new_tri . size ( ) ; + + n ) // search in newly created triangles to find new host
{
if ( new_tri [ n ] - > bound_location ( tmp_dem - > x , tmp_dem - > y ) )
{
tmp_dem - > host = new_tri [ n ] ;
tmp_dem - > err = fabs ( new_tri [ n ] - > interpolate ( tmp_dem - > x , tmp_dem - > y ) - tmp_dem - > elev ) ;
break ; // already found, no need to search more
}
}
2021-09-21 22:25:16 +08:00
}
}
2021-09-22 16:36:30 +08:00
// Find circum_host triangles for all DEM locations
// cnst_tri's circum area doesn't over cover new_tri's circum area
for ( int i = 0 ; i < dem_grid . size ( ) ; + + i )
2021-09-22 11:41:57 +08:00
{
2021-09-22 16:36:30 +08:00
for ( int n = 0 ; n < new_tri . size ( ) ; + + n ) // search in newly created triangles to find new circumcircle triangles
2021-09-22 11:41:57 +08:00
{
2021-09-22 16:36:30 +08:00
dist = ( new_tri [ n ] - > cx - dem_grid [ i ] - > x ) * ( new_tri [ n ] - > cx - dem_grid [ i ] - > x )
+ ( new_tri [ n ] - > cy - dem_grid [ i ] - > y ) * ( new_tri [ n ] - > cy - dem_grid [ i ] - > y ) ;
if ( ( dist - new_tri [ n ] - > cr ) < = ZERO ) // Points on the circumcircle are also included
{
new_tri [ n ] - > circum_dem . push_back ( dem_grid [ i ] ) ;
dem_grid [ i ] - > circum_host . push_back ( new_tri [ n ] ) ;
// no beak here. There might be more than one triangle's circumcircle includes the DEM location
}
2021-09-22 11:41:57 +08:00
}
}
2021-09-22 16:36:30 +08:00
// destroy memories used by cnst_edge
for ( int c = 0 ; c < cnst_tri . size ( ) ; + + c )
{
tmp_tri = cnst_tri [ c ] ;
tmp_tri - > circum_dem . clear ( ) ;
delete tmp_tri ; tmp_tri = nullptr ;
}
// Sort dem_grid in the desceding order with respect to the error
std : : sort ( dem_grid . begin ( ) , dem_grid . end ( ) , compare_dem_point ) ;
2021-09-21 22:25:16 +08:00
}
if ( err_records ! = nullptr )
{
2021-09-22 16:36:30 +08:00
err_records - > push_back ( dem_grid [ 0 ] - > err ) ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
// destroy remaining DEM data
for ( int i = 0 ; i < dem_grid . size ( ) ; + + i )
2021-09-21 22:25:16 +08:00
{
2021-09-22 16:36:30 +08:00
tmp_dem = dem_grid [ i ] ;
delete tmp_dem ; tmp_dem = nullptr ;
2021-09-21 22:25:16 +08:00
}
2021-09-22 16:36:30 +08:00
2021-09-21 22:25:16 +08:00
return ;
}
# endif // _TIN_DELAUNAY_H