libtin/src/lib/tin.h
2021-10-14 22:17:02 +08:00

220 lines
7.2 KiB
C++

/**
* ___________ __
* /_ __/ _/ | / /
* / / / // |/ /
* / / _/ // /| /
* /_/ /___/_/ |_/
*
* 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<dem_point*> 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<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);
/**
* @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_point> &dem, std::vector<vertex2dc*> &out_verts,
std::vector<triangle*> &out_tris, double maxi_err = 1e-0, std::vector<dem_point> *outline_poly = nullptr,
std::vector<double> *err_records = nullptr);
#endif // _TIN_DELAUNAY_H