Path_JC.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. double R_EN = 6371000.0;
  13. /**
  14. * 交换函数(自用)
  15. */
  16. void swap(double *a, double *b) {
  17. float temp = *a;
  18. *a = *b;
  19. *b = temp;
  20. }
  21. /**
  22. * 角转弧
  23. */
  24. double deg2rad(double deg) {
  25. return deg * PI / 180.0;
  26. }
  27. /**
  28. * 累计距离
  29. */
  30. void cumdist(studio_line_c *line, float *s, unsigned int size){
  31. for (int i = 1; i < size; i++) {
  32. float dx = line->data[i].x - line->data[i+1].x;
  33. float dy = line->data[i].y - line->data[i+1].y;
  34. s[i] = s[i - 1] + sqrtf(dx * dx + dy * dy);
  35. }
  36. }
  37. /**
  38. * 转笛卡尔(弧度简易版)
  39. */
  40. void deg2Des(studio_line_c *line, unsigned int size)
  41. {
  42. // 计算差值
  43. studio_point_c p_0 = studio_line_c_get_point(line,0);
  44. for (int i = 0; i < size; i++)
  45. {
  46. studio_point_c tmp;
  47. studio_point_c p_i = studio_line_c_get_point(line,i);
  48. tmp.x = p_i.x - p_0.x;
  49. tmp.y = p_i.y - p_0.y;
  50. studio_line_c_set_point(line, i, tmp);
  51. }
  52. // 转化成m
  53. for (int i = 0; i < size; i++)
  54. {
  55. studio_point_c tmp;
  56. studio_point_c p_i = studio_line_c_get_point(line,i);
  57. tmp.x = p_i.x * (PI / 180.0) * R_EN * cos(deg2rad(tmp.y));
  58. tmp.y = p_i.y * (PI / 180.0) * R_EN;
  59. studio_line_c_set_point(line, i, tmp);
  60. }
  61. }
  62. /**
  63. * 中值滤波
  64. */
  65. void median_filter_2d(studio_line_c *input, studio_line_c *output, unsigned int size, int window_size)
  66. {
  67. int half = window_size / 2;
  68. studio_point_c window[window_size];
  69. for (int i = 0; i < size; i++)
  70. {
  71. int k = 0;
  72. for (int j = i - half; j <= i + half; j++)
  73. {
  74. int idn = j;
  75. // 边界处理:复制边界值
  76. if (idn < 0) idn = 0;
  77. if (idn >= size) idn = size - 1;
  78. window[k++] = input->data[idn];
  79. }
  80. //排序(冒泡)
  81. for(int i = 0; i < window_size - 1; i++)
  82. {
  83. for(int j = 0; j < window_size - 1 - i; j++)
  84. {
  85. if(window[j].x > window[j + 1].x)
  86. {
  87. swap(&window[j].x, &window[j + 1].x);
  88. }
  89. if(window[j].y > window[j + 1].y)
  90. {
  91. swap(&window[j].y, &window[j + 1].y);
  92. }
  93. }
  94. }
  95. studio_line_c_add_point(output, window[window_size / 2]);
  96. }
  97. }
  98. /**
  99. * 残差滤波--计算量偏大
  100. */
  101. void var_filter(studio_line_c *in_before, studio_line_c *in_after, unsigned int size, float threshold)
  102. {
  103. // 残差
  104. for (int i = 0; i < size; i++) {
  105. in_after->data[i].x = in_before->data[i].x - in_after->data[i].x;
  106. in_after->data[i].y = in_before->data[i].y - in_after->data[i].y;
  107. }
  108. // 方差--可优化存储
  109. float mean_rx = 0, mean_ry = 0;
  110. for (int i = 0; i < size; i++) {
  111. mean_rx += in_after->data[i].x;
  112. mean_ry += in_after->data[i].y;
  113. }
  114. mean_rx /= size;
  115. mean_ry /= size;
  116. float std_rx = 0, std_ry = 0;
  117. for (int i = 0; i < size; i++) {
  118. std_rx += pow(in_after->data[i].x - mean_rx, 2);
  119. std_ry += pow(in_after->data[i].y - mean_ry, 2);
  120. }
  121. std_rx = sqrt(std_rx / size);
  122. std_ry = sqrt(std_ry / size);
  123. // 阈值判断
  124. bool outliers[size];
  125. for (int i = 0; i < size; i++) {
  126. outliers[i] = (fabs(in_after->data[i].x) > threshold * std_rx) || (fabs(in_after->data[i].y) > threshold * std_ry);
  127. }
  128. int idx = 0;
  129. for (int i = 0; i < size; i++) {
  130. if (outliers[i]) {
  131. studio_line_c_remove_point(in_before, idx);
  132. idx++;
  133. }
  134. }
  135. }
  136. /**
  137. * 样条插样
  138. */
  139. void spline_interpolation(float *s, studio_line_c *line, unsigned int size, studio_line_c *tmp, int set_outs) {
  140. // 输入检查
  141. if (size < 2 ) {
  142. printf("erro...SPLINE");
  143. return;
  144. }
  145. // 步长
  146. float step = (s[size - 1] - s[0]) / (set_outs - 1);
  147. // 计算插值
  148. int idx = 0;
  149. for (int i = 0; i < set_outs; i++) {
  150. float tar = s[0] + i * step;
  151. // 检索区间
  152. while (idx < size - 1 && s[idx + 1] < tar) {
  153. idx++;
  154. }
  155. // 边界检查
  156. if (tar <= s[0]) {
  157. tmp->data[i].x = line->data[0].x;
  158. tmp->data[i].y = line->data[0].y;
  159. } else if (tar >= s[size - 1]) {
  160. tmp->data[i].x = line->data[size - 1].x;
  161. tmp->data[i].y = line->data[size - 1].y;
  162. } else {
  163. // 插值计算
  164. if (fabs(s[idx + 1] - s[idx]) < 1e-10) {
  165. tmp->data[i].x = (line->data[idx].x + line->data[idx+1].x) / 2.0;
  166. tmp->data[i].y = (line->data[idx].y + line->data[idx+1].y) / 2.0; // 取平均值
  167. } else {
  168. 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]);
  169. 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]);
  170. }
  171. }
  172. }
  173. }