/** * ___________ __ * /_ __/ _/ | / / * / / / // |/ / * / / _/ // /| / * /_/ /___/_/ |_/ * * C++ library of the Triangular Irregular Network (TIN) * * Copyright (c) 2021-2031 Yi Zhang (zhangyiss@icloud.com) * All rights reserved. * */ #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(); /** * @brief Construct a new vertex2dc object * * @param inx initial x coordinate * @param iny initial y coordinate * @param inelev initial elevation * @param inid initial index */ vertex2dc(double inx, double iny, double inelev, unsigned int inid); /** * @brief Set a vertex2dc object * * @param inx initial x coordinate * @param iny initial y coordinate * @param inelev initial elevation * @param inid initial index */ void set(double inx, double iny, double inelev, unsigned int inid); }; /** * @brief Compare two vertexes * * @param a vertex a * @param b vertex b * @return true the two vertexes are at the same location * @return false the two vertexes are not at the same location */ bool operator ==(const vertex2dc &a, const vertex2dc &b); /** * @brief Test if the three points are on the same line * * @param a_ptr pointer of the vertex a * @param b_ptr pointer of the vertex b * @param c_ptr pointer of the vertex c * @return true the three vertexes are on the same line * @return false the three vertexes are not on the same line */ bool is_collinear(vertex2dc *a_ptr, vertex2dc *b_ptr, vertex2dc *c_ptr); /** * @brief Calculate the circumcircle from three points * * @param v0 pointer of the vertex v0 * @param v1 pointer of the vertex v1 * @param v2 pointer of the vertex v2 * @param cx x coordinate of the returned circumcircle * @param cy y coordinate of the returned circumcircle * @param cr squared radius of the returned circumcircle */ void circumcircle(vertex2dc *v0, vertex2dc *v1, vertex2dc *v2, double &cx, double &cy, double &cr); // End vertex definition // Start DEM definition struct triangle; 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 triangle *host; dem_point(); /** * @brief Construct a new DEM point object * * @param inx initial x coordinate * @param iny initial y coordinate * @param inelev initial elevation */ dem_point(double inx, double iny, double inelev); /** * @brief Set a DEM point object * * @param inx initial x coordinate * @param iny initial y coordinate * @param inelev initial elevation */ void set(double inx, double iny, double inelev); }; // End DEM definition /* Start triangle definition * v2 * /\ * / \ * n2 / \ n1 * / \ * /------------\ * v0 n0 v1 */ struct triangle { int id; vertex2dc *vert[3]; // vertex of the triangle triangle *neigh[3]; // neighbors of the triangle double cx, cy; // center of the triangle's circumcircle double cr; // radius of the circumcircle std::vector hosted_dem; triangle(); /** * @brief Construct a new triangle object * * @param v0ptr pointer of the vertex 0 * @param v1ptr pointer of the vertex 1 * @param v2ptr pointer of the vertex 2 */ triangle(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr); /** * @brief Set a triangle object * * @param v0ptr pointer of the vertex 0 * @param v1ptr pointer of the vertex 1 * @param v2ptr pointer of the vertex 2 */ void set(vertex2dc *v0ptr, vertex2dc *v1ptr, vertex2dc *v2ptr); /** * @brief Set neighbors of a triangle object * * @param n0ptr pointer of the neighboring vertex 0 * @param n1ptr pointer of the neighboring vertex 1 * @param n2ptr pointer of the neighboring vertex 2 */ void set_neighbor(triangle *n0ptr, triangle *n1ptr, triangle *n2ptr); /** * @brief Test if the location is inside the triangle * * @param inx x coordinate of the input location * @param iny y coordinate of the input location * @return true the input location is inside the triangle * @return false the input location is not inside the triangle */ bool bound_location(double inx, double iny); /** * @brief Interpolate the elevation of the given location inside the triangle * * @param inx x coordinate of the input location * @param iny y coordinate of the input location * @return double the interpolated elevation at the input location */ double interpolate(double inx, double iny); }; // End triangle definition /** * @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 &dem, double xmin, double xmax, double ymin, double ymax, double dx, double dy, std::vector &out_verts, std::vector &out_tris, double maxi_err = 1e-0, std::vector *err_records = nullptr); /** * @brief Generate the TIN from random DEM points * * @param dem Input DEM points * @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] outline_poly If this pointer is not NULL, Cut triangle outside the polygon. * @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, std::vector &out_verts, std::vector &out_tris, double maxi_err = 1e-0, std::vector *outline_poly = nullptr, std::vector *err_records = nullptr); #endif // _TIN_DELAUNAY_H