Compare commits

...

6 Commits
1.0 ... master

Author SHA1 Message Date
638c856620 update ignore 2025-01-15 01:20:04 +08:00
9823e241e0 bug fixed for src/cmakelists 2022-03-09 09:41:15 +08:00
1d3dd9ccf9 add regions to grd2tin and rnd2tin 2022-03-07 14:47:04 +08:00
f112ca41ee update cmakelists 2021-11-12 20:46:16 +08:00
fc0314750a Update CMakeLists.txt 2021-11-10 10:45:16 +08:00
fc2ce49c58 Successfully compiled on Win11 2021-11-10 10:43:49 +08:00
13 changed files with 12510 additions and 16225 deletions

3
.gitignore vendored
View File

@ -34,4 +34,5 @@
.DS_Store
backup/
build/
.vscode/
.vscode/
installer

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,13 @@
#
aux_source_directory(lib LIBTIN_SRC)
# GetOptWin https://gitee.com/yizhangss/getopt-win
if(WIN32)
find_package(GetOptWin REQUIRED)
message(STATUS "Found GetOpt-Win")
include_directories(${GetOptWin_INC_DIR})
endif()
#
#
# libcmake
@ -41,12 +48,10 @@ else()
EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
install(EXPORT ${PROJECT_NAME}Targets
DESTINATION ${CONFIG_FILE_PATH})
install(FILES
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CONFIG_FILE_PATH})
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CONFIG_FILE_PATH})
endif()
#
install(FILES lib/tin.h DESTINATION include)
@ -78,9 +83,15 @@ macro(add_tool name)
set_target_properties(${name} PROPERTIES INSTALL_RPATH /usr/local/lib)
#
target_link_libraries(${name} PUBLIC tin)
#
install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/sbin)
#
install(TARGETS ${name} DESTINATION sbin)
endmacro()
add_tool(grd2tin)
add_tool(rnd2tin)
add_tool(rnd2tin)
# Windowsgetopt BUG VStudio getopt
if(WIN32)
link_directories(${GetOptWin_LIB_DIR})
target_link_libraries(grd2tin PUBLIC ${GetOptWin_LIB})
target_link_libraries(rnd2tin PUBLIC ${GetOptWin_LIB})
endif()

View File

@ -14,10 +14,20 @@ int main(int argc, char const *argv[])
}
infile.close();
std::vector<vertex2dc> box(4);
box[0].id = 0; box[0].x = 500; box[0].y = 250;
box[1].id = 1; box[1].x = 750; box[1].y = 250;
box[2].id = 2; box[2].x = 750; box[2].y = 500;
box[3].id = 3; box[3].x = 500; box[3].y = 500;
std::vector<region> box_region(1);
box_region[0].set(box, 5.0);
std::vector<double> err_records;
std::vector<vertex2dc*> tin_vert;
std::vector<triangle*> tin_ele;
grd2tin(topo, 0, 1000, 0, 1000, 10, 10, tin_vert, tin_ele, 1.0, nullptr, &err_records);
//grd2tin(topo, 0, 1000, 0, 1000, 10, 10, tin_vert, tin_ele, 1.0, nullptr, &err_records, nullptr);
grd2tin(topo, 0, 1000, 0, 1000, 10, 10, tin_vert, tin_ele, 1.0, nullptr, &err_records, &box_region);
// Write a log file
std::ofstream logfile("data/topo_TIN.log");

View File

