You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

douglas.cpp 3.7 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /****************************************************************************
  2. * Copyright (C) 2020 by Simulation Team, NavInfo Ltd. *
  3. * *
  4. * This file is part of Simulation Core Software Stack. *
  5. * *
  6. * Simulation Core is a commerical autonomous driving simulation solution.*
  7. * *
  8. * You should have received a copy of the NavInfo EULA License along with *
  9. * the software. If not, please contact us, <simulation@navinfo.com>. *
  10. ****************************************************************************/
  11. #include <vector>
  12. #include "geo/private/math/douglas.h"
  13. #include "geo/private/math/distance.h"
  14. #include "geo/private/math/ns_geom_math.h"
  15. namespace ns
  16. {
  17. namespace geo
  18. {
  19. /**
  20. * @brief 道格拉斯-扑克算法,原始型点不动,指定点是否被抽希掉放在valid中
  21. *
  22. * @param points [in]
  23. * @param ptNum
  24. * @param threshold
  25. * @param valid [out ]大小和ptNum相等,false表示当前点被抽希掉,true表示为采样后的有效点
  26. * @return true
  27. * @return false
  28. */
  29. bool HadMath_douglasPeucker1(const PointD* points, uint32_t ptNum,
  30. double threshold, //
  31. std::vector<bool>& valid) //
  32. {
  33. if (points == NULL || ptNum <= 1 || threshold <= 0)
  34. return false;
  35. if (ptNum <= 2)
  36. {
  37. valid.insert(valid.begin(), ptNum, true);
  38. return true;
  39. }
  40. double dis = 0;
  41. PointD foot;
  42. uint32_t select = 1; // 初始值无用
  43. const PointD& start = points[0];
  44. const PointD& last = points[ptNum - 1];
  45. for (uint32_t i = 1; i < ptNum - 1; ++i)
  46. {
  47. double orthDis = pointSegmentDistance(points[i], start, last, foot);
  48. if (dis < orthDis)
  49. {
  50. select = i;
  51. dis = orthDis;
  52. }
  53. }
  54. if (dis < threshold)
  55. {
  56. valid.push_back(true);
  57. valid.insert(valid.begin() + 1, ptNum - 2, false);
  58. valid.push_back(true);
  59. }
  60. else // select一定在上面重新赋值
  61. {
  62. std::vector<bool> firstValid, secondValid;
  63. if (HadMath_douglasPeucker1(&start, select + 1, threshold, firstValid) &&
  64. HadMath_douglasPeucker1(&points[select], ptNum - select, threshold, secondValid))
  65. {
  66. valid.insert(valid.end(), firstValid.begin(), firstValid.end());
  67. valid.insert(valid.end(), secondValid.begin() + 1, secondValid.end());
  68. }
  69. }
  70. return true;
  71. }
  72. size_t douglasPeucker(PointD* points, size_t ptNum, double threshold, double zThreshold)
  73. {
  74. std::vector<bool> valid;
  75. HadMath_douglasPeucker1(points, static_cast<uint32_t>(ptNum), threshold, valid);
  76. // 过滤z值
  77. if (zThreshold < basic::DOUBLE_MAX)
  78. {
  79. int lastValidIndex = 0;
  80. for (size_t i = 1; i < valid.size(); i++)
  81. {
  82. if (valid[i])
  83. {
  84. lastValidIndex = static_cast<int>(i);
  85. }
  86. else if (valid[i] == false &&
  87. std::abs(points[i].z - points[lastValidIndex].z) >= zThreshold)
  88. {
  89. valid[i] = true;
  90. lastValidIndex = static_cast<int>(i);
  91. }
  92. }
  93. }
  94. // 滤出无效点,将剩下的点前置存储,并返回剩下的点的个数
  95. size_t num = 0;
  96. for (size_t i = 0; i < valid.size(); i++)
  97. {
  98. if (valid[i] == true)
  99. {
  100. points[num++] = points[i];
  101. }
  102. }
  103. return num;
  104. }
  105. } // namespace geo
  106. } // namespace ns