diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_surface_mesh.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_surface_mesh.cpp new file mode 100644 index 00000000000..a51ac32abc7 --- /dev/null +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_surface_mesh.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +using Kernel = CGAL::Simple_cartesian; +using Point = Kernel::Point_3; +using Mesh = CGAL::Surface_mesh; + +struct Weight_functor { + using Weight_t = double; + Weight_functor(const Mesh& mesh) : m_mesh(mesh) {} + double operator()(Mesh::Halfedge_index he) const { + Point A = m_mesh.point(m_mesh.vertex(m_mesh.edge(he), 0)); + Point B = m_mesh.point(m_mesh.vertex(m_mesh.edge(he), 1)); + return CGAL::sqrt(CGAL::squared_distance(A, B)); + } +private: + Mesh m_mesh; +}; + +using SNC = CGAL::Shortest_noncontractible_cycle; + +int main(int argc, char* argv[]) { + std::cout << "Program edgewidth_surface_mesh started.\n"; + Mesh sm; + std::ifstream in ((argc > 1) ? argv[1] : "data/3torus-smooth.off"); + in >> sm; + std::cout << "File loaded. Running the main program...\n"; + Weight_functor wf(sm); + SNC snc(sm, wf); + SNC::Path cycle; + SNC::Distance_type x; + std::cout << "Finding edge-width of the mesh...\n"; + snc.edge_width(cycle, &x); + if (cycle.size() == 0) { + std::cout << " Cannot find edge-width. Stop.\n"; + return 0; + } + + std::cout << " Number of edges in cycle: " << cycle.size() << std::endl; + std::cout << " Cycle length: " << x << std::endl; + std::cout << " Root: " << sm.point(sm.vertex(sm.edge(cycle[0]), 0)) << std::endl; + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_through_a_vertex.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_through_a_vertex.cpp index 38a61c738c6..0c96c4826cb 100644 --- a/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_through_a_vertex.cpp +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_through_a_vertex.cpp @@ -39,8 +39,6 @@ private: const LCC_3& m_lcc; }; - -// using SNC = CGAL::Shortest_noncontractible_cycle; using SNC = CGAL::Shortest_noncontractible_cycle; LCC_3 lcc; diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_using_BFS.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_using_BFS.cpp index 20f25b31595..2d33475ecee 100644 --- a/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_using_BFS.cpp +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/shortest_noncontractible_cycle_using_BFS.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -9,45 +9,30 @@ #include #define CGAL_USE_BASIC_VIEWER 1 - -struct Myitem -{ - template - struct Dart_wrapper - { - typedef CGAL::Cell_attribute_with_point Vertex_attribute; - typedef CGAL::Cell_attribute_with_point Edge_attribute; - typedef CGAL::cpp11::tuple Attributes; - }; -}; - -using Traits = CGAL::Linear_cell_complex_traits<3>; -using LCC_3 = CGAL::Linear_cell_complex_for_generalized_map<2, 3, Traits, Myitem>; -using Dart_handle = LCC_3::Dart_handle; -using Dart_const_handle = LCC_3::Dart_const_handle; -using Dart_container = std::vector; - +using LCC_3 = CGAL::Linear_cell_complex_for_combinatorial_map<2, 3>; +using size_type = LCC_3::size_type; using SNC = CGAL::Shortest_noncontractible_cycle; LCC_3 lcc; struct Draw_functor : public CGAL::DefaultDrawingFunctorLCC { - Draw_functor() {} + Draw_functor(size_type edge_mark, size_type vertex_mark) : m_edge_mark(edge_mark), m_vertex_mark(vertex_mark) {} template bool colored_vertex(const LCC& alcc, typename LCC::Dart_const_handle dh) const - {return alcc.template info<0>(dh) != CGAL::Color();} + {return alcc.is_marked(dh, m_vertex_mark);} template CGAL::Color vertex_color(const LCC& alcc, typename LCC::Dart_const_handle dh) const - {return alcc.template info<0>(dh);} + {return CGAL::Color(255, 0, 0);} template - bool colored_edge(const LCC& alcc, typename LCC::Dart_const_handle dh) const { return true; } + bool colored_edge(const LCC& alcc, typename LCC::Dart_const_handle dh) const + { return alcc.is_marked(dh, m_edge_mark); } template CGAL::Color edge_color(const LCC& alcc, typename LCC::Dart_const_handle dh) const - {return alcc.template info<1>(dh);} + {return CGAL::Color(0, 0, 255);} template bool colored_face(const LCC& alcc, typename LCC::Dart_const_handle dh) const {return true;} @@ -58,20 +43,19 @@ struct Draw_functor : public CGAL::DefaultDrawingFunctorLCC { template bool colored_volume(const LCC& alcc, typename LCC::Dart_const_handle dh) const { return false; } + +private: + size_type m_edge_mark, m_vertex_mark; }; int main(int argc, char* argv[]) { std::cout << "Program shortest_noncontractible_cycle_using_BFS started.\n"; std::ifstream inp; - if (argc == 1) inp = std::ifstream("../../examples/Surface_mesh_topology/data/3torus.off"); + if (argc == 1) inp = std::ifstream("data/3torus-smooth.off"); else inp = std::ifstream(argv[1]); CGAL::load_off(lcc, inp); - for (auto it = lcc.darts().begin(), itend = lcc.darts().end(); it != itend; ++it) { - lcc.set_attribute<1>(it, lcc.create_attribute<1>()); - lcc.set_attribute<0>(it, lcc.create_attribute<0>()); - } std::cout << "File loaded. Running the main program...\n"; - Draw_functor df; + SNC snc(lcc); SNC::Path cycle; SNC::Distance_type x; @@ -82,18 +66,16 @@ int main(int argc, char* argv[]) { std::cout << " Cannot find such cycle. Stop.\n"; return 0; } - LCC_3::size_type m = lcc.get_new_mark(); + size_type m = lcc.get_new_mark(), is_root = lcc.get_new_mark(); for (auto e : cycle) { lcc.mark_cell<1>(e, m); } - lcc.info<0>(root) = CGAL::Color(255, 0, 0); - for (auto dh = lcc.one_dart_per_cell<1>().begin(), dhend = lcc.one_dart_per_cell<1>().end(); dh != dhend; ++dh) - if (lcc.is_marked(dh, m)) { - lcc.info<1>(dh) = CGAL::Color(0, 0, 255); - } - lcc.free_mark(m); + lcc.mark_cell<0>(root, is_root); std::cout << " Number of edges in cycle: " << cycle.size() << std::endl; std::cout << " Cycle length: " << x << std::endl; std::cout << " Root: " << lcc.point_of_vertex_attribute(lcc.vertex_attribute(root)) << std::endl; + Draw_functor df(m, is_root); CGAL::draw(lcc, "Hello", false, df); + lcc.free_mark(m); + lcc.free_mark(is_root); } diff --git a/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h b/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h index e4ea5e76280..9cbd072ce1e 100644 --- a/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h +++ b/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h @@ -3,6 +3,9 @@ #include #include +#include +#include +#include namespace CGAL { @@ -12,7 +15,6 @@ class Shortest_noncontractible_cycle { public: using Gmap_origin = GeneralizedMap; - using Dart_const_handle_orig = typename Gmap_origin::Dart_const_handle; template struct Weight_functor { using Weight = T; }; @@ -25,7 +27,7 @@ public: struct Default_weight_functor { using Weight_t = unsigned int; - Weight_t operator() (Dart_const_handle_orig) const { return 1; } + Weight_t operator() (...) const { return 1; } }; using Weight = typename Weight_functor_selector::value, @@ -43,7 +45,110 @@ public: }; }; - using Gmap = CGAL::Generalized_map<2, Attributes>; + struct SNC_for_generalized_map { + using Generic_map = CGAL::Generalized_map<2, Attributes>; + using Dart_const_handle_orig = typename Gmap_origin::Dart_const_handle; + using Copy_to_origin_map = boost::unordered_map; + using Origin_to_copy_map = boost::unordered_map; + + static typename Generic_map::Dart_handle Get_opposite(Generic_map& amap, typename Generic_map::Dart_handle dh) { + return amap.template opposite<2>(dh); + } + static void copy(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, Copy_to_origin_map& copy_to_origin) { + target.copy(source, &origin_to_copy, ©_to_origin); + } + static void set_weights(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, const Weight& wf) { + // source.display_characteristics(std::cout); + for (auto it = source.darts().begin(), itend = source.darts().end(); it != itend; ++it) { + target.template info<1>(origin_to_copy[it]) = wf(it); + } + } + }; + + struct SNC_for_combinatorial_map { + using Generic_map = CGAL::Combinatorial_map<2, Attributes>; + using Dart_const_handle_orig = typename Gmap_origin::Dart_const_handle; + using Copy_to_origin_map = boost::unordered_map; + using Origin_to_copy_map = boost::unordered_map; + + static typename Generic_map::Dart_handle Get_opposite(Generic_map& amap, typename Generic_map::Dart_handle dh) { + return amap.opposite(dh); + } + static void copy(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, Copy_to_origin_map& copy_to_origin) { + target.copy(source, &origin_to_copy, ©_to_origin); + } + static void set_weights(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, const Weight& wf) { + // source.display_characteristics(std::cout); + for (auto it = source.darts().begin(), itend = source.darts().end(); it != itend; ++it) { + target.template info<1>(origin_to_copy[it]) = wf(it); + } + } + }; + + template + struct Generic_map_selector { + using Generic_map = CGAL::Combinatorial_map<2, Attributes>; + using Dart_const_handle_orig = typename boost::graph_traits::halfedge_descriptor; + using Copy_to_origin_map = boost::unordered_map; + using Origin_to_copy_map = boost::unordered_map; + + static typename Generic_map::Dart_handle Get_opposite(Generic_map& amap, typename Generic_map::Dart_handle dh) { + return amap.opposite(dh); + } + static void copy(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, Copy_to_origin_map& copy_to_origin) { + target.import_from_halfedge_graph(source, &origin_to_copy, ©_to_origin); + } + static void set_weights(Generic_map& target, const Gmap_origin& source, + Origin_to_copy_map& origin_to_copy, const Weight& wf) { + for (auto it = source.halfedges().begin(), itend = source.halfedges().end(); it != itend; ++it) { + target.template info<1>(origin_to_copy[*it]) = wf(*it); + } + } + }; + + template + struct Generic_map_selector< CGAL::Generalized_map > : SNC_for_generalized_map {}; + + template + struct Generic_map_selector< CGAL::Generalized_map_base + > : SNC_for_generalized_map {}; + + template class Map, class Storage> + struct Generic_map_selector< CGAL::Linear_cell_complex_for_generalized_map + > : SNC_for_generalized_map {}; + + template + struct Generic_map_selector< CGAL::Combinatorial_map > : SNC_for_combinatorial_map {}; + + template + struct Generic_map_selector< CGAL::Combinatorial_map_base + > : SNC_for_combinatorial_map {}; + + template class Map, class Storage> + struct Generic_map_selector< CGAL::Linear_cell_complex_for_combinatorial_map + > : SNC_for_combinatorial_map {}; + + // template class Map, class Refs, class Storage> + // struct Generic_map_selector< CGAL::Linear_cell_complex_base + // > : SNC_for_combinatorial_map {}; + + using Gmap = typename Generic_map_selector::Generic_map; + using Gmap_wrapper = Generic_map_selector; + using Dart_const_handle_orig = typename Gmap_wrapper::Dart_const_handle_orig; using Dart_handle = typename Gmap::Dart_handle; using size_type = typename Gmap::size_type; using Dart_container = std::vector; @@ -51,7 +156,7 @@ public: Shortest_noncontractible_cycle(const Gmap_origin& gmap, const Weight& wf = Weight()) { - m_gmap.copy(gmap, &m_origin_to_copy, &m_copy_to_origin); + Gmap_wrapper::copy(m_gmap, gmap, m_origin_to_copy, m_copy_to_origin); // m_gmap.display_characteristics(std::cerr); // std::cerr << '\n'; // Initialize 2-attributes @@ -65,11 +170,8 @@ public: m_gmap.template set_attribute<0>(it, m_gmap.template create_attribute<0>()); } // Initialize 1-attributes - for (auto it = gmap.template one_dart_per_cell<1>().begin(), itend = gmap.template one_dart_per_cell<1>().end(); it != itend; ++it) { - Dart_handle img_dart = m_origin_to_copy[it]; - m_gmap.template info<1>(img_dart) = wf(it); - } - // Initialize 0-attributes + Gmap_wrapper::set_weights(m_gmap, gmap, m_origin_to_copy, wf); + // Count number of vertices for (auto it = m_gmap.template one_dart_per_cell<0>().begin(), itend = m_gmap.template one_dart_per_cell<0>().end(); it != itend; ++it) { ++m_nb_of_vertices; // m_gmap.template info<0>(it) = -1; @@ -144,12 +246,10 @@ private: while (pq.size()) { int u_index = pq.top(); pq.pop(); - Dart_handle u = (u_index == 0) ? root : m_gmap.template alpha<0>(spanning_tree[u_index - 1]); + Dart_handle u = (u_index == 0) ? root : m_gmap.next(spanning_tree[u_index - 1]); CGAL_assertion(u_index == m_gmap.template info<0>(u)); - bool first_run = true; - for (auto it = u; first_run || it != u; it = m_gmap.template alpha<2,1>(it)) { - first_run = false; - Dart_handle v = m_gmap.template alpha<0>(it); + for (auto it = m_gmap.template one_dart_per_incident_cell<1,0>(u).begin(), itend = m_gmap.template one_dart_per_incident_cell<1,0>(u).end(); it != itend; ++it) { + Dart_handle v = m_gmap.next(it); Distance_type w = m_gmap.template info<1>(it); if (!m_gmap.is_marked(v, vertex_visited)) { int v_index = ++vertex_index; @@ -197,11 +297,10 @@ private: while (q.size()) { int u_index = q.front(); q.pop(); - Dart_handle u = (u_index == 0) ? root : m_gmap.template alpha<0>(spanning_tree[u_index-1]); - bool first_run = true; - for (auto it = u; first_run || it != u; it = m_gmap.template alpha<2,1>(it)) { - first_run = false; - Dart_handle v = m_gmap.template alpha<0>(it); + Dart_handle u = (u_index == 0) ? root : m_gmap.next(spanning_tree[u_index - 1]); + CGAL_assertion(u_index == m_gmap.template info<0>(u)); + for (auto it = m_gmap.template one_dart_per_incident_cell<1,0>(u).begin(), itend = m_gmap.template one_dart_per_incident_cell<1,0>(u).end(); it != itend; ++it) { + Dart_handle v = m_gmap.next(it); if (!m_gmap.is_marked(v, vertex_visited)) { int v_index = ++vertex_index; distance_from_root.push_back(1 + distance_from_root[u_index]); @@ -235,6 +334,9 @@ private: return true; } + Dart_handle opposite(Dart_handle dh) { + return Gmap_wrapper::Get_opposite(m_gmap, dh); + } /// Find E_nc @@ -277,7 +379,7 @@ private: m_gmap.template mark_cell<2>(dh_face, face_deleted); if (!m_gmap.is_marked(dh_face, edge_deleted)) m_gmap.template mark_cell<1>(dh_face, edge_deleted); - Dart_handle dh_adj_face = m_gmap.template alpha<2>(dh_face); + Dart_handle dh_adj_face = opposite(dh_face); if (m_gmap.is_marked(dh_adj_face, face_deleted)) continue; Dart_handle dh_only_edge = NULL; if (is_degree_one_face(dh_adj_face, dh_only_edge, edge_deleted)) @@ -295,7 +397,7 @@ private: void add_to_cycle(Dart_handle dh, Path& cycle) { CGAL_assertion(dh != NULL); if (m_gmap.template attribute<2>(dh) == NULL) - dh = m_gmap.template alpha<2>(dh); + dh = opposite(dh); CGAL_assertion(m_gmap.template attribute<2>(dh) != NULL); cycle.push_back(m_copy_to_origin[dh]); } @@ -315,7 +417,7 @@ private: Dart_handle min_noncon_edge; int min_a = -1, min_b = -1; for (auto dh : m_noncon_edges) { - Dart_handle a = dh, b = m_gmap.template alpha<0>(dh); + Dart_handle a = dh, b = m_gmap.next(dh); int index_a = m_gmap.template info<0>(a), index_b = m_gmap.template info<0>(b); Distance_type sum_distance = m_distance_from_root[index_a] + m_distance_from_root[index_b] + m_gmap.template info<1>(dh); @@ -341,15 +443,15 @@ private: add_to_cycle(min_noncon_edge, cycle); // Trace back the path from `b` to root for (int ind = min_b - 1; ind != -1; ind = m_trace_index[ind]) - add_to_cycle(m_gmap.template alpha<0>(m_spanning_tree[ind]), cycle); + add_to_cycle(opposite(m_spanning_tree[ind]), cycle); // CGAL_assertion(cycle.is_closed()); return true; } Gmap m_gmap; - boost::unordered_map m_origin_to_copy; - boost::unordered_map m_copy_to_origin; + typename Gmap_wrapper::Origin_to_copy_map m_origin_to_copy; + typename Gmap_wrapper::Copy_to_origin_map m_copy_to_origin; unsigned int m_nb_of_vertices = 0; Dart_container m_spanning_tree, m_noncon_edges; std::vector m_distance_from_root;