From 3fe83c7ce03c69f6a4c0fe21d82df6c8cca41692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 31 Oct 2025 11:36:44 +0100 Subject: [PATCH 01/10] handle non-triangular faces --- .../CGAL/boost/graph/Euler_operations.h | 9 ++-- .../BGL/data/polygon_mesh_to_collapse.off | 42 +++++++++++++++++++ BGL/test/BGL/test_Collapse_edge.cpp | 21 +++++++++- 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 BGL/test/BGL/data/polygon_mesh_to_collapse.off diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index f8c79165bc5..f788ec18113 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1575,9 +1575,8 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, bool lBottomFaceExists = ! is_border(qp,g); bool lTopLeftFaceExists = lTopFaceExists && ! is_border(pt,g); bool lBottomRightFaceExists = lBottomFaceExists && ! is_border(qb,g); - - CGAL_precondition( !lTopFaceExists || (lTopFaceExists && ( degree(target(pt, g), g) > 2 ) ) ) ; - CGAL_precondition( !lBottomFaceExists || (lBottomFaceExists && ( degree(target(qb, g), g) > 2 ) ) ) ; + bool lBottomIsTriangle = lBottomFaceExists && next(next(qp, g), g) == prev(qp,g); + bool lTopIsTriangle = lTopFaceExists && next(next(pq, g), g) == prev(pq,g); vertex_descriptor q = target(pq, g); vertex_descriptor p = source(pq, g); @@ -1585,7 +1584,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, bool lP_Erased = false; - if ( lTopFaceExists ) + if ( lTopFaceExists && lTopIsTriangle) { CGAL_precondition( ! is_border(opposite(pt, g),g) ) ; // p-q-t is a face of the mesh if ( lTopLeftFaceExists ) @@ -1612,7 +1611,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, } } - if ( lBottomFaceExists ) + if ( lBottomFaceExists && lBottomIsTriangle) { CGAL_precondition( ! is_border(opposite(qb, g),g) ) ; // p-q-b is a face of the mesh if ( lBottomRightFaceExists ) diff --git a/BGL/test/BGL/data/polygon_mesh_to_collapse.off b/BGL/test/BGL/data/polygon_mesh_to_collapse.off new file mode 100644 index 00000000000..1a25e940585 --- /dev/null +++ b/BGL/test/BGL/data/polygon_mesh_to_collapse.off @@ -0,0 +1,42 @@ +OFF +25 13 0 + +0.39160239696502686 1.3864846229553223 4.8046874923102223e-08 +0.053782559931278229 1.3864846229553223 4.8046874923102223e-08 +-0.94644606113433838 1.6651756763458252 4.8046874923102223e-08 +-1.3082554340362549 1.7385153770446777 4.8046874923102223e-08 +-1.3033660650253296 1.1860226392745972 4.8046874923102223e-08 +1.61628258228302 -0.17601536214351654 4.8046874923102223e-08 +0.55834579467773438 -0.19216139614582062 4.8046874923102223e-08 +0.053782559931278229 -0.17601536214351654 4.8046874923102223e-08 +-0.24240998923778534 -0.22679123282432556 4.8046874923102223e-08 +-0.58168435096740723 -0.25845989584922791 4.8046874923102223e-08 +-1.2915089130401611 -0.17601536214351654 4.8046874923102223e-08 +-1.50871741771698 -0.17601536214351654 4.8046874923102223e-08 +1.61628258228302 -1.7385153770446777 4.8046874923102223e-08 +1.1978726387023926 -1.7385153770446777 4.8046874923102223e-08 +0.71942150592803955 -1.7385153770446777 4.8046874923102223e-08 +0.053782559931278229 -1.7385153770446777 4.8046874923102223e-08 +-0.73973840475082397 -1.7385153770446777 4.8046874923102223e-08 +1.61628258228302 0.36264327168464661 4.8046874923102223e-08 +-0.26156377792358398 0.45463424921035767 4.8046874923102223e-08 +-0.028661971911787987 -0.78840988874435425 4.8046874923102223e-08 +0.053782559931278229 -1.2213115692138672 4.8046874923102223e-08 +-1.5918357372283936 1.5331641435623169 4.8046874923102223e-08 +-1.6162823438644409 0.87338578701019287 4.8046874923102223e-08 +-1.50871741771698 -0.0072435899637639523 4.8046874923102223e-08 +-1.50871741771698 -1.3000825643539429 4.8046874923102223e-08 +7 18 2 3 4 22 9 8 +3 2 18 1 +7 18 7 6 5 17 0 1 +7 12 5 6 7 8 19 13 +6 11 24 16 15 20 10 +3 9 19 8 +4 10 20 19 9 +3 7 18 8 +3 14 20 15 +4 13 19 20 14 +3 3 21 4 +4 9 22 23 10 +3 10 23 11 + diff --git a/BGL/test/BGL/test_Collapse_edge.cpp b/BGL/test/BGL/test_Collapse_edge.cpp index 69f1c347a5e..ecbaff8fe36 100644 --- a/BGL/test/BGL/test_Collapse_edge.cpp +++ b/BGL/test/BGL/test_Collapse_edge.cpp @@ -2,7 +2,6 @@ #include #include - #include #include @@ -213,12 +212,30 @@ collapse_edge_test() assert(found == 2); CGAL::clear(test_mesh); } + // Case 6 non pure triangle mesh + { + Mesh ref; + if(!CGAL::IO::read_OFF("data/polygon_mesh_to_collapse.off", ref)) + { + std::cout << "Error reading file: data/polygon_mesh_to_collapse.off" << std::endl; + exit(1); + } + std::size_t nbe=halfedges(ref).size(); + for (std::size_t i=0; i< nbe; ++i) + { + Mesh m = ref; + auto h = *std::next(halfedges(m).begin(), i); + + if (CGAL::Euler::does_satisfy_link_condition(edge(h,m),m)) + CGAL::Euler::collapse_edge(edge(h,m), m); + assert(CGAL::is_valid_polygon_mesh(m)); + } + } } int main() { - collapse_edge_test(); collapse_edge_test(); From 25005a97d8c5aa6c0643ae7990c45273c009ef43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 3 Nov 2025 09:24:31 +0100 Subject: [PATCH 02/10] clean up --- BGL/include/CGAL/boost/graph/Euler_operations.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index f788ec18113..91d7f51fe80 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1575,8 +1575,8 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, bool lBottomFaceExists = ! is_border(qp,g); bool lTopLeftFaceExists = lTopFaceExists && ! is_border(pt,g); bool lBottomRightFaceExists = lBottomFaceExists && ! is_border(qb,g); - bool lBottomIsTriangle = lBottomFaceExists && next(next(qp, g), g) == prev(qp,g); - bool lTopIsTriangle = lTopFaceExists && next(next(pq, g), g) == prev(pq,g); + bool lBottomIsTriangle = lBottomFaceExists && is_triangle(qp,g); + bool lTopIsTriangle = lTopFaceExists && is_triangle(pq,g); vertex_descriptor q = target(pq, g); vertex_descriptor p = source(pq, g); @@ -1584,7 +1584,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, bool lP_Erased = false; - if ( lTopFaceExists && lTopIsTriangle) + if ( lTopIsTriangle) { CGAL_precondition( ! is_border(opposite(pt, g),g) ) ; // p-q-t is a face of the mesh if ( lTopLeftFaceExists ) @@ -1611,7 +1611,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, } } - if ( lBottomFaceExists && lBottomIsTriangle) + if ( lBottomIsTriangle) { CGAL_precondition( ! is_border(opposite(qb, g),g) ) ; // p-q-b is a face of the mesh if ( lBottomRightFaceExists ) From 3c7d507530243834914c6a448071f8b4692bce1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 6 Nov 2025 19:40:48 +0100 Subject: [PATCH 03/10] update doc + apply changes to the constrained version --- .../CGAL/boost/graph/Euler_operations.h | 69 +++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 91d7f51fe80..89b58ad0c2b 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1543,10 +1543,10 @@ does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor * * After the collapse of edge `e` the following holds: * - The edge `e` is no longer in `g`. - * - The faces incident to edge `e` are no longer in `g`. + * - The triangle faces incident to edge `e` are no longer in `g`. * - `v0` is no longer in `g`. - * - If `h` is not a border halfedge, `p_h` is no longer in `g` and is replaced by `o_n_h`. - * - If the opposite of `h` is not a border halfedge, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`. + * - If `h` is part of a triangle face, `p_h` is no longer in `g` and is replaced by `o_n_h`. + * - If the opposite of `h` is part of a triangle face, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`. * - The halfedges kept in `g` that had `v0` as target and source now have `v1` as target and source, respectively. * - No other incidence information is changed in `g`. * @@ -1658,7 +1658,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, * collapses an edge in a graph having non-collapsable edges. * * Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`. - * Collapses the edge `e` replacing it with `v1`, as described in the paragraph above + * Collapses the edge `e` replacing it with `v1`, as described in the other overload * and guarantees that an edge `e2`, for which `get(edge_is_constrained_map, e2)==true`, * is not removed after the collapse. * @@ -1668,14 +1668,14 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, * * \returns vertex `v1`. * \pre This function requires `g` to be an oriented 2-manifold with or without boundaries. - * Furthermore, the edge `v0v1` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse. - * \pre `get(edge_is_constrained_map, v0v1)==false`. + * Furthermore, the edge `e` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse. + * \pre `get(edge_is_constrained_map, e)==false`. * \pre `v0` and `v1` are not both incident to a constrained edge. */ template typename boost::graph_traits::vertex_descriptor -collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, +collapse_edge(typename boost::graph_traits::edge_descriptor e, Graph& g, EdgeIsConstrainedMap Edge_is_constrained_map) { @@ -1683,11 +1683,11 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, typedef typename Traits::vertex_descriptor vertex_descriptor; typedef typename Traits::halfedge_descriptor halfedge_descriptor; - CGAL_precondition(is_valid_edge_descriptor(v0v1, g)); - CGAL_precondition(does_satisfy_link_condition(v0v1,g)); - CGAL_precondition(!get(Edge_is_constrained_map, v0v1)); + CGAL_precondition(is_valid_edge_descriptor(e, g)); + CGAL_precondition(does_satisfy_link_condition(e,g)); + CGAL_precondition(!get(Edge_is_constrained_map, e)); - halfedge_descriptor pq = halfedge(v0v1,g); + halfedge_descriptor pq = halfedge(e,g); halfedge_descriptor qp = opposite(pq,g); halfedge_descriptor pt = opposite(prev(pq,g),g); @@ -1697,6 +1697,8 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, bool lTopFaceExists = ! is_border(pq,g) ; bool lBottomFaceExists = ! is_border(qp,g) ; + bool lTopIsTriangle = lTopFaceExists && is_triangle(pq,g); + bool lBottomIsTriangle = lBottomFaceExists && is_triangle(qp,g); vertex_descriptor q = target(pq,g); vertex_descriptor p = source(pq,g); @@ -1707,7 +1709,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, // If the top facet exists, we need to choose one out of the two edges which one disappears: // p-t if it is not constrained and t-q otherwise - if ( lTopFaceExists ) + if ( lTopIsTriangle ) { if ( !get(Edge_is_constrained_map,edge(pt,g)) ) { @@ -1721,7 +1723,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, // If the bottom facet exists, we need to choose one out of the two edges which one disappears: // q-b if it is not constrained and b-p otherwise - if ( lBottomFaceExists ) + if ( lBottomIsTriangle ) { if ( !get(Edge_is_constrained_map,edge(qb,g)) ) { @@ -1732,7 +1734,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, } } - if (lTopFaceExists && lBottomFaceExists) + if (lTopIsTriangle && lBottomIsTriangle) { if ( face(edges_to_erase[0],g) == face(edges_to_erase[1],g) && (! is_border(edges_to_erase[0],g)) ) @@ -1779,7 +1781,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, } else { - if (lTopFaceExists) + if (lTopIsTriangle) { if (!(is_border(edges_to_erase[0],g))){ join_face(edges_to_erase[0],g); @@ -1794,21 +1796,32 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, remove_face(opposite(edges_to_erase[0],g),g); return q; } - - if (! (is_border(edges_to_erase[0],g))){ - // q will be removed, swap it with p - internal::swap_vertices(p, q, g); - join_face(edges_to_erase[0],g); - join_vertex(qp,g); - return q; - } - if(!is_border(opposite(next(qp,g),g),g)) + else { - // q will be removed, swap it with p - internal::swap_vertices(p, q, g); + if (lBottomIsTriangle) + { + if (! (is_border(edges_to_erase[0],g))){ + // q will be removed, swap it with p + internal::swap_vertices(p, q, g); + join_face(edges_to_erase[0],g); + join_vertex(qp,g); + CGAL_assertion(source(qp,g)==p); + return q; + } + if(!is_border(opposite(next(qp,g),g),g)) + { + // q will be removed, swap it with p + internal::swap_vertices(p, q, g); + } + remove_face(opposite(edges_to_erase[0],g),g); + return q; + } + else + { + join_vertex(pq,g); + return q; + } } - remove_face(opposite(edges_to_erase[0],g),g); - return q; } } From 3ef43324bb5f27b66f4b979d9b75802c5d135377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 7 Nov 2025 17:05:21 +0100 Subject: [PATCH 04/10] Fix bad 'if' condition & warning --- Stream_support/test/Stream_support/issue8155.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Stream_support/test/Stream_support/issue8155.cpp b/Stream_support/test/Stream_support/issue8155.cpp index f92bf9cca84..342cfe5979c 100644 --- a/Stream_support/test/Stream_support/issue8155.cpp +++ b/Stream_support/test/Stream_support/issue8155.cpp @@ -23,12 +23,13 @@ int main() std::vector pv_pairs; const std::function lambda = [&](const PointVectorPair& p) { - FT len = p.second.squared_length(); - if (len > 0 || len != 1.0) { - Vector_3 n = p.second * (1.0 / CGAL::sqrt(len)); - pv_pairs.push_back(std::make_pair(p.first, n)); - } - else pv_pairs.push_back(p); + const FT len = CGAL::sqrt(p.second.squared_length()); + if (len > 0) { + Vector_3 n = p.second / len; + pv_pairs.push_back(std::make_pair(p.first, n)); + } else { + pv_pairs.push_back(p); + } }; pv_pairs.clear(); From 31734df2ef4baeac3ca1f15806fb0255e9e8ec7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 7 Nov 2025 17:16:31 +0100 Subject: [PATCH 05/10] Fix warning about discarding return type of function with [[nodiscard]] --- GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h b/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h index 5f8c85c1d7f..75816b4ff2a 100644 --- a/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h +++ b/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h @@ -221,7 +221,10 @@ void DemosMainWindow::popupAboutBox(QString title, QString html_resource_name) { QFile about_CGAL(html_resource_name); - about_CGAL.open(QIODevice::ReadOnly); + if (!about_CGAL.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Could not open resource file: %1").arg(html_resource_name)); + return; + } QString about_CGAL_txt = QTextStream(&about_CGAL).readAll(); #ifdef CGAL_VERSION_STR QString cgal_version(CGAL_VERSION_STR); From 066159f7924d59e16ccd8755e4749f026a895228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 10 Nov 2025 10:17:33 +0100 Subject: [PATCH 06/10] assertion should be before the removal... --- BGL/include/CGAL/boost/graph/Euler_operations.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 89b58ad0c2b..e33ae5a6910 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1804,8 +1804,8 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, // q will be removed, swap it with p internal::swap_vertices(p, q, g); join_face(edges_to_erase[0],g); - join_vertex(qp,g); CGAL_assertion(source(qp,g)==p); + join_vertex(qp,g); return q; } if(!is_border(opposite(next(qp,g),g),g)) From 097fc2c5ab72ed422c77e117f4f744e0fe6fd2f1 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 12 Nov 2025 16:48:29 +0100 Subject: [PATCH 07/10] fix memory leaks --- .../demo/Periodic_3_triangulation_3/Scene.cpp | 2 +- .../demo/Triangulation_3/CMakeLists.txt | 3 - .../demo/Triangulation_3/T3_demo.cpp | 3 + .../demo/Triangulation_3/Viewer.cpp | 20 +- Triangulation_3/demo/Triangulation_3/Viewer.h | 211 +++++++++--------- 5 files changed, 120 insertions(+), 119 deletions(-) diff --git a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp index 63209099a8d..d481e237678 100644 --- a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp +++ b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp @@ -1878,7 +1878,7 @@ void Scene::draw_sphere(float R, int prec) } } -void Scene::draw_cylinder(float R, int prec, std::vector *vertices, std::vector *normals) +void Scene::draw_cylinder(float R, int prec, std::unique_ptr>& vertices, std::unique_ptr>& normals) { vertices->resize(0); int rings=360/prec, sectors=360/prec; diff --git a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt index 2333c9a9ffc..b579a045676 100644 --- a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt @@ -63,9 +63,6 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND) include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake) cgal_add_compilation_test(T3_demo) - include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake) - cgal_add_compilation_test(T3_demo) - else(CGAL_Qt6_FOUND AND Qt6_FOUND) set(TRIANGULATION_3_MISSING_DEPS "") diff --git a/Triangulation_3/demo/Triangulation_3/T3_demo.cpp b/Triangulation_3/demo/Triangulation_3/T3_demo.cpp index aef465639ff..38b5c83168b 100644 --- a/Triangulation_3/demo/Triangulation_3/T3_demo.cpp +++ b/Triangulation_3/demo/Triangulation_3/T3_demo.cpp @@ -25,6 +25,9 @@ int main(int argc, char** argv) app.setOrganizationName("INRIA"); app.setApplicationName("3D Triangulation Demo"); + // Import resources from libCGALQt (Qt6). + CGAL_QT_INIT_RESOURCES; + MainWindow mw; mw.show(); diff --git a/Triangulation_3/demo/Triangulation_3/Viewer.cpp b/Triangulation_3/demo/Triangulation_3/Viewer.cpp index 12308b48517..30786c8d44a 100644 --- a/Triangulation_3/demo/Triangulation_3/Viewer.cpp +++ b/Triangulation_3/demo/Triangulation_3/Viewer.cpp @@ -183,13 +183,13 @@ void Viewer::compile_shaders() "} \n" "\n" }; - QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex); + QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex, this); if(!vertex_shader->compileSourceCode(vertex_source)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source)) { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(vertex_source_spheres)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_spheres)) { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(vertex_source_cylinders)) { std::cerr<<"Compiling vertex source FAILED"< *vertices) +void Viewer::drawVertex(const Point_3& p, Coords_ptr& vertices) { vertices->push_back(p.x()); vertices->push_back(p.y()); vertices->push_back(p.z()); @@ -1636,13 +1636,13 @@ void Viewer::drawVertex(const Point_3& p, std::vector *vertices) } -void Viewer::drawEdge(const Point_3& from, const Point_3& to, std::vector *vertices) +void Viewer::drawEdge(const Point_3& from, const Point_3& to, Coords_ptr& vertices) { vertices->push_back( from.x()); vertices->push_back(from.y()); vertices->push_back(from.z()); vertices->push_back( to.x()); vertices->push_back(to.y()); vertices->push_back(to.z()); } -void Viewer::drawFacet(const Triangle_3& t, std::vector *vertices) +void Viewer::drawFacet(const Triangle_3& t, Coords_ptr& vertices) { Point_3 p0 = t.vertex(0); Point_3 p1 = t.vertex(1); @@ -2482,7 +2482,7 @@ void Viewer::incremental_insert() { } -void Viewer::draw_cylinder(float R, int prec, std::vector *vertices, std::vector *normals) +void Viewer::draw_cylinder(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals) { vertices->resize(0); normals->resize(0); @@ -2551,7 +2551,7 @@ void Viewer::draw_cylinder(float R, int prec, std::vector *vertices, std: } } -void Viewer::draw_sphere(float R, int prec, std::vector *vertices, std::vector *normals) +void Viewer::draw_sphere(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals) { vertices->resize(0); normals->resize(0); diff --git a/Triangulation_3/demo/Triangulation_3/Viewer.h b/Triangulation_3/demo/Triangulation_3/Viewer.h index e46753c6d4f..70c72181a29 100644 --- a/Triangulation_3/demo/Triangulation_3/Viewer.h +++ b/Triangulation_3/demo/Triangulation_3/Viewer.h @@ -42,42 +42,41 @@ public: , m_hasEmptyS(false) , m_showTrackball(true) , m_pDlgPrefer(nullptr) - { - pos_emptyFacet = new std::vector(); - pos_emptySphere= new std::vector(); - points_emptySphere = new std::vector(); - pos_points = new std::vector(); - pos_newPoint = new std::vector(); - pos_selectedVertex = new std::vector(); - pos_movingPoint = new std::vector(); - pos_queryPoint = new std::vector(); - pos_trackBall = new std::vector(); - pos_voronoi = new std::vector(); - pos_delaunay = new std::vector(); - pos_facets = new std::vector(); - pos_newFacet = new std::vector(); - pos_nearest_neighbor = new std::vector(); - points_locationSphere = new std::vector(); - points_cylinder = new std::vector(); - normals_cylinder = new std::vector(); - points_sphere = new std::vector(); - points_trackBall = new std::vector(); - normals_sphere = new std::vector(); - normals_emptySphere = new std::vector(); - normals_trackBall= new std::vector(); - transfo1_voronoi = new std::vector(); - transfo2_voronoi = new std::vector(); - transfo3_voronoi = new std::vector(); - transfo4_voronoi = new std::vector(); - transfo1_delaunay = new std::vector(); - transfo2_delaunay = new std::vector(); - transfo3_delaunay = new std::vector(); - transfo4_delaunay = new std::vector(); - incremental_points = new std::vector(); - incremental_next_point = new std::vector(); - incremental_facet = new std::vector(); - incremental_conflict = new std::vector(); - } + , pos_emptyFacet{new Coords} + , pos_emptySphere{new Coords} + , points_emptySphere{new Coords} + , pos_points{new Coords} + , pos_newPoint{new Coords} + , pos_selectedVertex{new Coords} + , pos_movingPoint{new Coords} + , pos_queryPoint{new Coords} + , pos_trackBall{ new Coords} + , pos_voronoi{new Coords} + , pos_delaunay{new Coords} + , pos_facets{new Coords} + , pos_newFacet{new Coords} + , pos_nearest_neighbor{new Coords} + , points_locationSphere{new Coords} + , points_cylinder{new Coords} + , normals_cylinder{new Coords} + , points_sphere{new Coords} + , points_trackBall{new Coords} + , normals_sphere{new Coords} + , normals_emptySphere{new Coords} + , normals_trackBall{new Coords} + , transfo1_voronoi{new Coords} + , transfo2_voronoi{new Coords} + , transfo3_voronoi{new Coords} + , transfo4_voronoi{new Coords} + , transfo1_delaunay{new Coords} + , transfo2_delaunay{new Coords} + , transfo3_delaunay{new Coords} + , transfo4_delaunay{new Coords} + , incremental_points{new Coords} + , incremental_next_point{new Coords} + , incremental_facet{new Coords} + , incremental_conflict{new Coords} + {} ~Viewer() { @@ -269,12 +268,15 @@ protected: QString helpString() const; private: + using Coords = std::vector; + using Coords_ptr = std::unique_ptr>; + // draw a 3d effect vertex - void drawVertex(const Point_3& p, std::vector *vertices); + void drawVertex(const Point_3& p, Coords_ptr& vertices); // draw a 3d effect edge - void drawEdge(const Point_3& from, const Point_3 &to, std::vector *vertices); + void drawEdge(const Point_3& from, const Point_3 &to, Coords_ptr& vertices); // draw a facet - void drawFacet(const Triangle_3& t, std::vector *vertices); + void drawFacet(const Triangle_3& t, Coords_ptr& vertices); // test whether the give 3D point is on the sphere inline bool isOnSphere( const Point_3 & pt ) { return ( (pt.x()*pt.x() + pt.y()*pt.y() + pt.z()*pt.z()) == (m_fRadius*m_fRadius) ); @@ -347,75 +349,74 @@ private: static const int vaoSize = 29; static const int vboSize = 34; // define material - QVector4D ambient; - QVector4D diffuse; - QVector4D specular; - GLfloat shininess ; - int poly_vertexLocation[3]; - int normalsLocation[3]; - int mvpLocation[3]; - int mvLocation[2]; - int centerLocation[5]; - int colorLocation[3]; - int lightLocation[5*2]; + QVector4D ambient; + QVector4D diffuse; + QVector4D specular; + GLfloat shininess ; + int poly_vertexLocation[3]; + int normalsLocation[3]; + int mvpLocation[3]; + int mvLocation[2]; + int centerLocation[5]; + int colorLocation[3]; + int lightLocation[5*2]; - bool are_buffers_initialized; - bool extension_is_found; + bool are_buffers_initialized; + bool extension_is_found; - std::vector *pos_emptyFacet; - std::vector *pos_emptySphere; - std::vector *points_emptySphere; - std::vector *pos_points; - std::vector *pos_newPoint; - std::vector *pos_selectedVertex; - std::vector *pos_movingPoint; - std::vector *pos_queryPoint; - std::vector *pos_trackBall; - std::vector *points_trackBall; - std::vector *pos_voronoi; - std::vector *pos_delaunay; - std::vector *pos_facets; - std::vector *pos_newFacet; - std::vector *pos_nearest_neighbor; - std::vector *points_locationSphere; - std::vector *points_cylinder; - std::vector *normals_cylinder; - std::vector *points_sphere; - std::vector *normals_sphere; - std::vector *normals_emptySphere; - std::vector *normals_trackBall; - std::vector *transfo1_voronoi; - std::vector *transfo2_voronoi; - std::vector *transfo3_voronoi; - std::vector *transfo4_voronoi; - std::vector *transfo1_delaunay; - std::vector *transfo2_delaunay; - std::vector *transfo3_delaunay; - std::vector *transfo4_delaunay; - std::vector *incremental_points; - std::vector *incremental_next_point; - std::vector *incremental_facet; - std::vector *incremental_conflict; + Coords_ptr pos_emptyFacet; + Coords_ptr pos_emptySphere; + Coords_ptr points_emptySphere; + Coords_ptr pos_points; + Coords_ptr pos_newPoint; + Coords_ptr pos_selectedVertex; + Coords_ptr pos_movingPoint; + Coords_ptr pos_queryPoint; + Coords_ptr pos_trackBall; + Coords_ptr pos_voronoi; + Coords_ptr pos_delaunay; + Coords_ptr pos_facets; + Coords_ptr pos_newFacet; + Coords_ptr pos_nearest_neighbor; + Coords_ptr points_locationSphere; + Coords_ptr points_cylinder; + Coords_ptr normals_cylinder; + Coords_ptr points_sphere; + Coords_ptr points_trackBall; + Coords_ptr normals_sphere; + Coords_ptr normals_emptySphere; + Coords_ptr normals_trackBall; + Coords_ptr transfo1_voronoi; + Coords_ptr transfo2_voronoi; + Coords_ptr transfo3_voronoi; + Coords_ptr transfo4_voronoi; + Coords_ptr transfo1_delaunay; + Coords_ptr transfo2_delaunay; + Coords_ptr transfo3_delaunay; + Coords_ptr transfo4_delaunay; + Coords_ptr incremental_points; + Coords_ptr incremental_next_point; + Coords_ptr incremental_facet; + Coords_ptr incremental_conflict; + //pickin + QMap picked_IDs; + QPoint picking_pos; - //picking - QMap picked_IDs; - QPoint picking_pos; - - QOpenGLBuffer buffers[vboSize]; - QOpenGLVertexArrayObject vao[vaoSize]; - QOpenGLShaderProgram rendering_program; - QOpenGLShaderProgram rendering_program_spheres; - QOpenGLShaderProgram rendering_program_cylinders; - typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); - typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); - PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced; - PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor; - void initialize_buffers(); - void compute_elements(); - void attrib_buffers(CGAL::QGLViewer*); - void compile_shaders(); - void draw_cylinder(float R, int prec, std::vector *vertices, std::vector *normals); - void draw_sphere(float R, int prec, std::vector *vertices, std::vector *normals); + QOpenGLBuffer buffers[vboSize]; + QOpenGLVertexArrayObject vao[vaoSize]; + QOpenGLShaderProgram rendering_program; + QOpenGLShaderProgram rendering_program_spheres; + QOpenGLShaderProgram rendering_program_cylinders; + typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); + typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); + PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced; + PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor; + void initialize_buffers(); + void compute_elements(); + void attrib_buffers(CGAL::QGLViewer*); + void compile_shaders(); + void draw_cylinder(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals); + void draw_sphere(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals); }; #endif From d226e504c499921d6ede9a2a7dac27abd8202dc2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 12 Nov 2025 16:48:59 +0100 Subject: [PATCH 08/10] fix a warning use the correct implementation `popupAboutCGAL` from the base class --- .../demo/Triangulation_3/MainWindow.cpp | 28 ------------------- .../demo/Triangulation_3/MainWindow.h | 3 -- 2 files changed, 31 deletions(-) diff --git a/Triangulation_3/demo/Triangulation_3/MainWindow.cpp b/Triangulation_3/demo/Triangulation_3/MainWindow.cpp index aad061f5e44..3f60296c955 100644 --- a/Triangulation_3/demo/Triangulation_3/MainWindow.cpp +++ b/Triangulation_3/demo/Triangulation_3/MainWindow.cpp @@ -209,31 +209,3 @@ void MainWindow::on_actionClear_Scene_triggered() // update viewer Q_EMIT( sceneChanged() ); } - -void MainWindow::popupAboutCGAL() -{ - // read contents from .html file - QFile about_CGAL(":/documentation/documentation/about_CGAL.html"); - about_CGAL.open(QIODevice::ReadOnly|QIODevice::Text); - QString about_CGAL_txt = QTextStream(&about_CGAL).readAll(); - - // popup a message box - QMessageBox mb(QMessageBox::NoIcon, - tr("About CGAL..."), - about_CGAL_txt, - QMessageBox::Ok, - this); - - // set links to be accessible by mouse or keyboard - QLabel* mb_label = mb.findChild("qt_msgbox_label"); - if(mb_label) { - mb_label->setTextInteractionFlags(mb_label->textInteractionFlags() | - ::Qt::LinksAccessibleByMouse | - ::Qt::LinksAccessibleByKeyboard); - } else { - std::cerr << "Cannot find child \"qt_msgbox_label\" in QMessageBox\n" - << " with Qt version " << QT_VERSION_STR << "!\n"; - } - - mb.exec(); -} diff --git a/Triangulation_3/demo/Triangulation_3/MainWindow.h b/Triangulation_3/demo/Triangulation_3/MainWindow.h index 6d126222450..6aba4346894 100644 --- a/Triangulation_3/demo/Triangulation_3/MainWindow.h +++ b/Triangulation_3/demo/Triangulation_3/MainWindow.h @@ -36,9 +36,6 @@ public Q_SLOTS: // show menu void on_actionClear_Scene_triggered(); - // about menu - void popupAboutCGAL(); - Q_SIGNALS: void sceneChanged(); From 12445cc6e16134a23d1bc966e8426baa43f63a8e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 13 Nov 2025 11:52:21 +0100 Subject: [PATCH 09/10] revert unintended modification --- .../demo/Periodic_3_triangulation_3/Scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp index d481e237678..63209099a8d 100644 --- a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp +++ b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/Scene.cpp @@ -1878,7 +1878,7 @@ void Scene::draw_sphere(float R, int prec) } } -void Scene::draw_cylinder(float R, int prec, std::unique_ptr>& vertices, std::unique_ptr>& normals) +void Scene::draw_cylinder(float R, int prec, std::vector *vertices, std::vector *normals) { vertices->resize(0); int rings=360/prec, sectors=360/prec; From e12a760f03363f84d0c01455068109d7acc78a62 Mon Sep 17 00:00:00 2001 From: Sven Oesau Date: Thu, 13 Nov 2025 16:32:40 +0100 Subject: [PATCH 10/10] fixed Metis/Eigen3/Qt6 links in Thirdparty removed LEDA from doc as it is outdated --- .../doc/Documentation/Third_party.txt | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 002e6934934..ad4ef89dd11 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -117,14 +117,14 @@ Qt is a cross-platform application and UI framework. The component `CGAL_Qt6` is essential to run the \cgal demos and basic viewers. It requires \qt6 installed on your system. In case \qt is not yet installed on your system, you can download -it from `https://www.qt-project.org/`. +it from `https://contribute.qt-project.org/`. The exhaustive list of \qt6 components used in demos is: `Core`, `Gui`, `Help`, `OpenGL`, `OpenGLWidgets`, `Qml`, `Svg`, `Widgets`, `WebSockets`, `Network`, and `qcollectiongenerator` (with `sqlite` driver plugin). \subsection thirdpartyEigen Eigen -Version 3.3.7 or later +Version 3.3.7 or later (including Eigen3 5.0.0) \eigen is a `C++` template library for linear algebra. \eigen supports all matrix sizes, various matrix decomposition methods and sparse linear solvers. @@ -138,7 +138,7 @@ Overview page. In order to use Eigen in \cgal programs, the executables should be linked with the CMake imported target `CGAL::Eigen3_support` provided in `CGAL_Eigen3_support.cmake`. -The \eigen web site is `https://eigen.tuxfamily.org`. +The \eigen web site is `https://libeigen.gitlab.io/`. \subsection thirdpartyOpenGR OpenGR @@ -167,17 +167,6 @@ Alternatively, version 1.3.1 of \libpointmatcher is supported with version 3.3.7 `https://github.com/ethz-asl/libpointmatcher/blob/master/doc/Compilation.md`:`NABO_INCLUDE_DIR` becomes `libnabo_INCLUDE_DIRS` and `NABO_LIBRARY` becomes `libnabo_LIBRARIES` in the "Build libpointmatcher" section. -\subsection thirdpartyLeda LEDA -Version 6.2 or later - -\leda is a library of efficient data structures and -algorithms. Like \core, \leda offers a real number data type. - -In \cgal this library is optional, and its number types can -be used as an alternative to \gmp, \mpfr, and \core. - -Free and commercial editions of \leda are available from `https://www.algorithmic-solutions.com`. - \subsection thirdpartyMPFI Multiple Precision Floating-point Interval (MPFI) Version 1.4 or later @@ -278,7 +267,7 @@ vcpkg install suitesparse \subsection thirdpartyMETIS METIS Version 5.1 or later -\metis is a library developed by the Karypis Lab +\metis is a library developed by the Karypis Lab and designed to partition graphs and produce fill-reducing matrix orderings. \cgal offers wrappers around some of the methods of the \metis library @@ -287,7 +276,7 @@ to allow the partitioning of graphs that are models of the concepts of the and, by extension, of surface meshes (see Section \ref BGLPartitioning of the package \ref PkgBGL). More information is available on the METIS library -at `http://glaros.dtc.umn.edu/gkhome/metis/metis/overview`. +at `https://github.com/KarypisLab/METIS`. \subsection thirdpartyzlib zlib