mirror of https://github.com/CGAL/cgal
Use attributes for vertices, remove boolean marks
This commit is contained in:
parent
e4dcdec00c
commit
0171659bcf
|
|
@ -2,46 +2,56 @@
|
|||
#define CGAL_SHORTEST_NONCONTRACTIBLE_CYCLE_H
|
||||
|
||||
#include <queue>
|
||||
#include <CGAL/Generalized_map.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class GeneralizedMap>
|
||||
class Shortest_noncontractible_cycle {
|
||||
|
||||
public:
|
||||
using Gmap = GeneralizedMap;
|
||||
|
||||
using Gmap_origin = GeneralizedMap;
|
||||
|
||||
struct Attributes {
|
||||
template <class GMap>
|
||||
struct Dart_wrapper {
|
||||
using Vertex_attribute = CGAL::Cell_attribute<GMap, int>;
|
||||
using Edge_attribute = void;
|
||||
using Face_attribute = void;
|
||||
using Attributes = CGAL::cpp11::tuple<Vertex_attribute, Edge_attribute, Face_attribute>;
|
||||
};
|
||||
};
|
||||
|
||||
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<Dart_const_handle>;
|
||||
using Path = Dart_container; // Consider: CGAL::Path_on_surface<Gmap>;
|
||||
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_type> distance_from_root;
|
||||
std::vector<size_type> index_marks;
|
||||
std::vector<int> 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<int>& distance_from_root, std::vector<int>& 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<std::pair<Dart_const_handle, int> > q;
|
||||
std::queue<std::pair<Dart_handle, int> > 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<size_type>& 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<typename Gmap_origin::Dart_const_handle, Dart_handle> m_origin_to_copy;
|
||||
boost::unordered_map<Dart_handle, typename Gmap_origin::Dart_const_handle> m_copy_to_origin;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue