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