polygon3d.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include "math/polygon3d.h"
  2. #include "math/math_utils.h"
  3. #include <algorithm>
  4. #include <sstream>
  5. using namespace decision::math;
  6. Polygon3d::Polygon3d(const std::vector<Vec3d>& points)
  7. : _points(points)
  8. {
  9. build_from_points();
  10. }
  11. Polygon2d Polygon3d::polygon2d() const
  12. {
  13. return Polygon2d(_points2d);
  14. }
  15. inline size_t Polygon3d::next(size_t at) const
  16. {
  17. return at >= _points.size() - 1 ? 0 : at + 1;
  18. }
  19. inline size_t Polygon3d::prev(size_t at) const
  20. {
  21. return at == 0 ? _points.size() - 1 : at - 1;
  22. }
  23. void Polygon3d::build_from_points()
  24. {
  25. auto num_points = _points.size();
  26. CHECK_GE(num_points, 3u);
  27. // remove duplicates
  28. std::vector<Vec3d> points_tmp(std::move(_points));
  29. _points.clear();
  30. _points2d.clear();
  31. for (size_t i = 0; i < num_points; ++i) {
  32. Vec3d vec3d(points_tmp[i].x(), points_tmp[i].y(), points_tmp[i].z());
  33. auto pos = std::find(_points.begin(), _points.end(), vec3d);
  34. if (pos == _points.end()) {
  35. _points2d.emplace_back(vec3d.x(), vec3d.y());
  36. _points.emplace_back(points_tmp[i]);
  37. }
  38. }
  39. num_points = _points.size();
  40. CHECK_GE(num_points, 3u);
  41. // Make sure the points are in ccw order.
  42. double area = 0.0;
  43. for (size_t i = 1; i < num_points; ++i) {
  44. area += cross_prod(_points2d[0], _points2d[i - 1], _points2d[i]);
  45. }
  46. if (area < 0) {
  47. area = -area;
  48. std::reverse(_points2d.begin(), _points2d.end());
  49. std::reverse(_points.begin(), _points.end());
  50. }
  51. CHECK_GT(area, kMathEpsilon);
  52. // Construct segments.
  53. _segments.reserve(num_points);
  54. for (size_t i = 0; i < num_points; ++i) {
  55. _segments.emplace_back(_points[i], _points[next(i)]);
  56. }
  57. }
  58. std::string Polygon3d::debug_string() const
  59. {
  60. std::ostringstream sout;
  61. sout << "polygon3d ( num_points = " << _points.size() << " points = (";
  62. for (const auto& pt : _points) {
  63. sout << " " << pt.debug_string();
  64. }
  65. sout.flush();
  66. return sout.str();
  67. }