@ -13,6 +13,10 @@
*/
#include "tin.h"
#include "cmath"
#include "algorithm"
#include "exception"
#include "stdexcept"
// Start vertex definition
vertex2dc::vertex2dc()
@ -21,12 +25,12 @@ vertex2dc::vertex2dc()
id = 0;
}
vertex2dc::vertex2dc(double inx, double iny, double inelev, unsigned int inid)
vertex2dc::vertex2dc(double inx, double iny, double inelev, size_t inid)
{
set(inx, iny, inelev, inid);
}
void vertex2dc::set(double inx, double iny, double inelev, unsigned int inid)
void vertex2dc::set(double inx, double iny, double inelev, size_t inid)
{
x = inx; y = iny; elev = inelev; id = inid;
return;
@ -42,6 +46,15 @@ bool operator ==(const vertex2dc &a, const vertex2dc &b)
return false;
}
bool duplicated_vertex(const vertex2dc &a, const vertex2dc &b)
{
if (a == b && a.id == b.id)
{
return true;
}
return false;
}
// Test if the three points are on the same line
bool is_collinear(vertex2dc *a_ptr, vertex2dc *b_ptr, vertex2dc *c_ptr)
{
@ -62,16 +75,47 @@ void circumcircle(vertex2dc *v0, vertex2dc *v1, vertex2dc *v2, double &cx, doubl
cx = ((v2->y - v0->y)*m + (v0->y - v1->y)*u)*s;
cy = ((v0->x - v2->x)*m + (v1->x - v0->x)*u)*s;
cr = (v0->x - cx)*(v0->x - cx) + (v0->y - cy)*(v0->y - cy); // not need to calculate the squared root here
// not need to calculate the squared root here
cr = (v0->x - cx)*(v0->x - cx) + (v0->y - cy)*(v0->y - cy);
return;
}
// End vertex definition
// Start region definition
region::region()
{
maxi_err = 0.0;
}
region::region(const std::vector<vertex2dc> &outline_vert, double err)
{
set(outline_vert, err);
}
void region::set(const std::vector<vertex2dc> &outline_vert, double err)
{
if (err <= 0.0)
{
throw std::invalid_argument("Invalid maximal allowed error.");
}
if (outline_vert.size() < 3)
{
throw std::runtime_error("The input polygon must have at least 3 vertexes.");
}
maxi_err = err;
poly_vert = outline_vert;
return;
}
// End region definition
// Start DEM definition
dem_point::dem_point()
{
x = y = elev = NAN;
err = 0.0;
allowed_err = -1.0;
host = nullptr;
}
@ -82,11 +126,14 @@ dem_point::dem_point(double inx, double iny, double inelev)
void dem_point::set(double inx, double iny, double inelev)
{
x = inx; y = iny; elev = inelev; err = 0.0; host = nullptr;
x = inx; y = iny; elev = inelev;
err = 0.0;
allowed_err = -1.0;
host = nullptr;
return;
}
bool compare_dem_point(dem_point *a, dem_point *b) // determination function for std::sort
bool compare_dem_error(dem_point *a, dem_point *b) // determination function for std::sort
{
if (a->err > b->err) return true;
return false;
@ -102,13 +149,13 @@ triangle::triangle()
triangle::triangle(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr)
{
set(v0ptr, v1ptr, v2ptr);
set_vertex(v0ptr, v1ptr, v2ptr);
neigh[0] = neigh[1] = neigh[2] = nullptr;
}
void triangle::set(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr)
void triangle::set_vertex(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr)
{
vert[0] = v0ptr; vert[1] = v1ptr; vert[2] = v2ptr;
neigh[0] = neigh[1] = neigh[2] = nullptr;
circumcircle(vert[0], vert[1], vert[2], cx, cy, cr);
return;
}
@ -256,17 +303,27 @@ void flip_neighboring_triangles(triangle *t, triangle *n, int t_id, int n_id)
{
tmp_dem = n->hosted_dem[i];
tmp_dem->err = fabs(n->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
}
for (int i = 0; i < t->hosted_dem.size(); i++)
{
tmp_dem = t->hosted_dem[i];
tmp_dem->err = fabs(t->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
}
// Sort maximal errors for triangles t and n
std::sort(t->hosted_dem.begin(), t->hosted_dem.end(), compare_dem_point);
std::sort(n->hosted_dem.begin(), n->hosted_dem.end(), compare_dem_point);
std::sort(t->hosted_dem.begin(), t->hosted_dem.end(), compare_dem_error);
std::sort(n->hosted_dem.begin(), n->hosted_dem.end(), compare_dem_error);
return;
}
@ -396,7 +453,7 @@ triangle *split_triangle(vertex2dc *v, triangle *t, triangle *new_t[4])
break;
}
}
return t->neigh[i]; // Return the neighboring tiangle to be deleted
return t->neigh[i]; // Return the neighboring triangle to be deleted
}
}
@ -444,7 +501,7 @@ bool triangle_inside_polygon(triangle *tri_p, std::vector<vertex2dc> *poly_vert)
// If any vertexes of the input triangle is outside of the polygon, return false. Otherwise, return true
if (poly_vert->size() < 3)
{
return true;
throw std::runtime_error("The input polygon must have at least 3 vertexes.");
}
else
{
@ -500,7 +557,7 @@ bool triangle_inside_polygon(triangle *tri_p, std::vector<vertex2dc> *poly_vert)
}
/**
* @brief Test if the input locaiton is inside of the given polygon
* @brief Test if the input location is inside of the given polygon
*
* @param x Input x coordinate
* @param y Input y coordinate
@ -513,7 +570,7 @@ bool location_inside_polygon(double x, double y, std::vector<vertex2dc> *poly_ve
// If any vertexes of the input triangle is outside of the polygon, return false. Otherwise, return true
if (poly_vert->size() < 3)
{
return true;
throw std::runtime_error("The input polygon must have at least 3 vertexes.");
}
else
{
@ -566,7 +623,7 @@ bool location_inside_polygon(double x, double y, std::vector<vertex2dc> *poly_ve
/**
* @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] dem Input DEM grid (Ordered from lower left corner to the upper right corner in a row-major fashion)
* @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
@ -580,24 +637,48 @@ bool location_inside_polygon(double x, double y, std::vector<vertex2dc> *poly_ve
*/
void grd2tin(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,
std::vector<vertex2dc> *outline_poly, std::vector<double> *err_records)
std::vector<vertex2dc> *outline_poly, std::vector<double> *err_records,
std::vector<region> *regions, std::vector<double> *dem_error)
{
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;
if (maxi_err <= 0.0)
{
throw std::invalid_argument("Invalid maximal allowed error.");
}
if (dx <= 0.0 || dy <= 0.0 || xmin >= xmax || ymin >= ymax || (xmin + dx) > xmax || (ymin + dy) > ymax)
{
throw std::invalid_argument("Invalid DEM parameters.");
}
int xnum = round((xmax - xmin)/dx) + 1;
int ynum = round((ymax - ymin)/dy) + 1;
if (dem.size() != xnum*ynum) return;
if (dem.size() != xnum*ynum)
{
throw std::invalid_argument("Invalid size of the input DEM values w.r.t. the DEM parameters.");
}
// Prepare the DEM points
dem_point *tmp_dem = nullptr;
dem_point *maxi_err_dem = nullptr;
std::vector<dem_point*>::iterator d_iter;
if (dem_error != nullptr)
{
if (dem_error->size() != xnum*ynum)
{
throw std::invalid_argument("Invalid size of the input DEM errors w.r.t. the DEM parameters.");
}
for (size_t i = 0; i < xnum*ynum; i++)
{
if (dem_error->at(i) <= 0.0)
{
throw std::runtime_error("Invalid input DEM error value.");
}
}
}
// Prepare the initial vertexes and triangles from corner DEM points
vertex2dc *tmp_vert = nullptr;
tmp_vert = new vertex2dc(xmin, ymin, dem[0], out_verts.size()); // lower left corner
@ -612,9 +693,7 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_vert = new vertex2dc(xmin, ymax, dem[xnum*(ynum-1)], out_verts.size()); // upper left corner
out_verts.push_back(tmp_vert);
triangle *old_tri = nullptr, *tmp_tri = nullptr;
triangle *cnst_tri[4];
std::vector<triangle*>::iterator t_iter;
triangle *tmp_tri = nullptr;
if (!is_collinear(out_verts[0], out_verts[1], out_verts[2])) // Do not create triangle if the vertexes are collinear
{
@ -628,13 +707,18 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
out_tris.push_back(tmp_tri); tmp_tri = nullptr;
}
if (out_tris.size() != 2) return;
if (out_tris.size() != 2)
{
throw std::runtime_error("Fail to construct the initial triangles.");
}
out_tris[0]->set_neighbor(nullptr, nullptr, out_tris[1]);
out_tris[1]->set_neighbor(out_tris[0], nullptr, nullptr);
// Find host triangle for all DEM locations
int tmp_id;
dem_point *tmp_dem = nullptr;
if (outline_poly == nullptr)
{
for (int i = 0; i < ynum; ++i)
@ -642,9 +726,11 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
for (int j = 0; j < xnum; ++j)
{
tmp_id = j + i*xnum;
if (tmp_id != 0 && tmp_id != (xnum-1) && tmp_id != (xnum*ynum-1) && tmp_id != (xnum*(ynum-1))) // the four corners are already used
if (tmp_id != 0 && tmp_id != (xnum-1) &&
tmp_id != (xnum*ynum-1) && tmp_id != (xnum*(ynum-1))) // the four corners are already used
{
tmp_dem = new dem_point(xmin + dx*j, ymin + dy*i, dem[j + i*xnum]);
for (int t = 0; t < out_tris.size(); ++t)
{
if (out_tris[t]->bound_location(tmp_dem->x, tmp_dem->y))
@ -652,6 +738,29 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_dem->host = out_tris[t];
tmp_dem->err = fabs(out_tris[t]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
out_tris[t]->hosted_dem.push_back(tmp_dem);
// Find region
if (regions != nullptr)
{
for (size_t r = 0; r < regions->size(); r++)
{
if (location_inside_polygon(tmp_dem->x, tmp_dem->y, &(regions->at(r).poly_vert)))
{
tmp_dem->allowed_err = regions->at(r).maxi_err;
break;
}
}
}
if (dem_error != nullptr)
{
tmp_dem->allowed_err = dem_error->at(tmp_id);
}
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break; // already found, no need to search more
}
}
@ -666,11 +775,14 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
for (int j = 0; j < xnum; ++j)
{
tmp_id = j + i*xnum;
// the four corners are already used
// We also check to see if the candidate dem point is inside the outline polygon
if (tmp_id != 0 && tmp_id != (xnum-1) &&
tmp_id != (xnum*ynum-1) && tmp_id != (xnum*(ynum-1)) &&
location_inside_polygon(xmin+dx*j, ymin+dy*i, outline_poly)) // the four corners are already used
location_inside_polygon(xmin+dx*j, ymin+dy*i, outline_poly))
{
tmp_dem = new dem_point(xmin + dx*j, ymin + dy*i, dem[j + i*xnum]);
for (int t = 0; t < out_tris.size(); ++t)
{
if (out_tris[t]->bound_location(tmp_dem->x, tmp_dem->y))
@ -678,6 +790,29 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_dem->host = out_tris[t];
tmp_dem->err = fabs(out_tris[t]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
out_tris[t]->hosted_dem.push_back(tmp_dem);
// Find region
if (regions != nullptr)
{
for (size_t r = 0; r < regions->size(); r++)
{
if (location_inside_polygon(tmp_dem->x, tmp_dem->y, &(regions->at(r).poly_vert)))
{
tmp_dem->allowed_err = regions->at(r).maxi_err;
break;
}
}
}
if (dem_error != nullptr)
{
tmp_dem->allowed_err = dem_error->at(tmp_id);
}
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break; // already found, no need to search more
}
}
@ -688,9 +823,10 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
// Sort hosted_dem in the desceding order with respect to the error. Get pointer of the dem_point with maximal error
double maxi_err_tmp = -1.0;
dem_point *maxi_err_dem = nullptr;
for (int t = 0; t < out_tris.size(); ++t)
{
std::sort(out_tris[t]->hosted_dem.begin(), out_tris[t]->hosted_dem.end(), compare_dem_point);
std::sort(out_tris[t]->hosted_dem.begin(), out_tris[t]->hosted_dem.end(), compare_dem_error);
if (out_tris[t]->hosted_dem[0]->err > maxi_err_tmp)
{
maxi_err_tmp = out_tris[t]->hosted_dem[0]->err;
@ -698,6 +834,9 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
}
}
triangle *old_tri = nullptr, *cnst_tri[4];
std::vector<dem_point*>::iterator d_iter;
std::vector<triangle*>::iterator t_iter;
while (maxi_err_dem->err >= maxi_err) // quit til the threshold is meet
{
if (err_records != nullptr)
@ -768,6 +907,11 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -783,6 +927,11 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -792,7 +941,7 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
{
if (cnst_tri[n] != nullptr)
{
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_point);
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_error);
}
}
@ -816,6 +965,11 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -825,7 +979,7 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
{
if (cnst_tri[n] != nullptr)
{
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_point);
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_error);
}
}
@ -917,15 +1071,39 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
* @param[in] err_records If this pointer is not NULL, record maximal error values after each insertion of vertex.
*/
void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_verts, std::vector<triangle*> &out_tris,
double maxi_err, std::vector<vertex2dc> *outline_poly, std::vector<double> *err_records)
double maxi_err, std::vector<vertex2dc> *outline_poly, std::vector<double> *err_records,
std::vector<region> *regions, std::vector<double> *dem_error)
{
if (dem.size() < 3) return;
if (maxi_err <= 0.0) return;
if (dem.size() < 3)
{
throw std::runtime_error("The input DEM must have at least 3 points.");
}
if (maxi_err <= 0.0)
{
throw std::invalid_argument("Invalid maximal allowed error.");
}
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 (dem_error != nullptr)
{
if (dem_error->size() != dem.size())
{
throw std::invalid_argument("Invalid size of the input DEM errors w.r.t. the DEM parameters.");
}
for (size_t i = 0; i < dem.size(); i++)
{
if (dem_error->at(i) <= 0.0)
{
throw std::runtime_error("Invalid input DEM error value.");
}
}
}
// locate the surrounding box and initiate the staring two triangles
double xmin = dem[0].x, xmax = dem[0].x;
double ymin = dem[0].y, ymax = dem[0].y;
@ -972,7 +1150,10 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
out_tris.push_back(tmp_tri); tmp_tri = nullptr;
}
if (out_tris.size() != 2) return;
if (out_tris.size() != 2)
{
throw std::runtime_error("Fail to construct the initial triangles.");
}
out_tris[0]->set_neighbor(nullptr, nullptr, out_tris[1]);
out_tris[1]->set_neighbor(out_tris[0], nullptr, nullptr);
@ -995,6 +1176,29 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
tmp_dem->host = out_tris[t];
tmp_dem->err = fabs(out_tris[t]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
out_tris[t]->hosted_dem.push_back(tmp_dem);
// Find region
if (regions != nullptr)
{
for (size_t r = 0; r < regions->size(); r++)
{
if (location_inside_polygon(tmp_dem->x, tmp_dem->y, &(regions->at(r).poly_vert)))
{
tmp_dem->allowed_err = regions->at(r).maxi_err;
break;
}
}
}
if (dem_error != nullptr)
{
tmp_dem->allowed_err = dem_error->at(d);
}
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break; // already found, no need to search more
}
}
@ -1014,6 +1218,29 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
tmp_dem->host = out_tris[t];
tmp_dem->err = fabs(out_tris[t]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
out_tris[t]->hosted_dem.push_back(tmp_dem);
// Find region
if (regions != nullptr)
{
for (size_t r = 0; r < regions->size(); r++)
{
if (location_inside_polygon(tmp_dem->x, tmp_dem->y, &(regions->at(r).poly_vert)))
{
tmp_dem->allowed_err = regions->at(r).maxi_err;
break;
}
}
}
if (dem_error != nullptr)
{
tmp_dem->allowed_err = dem_error->at(d);
}
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break; // already found, no need to search more
}
}
@ -1025,7 +1252,7 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
double maxi_err_tmp = -1.0;
for (int t = 0; t < out_tris.size(); ++t)
{
std::sort(out_tris[t]->hosted_dem.begin(), out_tris[t]->hosted_dem.end(), compare_dem_point);
std::sort(out_tris[t]->hosted_dem.begin(), out_tris[t]->hosted_dem.end(), compare_dem_error);
if (out_tris[t]->hosted_dem[0]->err > maxi_err_tmp)
{
maxi_err_tmp = out_tris[t]->hosted_dem[0]->err;
@ -1103,6 +1330,11 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -1118,6 +1350,11 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -1127,7 +1364,7 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
{
if (cnst_tri[n] != nullptr)
{
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_point);
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_error);
}
}
@ -1151,6 +1388,11 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
tmp_dem->host = cnst_tri[n];
tmp_dem->err = fabs(cnst_tri[n]->interpolate(tmp_dem->x, tmp_dem->y) - tmp_dem->elev);
cnst_tri[n]->hosted_dem.push_back(tmp_dem);
// If the dem point belongs to a region, then set err to 0 if satisfy the region's threshold
if (tmp_dem->allowed_err > 0.0 && tmp_dem->err <= tmp_dem->allowed_err)
{
tmp_dem->err = 0.0;
}
break;
}
}
@ -1160,7 +1402,7 @@ void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_ver
{
if (cnst_tri[n] != nullptr)
{
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_point);
std::sort(cnst_tri[n]->hosted_dem.begin(), cnst_tri[n]->hosted_dem.end(), compare_dem_error);
}
}

