Path_JC.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /**
  2. ******************************************************************************
  3. * @file : 拟合算法及功能函数
  4. * @author : yall
  5. * @brief :
  6. * @attention : None
  7. * @date : 2025/6/18
  8. ******************************************************************************
  9. */
  10. #include "Path_JC.h"
  11. #include "studio_geo_c.h"
  12. /**
  13. * 交换函数(自用)
  14. */
  15. void swap(float *a, float *b) {
  16. float temp = *a;
  17. *a = *b;
  18. *b = temp;
  19. }
  20. /**
  21. * 角转弧
  22. */
  23. double deg2rad(double deg) {
  24. return deg * PI / 180.0;
  25. }
  26. /**
  27. * 累计距离
  28. */
  29. void cumdist(studio_line_c *line, float *s, unsigned int size){
  30. for (int i = 1; i < size; i++) {
  31. float dx = line->data[i].x - line->data[i+1].x;
  32. float dy = line->data[i].y - line->data[i+1].y;
  33. s[i] = s[i - 1] + sqrtf(dx * dx + dy * dy);
  34. }
  35. }
  36. /**
  37. * 转笛卡尔(弧度简易版)
  38. */
  39. void deg2Des(studio_line_c *line, unsigned int size)
  40. {
  41. // 计算差值
  42. studio_point_c p_0 = studio_line_c_get_point(line,0);
  43. for (int i = 0; i < size; i++)
  44. {
  45. studio_point_c tmp;
  46. studio_point_c p_i = studio_line_c_get_point(line,i);
  47. tmp.x = p_i.x - p_0.x;
  48. tmp.y = p_i.y - p_0.y;
  49. studio_line_c_set_point(line, i, tmp);
  50. }
  51. // 转化成m
  52. for (int i = 0; i < size; i++)
  53. {
  54. studio_point_c tmp;
  55. studio_point_c p_i = studio_line_c_get_point(line,i);
  56. tmp.x = p_i.x * (PI / 180.0) * R_EN * cos(deg2rad(tmp.y));
  57. tmp.y = p_i.y * (PI / 180.0) * R_EN;
  58. studio_line_c_set_point(line, i, tmp);
  59. }
  60. }
  61. /**
  62. * 中值滤波
  63. */
  64. void median_filter_2d(studio_line_c *input, studio_line_c *output, unsigned int size, int window_size)
  65. {
  66. int half = window_size / 2;
  67. studio_point_c window[window_size];
  68. for (int i = 0; i < size; i++)
  69. {
  70. int k = 0;
  71. for (int j = i - half; j <= i + half; j++)
  72. {
  73. int idn = j;
  74. // 边界处理:复制边界值
  75. if (idn < 0) idn = 0;
  76. if (idn >= size) idn = size - 1;
  77. window[k++] = input->data[idn];
  78. }
  79. //排序(冒泡)
  80. for(int i = 0; i < window_size - 1; i++)
  81. {
  82. for(int j = 0; j < window_size - 1 - i; j++)
  83. {
  84. if(window[j].x > window[j + 1].x)
  85. {
  86. swap(&window[j].x, &window[j + 1].x);
  87. }
  88. if(window[j].y > window[j + 1].y)
  89. {
  90. swap(&window[j].y, &window[j + 1].y);
  91. }
  92. }
  93. }
  94. studio_line_c_add_point(output, window[window_size / 2]);
  95. }
  96. }
  97. /**
  98. * 残差滤波--计算量偏大
  99. */
  100. void var_filter(studio_line_c *in_before, studio_line_c *in_after, unsigned int size, float threshold)
  101. {
  102. // 残差
  103. for (int i = 0; i < size; i++) {
  104. in_after->data[i].x = in_before->data[i].x - in_after->data[i].x;
  105. in_after->data[i].y = in_before->data[i].y - in_after->data[i].y;
  106. }
  107. // 方差--可优化存储
  108. float mean_rx = 0, mean_ry = 0;
  109. for (int i = 0; i < size; i++) {
  110. mean_rx += in_after->data[i].x;
  111. mean_ry += in_after->data[i].y;
  112. }
  113. mean_rx /= size;
  114. mean_ry /= size;
  115. float std_rx = 0, std_ry = 0;
  116. for (int i = 0; i < size; i++) {
  117. std_rx += pow(in_after->data[i].x - mean_rx, 2);
  118. std_ry += pow(in_after->data[i].y - mean_ry, 2);
  119. }
  120. std_rx = sqrt(std_rx / size);
  121. std_ry = sqrt(std_ry / size);
  122. // 阈值判断
  123. bool outliers[size];
  124. for (int i = 0; i < size; i++) {
  125. outliers[i] = (fabs(in_after->data[i].x) > threshold * std_rx) || (fabs(in_after->data[i].y) > threshold * std_ry);
  126. }
  127. int idx = 0;
  128. for (int i = 0; i < size; i++) {
  129. if (outliers[i]) {
  130. studio_line_c_remove_point(in_before, idx);
  131. idx++;
  132. }
  133. }
  134. }
  135. /**
  136. * 样条插样
  137. */
  138. void spline_interpolation(float *s, studio_line_c *line, unsigned int size, studio_line_c *tmp, int set_outs) {
  139. // 输入检查
  140. if (size < 2 ) {
  141. printf("erro...SPLINE");
  142. return;
  143. }
  144. // 步长
  145. float step = (s[size - 1] - s[0]) / (set_outs - 1);
  146. // 计算插值
  147. int idx = 0;
  148. for (int i = 0; i < set_outs; i++) {
  149. float tar = s[0] + i * step;
  150. // 检索区间
  151. while (idx < size - 1 && s[idx + 1] < tar) {
  152. idx++;
  153. }
  154. // 边界检查
  155. if (tar <= s[0]) {
  156. tmp->data[i].x = line->data[0].x;
  157. tmp->data[i].y = line->data[0].y;
  158. } else if (tar >= s[size - 1]) {
  159. tmp->data[i].x = line->data[size - 1].x;
  160. tmp->data[i].y = line->data[size - 1].y;
  161. } else {
  162. // 插值计算
  163. if (fabs(s[idx + 1] - s[idx]) < 1e-10) {
  164. tmp->data[i].x = (line->data[idx].x + line->data[idx+1].x) / 2.0;
  165. tmp->data[i].y = (line->data[idx].y + line->data[idx+1].y) / 2.0; // 取平均值
  166. } else {
  167. tmp->data[i].x = line->data[idx].x + (line->data[idx+1].x - line->data[idx].x) * (tar - s[idx]) / (s[idx+1] + s[idx]);
  168. tmp->data[i].y = line->data[idx].y + (line->data[idx+1].y - line->data[idx].y) * (tar - s[idx]) / (s[idx+1] + s[idx]);
  169. }
  170. }
  171. }
  172. }
  173. /**
  174. 拟合过程
  175. struct ArrayWrapper Path_fit(double data[MAX_POINTS][2], int window_size)
  176. {
  177. // 实际数据点数
  178. int n = MAX_POINTS;
  179. // 提取经纬度数据
  180. double longitude[MAX_POINTS], latitude[MAX_POINTS];
  181. for (int i = 0; i < n; i++) {
  182. longitude[i] = data[i][0];
  183. latitude[i] = data[i][1];
  184. }
  185. // 计算与第一个点的经纬度差值
  186. double delta_lon[MAX_POINTS], delta_lat[MAX_POINTS];
  187. for (int i = 0; i < n; i++) {
  188. delta_lon[i] = longitude[i] - longitude[0];
  189. delta_lat[i] = latitude[i] - latitude[0];
  190. }
  191. // 转换为米单位坐标
  192. double delta_x[MAX_POINTS], delta_y[MAX_POINTS];
  193. for (int i = 0; i < n; i++) {
  194. delta_x[i] = delta_lon[i] * (PI / 180.0) * R_EN * cos(deg2rad(latitude[i]));
  195. delta_y[i] = delta_lat[i] * (PI / 180.0) * R_EN;
  196. }
  197. // 中值滤波
  198. double x_filtered[MAX_POINTS], y_filtered[MAX_POINTS];
  199. medfilt1(delta_x, x_filtered, n, window_size);
  200. medfilt1(delta_y, y_filtered, n, window_size);
  201. // 删除离群值
  202. double residual_x[MAX_POINTS], residual_y[MAX_POINTS];
  203. for (int i = 0; i < n; i++) {
  204. residual_x[i] = delta_x[i] - x_filtered[i];
  205. residual_y[i] = delta_y[i] - y_filtered[i];
  206. }
  207. double threshold_x = 0.1, threshold_y = 0.1; // 阈值
  208. int outliers[MAX_POINTS] = {0};
  209. for (int i = 0; i < n; i++) {
  210. if (fabs(residual_x[i]) > threshold_x || fabs(residual_y[i]) > threshold_y) {
  211. outliers[i] = 1;
  212. }
  213. }
  214. double x_cleaned[MAX_POINTS], y_cleaned[MAX_POINTS];
  215. int cleaned_count = 0;
  216. for (int i = 0; i < n; i++) {
  217. if (!outliers[i]) {
  218. x_cleaned[cleaned_count] = x_filtered[i];
  219. y_cleaned[cleaned_count] = y_filtered[i];
  220. cleaned_count++;
  221. }
  222. }
  223. // 参数化数据点:计算累积距离
  224. double dist[MAX_POINTS] = {0};
  225. for (int i = 1; i < cleaned_count; i++) {
  226. dist[i] = sqrt(pow(x_cleaned[i] - x_cleaned[i - 1], 2) + pow(y_cleaned[i] - y_cleaned[i - 1], 2));
  227. }
  228. double cumdist[MAX_POINTS] = {0};
  229. for (int i = 1; i < cleaned_count; i++) {
  230. cumdist[i] = cumdist[i - 1] + dist[i];
  231. }
  232. // 生成均匀分布的参数值
  233. int num_points = 10000;
  234. double t_uniform[num_points];
  235. for (int i = 0; i < num_points; i++) {
  236. t_uniform[i] = (cumdist[cleaned_count - 1] * i) / (num_points - 1);
  237. }
  238. // 样条插值拟合
  239. double x_fit[num_points], y_fit[num_points];
  240. spline_interpolation(cumdist, x_cleaned, cleaned_count, t_uniform, x_fit, num_points);
  241. spline_interpolation(cumdist, y_cleaned, cleaned_count, t_uniform, y_fit, num_points);
  242. // 均匀采样30个点
  243. int num_uniform = 30;
  244. double t_uniform_samples[num_uniform];
  245. for (int i = 0; i < num_uniform; i++) {
  246. t_uniform_samples[i] = (cumdist[cleaned_count - 1] * i) / (num_uniform - 1);
  247. }
  248. double x_uniform[num_uniform], y_uniform[num_uniform];
  249. spline_interpolation(cumdist, x_cleaned, cleaned_count, t_uniform_samples, x_uniform, num_uniform);
  250. spline_interpolation(cumdist, y_cleaned, cleaned_count, t_uniform_samples, y_uniform, num_uniform);
  251. struct ArrayWrapper xy;
  252. // 输出均匀采样的点
  253. for (int i = 0; i < num_uniform; i++) {
  254. xy.data_xy[i][0] = x_uniform[i];
  255. xy.data_xy[i][1] = y_uniform[i];
  256. }
  257. return xy;
  258. }
  259. */