From 1ce993f296589313cc7623e25ad511bb3c379ce5 Mon Sep 17 00:00:00 2001 From: Tarik Moussa Date: Mon, 16 Mar 2026 17:20:15 +0200 Subject: [PATCH] ad simple visualization --- code/CMakeLists.txt | 10 ++-- code/include/simple_visualize.h | 64 +++++++++++++++++++++ code/src/apps/v0/conformallab_cli.cpp | 80 ++++++++++++++------------- 3 files changed, 111 insertions(+), 43 deletions(-) create mode 100644 code/include/simple_visualize.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index e2faa85..583312c 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -38,8 +38,9 @@ add_subdirectory(deps/glfw-3.4) # --------- Executable --------- add_executable(${PROJECT_NAME} src/apps/v0/conformallab_cli.cpp ) -target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/include +target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE + + ${CMAKE_CURRENT_SOURCE_DIR}/deps/single_includes ${CMAKE_CURRENT_SOURCE_DIR}/deps/eigen-3.4.0/ ${CMAKE_CURRENT_SOURCE_DIR}/deps/CGAL-6.1.1/include @@ -47,8 +48,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-2.6.0/include ${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/include ) - - +target_include_directories(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/include +) add_library(glad STATIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/src/glad.c ) diff --git a/code/include/simple_visualize.h b/code/include/simple_visualize.h new file mode 100644 index 0000000..8293a8c --- /dev/null +++ b/code/include/simple_visualize.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include + + +namespace mesh_utils { + +template +void cgal_to_eigen(CGAL::Surface_mesh& mesh, + Eigen::MatrixXd& V, Eigen::MatrixXi& F) { + V.resize(mesh.num_vertices(), 3); + F.resize(mesh.num_faces(), 3); + + for (auto v : mesh.vertices()) { + auto p = mesh.point(v); + V.row(v.idx()) << p.x(), p.y(), p.z(); + } + + Eigen::Index face_idx = 0; + for (auto f : mesh.faces()) { + int vertex_count = 0; + for (auto h : CGAL::halfedges_around_face(mesh.halfedge(f), mesh)) { + auto v = mesh.target(h); + F(face_idx, vertex_count) = v.idx(); + ++vertex_count; + } + face_idx++; + } +} + +template +void simple_visualize_mesh( CGAL::Surface_mesh& mesh, bool triangulate = true) { + if(CGAL::is_triangle_mesh(mesh)) { + std::cerr << "Warning: Mesh is not triangulated. Visualizer expects triangles.\n"; + + + if(triangulate){ + std::cerr << "Triangulating mesh for visualization...\n"; + CGAL::Polygon_mesh_processing::triangulate_faces(mesh); + } + else{ + std::cerr << " exit without visualizetion.\n"; + return; + } + } + Eigen::MatrixXd V; Eigen::MatrixXi F; + cgal_to_eigen(mesh, V, F); + igl::opengl::glfw::Viewer viewer; + viewer.data().set_mesh(V, F); + viewer.launch(); +} + +// Zero-Copy Map für V (optional) +template +Eigen::Map> +get_vertex_map(CGAL::Surface_mesh& mesh) { + auto& points = mesh.points(); + double* data = reinterpret_cast(&points[0][0]); + return {data, static_cast(points.size()), 3}; +} + +} // namespace diff --git a/code/src/apps/v0/conformallab_cli.cpp b/code/src/apps/v0/conformallab_cli.cpp index d99cd14..c4df0c2 100644 --- a/code/src/apps/v0/conformallab_cli.cpp +++ b/code/src/apps/v0/conformallab_cli.cpp @@ -1,31 +1,38 @@ #include #include #include +#include "simple_visualize.h" -#include #include #include #include -#include + #include using Kernel = CGAL::Simple_cartesian; using Point = Kernel::Point_3; using Mesh = CGAL::Surface_mesh; -namespace PMP = CGAL::Polygon_mesh_processing; -int main(int argc, char* argv[]) -{ + + + +bool parse_arguments(int argc, char* argv[], std::string& input_file, std::string& output_file, bool& show, bool& verbose) { CLI::App app{"demo of conformallab"}; - std::string input_file; - std::string output_file; // default output file name - app.add_option("-i,--input", input_file, "Input OFF file")->required(); app.add_option("-o,--output", output_file, "Output OFF file (optional)"); - CLI11_PARSE(app, argc, argv); + app.add_flag("-s,--show", show, "Show the input mesh in a viewer"); + app.add_flag("-v,--verbose",verbose, "Enable verbose output"); + app.set_help_flag("-h,--help", "Show this help message and exit"); + + try { + CLI11_PARSE(app, argc, argv); + } catch (const CLI::ParseError &e) { + return false; + } + return true; if (input_file.empty()) { std::cerr << "Input file is required.\n"; @@ -36,6 +43,28 @@ int main(int argc, char* argv[]) std::cerr << "Unsupported file format. Please provide an OFF file.\n"; return EXIT_FAILURE; } +} + + + + + +int main(int argc, char* argv[]) +{ + std::string input_file; + std::string output_file; + bool show = false; + bool verbose = false; + + if(!parse_arguments(argc, argv, input_file, output_file, show, verbose)) { + std::cerr << "Failed to parse arguments.\n"; + return EXIT_FAILURE; + } + + std::cout << "Input file: " << input_file << "\n"; + std::cout << "Output file: " << output_file << "\n"; + std::cout << "Show mesh: " << (show ? "Yes" : "No") << "\n"; + std::cout << "Verbose: " << (verbose ? "Yes" : "No") << "\n"; Mesh surface_mesh; if (!CGAL::IO::read_polygon_mesh(input_file, surface_mesh) || surface_mesh.is_empty()) { @@ -52,36 +81,9 @@ int main(int argc, char* argv[]) // CGAL -> libigl - PMP::triangulate_faces(surface_mesh); - //todo : we should check if the mesh is already triangulated, and only call this if it isn't, to avoid unnecessary processing. CGAL::Polygon_mesh_processing::is_triangulated() can be used for this check. - Eigen::MatrixXd Vertices; - Eigen::MatrixXi Faces; - Vertices.resize(surface_mesh.number_of_vertices(), 3); - Faces.resize(surface_mesh.number_of_faces(), 3); - - for (auto v : surface_mesh.vertices()) { - const auto& p = surface_mesh.point(v); - Vertices(v.idx(), 0) = p.x(); - Vertices(v.idx(), 1) = p.y(); - Vertices(v.idx(), 2) = p.z(); - } - - int f_i = 0; - for (auto f : surface_mesh.faces()) { - int k = 0; - for (auto hv : CGAL::halfedges_around_face(surface_mesh.halfedge(f), surface_mesh)) { - auto v = surface_mesh.target(hv); - Faces(f_i, k) = v.idx(); - ++k; - } - ++f_i; - } - - igl::opengl::glfw::Viewer viewer; - viewer.data().set_mesh(Vertices, Faces); - viewer.launch(); - - + if(show){ + mesh_utils::simple_visualize_mesh(surface_mesh,true); + } // for now, we just write the input mesh to the output file as a placeholder if (!output_file.empty() && !CGAL::IO::write_polygon_mesh(output_file, surface_mesh)) {