From d749d3f0032d7ca0bb0e6655e10d904c5f110cd5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 20 Nov 2018 18:21:19 +0100 Subject: [PATCH] Make iDT the default and explain O() complexity --- .../doc/Heat_method_3/Heat_method_3.txt | 41 ++++++++------ Heat_method_3/doc/Heat_method_3/examples.txt | 2 +- .../examples/Heat_method_3/CMakeLists.txt | 2 +- ...pp => heat_method_surface_mesh_direct.cpp} | 2 +- .../Surface_mesh_geodesic_distances_3.h | 8 +-- .../test/Heat_method_3/CMakeLists.txt | 2 +- ... heat_method_surface_mesh_direct_test.cpp} | 4 +- Heat_method_3/test/Heat_method_3/idt.cpp | 56 ------------------- 8 files changed, 35 insertions(+), 82 deletions(-) rename Heat_method_3/examples/Heat_method_3/{heat_method_surface_mesh_intrinsic.cpp => heat_method_surface_mesh_direct.cpp} (95%) rename Heat_method_3/test/Heat_method_3/{heat_method_surface_mesh_intrinsic_test.cpp => heat_method_surface_mesh_direct_test.cpp} (96%) delete mode 100644 Heat_method_3/test/Heat_method_3/idt.cpp 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 e883eaefc03..48f2721f5dc 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 @@ -26,7 +26,7 @@ on a fixed domain, since precomputation done for the first query can be re-used. As a rule of thumb, the method works well on triangle meshes, which are Delaunay, though in practice may also work fine for meshes that are far from -Delaunay. In order to ensure good behavior, one can optionally enable a +Delaunay. In order to ensure good behavior, we enable a preprocessing step that constructs an intrinsic Delaunay triangulation (iDT); this triangulation will not change the input geometry, but generally improves the quality of the solution. The cost of this preprocessing @@ -80,17 +80,15 @@ the distances with respect to these two sources. \cgalExample{Heat_method_3/heat_method_surface_mesh.cpp} -\subsection HM_example_Intrinsic Using the Intrinsic Delaunay Triangulation +\subsection HM_example_Intrinsic Switching off the Intrinsic Delaunay Triangulation -The following example shows the heat method on a triangle mesh using the -intrinsic Delaunay triangulation (iDT) algorithm. The iDT -should be used when the input mesh has poor quality, or when results of -distance computation appear to be highly inaccurate. (Poor quality in this -case means that the input is far from Delaunay, though even in this case -one may still get good results without iDT, depending on the specific -geometry of the surface.) +The following example shows the heat method on a triangle mesh without using the +intrinsic Delaunay triangulation (iDT) algorithm, for example because by constrution +your meshes have a good quality (Poor quality in this case means that the input +is far from Delaunay, though even in this case one may still get good results without iDT, +depending on the specific geometry of the surface.) -\cgalExample{Heat_method_3/heat_method_surface_mesh_intrinsic.cpp} +\cgalExample{Heat_method_3/heat_method_surface_mesh_direct.cpp} @@ -216,15 +214,26 @@ The algorithm is as follows: \section sec_HM_Performance Performance +The time complexity of the algorithm is determined primarily by the +choice of linear solver. In the current implementation, Cholesky +prefactorization is roughly \f$ O(N^1.5)\f$ and evaluation of distance is +roughly \f$ O(N)\f$, where \f$ N\f$ is the number of vertices in the triangulation. +The algorithm uses two \f$ N \times N\f$ matrices, both with the same pattern of +nonzeros as the graph Laplacian of the edge graph (roughly 7 nonzeros +per row/column). The cost of computation is independent of the size +of the source set. Primitive operations include sparse numerical +linear algebra (in double precision), and basic arithmetic operations +(including square roots). + We perform the benchmark on an Intel Core i7-7700HQ, 2.8HGz, and compiled with Visual Studio 2013.
-Number of triangles | Initialization (sec) | Distance computation (sec) | Initialization iDT (sec) | Distance computation iDT (sec) ---------------------:| ----------- : | ---------------- : | ------------------: | --------------: -30,000 | 0.12 | 0.01 | 0.18 | 0.02 -200,000 | 1.32 | 0.11 | 1.82 | 1.31 -500,000 | 8.07 | 0.55 | 10.45 | 0.75 -1,800,000 | 35.68 | 1.1 | 38.91 | 2.24 +Number of triangles | Initialization iDT (sec) | Distance computation iDT (sec) | Initialization Direct (sec) | Distance computation Direct (sec) +--------------------:| ----------- : | ---------------- : | ------------------: | --------------: +30,000 | 0.18 | 0.02 | 0.12 | 0.01 +200,000 | 1.82 | 1.31 | 1.32 | 0.11 +500,000 | 10.45 | 0.75 | 8.07 | 0.55 +1,800,000 | 38.91 | 2.24 | 35.68 | 1.1
diff --git a/Heat_method_3/doc/Heat_method_3/examples.txt b/Heat_method_3/doc/Heat_method_3/examples.txt index 089f321e369..0d5ef9a3621 100644 --- a/Heat_method_3/doc/Heat_method_3/examples.txt +++ b/Heat_method_3/doc/Heat_method_3/examples.txt @@ -2,5 +2,5 @@ \example Heat_method_3/heat_method.cpp \example Heat_method_3/heat_method_polyhedron.cpp \example Heat_method_3/heat_method_surface_mesh.cpp -\example Heat_method_3/heat_method_surface_mesh_intrinsic.cpp +\example Heat_method_3/heat_method_surface_mesh_direct.cpp */ diff --git a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt index ceb5dd6ffaf..bd784bb1f76 100644 --- a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt +++ b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt @@ -56,4 +56,4 @@ include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "heat_method.cpp" ) create_single_source_cgal_program( "heat_method_polyhedron.cpp" ) create_single_source_cgal_program( "heat_method_surface_mesh.cpp" ) -create_single_source_cgal_program( "heat_method_surface_mesh_intrinsic.cpp" ) +create_single_source_cgal_program( "heat_method_surface_mesh_direct.cpp" ) 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_direct.cpp similarity index 95% rename from Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh_intrinsic.cpp rename to Heat_method_3/examples/Heat_method_3/heat_method_surface_mesh_direct.cpp index 89ff35b71bf..32a4e3a959d 100644 --- 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_direct.cpp @@ -14,7 +14,7 @@ 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::Surface_mesh_geodesic_distances_3 Heat_method_idt; +typedef CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 Heat_method_idt; int main(int argc, char* argv[]) diff --git a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h index e4b5642d8dc..d0116cd1ff8 100644 --- a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h +++ b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h @@ -948,7 +948,7 @@ public: /// with `boost::graph_traits::%vertex_descriptor` as key type and `double` as value type. /// \tparam Mode either the tag `Direct` or `Intrinsic_Delaunay`, which determines if the geodesic distance /// is computed directly on the mesh or if the intrinsic Delaunay triangulation is applied first. -/// The default is `Direct`. +/// The default is `Intrinsic_Delaunay`. /// \warning The return type is `double` even when used with an exact kernel. /// /// \sa CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 @@ -972,7 +972,7 @@ estimate_geodesic_distances(const TriangleMesh& tm, VertexDistanceMap vdm, typename boost::graph_traits::vertex_descriptor source) { - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_source(source); hm.estimate_geodesic_distances(vdm); } @@ -989,7 +989,7 @@ estimate_geodesic_distances(const TriangleMesh& tm, /// \tparam VertexConstRange a model of the concept `ConstRange` with value type `boost::graph_traits::%vertex_descriptor` /// \tparam Mode either the tag `Direct` or `Intrinsic_Delaunay`, which determines if the geodesic distance /// is computed directly on the mesh or if the intrinsic Delaunay triangulation is applied first. -/// The default is `Direct`. +/// The default is `Intrinsic_Delaunay`. /// \warning The return type is `double` even when used with an exact kernel. /// \sa CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 template @@ -1020,7 +1020,7 @@ estimate_geodesic_distances(const TriangleMesh& tm, typename boost::has_range_const_iterator >::type* = 0) { - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_sources(sources); hm.estimate_geodesic_distances(vdm); } diff --git a/Heat_method_3/test/Heat_method_3/CMakeLists.txt b/Heat_method_3/test/Heat_method_3/CMakeLists.txt index 9367688a2fb..d498076d5b6 100644 --- a/Heat_method_3/test/Heat_method_3/CMakeLists.txt +++ b/Heat_method_3/test/Heat_method_3/CMakeLists.txt @@ -53,4 +53,4 @@ include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "heat_method_concept.cpp" ) create_single_source_cgal_program( "heat_method_surface_mesh_test.cpp" ) -create_single_source_cgal_program( "heat_method_surface_mesh_intrinsic_test.cpp" ) +create_single_source_cgal_program( "heat_method_surface_mesh_direct_test.cpp" ) diff --git a/Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_intrinsic_test.cpp b/Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_direct_test.cpp similarity index 96% rename from Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_intrinsic_test.cpp rename to Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_direct_test.cpp index 0f1daa617ef..710eed07757 100644 --- a/Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_intrinsic_test.cpp +++ b/Heat_method_3/test/Heat_method_3/heat_method_surface_mesh_direct_test.cpp @@ -12,7 +12,7 @@ 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::Surface_mesh_geodesic_distances_3 Heat_method; +typedef CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 Heat_method; @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) assert(sdistance < CGAL_PI); - CGAL::Heat_method_3::estimate_geodesic_distances(sm, vertex_distance, source, CGAL::Heat_method_3::Intrinsic_Delaunay()); + CGAL::Heat_method_3::estimate_geodesic_distances(sm, vertex_distance, source, CGAL::Heat_method_3::Direct()); sdistance = 0; BOOST_FOREACH(vertex_descriptor vd , vertices(sm)){ if(get(vertex_distance,vd) > sdistance){ diff --git a/Heat_method_3/test/Heat_method_3/idt.cpp b/Heat_method_3/test/Heat_method_3/idt.cpp deleted file mode 100644 index 1c01083b2c8..00000000000 --- a/Heat_method_3/test/Heat_method_3/idt.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#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 CGAL::Heat_method_3::Intrinsic_Delaunay_triangulation_3 Idt; - - -int validate(char* fname) -{ - std::string s(fname); - std::string base = s.substr(0,s.length()-4); - Surface_mesh sm; - - std::ifstream in(fname); - in >> sm; - if(!in || num_vertices(sm) == 0) { - std::cerr << "Problem loading the input data" << std::endl; - return 1; - } - - Idt idt(sm); - boost::property_map::type vpm = get(CGAL::vertex_point_t(),idt); - std::cout.precision(17); - BOOST_FOREACH(boost::graph_traits::face_descriptor fd, faces(idt)){ - BOOST_FOREACH(boost::graph_traits::vertex_descriptor vd, vertices_around_face(halfedge(fd,idt),idt)){ - std::cout << get(vpm, vd) << std::endl; - } - } - std::cout << "done" << std::endl; - - return 0; -} - -int main(int argc, char*argv[]) -{ - int res = 0; - for(int i=1; i < argc; i++){ - std::cout << "validate("<< argv[i] << ")"<< std::endl; - validate(argv[i]); - res++; - } - return res; -}