/**
******************************************************************************
* @file : studio_geo_algo_c.h
* @author : wangyingjie
* @brief : C 语言版几何算法库,包含常用的空间计算、线段抽稀、去除离群点等几何操作算法。
* 提供多种几何计算函数,如计算点之间的距离、方位角、点到线段的最短距离、以及线段的抽稀处理(Douglas-Peucker算法等)。
* 适用于笛卡尔坐标系和大地坐标系(经纬度)的应用场景。
* @attention : None
* @date : 2025/5/11
******************************************************************************
*/
#ifndef STUDIO_GEO_ALGO_C_H
#define STUDIO_GEO_ALGO_C_H
#include "studio_geo_c.h"
/////////////////// 基础适量算法 ///////////////////
/// 计算两点之间的距离的平方 (笛卡尔坐标系)
/// @param p1
/// @param p2
/// @return
double distance_squared_c(const studio_point_c *p1, const studio_point_c *p2);
/// 计算点到线段的距离的平方 (笛卡尔坐标系)
/// \param p 点
/// \param start 线段起点
/// \param end 线段终点
/// \return 距离的平方 (单位 米)
double point_line_dist_square_c(const studio_point_c *p, const studio_point_c *start, const studio_point_c *end);
/// 计算两点之间的方位角 (笛卡尔坐标系)
/// 方位角是从点 p_from 指向点 p_to 的向量与正北方向的顺时针夹角,单位为度
/// @param p_from
/// @param p_to
/// @return
double azimuth_angle_c(const studio_point_c *p_from, const studio_point_c *p_to);
/// 计算两个经纬度之间的距离的平方 (大地坐标系)
/// @param p1
/// @param p2
/// @return 距离的平方 (单位 米)
double distance_squared_gcs_c(const studio_point_c *p1, const studio_point_c *p2);
/// 计算经纬度点到经纬度线的距离的平方 (大地坐标系)
/// \param p 点
/// \param start 线段起点
/// \param end 线段终点
/// \return 距离的平方 (单位 米)
double point_line_dist_square_gcs_c(const studio_point_c *p, const studio_point_c *start, const studio_point_c *end);
/// 计算两点之间的方位角 (大地坐标系)
/// 方位角是从点 p_from 指向点 p_to 的向量与正北方向的顺时针夹角,单位为度
/// @param p_from
/// @param p_to
/// @return
double azimuth_angle_gcs_c(const studio_point_c *p_from, const studio_point_c *p_to);
///
/// 计算经纬度点移动一定距离后的新点
///
///
/// X方向移动距离,单位为米
/// Y方向移动距离,单位为米
///
studio_point_c lonlat_move_by(const studio_point_c *pt, double delta_x, double delta_y);
/////////////////// 矢量(线)抽稀算法 ///////////////////
/// Douglas-Peucker算法,线段压缩
/// \param points 线段
/// \param start 线段起点索引
/// \param end 线段终点索引
/// \param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon,则保留该点,单位与适量坐标系的单位一致
/// \param indices 存储简化后的点索引
/// \param index_count 存储简化后的点索引数量
void douglas_peucker_c(const studio_line_c *points, size_t start, size_t end, double epsilon, unsigned int *indices, unsigned int *index_count);
/// 矢量线段抽稀算法
/// \param line 原始线段
/// \param max_points 压缩后最大点
/// \param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon,则保留该点,单位与适量坐标系的单位一致
/// \param vacuate_line 抽稀后的线段
/// \return
bool line_vacuate_c(const studio_line_c *line, const int max_points, const double epsilon, studio_line_c *vacuate_line);
/// 矢量线段抽稀算法 大地坐标系(GCS), 坐标点为十进制经纬度
/// @param line 原始线段
/// @param max_points 压缩后最大点
/// @param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon,这里单位是米
/// @param vacuate_line 抽稀后的线段
/// @return
bool line_vacuate_gcs_c(const studio_line_c *line, const int max_points, const double epsilon, studio_line_c *vacuate_line);
/////////////////// 移除线段中的离群点 ///////////////////
/// 计算哈希值
/// \param value
/// \param size
/// \return
unsigned int hash(unsigned int value, unsigned int size);
/// 移除重复点 保持原有顺序
/// \param indices 点索引
/// \param size 点索引数量
void remove_duplicates(unsigned int **indices, unsigned int *size);
/// 移除线段中的离群点
/// @param line 原始线段
/// @param distance 离群点距离
/// @param outliers_line 滤波后的线段
/// @return
bool remove_outliers_c(const studio_line_c *line, double distance, studio_line_c *outliers_line);
#endif // STUDIO_GEO_ALGO_C_H