From 0171659bcfede4f9f592e95e4e750901b091d91d Mon Sep 17 00:00:00 2001 From: Thien Hoang Date: Sun, 9 Jun 2019 15:18:17 +0700 Subject: [PATCH] Use attributes for vertices, remove boolean marks --- .../CGAL/Shortest_noncontractible_cycle.h | 88 ++++++++----------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h b/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h index 3962b901ff7..f689f2b3ca6 100644 --- a/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h +++ b/Surface_mesh_topology/include/CGAL/Shortest_noncontractible_cycle.h @@ -2,46 +2,56 @@ #define CGAL_SHORTEST_NONCONTRACTIBLE_CYCLE_H #include +#include namespace CGAL { template class Shortest_noncontractible_cycle { + public: - using Gmap = GeneralizedMap; + + using Gmap_origin = GeneralizedMap; + + struct Attributes { + template + struct Dart_wrapper { + using Vertex_attribute = CGAL::Cell_attribute; + using Edge_attribute = void; + using Face_attribute = void; + using Attributes = CGAL::cpp11::tuple; + }; + }; + + using Gmap = CGAL::Generalized_map<2, Attributes>; using Dart_handle = typename Gmap::Dart_handle; using size_type = typename Gmap::size_type; using Dart_const_handle = typename Gmap::Dart_const_handle; using Dart_container = std::vector; using Path = Dart_container; // Consider: CGAL::Path_on_surface; using Distance_type = int; - - Shortest_noncontractible_cycle(Gmap& gmap) : - m_gmap(gmap) { } - Path find_cycle(Dart_const_handle root) { + Shortest_noncontractible_cycle(const Gmap_origin& gmap) { + m_gmap.copy(gmap, &m_origin_to_copy, &m_copy_to_origin); + } + + Path find_cycle(typename Gmap_origin::Dart_const_handle root_vertex) { + Dart_handle root = m_origin_to_copy[root_vertex]; Dart_container spanning_tree, noncon_edges; std::vector distance_from_root; - std::vector index_marks; std::vector trace_index; BFS(root, spanning_tree, distance_from_root, trace_index); std::cerr << "Done BFS. spanning_tree.size() = " << spanning_tree.size() << '\n'; find_noncon_edges(spanning_tree, noncon_edges); std::cerr << "Done find_noncon_edges. noncon_edges.size() = " << noncon_edges.size() << '\n'; - mark_vertices_with_indices(spanning_tree, index_marks); - std::cerr << "Done mark_vertices_with_indices.\n"; Distance_type min_distance = -1; Dart_const_handle min_noncon_edge; int min_a = -1, min_b = -1; for (auto dh : noncon_edges) { Dart_const_handle a = dh, b = m_gmap.template alpha<0>(a); - int index_a = 0, index_b = 0; - for (int i = 0; i < index_marks.size(); ++i) { - if (m_gmap.is_marked(a, index_marks[i])) index_a ^= (1 << i); - if (m_gmap.is_marked(b, index_marks[i])) index_b ^= (1 << i); - } + int index_a = m_gmap.template info<0>(a), index_b = m_gmap.template info<0>(b); Distance_type sum_distance = distance_from_root[index_a] + distance_from_root[index_b]; if (min_distance < 0 || min_distance > sum_distance) { min_distance = sum_distance; @@ -51,9 +61,6 @@ public: } } - for (int i = 0; i < index_marks.size(); ++i) - m_gmap.free_mark(index_marks[i]); - Path cycle; if (min_distance < 0) return cycle; // empty cycle; // Trace back the path from `a` to root @@ -76,26 +83,21 @@ private: /// Create a spanning tree using BFS - void BFS(Dart_const_handle root, Dart_container& spanning_tree, + void BFS(Dart_handle root, Dart_container& spanning_tree, std::vector& distance_from_root, std::vector& trace_index) { - size_type vertex_visited; - try { - vertex_visited = m_gmap.get_new_mark(); - } catch (typename Gmap::Exception_no_more_available_mark) { - std::cerr << "No more free mark, exit." << std::endl; - exit(-1); - } // The first of pair is a dart of a 0-cell, // the second of pair is the index of the dart leading to this 0-cell in spanning_tree - std::queue > q; + std::queue > q; + int vertex_index = 0; // spanning_tree is empty (so far), so the index is -1 q.push(std::make_pair(root, -1)); - m_gmap.template mark_cell<0>(root, vertex_visited); + m_gmap.template set_attribute<0>(root, m_gmap.template create_attribute<0>()); + m_gmap.template info<0>(root) = vertex_index++; distance_from_root.push_back(0); // Note: distance_from_root will have n (= #0-cells) elements while spanning_tree only has n-1 while (q.size()) { - Dart_const_handle u = q.front().first; + Dart_handle u = q.front().first; int ind = q.front().second; q.pop(); // TODO: This iterator (one_dart_per_incident_cell) can have some overhead for time complexity @@ -103,9 +105,10 @@ private: 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_const_handle v = m_gmap.template alpha<0>(it); - if (!m_gmap.is_marked(v, vertex_visited)) { - m_gmap.template mark_cell<0>(v, vertex_visited); + Dart_handle v = m_gmap.template alpha<0>(it); + if (m_gmap.template attribute<0>(v) == NULL) { + m_gmap.template set_attribute<0>(v, m_gmap.template create_attribute<0>()); + m_gmap.template info<0>(v) = vertex_index++; if (ind == -1) distance_from_root.push_back(1); else @@ -118,7 +121,6 @@ private: } } } - m_gmap.free_mark(vertex_visited); } @@ -178,27 +180,9 @@ private: m_gmap.free_mark(face_deleted); } - void mark_vertices_with_indices(const Dart_container& spanning_tree, std::vector& index_marks) { - int n = spanning_tree.size()+1, bit_count = 0; - while (n) ++bit_count, n /= 2; - index_marks.resize(bit_count); - try { - for (int i = 0; i < index_marks.size(); ++i) - index_marks[i] = m_gmap.get_new_mark(); - } catch (typename Gmap::Exception_no_more_available_mark) { - std::cerr << "No more free mark, exit." << std::endl; - exit(-1); - } - n = 0; - for (auto dh : spanning_tree) { - ++n; - Dart_const_handle v = m_gmap.template alpha<0>(dh); - for (int i = 0; i < index_marks.size(); ++i) - if (n & (1 << i)) m_gmap.template mark_cell<0>(v, index_marks[i]); - } - } - - Gmap& m_gmap; + Gmap m_gmap; + boost::unordered_map m_origin_to_copy; + boost::unordered_map m_copy_to_origin; }; }