From 15a15ae2502784e32ff5d043b4713c967c5be701 Mon Sep 17 00:00:00 2001
From: bobarna <barnabas.borcsok@gmail.com>
Date: Sat, 4 Apr 2020 16:39:41 +0200
Subject: [PATCH] first iteration (not working) ear cutting

---
 sirius.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 101 insertions(+), 24 deletions(-)

diff --git a/sirius.cpp b/sirius.cpp
index 516c815..9ea5f62 100644
--- a/sirius.cpp
+++ b/sirius.cpp
@@ -121,12 +121,9 @@ public:
 };
 
 class BaseCircle : public Drawable {
-  BaseCircle() = default;
 
 public:
-  static BaseCircle generate() {
-    BaseCircle baseCircle;
-    std::vector<vec2> &vertices = baseCircle.vertices;
+  BaseCircle() {
     // calculate all the vertices of the base circle:
     float step = 360.0 / BASE_CIRCLE_SEGMENTS;
     float currAngle = 0;
@@ -144,11 +141,10 @@ public:
       currAngle += step;
       vertices.emplace_back(cos(degToRad(currAngle)), sin(degToRad(currAngle)));
     }
-
-    return baseCircle;
   }
 
   void draw() override {
+    init();
     glBindVertexArray(vao); // Draw call
     glDrawArrays(GL_TRIANGLES, 0, vertices.size());
   }
@@ -198,20 +194,95 @@ public:
     printf("%f %f\n", cx, cy);
     c = vec2(cx, cy);
     r = sqrtf((c.x - p1.x) * (c.x - p1.x) + (c.y - p1.y) * (c.y - p1.y));
+  }
 
-//    init();
+};
 
+inline float lengthv2(vec2 v) {
+  return sqrt(v.x * v.x + v.y * v.y);
+}
+
+inline float crossv2(vec2 a, vec2 b) {
+  return a.x * b.y - a.y * b.x;
+}
+
+inline bool intersectEachOther(vec2 p1, vec2 p2, vec2 q1, vec2 q2) {
+  return
+    lengthv2(crossv2(q1 - q2, p1 - q1)) * lengthv2(crossv2(q1 - q2, p2 - q1)) < 0 &&
+    lengthv2(crossv2(q1 - q2, p1 - q1)) * lengthv2(crossv2(q1 - q2, p2 - q1)) < 0;
+}
+
+class Triangulated : public Drawable {
+  std::vector<vec2> remainingVertices;
+
+public:
+  explicit Triangulated(std::vector<vec2> points) {
+    remainingVertices = points;
+    vertices.reserve(remainingVertices.size() * 3);
+    triangulate();
+  };
+
+  void triangulate() {
+    while (!remainingVertices.empty()) {
+      //finding an ear
+      auto currVertex = remainingVertices.begin();
+      //check if current vertex is an ear
+      vec2 currPotDiag1 = *getNextVertex(currVertex);
+      vec2 currPotDiag2 = *getPreviousVertex(currVertex);
+
+      //check if current potential diagonal intersects any edges
+      // skipping edges that share a vertex with it
+
+      for (auto currEdgeStart = getPreviousVertex(getPreviousVertex(currVertex));
+           currEdgeStart != getNextVertex(getNextVertex(currVertex)); currEdgeStart = getPreviousVertex(currEdgeStart))
+        if (intersectEachOther(vec2(currEdgeStart->x, currEdgeStart->y),
+                               vec2(getNextVertex(currEdgeStart)->x, getNextVertex(currEdgeStart)->y),
+                               currPotDiag1, currPotDiag2))
+          break;
+
+      //check if current potential diagonal is fully outside the polygon
+      vec2 infinity(250, 250);
+      vec2 middle((currPotDiag1 + currPotDiag2)/2);
+      int numberOfIntersections = 0;
+      for(auto currEdgeStart = remainingVertices.begin(); currEdgeStart != remainingVertices.begin(); currEdgeStart = getPreviousVertex(currEdgeStart))
+        if(intersectEachOther(currEdgeStart->x, *getNextVertex(currEdgeStart), infinity, middle))
+          numberOfIntersections++;
+      if(numberOfIntersections%2 == 0)
+        break; // the potential diagonal is fully outside, it's not an ear.
+
+      //it's an ear!
+      vertices.emplace_back(*currVertex);
+      vertices.emplace_back(currPotDiag1);
+      vertices.emplace_back(currPotDiag2);
+
+      remainingVertices.erase(currVertex);
+    }
   }
 
-//  void draw() override {
-//    glBindVertexArray(vao); // Draw call
-//    setColor(vec3(1, 0, 0));
-//    glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
-//  }
+  std::vector<vec2>::iterator getPreviousVertex(std::vector<vec2>::iterator currVertex) {
+    if (currVertex == remainingVertices.begin())
+      return remainingVertices.end();
+    else
+      return --currVertex;
+  }
+
+  std::vector<vec2>::iterator getNextVertex(std::vector<vec2>::iterator currVertex) {
+    if (currVertex == remainingVertices.end())
+      return remainingVertices.begin();
+    else
+      return ++currVertex;
+  };
+
+  void draw() override {
+    init();
+    glBindVertexArray(vao); // Draw call
+    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
+  }
 };
 
 class SiriusTriangle : public Drawable {
   std::vector<Point> points;
+  std::vector<Triangulated> triangulated;
 
 public:
   int n = 0;
@@ -224,8 +295,11 @@ public:
     if (n > 3) printf("Can't add 4th point to a triangle!\n");
     printf("%d\n", n);
     if (n == 2) generateLineSegment(points[0], points[1]);
-    if (n == 3) generateLineSegment(points[2], points[0]);
-    if (n == 3) generateLineSegment(points[1], points[2]);
+    if (n == 3) {
+      generateLineSegment(points[2], points[0]);
+      generateLineSegment(points[1], points[2]);
+      triangulated.emplace_back(Triangulated(vertices));
+    }
 
   }
 
