diff --git a/Constrained_triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h b/Constrained_triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h index d37e8bff102..bd6d4fe0e7d 100644 --- a/Constrained_triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h +++ b/Constrained_triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h @@ -59,6 +59,7 @@ #include #include #include +#include #if __has_include() # include # include @@ -71,6 +72,51 @@ namespace CGAL { #ifndef DOXYGEN_RUNNING +template +auto segment_soup_to_polylines_point_type_aux(const Range_of_segments& segment_soup) { + for(auto [a, b]: segment_soup) { + return a; + } +} + +template +auto segment_soup_to_polylines(const Range_of_segments& segment_soup) { + using Point = decltype(segment_soup_to_polylines_point_type_aux(segment_soup)); + + std::vector> polylines; + + using Graph = boost::adjacency_list; + using Map2v = std::map; + Graph graph; + Map2v map2v; + auto get_v = [&](const Point& p) { + auto it = map2v.find(p); + if(it != map2v.end()) return it->second; + auto v = boost::add_vertex(p, graph); + map2v.emplace(p, v); + return v; + }; + for(auto [a, b]: segment_soup) { + auto va = get_v(a); + auto vb = get_v(b); + boost::add_edge(va, vb, graph); + } + + struct Polylines_visitor + { + Graph& graph; + std::vector>& polylines; + + void start_new_polyline() { polylines.emplace_back(); } + void add_node(typename Graph::vertex_descriptor vd) { polylines.back().push_back(graph[vd]); } + void end_polyline() {} + }; + Polylines_visitor visitor{graph, polylines}; + CGAL::split_graph_into_polylines(graph, visitor); + + return polylines; +} + template typename K::Boolean does_first_triangle_intersect_second_triangle_interior(const typename K::Triangle_3& t1, @@ -571,34 +617,108 @@ public: auto mesh_vp_map = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), get(CGAL::vertex_point, mesh)); - [[maybe_unused]] /* TODO */ - auto mesh_face_patch_map = parameters::choose_parameter(parameters::get_parameter(np, internal_np::face_patch), - boost::identity_property_map{}); + auto mesh_face_patch_map = parameters::get_parameter(np, internal_np::face_patch); + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + std::vector>> patch_edges; + + auto v_selected_map = get(CGAL::dynamic_vertex_property_t{}, mesh); + + int number_of_patches = 0; + constexpr bool has_face_patch_map = !std::is_same_v; + if constexpr (has_face_patch_map) { + int max_patch_id = 0; + for(auto f : faces(mesh)) { + max_patch_id = (std::max)(max_patch_id, get(mesh_face_patch_map, f)); + } + for(auto f : faces(mesh)) { + if(get(mesh_face_patch_map, f) < 0) { + put(mesh_face_patch_map, f, max_patch_id++); + } + } + number_of_patches = max_patch_id + 1; + patch_edges.resize(number_of_patches); + for(auto h : halfedges(mesh)) { + if(is_border(h, mesh)) + continue; + auto f = face(h, mesh); + auto patch_id = get(mesh_face_patch_map, f); + auto opp = opposite(h, mesh); + if(is_border(opp, mesh) || patch_id != get(mesh_face_patch_map, face(opp, mesh))) { + auto va = source(h, mesh); + auto vb = target(h, mesh); + patch_edges[patch_id].emplace_back(va, vb); + put(v_selected_map, va, true); + put(v_selected_map, vb, true); + } + } + + } else { + number_of_patches = num_faces(mesh); + } using Vertex_handle = typename Triangulation::Vertex_handle; using Cell_handle = typename Triangulation::Cell_handle; auto tr_vertex_map = get(CGAL::dynamic_vertex_property_t(), mesh); Cell_handle hint_ch{}; for(auto v : vertices(mesh)) { + if constexpr(has_face_patch_map) { + if(false == get(v_selected_map, v)) continue; + } auto p = get(mesh_vp_map, v); auto vh = cdt_impl.insert(p, hint_ch, false); hint_ch = vh->cell(); put(tr_vertex_map, v, vh); } + struct { decltype(tr_vertex_map)* vertex_map; - Vertex_handle operator()(typename boost::graph_traits::vertex_descriptor v) const { - return get(*vertex_map, v); + auto operator()(vertex_descriptor v) const { return get(*vertex_map, v); } + } tr_vertex_fct{&tr_vertex_map}; + + if constexpr(has_face_patch_map) { + for(int i = 0; i < number_of_patches; ++i) { + auto& edges = patch_edges[i]; + if(edges.empty()) + continue; + auto polylines = segment_soup_to_polylines(edges); + while(true) { + const auto non_closed_polylines_begin = + std::partition(polylines.begin(), polylines.end(), + [](const auto& polyline) { return polyline.front() == polyline.back(); }); + if(non_closed_polylines_begin == polylines.end()) + break; + edges.clear(); + for(auto it = non_closed_polylines_begin; it != polylines.end(); ++it) { + auto& polyline = *it; + for(auto it = polyline.begin(), end = polyline.end() - 1; it != end; ++it) { + edges.emplace_back(*it, *(it + 1)); + } + } + polylines.erase(non_closed_polylines_begin, polylines.end()); + auto other_polylines = segment_soup_to_polylines(edges); + polylines.insert(polylines.end(), std::make_move_iterator(other_polylines.begin()), + std::make_move_iterator(other_polylines.end())); + } + + std::optional face_index; + for(auto& polyline : polylines) { + CGAL_assertion(polyline.front() == polyline.back()); + polyline.pop_back(); + auto begin = boost::make_transform_iterator(polyline.begin(), tr_vertex_fct); + auto end = boost::make_transform_iterator(polyline.end(), tr_vertex_fct); + cdt_impl.insert_constrained_face(CGAL::make_range(begin, end), false, + face_index ? *face_index : -1); + } } - } transform_function{&tr_vertex_map}; + } else { + for(auto f : faces(mesh)) { + auto face_vertices = vertices_around_face(halfedge(f, mesh), mesh); - for(auto f : faces(mesh)) { - auto face_vertices = vertices_around_face(halfedge(f, mesh), mesh); + auto begin = boost::make_transform_iterator(face_vertices.begin(), tr_vertex_fct); + auto end = boost::make_transform_iterator(face_vertices.end(), tr_vertex_fct); - auto begin = boost::make_transform_iterator(face_vertices.begin(), transform_function); - auto end = boost::make_transform_iterator(face_vertices.end(), transform_function); - - cdt_impl.insert_constrained_face(CGAL::make_range(begin, end), false); + cdt_impl.insert_constrained_face(CGAL::make_range(begin, end), false); + } } cdt_impl.restore_Delaunay(); cdt_impl.restore_constrained_Delaunay(); diff --git a/Lab/demo/Lab/CGAL_Lab_CDT_3.cpp b/Lab/demo/Lab/CGAL_Lab_CDT_3.cpp index 818be1069ac..5874b8a718e 100644 --- a/Lab/demo/Lab/CGAL_Lab_CDT_3.cpp +++ b/Lab/demo/Lab/CGAL_Lab_CDT_3.cpp @@ -13,6 +13,6 @@ int main(int argc, char **argv) CGAL_Lab app(argc, argv, "CGAL Lab (3D Constrained Delaunay Triangulations)", "Polyhedron_3 demo", - QStringList() << "Viewer" << "CDT_3"); + QStringList() << "IO_surface_meshes" << "CDT_3"); return app.try_exec(); } diff --git a/Lab/demo/Lab/CGALlab_macros.cmake b/Lab/demo/Lab/CGALlab_macros.cmake index 73f2733bc79..c0d73bd4cec 100644 --- a/Lab/demo/Lab/CGALlab_macros.cmake +++ b/Lab/demo/Lab/CGALlab_macros.cmake @@ -29,7 +29,7 @@ add_dependencies(CGALlab_compile_all_plugins CGALlab_all_plugins) add_file_dependencies( ${moc_file_name} "${CMAKE_CURRENT_SOURCE_DIR}/${plugin_implementation_base_name}.cpp" ) endif() - add_library(${plugin_name} MODULE ${option} ${moc_file_name} ${plugin_implementation_base_name}.cpp ${other_sources}) + qt_add_plugin(${plugin_name} SHARED ${option} ${moc_file_name} ${plugin_implementation_base_name}.cpp ${other_sources}) set_property(TARGET ${plugin_name} PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CGAL_LAB_DEMO_PLUGINS_DIR}") diff --git a/Lab/demo/Lab/CMakeLists.txt b/Lab/demo/Lab/CMakeLists.txt index f2961a25e43..176fe93e6d3 100644 --- a/Lab/demo/Lab/CMakeLists.txt +++ b/Lab/demo/Lab/CMakeLists.txt @@ -408,7 +408,7 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND) add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGAL_Mesh_3) add_executable(CGAL_CDT_3 CGAL_Lab_CDT_3.cpp) - add_dependencies(CGAL_CDT_3 CDT_3 Viewer) + add_dependencies(CGAL_CDT_3 CDT_3 IO_surface_meshes) target_link_libraries(CGAL_CDT_3 PRIVATE cgal_lab) add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGAL_CDT_3) diff --git a/Lab/demo/Lab/MainWindow.cpp b/Lab/demo/Lab/MainWindow.cpp index 25f80d04a92..d7ba66519ad 100644 --- a/Lab/demo/Lab/MainWindow.cpp +++ b/Lab/demo/Lab/MainWindow.cpp @@ -49,7 +49,7 @@ #include #include #include - +#include #include #include @@ -543,6 +543,8 @@ void MainWindow::setMenus(QString name, QString parentName, QAction* a ) } } +QLoggingCategory qlog_cgallab_plugins("cgal.lab.plugins"); + bool MainWindow::load_plugin(QString fileName, bool blacklisted) { if(fileName.contains("plugin") && QLibrary::isLibrary(fileName)) { @@ -563,9 +565,8 @@ bool MainWindow::load_plugin(QString fileName, bool blacklisted) return true; } } - QDebug qdebug = qDebug(); if(verbose) - qdebug << "### Loading \"" << fileName.toUtf8().data() << "\"... "; + qCDebug(qlog_cgallab_plugins) << "### Loading \"" << fileName.toUtf8().data() << "\"... "; QPluginLoader loader; loader.setFileName(fileinfo.absoluteFilePath()); QJsonArray keywords = loader.metaData().value("MetaData").toObject().value("Keywords").toArray(); @@ -595,7 +596,7 @@ bool MainWindow::load_plugin(QString fileName, bool blacklisted) bool init2 = initIOPlugin(obj); if (!init1 && !init2) { - pluginsStatus_map[name] = QString("Not for this program."); + pluginsStatus_map[name] = QString("ERROR: Not for this program."); } else{ QJSValue objectValue = @@ -607,12 +608,16 @@ bool MainWindow::load_plugin(QString fileName, bool blacklisted) } else if(!do_load) { - pluginsStatus_map[name]="Wrong Keywords."; + pluginsStatus_map[name]="ERROR: Wrong Keywords."; ignored_map[name] = true; } else{ - pluginsStatus_map[name] = loader.errorString(); - + pluginsStatus_map[name] = "ERROR: " + loader.errorString(); + } + if(verbose && pluginsStatus_map[name].startsWith("ERROR")) { + qCDebug(qlog_cgallab_plugins) << " plugin " << name << ": " << pluginsStatus_map[name] + << "\n plugin keywords: " << s_keywords + << "\n app keywords: " << accepted_keywords; } PathNames_map[name].push_back(fileinfo.absoluteDir().absolutePath()); return true; diff --git a/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp b/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp index 2d91c078115..aeee9600cda 100644 --- a/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp +++ b/Lab/demo/Lab/Plugins/CDT_3/CDT_3_plugin.cpp @@ -44,22 +44,24 @@ class CDT_3_plugin : public QObject, public CGAL_Lab_plugin_interface { Q_OBJECT Q_INTERFACES(CGAL::Three::CGAL_Lab_plugin_interface) - Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.PluginInterface/1.0") + Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.PluginInterface/1.0" FILE "cdt_3_plugin.json") QAction* actionCDT; CGAL::Three::Scene_interface* scene; void cdt_3() { - Scene_surface_mesh_item* item = + Scene_surface_mesh_item* mesh_item = qobject_cast(scene->item(scene->mainSelectionIndex())); - if(!item) + if(!mesh_item) return; - auto* mesh = item->face_graph(); + auto* mesh = mesh_item->face_graph(); if(!mesh) return; - using CDT = CGAL::Constrained_Delaunay_triangulation_3; - CDT cdt = CGAL::make_constrained_Delaunay_triangulation_3(*mesh); + auto patch_id_pmap = mesh->property_map("f:patch_id"); + auto cdt = patch_id_pmap + ? CGAL::make_constrained_Delaunay_triangulation_3(*mesh, CGAL::parameters::face_patch_map(*patch_id_pmap)) + : CGAL::make_constrained_Delaunay_triangulation_3(*mesh); const auto& cdt_tr = cdt.triangulation(); auto triangulation_item = std::make_unique(); auto& item_tr = triangulation_item->triangulation(); @@ -68,10 +70,11 @@ class CDT_3_plugin : public QObject, public CGAL_Lab_plugin_interface item_tr.set_infinite_vertex(inf_v); triangulation_item->triangulation_changed(); - triangulation_item->setParent(item->parent()); - triangulation_item->setName("CDT of " + item->name()); + triangulation_item->setParent(mesh_item->parent()); + triangulation_item->setName("CDT of " + mesh_item->name()); triangulation_item->show_intersection(false); scene->addItem(triangulation_item.release()); + mesh_item->setVisible(false); } public: diff --git a/Lab/demo/Lab/Plugins/IO/CMakeLists.txt b/Lab/demo/Lab/Plugins/IO/CMakeLists.txt index c6247c39212..a9338399747 100644 --- a/Lab/demo/Lab/Plugins/IO/CMakeLists.txt +++ b/Lab/demo/Lab/Plugins/IO/CMakeLists.txt @@ -22,7 +22,7 @@ cgal_lab_plugin(nef_io_plugin Nef_io_plugin KEYWORDS Viewer) target_link_libraries(nef_io_plugin PUBLIC scene_nef_polyhedron_item) cgal_lab_plugin(off_plugin OFF_io_plugin - KEYWORDS Viewer Mesh_3 PointSetProcessing Classification PMP) + KEYWORDS Viewer Mesh_3 PointSetProcessing Classification PMP IO_surface_meshes) target_link_libraries(off_plugin PUBLIC scene_polygon_soup_item scene_points_with_normal_item scene_surface_mesh_item) cgal_lab_plugin(off_to_nef_plugin OFF_to_nef_io_plugin KEYWORDS Viewer) @@ -34,10 +34,10 @@ target_link_libraries(polylines_io_plugin PUBLIC scene_polylines_item) cgal_lab_plugin(wkt_plugin WKT_io_plugin KEYWORDS Viewer PointSetProcessing Mesh_3) target_link_libraries(wkt_plugin PUBLIC scene_polylines_item) -cgal_lab_plugin(stl_plugin STL_io_plugin KEYWORDS Viewer PMP) +cgal_lab_plugin(stl_plugin STL_io_plugin KEYWORDS Viewer PMP IO_surface_meshes) target_link_libraries(stl_plugin PUBLIC scene_surface_mesh_item scene_polygon_soup_item) -cgal_lab_plugin(surf_io_plugin Surf_io_plugin KEYWORDS Viewer PMP) +cgal_lab_plugin(surf_io_plugin Surf_io_plugin KEYWORDS Viewer PMP IO_surface_meshes) target_link_libraries(surf_io_plugin PUBLIC scene_surface_mesh_item) cgal_lab_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS Viewer) @@ -79,7 +79,7 @@ endif() cgal_lab_plugin(xyz_plugin XYZ_io_plugin KEYWORDS Viewer PointSetProcessing Classification) target_link_libraries(xyz_plugin PUBLIC scene_points_with_normal_item) -cgal_lab_plugin(ply_plugin PLY_io_plugin KEYWORDS Viewer PointSetProcessing Classification PMP) +cgal_lab_plugin(ply_plugin PLY_io_plugin KEYWORDS Viewer PointSetProcessing Classification PMP IO_surface_meshes) target_link_libraries(ply_plugin PUBLIC scene_points_with_normal_item scene_polygon_soup_item scene_surface_mesh_item scene_textured_item) if (TARGET CGAL::LASLIB_support) cgal_lab_plugin(las_plugin LAS_io_plugin KEYWORDS Viewer PointSetProcessing Classification) diff --git a/Lab/demo/Lab/Plugins/PMP/CMakeLists.txt b/Lab/demo/Lab/Plugins/PMP/CMakeLists.txt index 507cd7b1df1..90595f9b6bd 100644 --- a/Lab/demo/Lab/Plugins/PMP/CMakeLists.txt +++ b/Lab/demo/Lab/Plugins/PMP/CMakeLists.txt @@ -65,7 +65,7 @@ if(TARGET CGAL::Eigen3_support) qt6_wrap_ui(remeshPlanarPatchesUI_FILES Remesh_planar_patches_dialog.ui) cgal_lab_plugin(remesh_planar_patches_plugin Remesh_planar_patches_plugin - ${remeshPlanarPatchesUI_FILES} KEYWORDS PMP) + ${remeshPlanarPatchesUI_FILES} KEYWORDS PMP CDT_3) target_link_libraries(remesh_planar_patches_plugin PUBLIC scene_surface_mesh_item CGAL::Eigen3_support) if(CGAL_ENABLE_TESTING AND NOT CMAKE_VS_MSBUILD_COMMAND) diff --git a/Lab/demo/Lab/Plugins/PMP/Remesh_planar_patches_plugin.cpp b/Lab/demo/Lab/Plugins/PMP/Remesh_planar_patches_plugin.cpp index 49797844677..555f02749c8 100644 --- a/Lab/demo/Lab/Plugins/PMP/Remesh_planar_patches_plugin.cpp +++ b/Lab/demo/Lab/Plugins/PMP/Remesh_planar_patches_plugin.cpp @@ -57,7 +57,7 @@ class CGAL_Lab_remesh_planar_patches_plugin : { Q_OBJECT Q_INTERFACES(CGAL::Three::CGAL_Lab_plugin_interface) - Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.PluginInterface/1.0" FILE "isotropic_remeshing_plugin.json") + Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.PluginInterface/1.0" FILE "remesh_planar_patches_plugin.json") typedef Scene_surface_mesh_item::Face_graph Mesh; typedef boost::graph_traits::face_descriptor face_descriptor; diff --git a/Triangulation_3/test/Triangulation_3/CMakeLists.txt b/Triangulation_3/test/Triangulation_3/CMakeLists.txt index e0a25bec686..10002fe55b6 100644 --- a/Triangulation_3/test/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/test/Triangulation_3/CMakeLists.txt @@ -147,7 +147,8 @@ CGAL_add_cdt3_from_local_off_test(error_mesh-p_not_equal_0-min2) include(./Thingi10k-CDT.cmake) add_test(NAME "execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" COMMAND cdt_3_from_off_CGAL_DEBUG_CDT_3 ${CGAL_DATA_DIR}/meshes/3torus.off) -cgal_setup_test_properties("execution of cdt_3_from_off_CGAL_DEBUG_CDT_3" cdt_3_from_off_CGAL_DEBUG_CDT_3) +cgal_add_compilation_test(cdt_3_from_off_CGAL_DEBUG_CDT_3) +cgal_setup_test_properties("execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" cdt_3_from_off_CGAL_DEBUG_CDT_3) get_directory_property(all_tests TESTS) foreach(test ${all_tests}) diff --git a/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp b/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp index 63726a72608..118e5752ced 100644 --- a/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp +++ b/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp @@ -339,44 +339,6 @@ int main(int argc, char* argv[]) } } -template -auto segment_soup_to_polylines(Range_of_segments&& segment_soup) { - using Point = decltype([&](){ using std::begin; auto [a, b] = *begin(segment_soup); return a; } ()); - - std::vector> polylines; - - using Graph = boost::adjacency_list; - using Map2v = std::map; - Graph graph; - Map2v map2v; - auto get_v = [&](const Point& p) { - auto it = map2v.find(p); - if(it != map2v.end()) return it->second; - auto v = boost::add_vertex(p, graph); - map2v.emplace(p, v); - return v; - }; - for(auto [a, b]: segment_soup) { - auto va = get_v(a); - auto vb = get_v(b); - boost::add_edge(va, vb, graph); - } - - struct Polylines_visitor - { - Graph& graph; - std::vector>& polylines; - - void start_new_polyline() { polylines.emplace_back(); } - void add_node(typename Graph::vertex_descriptor vd) { polylines.back().push_back(graph[vd]); } - void end_polyline() {} - }; - Polylines_visitor visitor{graph, polylines}; - CGAL::split_graph_into_polylines(graph, visitor); - - return polylines; -} - int go(Mesh mesh, CDT_options options) { CDT cdt; cdt.debug_Steiner_points(options.verbose > 0); @@ -709,16 +671,10 @@ int go(Mesh mesh, CDT_options options) { for(auto& polyline: polylines) { assert(polyline.front() == polyline.back()); polyline.pop_back(); - if(face_index) { - cdt.insert_constrained_face( - polyline | std::views::transform([&](vertex_descriptor v) { return get(tr_vertex_pmap, v); }), - false, - *face_index); - } else { - face_index = cdt.insert_constrained_face( - polyline | std::views::transform([&](vertex_descriptor v) { return get(tr_vertex_pmap, v); }), - false); - } + cdt.insert_constrained_face( + polyline | std::views::transform([&](vertex_descriptor v) { return get(tr_vertex_pmap, v); }), + false, + face_index ? *face_index : -1); } } } else {