diff --git a/Heat_method_3/doc/Heat_method_3/Heat_method_3.txt b/Heat_method_3/doc/Heat_method_3/Heat_method_3.txt index 5a7198d4358..b2a66524740 100644 --- a/Heat_method_3/doc/Heat_method_3/Heat_method_3.txt +++ b/Heat_method_3/doc/Heat_method_3/Heat_method_3.txt @@ -49,7 +49,7 @@ The sum is taken over all of the neighboring vertices \f$j\f$. Further, \f$\alph From this, the symmetric positive-definite system \f$(M-tL_C)u = \delta_{\gamma}\f$ can be solved to find \f$u\f$ where \f$\delta_{\gamma}\f$ is the Kronecker delta over \f$\gamma\f$. -Next, the gradent in a given triangle can be expressed as: +Next, the gradient in a given triangle can be expressed as: \f$\nabla \cdot X = \frac{1}{2} \sum_j cot\theta_1 (e_1 \cdot X_j) + cot \theta_2 (e_2 \cdot X_j)\f$ @@ -67,46 +67,42 @@ Finally, let \f$b \in R^{|V|}\f$ be the integrated divergences of the normalized The intrinsic Delaunay triangulation thus relies on edge lengths and angles, as does the heat method. The intrinsic Delaunay triangulation does not actually flip the edge. Instead, the edge flips are intrinsic and so the shape of the original embedded mesh does not change. Instead, the IDT mesh is considered as an abstract surface with a locally Euclidean metric. Instead of actually flipping an edge, the algorithm performs a combinatorial flip on it and updates its length. Thus, there is no change to the intrinsic geometry of the input mesh. - Let \f$ K = (V,E,T) \f$ be a 2-manifold triangle mesh, where \f$V\f$ is the vertex set, \f$ E \f$ is the edge set and \f$ T \f$ is the face set (triangle set). Let \f$ L \f$ be the set of Euclidean distances, where \f$ L(e_{ij}) = l_{ij} = || p_i - p_j || \f$ , where \f$ p_i \f$ and \f$ p_j \f$ are the point positions \f$ \in R^3 \f$ of vertices \f$ i \f$ and \f$ j \f$ respectively. Then, let the pair \f$ (K,L) \f$ be the input to the iDT algorithm which returns the pair \f$(\dot K, \dot L)\f$, which are the intrinsic Delaunay mesh and the intrinsic lengths. The algorithm is as follows: - - \f$ \forall e \in E : Mark(e) \f$ - - Stack \f$ s \leftarrow E \f$ - - while !Empty(\f$s\f$) do - - \f$e_{ij} \leftarrow \f$ Pop(\f$s\f$) and Unmark(\f$e_ij\f$) - - if !Delaunay(\f$e_{ij}\f$) then - - \f$e_{kl} \leftarrow\f$ Flip(\f$e_ij\f$) and compute the new length \f$l_{kl}\f$ - - for all \f$e \in {e_{kj}, e_{jl}, e_{li}, e_{ik}}\f$ do - - if !Mark(\f$e\f$) then - - Mark(\f$e\f$) and Push(\f$s,e\f$) - + Let \f$ K = (V,E,T) \f$ be a 2-manifold triangle mesh, where \f$V\f$ is the vertex set, \f$ E \f$ is the edge set and \f$ T \f$ is the face set (triangle set). Let \f$ L \f$ be the set of Euclidean distances, where \f$ L(e_{ij}) = l_{ij} = || p_i - p_j || \f$ , where \f$ p_i \f$ and \f$ p_j \f$ are the point positions \f$ \in R^3 \f$ of vertices \f$ i \f$ and \f$ j \f$ respectively. Then, let the pair \f$ (K,L) \f$ be the input to the iDT algorithm which returns the pair \f$(\tilde K, \tilde L)\f$, which are the intrinsic Delaunay mesh and the intrinsic lengths. The algorithm is as follows: + \code + for all edge e in E : Mark(e) + Stack s <-- E + while !Empty(s) do + edge(ij) = Pop(s) and Unmark(edge(ij)) + if !Delaunay(edge(ij)) then + edge(kl) = Flip(edge(ij)) and compute the new length length(kl) using the Cosine Theorem + for all edge e in {edge(kj), edge(jl), edge(li), edge(ik)} do + if !Mark(e) then + Mark(e) and Push(s,e) end if - end for - end if - end while + return (~K,~L) + \endcode - return \f$(\dot K, \dot L)\f$ \f$\leftarrow (K,L)\f$ - The new \f$(\dot K, \dot L)\f$ are used in the Heat Method distance computation. + The new \f$(\tilde K, \tilde L)\f$ are then used in the Heat Method distance computation. \section sec_HM_examples Examples -\subsection HM_FirstExample First Example +\subsection HM_FirstExample Heat Method +The following example shows the heat method on a triangle mesh. The example adds the first vertex into the source set and then uses the heat_intensity property map to read the distance values. +\cgalExample{Heat_method_3/heat_method_surface_mesh.cpp} -The following example shows ... -\section sec_HM_history Design and Implementation History +\subsection HM_FirstExample Heat Method with Intrinsic Delaunay Triangulation +The following example shows the heat method on a triangle mesh using the intrinsic delaunay remeshing algorithm first. The distance values are then printed using the vertex_distance property map. +\cgalExample{Heat_method_3/heat_method_surface_mesh_intrinsic.cpp} + + +\section sec_HM_history Implementation History +A first version of this package was started by Christina Vaz, Keenan Crane and Andreas Fabri as part of the 2018 Google Summer of Code. + -This package ... */ } /* namespace CGAL */ diff --git a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt index 77bccbbd586..d05e3a59f0e 100644 --- a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt +++ b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt @@ -12,7 +12,7 @@ find_package( CGAL QUIET COMPONENTS ) if ( NOT CGAL_FOUND ) message(STATUS "This project requires the CGAL library, and will not be compiled.") - return() + return() endif() @@ -27,7 +27,7 @@ if ( NOT Boost_FOUND ) message(STATUS "This project requires the Boost library, and will not be compiled.") - return() + return() endif() @@ -36,7 +36,7 @@ find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) include( ${EIGEN3_USE_FILE} ) -else() +else() message(STATUS "This project requires the Boost library, and will not be compiled.") return() @@ -55,5 +55,4 @@ include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "heat_method_surface_mesh.cpp" ) create_single_source_cgal_program( "flip.cpp" ) - - +create_single_source_cgal_program( "heat_method_surface_mesh_intrinsic.cpp" ) diff --git a/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh.cpp b/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh.cpp index 49275d3eff7..21a77d7e702 100644 --- a/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh.cpp +++ b/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh.cpp @@ -4,34 +4,40 @@ #include #include - -#include +#include +#include +#include typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point; -typedef CGAL::Surface_mesh Mesh; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef Mesh::Property_map Vertex_distance_map; -typedef CGAL::Heat_method_3::Heat_method_3 Heat_method; +typedef Kernel::Point_2 Point_2; +typedef CGAL::Surface_mesh Surface_mesh; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef Surface_mesh::Property_map Vertex_distance_map; +typedef CGAL::Heat_method_3::Heat_method_3 Heat_method; -int main(int argc, char* argv[]) +int main(int argc, char* argv[]) { - Mesh sm; - std::ifstream in(argv[1]); + //read in mesh + Surface_mesh sm; + const char* filename = (argc > 1) ? argv[1] : "../data/bunny.off"; + std::ifstream in(filename); in >> sm; - Vertex_distance_map heat_intensity = - sm.add_property_map("v:heat_intensity", 0).first; + //the heat intensity will hold the distance values from the source set + Vertex_distance_map heat_intensity = sm.add_property_map("v:heat_intensity", 0).first; Heat_method hm(sm, heat_intensity); + //add the first vertex as the source set vertex_descriptor source = *(vertices(sm).first); hm.add_source(source); + hm.update(); BOOST_FOREACH(vertex_descriptor vd , vertices(sm)){ - std::cout << vd << " is at distance " << hm.distance(vd) << " from " << source << std::endl; + std::cout << vd << " is at distance " << get(heat_intensity, vd) << " from " << source << std::endl; } - std::cout << "done" << std::endl; return 0; } diff --git a/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh_intrinsic.cpp b/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh_intrinsic.cpp new file mode 100644 index 00000000000..dedc19003c8 --- /dev/null +++ b/Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh_intrinsic.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point; +typedef Kernel::Point_2 Point_2; +typedef CGAL::Surface_mesh Surface_mesh; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef Surface_mesh::Property_map Vertex_distance_map; +typedef CGAL::Intrinsic_Delaunay_Triangulation_3::Intrinsic_Delaunay_Triangulation_3 Idt; + +typedef CGAL::Heat_method_3::Heat_method_3 Heat_method_idt; + + +int main(int argc, char* argv[]) +{ + //read in mesh + Surface_mesh sm; + const char* filename = (argc > 1) ? argv[1] : "../data/bunny.off"; + std::ifstream in(filename); + in >> sm; + //the vertex distance map will hold the distance values from the source set + Vertex_distance_map vdm_idt = sm.add_property_map("v:idt",0).first; + //first call the idt remeshing algorithm + Idt idt(sm, vdm_idt); + + //pass in the idt object and its vertex_distance_map + Heat_method_idt hm_idt(idt, idt.vertex_distance_map()); + + //add the first vertex as the source set + vertex_descriptor source = *(vertices(sm).first); + hm_idt.add_source(source); + hm_idt.update(); + + BOOST_FOREACH(vertex_descriptor vd , vertices(sm)){ + std::cout << vd << " is at distance " << get(vdm_idt, vd) << " from " << source << std::endl; + } + + return 0; +}