@@ -270,16 +344,22 @@ public:
   }
 
   void draw() override {
-    for (auto &point: points)
-      point.draw();
+    //filling out the triangulated area
+    if(n == 3)
+      triangulated[0].draw();
+
 
     //Time to draw the edges
     if (n == 3) {
       init();
       glBindVertexArray(vao); // Draw call
-      setColor(vec3(1, 0, 0));
+      setColor(vec3(0.6, 0.2, 0.6));
       glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
     }
+
+
+    for (auto &point: points)
+      point.draw();
   }
 };
 
@@ -305,7 +385,7 @@ public:
   }
 };
 
-BaseCircle baseCircle = BaseCircle::generate();
+BaseCircle baseCircle = BaseCircle();
 SiriusTriangleManager siriusTriangleManager = SiriusTriangleManager();
 
 // Initialization, create an OpenGL context
@@ -314,7 +394,7 @@ void onInitialization() {
 
   baseCircle.init();
   siriusTriangleManager.addPoint(vec2(-0.6, 0.4));
-  siriusTriangleManager.addPoint(vec2(-0.8, 0.2));
+  siriusTriangleManager.addPoint(vec2(-0.8, -0.2));
   siriusTriangleManager.addPoint(vec2(-0.2, -0.6));
 
   // create program for the GPU
@@ -383,11 +463,6 @@ void onMouse(int button, int state, int pX,
       break;
   }
 
-//    siriusTriangleManager.addPoint(vec2(-.8f, -.4f));
-//    siriusTriangleManager.addPoint(vec2(-.2f, -.6f));
-//    siriusTriangleManager.addPoint(vec2(-.4f, .4f));
-//    siriusTriangleManager.draw();
-
   if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
     siriusTriangleManager.addPoint(vec2(cX, cY));
     siriusTriangleManager.draw();
@@ -399,3 +474,5 @@ void onMouse(int button, int state, int pX,
 void onIdle() {
   long time = glutGet(GLUT_ELAPSED_TIME); // elapsed time since the start of the program
 }
+
+#include <utility>
-- 
GitLab