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

147 lines
3.5 KiB

  1. #pragma once
  2. #ifdef DELAUNATOR_HEADER_ONLY
  3. #define INLINE inline
  4. #else
  5. #define INLINE
  6. #endif
  7. #include <limits>
  8. #include <vector>
  9. #include <ostream>
  10. namespace delaunator {
  11. constexpr std::size_t INVALID_INDEX =
  12. (std::numeric_limits<std::size_t>::max)();
  13. class Point
  14. {
  15. public:
  16. Point(double x, double y) : m_x(x), m_y(y)
  17. {}
  18. Point() : m_x(0), m_y(0)
  19. {}
  20. double x() const
  21. { return m_x; }
  22. double y() const
  23. { return m_y; }
  24. double magnitude2() const
  25. { return m_x * m_x + m_y * m_y; }
  26. static double determinant(const Point& p1, const Point& p2)
  27. {
  28. return p1.m_x * p2.m_y - p1.m_y * p2.m_x;
  29. }
  30. static Point vector(const Point& p1, const Point& p2)
  31. {
  32. return Point(p2.m_x - p1.m_x, p2.m_y - p1.m_y);
  33. }
  34. static double dist2(const Point& p1, const Point& p2)
  35. {
  36. Point vec = vector(p1, p2);
  37. return vec.m_x * vec.m_x + vec.m_y * vec.m_y;
  38. }
  39. static bool equal(const Point& p1, const Point& p2, double span)
  40. {
  41. double dist = dist2(p1, p2) / span;
  42. // ABELL - This number should be examined to figure how how
  43. // it correlates with the breakdown of calculating determinants.
  44. return dist < 1e-20;
  45. }
  46. private:
  47. double m_x;
  48. double m_y;
  49. };
  50. inline std::ostream& operator<<(std::ostream& out, const Point& p)
  51. {
  52. out << p.x() << "/" << p.y();
  53. return out;
  54. }
  55. class Points
  56. {
  57. public:
  58. using const_iterator = Point const *;
  59. Points(const std::vector<double>& coords) : m_coords(coords)
  60. {}
  61. const Point& operator[](size_t offset)
  62. {
  63. return reinterpret_cast<const Point&>(
  64. *(m_coords.data() + (offset * 2)));
  65. };
  66. Points::const_iterator begin() const
  67. { return reinterpret_cast<const Point *>(m_coords.data()); }
  68. Points::const_iterator end() const
  69. { return reinterpret_cast<const Point *>(
  70. m_coords.data() + m_coords.size()); }
  71. size_t size() const
  72. { return m_coords.size() / 2; }
  73. private:
  74. const std::vector<double>& m_coords;
  75. };
  76. class Delaunator {
  77. public:
  78. std::vector<double> const& coords;
  79. Points m_points;
  80. // 'triangles' stores the indices to the 'X's of the input
  81. // 'coords'.
  82. std::vector<std::size_t> triangles;
  83. // 'halfedges' store indices into 'triangles'. If halfedges[X] = Y,
  84. // It says that there's an edge from X to Y where a) X and Y are
  85. // both indices into triangles and b) X and Y are indices into different
  86. // triangles in the array. This allows you to get from a triangle to
  87. // its adjacent triangle. If the a triangle edge has no adjacent triangle,
  88. // its half edge will be INVALID_INDEX.
  89. std::vector<std::size_t> halfedges;
  90. std::vector<std::size_t> hull_prev;
  91. std::vector<std::size_t> hull_next;
  92. // This contains indexes into the triangles array.
  93. std::vector<std::size_t> hull_tri;
  94. std::size_t hull_start;
  95. INLINE Delaunator(std::vector<double> const& in_coords);
  96. INLINE double get_hull_area();
  97. INLINE double get_triangle_area();
  98. private:
  99. std::vector<std::size_t> m_hash;
  100. Point m_center;
  101. std::size_t m_hash_size;
  102. std::vector<std::size_t> m_edge_stack;
  103. INLINE std::size_t legalize(std::size_t a);
  104. INLINE std::size_t hash_key(double x, double y) const;
  105. INLINE std::size_t add_triangle(
  106. std::size_t i0,
  107. std::size_t i1,
  108. std::size_t i2,
  109. std::size_t a,
  110. std::size_t b,
  111. std::size_t c);
  112. INLINE void link(std::size_t a, std::size_t b);
  113. };
  114. } //namespace delaunator
  115. #undef INLINE