Advertisement
Guest User

Untitled

a guest
Jun 9th, 2020
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* The header file. */
  2.  
  3. // Given a set of points, defined by corresponding entries in x and y, compute the triangulation
  4. // for the points.
  5. // Returns a list of indices where each set of triples are the indices of a triangle.
  6. // You could change this to double instead of float if you like. All the important stuff in the inside is templated.
  7. void Triangulator(const std::vector<float>& x, const std::vector<float>& y, std::vector<int>* indices);
  8.  
  9.  
  10. /* The CC file. */
  11. #include <vector>
  12.  
  13. namespace {
  14.  
  15. template <typename T>
  16. struct Vector2 {
  17.   using Type = T;
  18.  
  19.   Vector2(const Vector2<T> &v) = default;
  20.   Vector2(Vector2<T>&&) = default;
  21.  
  22.   Vector2(T vx, T vy)
  23.     : x(vx), y(vy) {}
  24.  
  25.   T dist2(const Vector2<T> &v) const {
  26.     const T dx = x - v.x;
  27.     const T dy = y - v.y;
  28.     return dx * dx + dy * dy;
  29.   }
  30.  
  31.   T norm2() const { return x * x + y * y; }
  32.  
  33.   T x, y;
  34. };
  35.  
  36. struct IndexTriangle {
  37.   IndexTriangle(int a, int b, int c)
  38.     : a(a), b(b), c(c), bad(false) {}
  39.   int a, b, c;
  40.   bool bad;
  41. };
  42.  
  43. struct IndexEdge {
  44.   IndexEdge(int a, int b)
  45.     : a(a), b(b), bad(false) {}
  46.  
  47.   bool IsSame(const IndexEdge& e) {
  48.     return (e.a == a && e.b == b) || (e.a == b && e.b == a);
  49.   }
  50.  
  51.   int a, b;
  52.   bool bad;
  53. };
  54.  
  55. template<typename VertexType>
  56. std::vector<IndexTriangle> Triangulate(std::vector<VertexType> &vertices) {
  57.   using T = typename VertexType::Type;
  58.   // Determine the super triangle.
  59.   auto CompareX = [](const VertexType& a, const VertexType& b) { return a.x < b.x; };
  60.   auto CompareY = [](const VertexType& a, const VertexType& b) { return a.y < b.y; };
  61.   T minX = std::min_element(vertices.begin(), vertices.end(), CompareX)->x;
  62.   T minY = std::min_element(vertices.begin(), vertices.end(), CompareY)->y;
  63.   T maxX = std::max_element(vertices.begin(), vertices.end(), CompareX)->x;
  64.   T maxY = std::max_element(vertices.begin(), vertices.end(), CompareY)->y;
  65.  
  66.   const T dx = maxX - minX;
  67.   const T dy = maxY - minY;
  68.   const T deltaMax = std::max(dx, dy);
  69.   const T midx = (minX + maxX) / 2;
  70.   const T midy = (minY + maxY) / 2;
  71.  
  72.   const VertexType p1(midx - 20 * deltaMax, midy - deltaMax);
  73.   const VertexType p2(midx, midy + 20 * deltaMax);
  74.   const VertexType p3(midx + 20 * deltaMax, midy - deltaMax);
  75.  
  76.   // Create a list of triangles, and add the super triangle in it.
  77.   std::vector<IndexTriangle> triangles = {IndexTriangle(-1, -2, -3)};
  78.  
  79.   const auto& Lookup = [&](int index) {
  80.     if (index >= 0) {
  81.       // The coordinates do not belong to the super triangle. This is the common case.
  82.       return vertices[index];
  83.     } else if (index == -1) {
  84.       return p1;
  85.     } else if (index == -2) {
  86.       return p2;
  87.     } else {
  88.       return p3;
  89.     }
  90.   };
  91.  
  92.   auto CircleContains = [&](const IndexTriangle& t, const VertexType &v) {
  93.     const VertexType& A = Lookup(t.a);
  94.     const VertexType& B = Lookup(t.b);
  95.     const VertexType& C = Lookup(t.c);
  96.     const T Asq = A.norm2();
  97.     const T Bsq = B.norm2();
  98.     const T Csq = C.norm2();
  99.     // https://en.wikipedia.org/wiki/Circumscribed_circle#Circumcenter_coordinates
  100.     const T circum_x = (Asq * (C.y - B.y) + Bsq * (A.y - C.y) + Csq * (B.y - A.y)) /
  101.                    2 / (A.x * (C.y - B.y) + B.x * (A.y - C.y) + C.x * (B.y - A.y));
  102.     const T circum_y = (Asq * (C.x - B.x) + Bsq * (A.x - C.x) + Csq * (B.x - A.x)) /
  103.                    2 / (A.y * (C.x - B.x) + B.y * (A.x - C.x) + C.y * (B.x - A.x));
  104.  
  105.     const VertexType circum(circum_x, circum_y);
  106.     // Test if v is closer to the center of the circle than A (which is on the radius).
  107.     return v.dist2(circum) <= A.dist2(circum);
  108.   };
  109.  
  110.   for (int vertex_index = 0; vertex_index < vertices.size(); ++vertex_index) {
  111.     std::vector<IndexEdge> polygon;
  112.     for (IndexTriangle& t : triangles) {
  113.       if (CircleContains(t, vertices[vertex_index])) {
  114.         t.bad = true;
  115.         polygon.emplace_back(t.a, t.b);
  116.         polygon.emplace_back(t.b, t.c);
  117.         polygon.emplace_back(t.c, t.a);
  118.       }
  119.     }
  120.  
  121.     triangles.erase(std::remove_if(triangles.begin(), triangles.end(),
  122.                                    [](const IndexTriangle &t){ return t.bad; }), triangles.end());
  123.     // Remove duplicate edges.
  124.     for (auto e1 = polygon.begin(); e1 != polygon.end(); ++e1) {
  125.       for (auto e2 = e1 + 1; e2 != polygon.end(); ++e2) {
  126.         if(e1->IsSame(*e2)) {
  127.           e1->bad = true;
  128.           e2->bad = true;
  129.         }
  130.       }
  131.     }
  132.     polygon.erase(std::remove_if(
  133.         polygon.begin(), polygon.end(), [](const IndexEdge &e) { return e.bad; }), polygon.end());
  134.  
  135.     for (const IndexEdge& edge : polygon) {
  136.       triangles.emplace_back(edge.a, edge.b, vertex_index);
  137.     }
  138.   }
  139.   // Remove triangles that include the super triangle.
  140.   auto IncludesSuperTriangle = [](const IndexTriangle &t) { return t.a < 0 || t.b < 0 || t.c < 0; };
  141.   triangles.erase(std::remove_if(
  142.       triangles.begin(), triangles.end(), IncludesSuperTriangle), triangles.end());
  143.  
  144.   return triangles;
  145. }
  146.  
  147. }  // anonymous namespace
  148.  
  149. void Triangulator(const std::vector<float>& x,
  150.                   const std::vector<float>& y,
  151.                   std::vector<int>* indices) {
  152.   std::vector<Vector2<float>> points;
  153.   points.reserve(x.size());
  154.   for (int i = 0; i < x.size(); ++i) {
  155.     points.emplace_back(x[i], y[i]);
  156.   }
  157.  
  158.   std::vector<IndexTriangle> triangles = Triangulate(points);
  159.   indices->reserve(triangles.size() * 3);
  160.   // Vertices of triangle:
  161.   //   points[tri.a] (or x[tri.a], y[tri.b])
  162.   //   points[tri.a]
  163.   //   points[tri.b]
  164.   // Edges of triangle:
  165.   //   points[tri.a] -- points[tri.b]
  166.   //   points[tri.a] -- points[tri.c]
  167.   //   points[tri.b] -- points[tri.c]
  168.   // Indices VBO are stored in indices.
  169.   // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
  170.   for (const auto& tri : triangles) {
  171.     indices->push_back(tri.a);
  172.     indices->push_back(tri.b);
  173.     indices->push_back(tri.c);
  174.   }
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement