From 01613d1977c232c156da0925e48fc15b21ba2c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 19 Apr 2022 22:14:52 +0200 Subject: [PATCH] Implement simple hole stencil to resolve holes in GDS polygons. --- .../poly2tri-wrapper/src/poly2tri-wrapper.cpp | 74 +++++++++++++++++++ preview-rendering/src/preview-rendering-gui.c | 41 ++++++++-- 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/preview-rendering/poly2tri-wrapper/src/poly2tri-wrapper.cpp b/preview-rendering/poly2tri-wrapper/src/poly2tri-wrapper.cpp index 506d284..1344fce 100644 --- a/preview-rendering/poly2tri-wrapper/src/poly2tri-wrapper.cpp +++ b/preview-rendering/poly2tri-wrapper/src/poly2tri-wrapper.cpp @@ -4,6 +4,74 @@ //#include #include +class Hole { +private: + std::vector hole_vertices; +public: + const std::vector &get_vertices() + { + return hole_vertices; + } + + void add_vertex(const p2t::Point &point) + { + auto pt = new p2t::Point(point); + hole_vertices.push_back(pt); + } + + Hole(std::vector::iterator start, std::vector::iterator end) + { + hole_vertices = std::vector(start, end); + } + +}; + + +static std::vector resolve_holes_in_polyline(std::vector &polyline) +{ + bool found = false; + std::vector holes; + std::vector::iterator, + std::vector::iterator> + > points_to_remove; + + for (auto start_it = polyline.begin(); start_it != polyline.end(); start_it++) { + for (auto check_it = std::next(start_it); check_it != polyline.end(); check_it++) { + /* Check if points are equal */ + if (**start_it == **check_it) { + if (**std::prev(check_it) == **std::next(start_it)) { + /* Found a hole. Everything between start_it and check_it can be removed */ + auto hole = Hole(std::next(start_it)+1, check_it); + holes.push_back(hole); + auto tbd = std::make_pair(start_it, check_it); + points_to_remove.push_back(tbd); + found = true; + break; + } + } + } + if (found) + break; + } + + /* Remove form polyline */ + for (auto it_pair_it = points_to_remove.begin(); it_pair_it != points_to_remove.end(); it_pair_it++) { + auto it_pair = *it_pair_it; + delete *it_pair.first; + delete *std::next(it_pair.first); + polyline.erase(it_pair.first, it_pair.second); + } + + if (found) { + auto new_holes = resolve_holes_in_polyline(polyline); + holes.insert(holes.end(), new_holes.begin(), new_holes.end()); + } + + + return holes; +} + int tesselator_triangulate_polygon(const struct gds_graphics *gfx, double scale, float** output_vertices, size_t *vertex_count) { GList *vertex_iter; @@ -18,8 +86,14 @@ int tesselator_triangulate_polygon(const struct gds_graphics *gfx, double scale, polyline.push_back(pt); } + auto holes = resolve_holes_in_polyline(polyline); + auto my_cdt = p2t::CDT(polyline); + for (auto hole_it = holes.begin(); hole_it != holes.end(); hole_it++) { + my_cdt.AddHole((*hole_it).get_vertices()); + } + my_cdt.Triangulate(); auto triangles = my_cdt.GetTriangles(); diff --git a/preview-rendering/src/preview-rendering-gui.c b/preview-rendering/src/preview-rendering-gui.c index 489bf59..c602fa2 100644 --- a/preview-rendering/src/preview-rendering-gui.c +++ b/preview-rendering/src/preview-rendering-gui.c @@ -8,6 +8,7 @@ struct _OpenGlPreviewGui { GtkGLArea *gl_area; unsigned int polygon_shader_prog; unsigned int vao; + unsigned int vao_vertex_count; unsigned int vbo; float color[4]; gboolean line; @@ -54,7 +55,7 @@ static gboolean gl_area_render(GtkGLArea *area, GdkGLContext *context, gpointer glBindVertexArray(gui->vao); loc = glGetUniformLocation(gui->polygon_shader_prog, "const_color"); glUniform4fv(loc, 1, gui->color); - glDrawArrays(GL_TRIANGLES, 0, 10*3); + glDrawArrays(GL_TRIANGLES, 0, gui->vao_vertex_count); glFlush(); @@ -94,7 +95,7 @@ static gboolean gl_area_realize(GtkGLArea *area, gpointer user) OpenGlPreviewGui *gui; int success; struct gds_graphics gfx; - struct gds_point points[12]; + struct gds_point points[20]; size_t vertex_count; gui = GDS_RENDER_OPENGL_PREVIEW_GUI(user); @@ -158,28 +159,54 @@ static gboolean gl_area_realize(GtkGLArea *area, gpointer user) points[7].x = 20; points[7].y = 20; - points[8].x = 1; + points[8].x = 0; points[8].y = 20; - points[9].x = 1; + points[9].x = 0; points[9].y = 100; points[10].x = 100; points[10].y = 100; + points[11].x = 100; - points[11].y = -100; + points[11].y = 5; + + points[12].x = 60; + points[12].y = 5; + + points[13].x = 60; + points[13].y = 20; + + points[14].x = 50; + points[14].y = 20; + + points[15].x = 50; + points[15].y = 0; + + points[16].x = 60; + points[16].y = 0; + + points[17].x = 60; + points[17].y = 5; + + points[18].x = 100; + points[18].y = 5; + + + points[19].x = 100; + points[19].y = -100; gfx.gfx_type = GRAPHIC_POLYGON; - for (int i = 0; i < 12; i++) { + for (int i = 0; i < 20; i++) { gfx.vertices = g_list_append(gfx.vertices, &points[i]); } float *vertices = NULL; tesselator_triangulate_polygon(&gfx, 180.0, &vertices, &vertex_count); - + gui->vao_vertex_count = vertex_count; glGenVertexArrays(1, &vao); glBindVertexArray(vao);