View File

@ -14,16 +14,14 @@
#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
size_t id; // index of the vertex
double x, y; // position of the vertex
double elev; // elevation at the vertex
@ -37,7 +35,7 @@ struct vertex2dc
* @param inelev initial elevation
* @param inid initial index
*/
vertex2dc(double inx, double iny, double inelev, unsigned int inid);
vertex2dc(double inx, double iny, double inelev, size_t inid);
/**
* @brief Set a vertex2dc object
@ -47,7 +45,7 @@ struct vertex2dc
* @param inelev initial elevation
* @param inid initial index
*/
void set(double inx, double iny, double inelev, unsigned int inid);
void set(double inx, double iny, double inelev, size_t inid);
};
/**
@ -60,6 +58,16 @@ struct vertex2dc
*/
bool operator ==(const vertex2dc &a, const vertex2dc &b);
/**
* @brief Compare two vertexes to see if they are duplicated.
*
* @param a vertex a
* @param b vertex b
* @return true the two vertexes are at the same location and a same index
* @return false the two vertexes are not at the same location and a same index
*/
bool duplicated_vertex(const vertex2dc &a, const vertex2dc &b);
/**
* @brief Test if the three points are on the same line
*
@ -84,6 +92,20 @@ bool is_collinear(vertex2dc *a_ptr, vertex2dc *b_ptr, vertex2dc *c_ptr);
void circumcircle(vertex2dc *v0, vertex2dc *v1, vertex2dc *v2, double &cx, double &cy, double &cr);
// End vertex definition
// Start region definition
struct region
{
double maxi_err;
std::vector<vertex2dc> poly_vert;
region();
region(const std::vector<vertex2dc> &outline_vert, double err);
void set(const std::vector<vertex2dc> &outline_vert, double err);
};
// End region definition
// Start DEM definition
struct triangle;
@ -92,6 +114,7 @@ struct dem_point
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
double allowed_err; // point specified threshold of maximal allowed error
triangle *host; // pointer of the triangle that the dem_point falls inside of
dem_point();
@ -152,7 +175,7 @@ struct triangle
* @param v1ptr pointer of the vertex 1
* @param v2ptr pointer of the vertex 2
*/
void set(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr);
void set_vertex(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr);
/**
* @brief Set neighbors of a triangle object
@ -202,7 +225,8 @@ struct triangle
*/
void grd2tin(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<vertex2dc> *outline_poly = nullptr, std::vector<double> *err_records = nullptr);
double maxi_err = 1e-0, std::vector<vertex2dc> *outline_poly = nullptr, std::vector<double> *err_records = nullptr,
std::vector<region> *regions = nullptr, std::vector<double> *dem_error = nullptr);
/**
* @brief Generate the TIN from random DEM points
@ -216,6 +240,7 @@ void grd2tin(const std::vector<double> &dem, double xmin, double xmax, double ym
*/
void rnd2tin(const std::vector<dem_point> &dem, std::vector<vertex2dc*> &out_verts,
std::vector<triangle*> &out_tris, double maxi_err = 1e-0, std::vector<vertex2dc> *outline_poly = nullptr,
std::vector<double> *err_records = nullptr);
std::vector<double> *err_records = nullptr, std::vector<region> *regions = nullptr,
std::vector<double> *dem_error = nullptr);
#endif // _TIN_DELAUNAY_H

View File

@ -6,11 +6,16 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iomanip>
#include <sys/ioctl.h>
#include "vector"
#if defined _WINDOWS || __WIN32__
#include "windows.h"
#else
#include "sys/ioctl.h"
#include "unistd.h"
#endif
using namespace std;
typedef vector<string> strArray;
@ -101,9 +106,19 @@ void dispHelp::show()
int line_length;
string segment,full_message;
stringstream ss_message;
int width;
//获取终端窗口的行列数
#if defined _WINDOWS || __WIN32__
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
width = csbi.srWindow.Right - csbi.srWindow.Left;
#else
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
width = w.ws_col;
#endif
//显示头信息
full_message = ex_name + " " + version + " - " + descript;
ss_message.clear(); ss_message.str(full_message);
@ -111,7 +126,7 @@ void dispHelp::show()
line_length = front_space + back_space;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space + back_space))
{
@ -139,7 +154,7 @@ void dispHelp::show()
line_length = front_space + back_space;;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space + back_space))
{
@ -174,7 +189,7 @@ void dispHelp::show()
line_length = front_space + back_space + 4;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+4))
{
@ -214,7 +229,7 @@ void dispHelp::show()
line_length = front_space + back_space + 4;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+4))
{
@ -247,7 +262,7 @@ void dispHelp::show()
line_length = front_space + back_space + 9;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+9))
{
@ -281,7 +296,7 @@ void dispHelp::show()
line_length = front_space + back_space + 4;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+4))
{
@ -314,7 +329,7 @@ void dispHelp::show()
line_length = front_space + back_space + 9;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+9))
{
@ -354,7 +369,7 @@ void dispHelp::show()
line_length = front_space + back_space + 4;
while(ss_message >> segment)
{
if ((line_length+segment.length()+1) <= w.ws_col)
if ((line_length+segment.length()+1) <= width)
{
if (line_length == (front_space+back_space+4))
{

File diff suppressed because it is too large Load Diff

View File

@ -1,230 +0,0 @@
/******************************************************//**
*
*
*
*
*
*
* Geophysical Computational Tools & Library
*
* Copyright (c) 2019-2029 The GCTL developing team.
* Correspondents: Dr. Yi Zhang (zhangyiss@icloud.com)
* All rights reserved.
*
* This file is part of the GCTL software. Permission is hereby granted to any
* person obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* 1. The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 2. The GCTL is only free of charge for academic and non-profit purpose. For
* commercial purpose, A commercial license must be obtained by contacting the
* developing team.
* 3. Publications which have used the GCTL must include a reference to the GCTL
* package.
* 4. Bugs and fixings shall be sent to the developing team for review.
* 5. Updated affiliations shall be sent to the developing team for review.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*********************************************************/
/* Declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2009,2010
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifndef __THROW
# ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) (0)
# endif
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# else
# define __THROW
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW;
# if defined __need_getopt && defined __USE_POSIX2 \
&& !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
/* The GNU getopt has more functionality than the standard version. The
additional functionality can be disable at runtime. This redirection
helps to also do this at runtime. */
# ifdef __REDIRECT
extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
const char *__shortopts),
__posix_getopt);
# else
extern int __posix_getopt (int ___argc, char *const *___argv,
const char *__shortopts) __THROW;
# define getopt __posix_getopt
# endif
# endif
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
#ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
#endif
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

View File

@ -5,12 +5,8 @@
#include "fstream"
#include "sstream"
#include "string"
#ifdef _WINDOWS
#include "getopt_win.h"
#else
#include "cmath"
#include "getopt.h"
#endif
void display_help(std::string exe_name)
{

View File

@ -5,12 +5,7 @@
#include "fstream"
#include "sstream"
#include "string"
#ifdef _WINDOWS
#include "getopt_win.h"
#else
#include "getopt.h"
#endif
void display_help(std::string exe_name)
{