summaryrefslogtreecommitdiff
path: root/src/Skeleton_blocker/include
diff options
context:
space:
mode:
authorsalinasd <salinasd@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2015-02-06 16:54:41 +0000
committersalinasd <salinasd@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2015-02-06 16:54:41 +0000
commite50f918673baf48d35c2e2ffa7bfc0e23206612f (patch)
treea6bdbb0a32b1f42cb622f673f55875b0eb421ea1 /src/Skeleton_blocker/include
parent8802dc5353020c75012f6ae8c26afefb4c78b161 (diff)
skbl nettoyage + suppression Skeleton_blocker_simplifiable_complex
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@464 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d0d2441ac3f6e3c4d16b0f0da098b090ce8743dd
Diffstat (limited to 'src/Skeleton_blocker/include')
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h17
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h281
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h6
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h1140
4 files changed, 906 insertions, 538 deletions
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h
index 7057437c..049db6d5 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h
+++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h
@@ -93,16 +93,17 @@ their simplices.
\subsection Overview
-Four classes are implemented for simplicial complex in this representation namely (most user will just need to use Skeleton_blocker_geometric_complex):
+Two main classes of this package are Skeleton_blocker_complex and Skeleton_blocker_geometric_complex.
+The first one can be used to represent an abstract simplicial complex and supports most used
+operations in a simplicial complex such as :
-\li Skeleton_blocker_complex : a simplicial complex with basic operations such as vertex/edge/simplex enumeration and construction
-\li Skeleton_blocker_link_complex : the link of a simplex in a parent complex. It is represented as a sub complex
-of the parent complex
-\li Skeleton_blocker_simplifiable_complex : a simplicial complex with simplification operations such as edge contraction or simplex collapse
-\li Skeleton_blocker_geometric_complex : a simplifiable simplicial complex who has access to geometric points in \f$R^d\f$
+\li vertex/edge/simplex enumeration
+\li simplifications operations such as remove star, add star (e.g. general form of collapse),
+edge contractions
+
+The class Skeleton_blocker_geometric_complex supports the same methods as Skeleton_blocker_complex
+and point access in addition.
-The two last classes are derived classes from the Skeleton_blocker_complex class. The class Skeleton_blocker_link_complex inheritates from a template passed parameter
-that may be either Skeleton_blocker_complex or Skeleton_blocker_geometric_complex (a link may store points coordinates or not).
\subsection Visitor
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h
index 12555904..7b7ac7a9 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h
+++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h
@@ -302,6 +302,31 @@ class Skeleton_blocker_complex {
return *this;
}
+
+ /**
+ * return true if both complexes have the same simplices.
+ */
+ bool operator==(const Skeleton_blocker_complex& other) const{
+ if(other.num_vertices() != num_vertices()) return false;
+ if(other.num_edges() != num_edges()) return false;
+ if(other.num_blockers() != num_blockers()) return false;
+
+ for(auto v : vertex_range())
+ if(!other.contains_vertex(v)) return false;
+
+ for(auto e : edge_range())
+ if(!other.contains_edge(first_vertex(e),second_vertex(e))) return false;
+
+ for(const auto b : const_blocker_range())
+ if(!other.contains_blocker(*b)) return false;
+
+ return true;
+ }
+
+ bool operator!=(const Skeleton_blocker_complex& other) const{
+ return !(*this == other);
+ }
+
/**
* The destructor delete all blockers allocated.
*/
@@ -763,7 +788,7 @@ class Skeleton_blocker_complex {
Vertex_handle a = s->first_vertex();
- for (auto blocker : const_blocker_range(a)) {
+ for (const auto blocker : const_blocker_range(a)) {
if (s == *blocker)
return true;
}
@@ -864,6 +889,29 @@ class Skeleton_blocker_complex {
}
public:
+ typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex> Link_complex;
+
+ /**
+ * Constructs the link of 'simplex' with points coordinates.
+ */
+ Link_complex link(Vertex_handle v) const {
+ return Link_complex(*this, Simplex_handle(v));
+ }
+
+ /**
+ * Constructs the link of 'simplex' with points coordinates.
+ */
+ Link_complex link(Edge_handle edge) const {
+ return Link_complex(*this, edge);
+ }
+
+ /**
+ * Constructs the link of 'simplex' with points coordinates.
+ */
+ Link_complex link(const Simplex_handle& simplex) const {
+ return Link_complex(*this, simplex);
+ }
+
/**
* @brief Compute the local vertices of 's' in the current complex
* If one of them is not present in the complex then the return value is uninitialized.
@@ -986,7 +1034,216 @@ class Skeleton_blocker_complex {
}
//@}
-
+ /** @Simplification operations
+ */
+ //@{
+
+ /**
+ * Returns true iff the blocker 'sigma' is popable.
+ * To define popable, let us call 'L' the complex that
+ * consists in the current complex without the blocker 'sigma'.
+ * A blocker 'sigma' is then "popable" if the link of 'sigma'
+ * in L is reducible.
+ *
+ */
+ bool is_popable_blocker(Blocker_handle sigma) const;
+
+ /**
+ * Removes all the popable blockers of the complex and delete them.
+ * @returns the number of popable blockers deleted
+ */
+ void remove_popable_blockers();
+
+ /**
+ * Removes all the popable blockers of the complex passing through v and delete them.
+ */
+ void remove_popable_blockers(Vertex_handle v);
+
+ /**
+ * @brief Removes all the popable blockers of the complex passing through v and delete them.
+ * Also remove popable blockers in the neighborhood if they became popable.
+ *
+ */
+ void remove_all_popable_blockers(Vertex_handle v);
+
+ /**
+ * Remove the star of the vertex 'v'
+ */
+ void remove_star(Vertex_handle v) ;
+
+private:
+ /**
+ * after removing the star of a simplex, blockers sigma that contains this simplex must be removed.
+ * Furthermore, all simplices tau of the form sigma \setminus simplex_to_be_removed must be added
+ * whenever the dimension of tau is at least 2.
+ */
+ void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed);
+
+public:
+ /**
+ * Remove the star of the edge connecting vertices a and b.
+ * @returns the number of blocker that have been removed
+ */
+ void remove_star(Vertex_handle a, Vertex_handle b) ;
+
+ /**
+ * Remove the star of the edge 'e'.
+ */
+ void remove_star(Edge_handle e) ;
+
+ /**
+ * Remove the star of the simplex 'sigma' which needs to belong to the complex
+ */
+ void remove_star(const Simplex_handle& sigma);
+
+ /**
+ * @brief add a maximal simplex plus all its cofaces.
+ * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
+ */
+ void add_simplex(const Simplex_handle& sigma);
+
+private:
+ /**
+ * remove all blockers that contains sigma
+ */
+ void remove_blocker_containing_simplex(const Simplex_handle& sigma) ;
+
+ /**
+ * remove all blockers that contains sigma
+ */
+ void remove_blocker_include_in_simplex(const Simplex_handle& sigma);
+
+public:
+ enum simplifiable_status {
+ NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
+ };
+
+ simplifiable_status is_remove_star_homotopy_preserving(const Simplex_handle& simplex) {
+ // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of Skeleton_blocker_geometric_complex
+ // then call it there to build the link and return the value of link.is_contractible()
+ return MAYBE_HOMOTOPY_EQ;
+ }
+
+ enum contractible_status {
+ NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
+ };
+
+ /**
+ * @brief %Test if the complex is reducible using a strategy defined in the class
+ * (by default it tests if the complex is a cone)
+ * @details Note that NO could be returned if some invariant ensures that the complex
+ * is not a point (for instance if the euler characteristic is different from 1).
+ * This function will surely have to return MAYBE in some case because the
+ * associated problem is undecidable but it in practice, it can often
+ * be solved with the help of geometry.
+ */
+ virtual contractible_status is_contractible() const {
+ if (this->is_cone()) {
+ return CONTRACTIBLE;
+ } else {
+ return MAYBE_CONTRACTIBLE;
+ }
+ }
+ //@}
+
+ /** @Edge contraction operations
+ */
+ //@{
+
+ /**
+ * @return If ignore_popable_blockers is true
+ * then the result is true iff the link condition at edge ab is satisfied
+ * or equivalently iff no blocker contains ab.
+ * If ignore_popable_blockers is false then the
+ * result is true iff all blocker containing ab are popable.
+ */
+ bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const{
+ for (auto blocker : this->const_blocker_range(a))
+ if (blocker->contains(b)) {
+ // false if ignore_popable_blockers is false
+ // otherwise the blocker has to be popable
+ return ignore_popable_blockers && is_popable_blocker(blocker);
+ }
+ return true;
+
+ }
+
+ /**
+ * @return If ignore_popable_blockers is true
+ * then the result is true iff the link condition at edge ab is satisfied
+ * or equivalently iff no blocker contains ab.
+ * If ignore_popable_blockers is false then the
+ * result is true iff all blocker containing ab are popable.
+ */
+ bool link_condition(Edge_handle e, bool ignore_popable_blockers = false) const {
+ const Graph_edge& edge = (*this)[e];
+ assert(this->get_address(edge.first()));
+ assert(this->get_address(edge.second()));
+ Vertex_handle a(*this->get_address(edge.first()));
+ Vertex_handle b(*this->get_address(edge.second()));
+ return link_condition(a, b, ignore_popable_blockers);
+ }
+
+protected:
+ /**
+ * Compute simplices beta such that a.beta is an order 0 blocker
+ * that may be used to construct a new blocker after contracting ab.
+ * It requires that the link condition is satisfied.
+ */
+ void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const;
+
+private:
+ /**
+ * @brief "Replace" the edge 'bx' by the edge 'ax'.
+ * Assume that the edge 'bx' was present whereas 'ax' was not.
+ * Precisely, it does not replace edges, but remove 'bx' and then add 'ax'.
+ * The visitor 'on_swaped_edge' is called just after edge 'ax' had been added
+ * and just before edge 'bx' had been removed. That way, it can
+ * eventually access to information of 'ax'.
+ */
+ void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x);
+
+private:
+ /**
+ * @brief removes all blockers passing through the edge 'ab'
+ */
+ void delete_blockers_around_vertex(Vertex_handle v);
+
+ /**
+ * @brief removes all blockers passing through the edge 'ab'
+ */
+ void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b);
+
+public:
+ /**
+ * Contracts the edge.
+ * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
+ * it removes first all blockers passing through 'ab'
+ */
+ void contract_edge(Edge_handle edge) {
+ contract_edge(this->first_vertex(edge), this->second_vertex(edge));
+ }
+
+ /**
+ * Contracts the edge connecting vertices a and b.
+ * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
+ * it removes first all blockers passing through 'ab'
+ */
+ void contract_edge(Vertex_handle a, Vertex_handle b);
+
+private:
+ void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b, std::set<Simplex_handle>& blockers_to_add);
+
+ /**
+ * delete all blockers that passes through a or b
+ */
+ void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b);
+ void update_edges_after_contraction(Vertex_handle a, Vertex_handle b) ;
+
+ void notify_changed_edges(Vertex_handle a) ;
+ //@}
+
+public:
/////////////////////////////////////////////////////////////////////////////
/** @name Vertex iterators
*/
@@ -1259,10 +1516,16 @@ class Skeleton_blocker_complex {
stream << *b << std::endl;
return stream.str();
}
-
//@}
+
+
+
+
+
};
+
+
/**
* build a simplicial complex from a collection
* of top faces.
@@ -1342,20 +1605,14 @@ Complex make_complex_from_top_faces(SimplexHandleIterator simplex_begin, Simplex
}
}
return complex;
- // std::vector<Simplex_handle> simplices;
- //
- // for (auto top_face = simplex_begin; top_face != simplex_end; ++top_face) {
- // auto subfaces_topface = subfaces(*top_face);
- // simplices.insert(simplices.end(),subfaces_topface.begin(),subfaces_topface.end());
- // }
- //
- // complex = Complex(simplices.begin(),simplices.end());
- // return simplices.size();
}
} // namespace skbl
} // namespace Gudhi
+#include "Skeleton_blocker_simplifiable_complex.h"
+
+
#endif // SRC_SKELETON_BLOCKER_INCLUDE_GUDHI_SKELETON_BLOCKER_COMPLEX_H_
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h
index e6656a95..f2c1e447 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h
+++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h
@@ -23,7 +23,7 @@
#define SRC_SKELETON_BLOCKER_INCLUDE_GUDHI_SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_
#include "gudhi/Utils.h"
-#include "gudhi/Skeleton_blocker_simplifiable_complex.h"
+#include "gudhi/Skeleton_blocker_complex.h"
#include "gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h"
namespace Gudhi {
@@ -37,11 +37,11 @@ namespace skbl {
*/
template<typename SkeletonBlockerGeometricDS>
class Skeleton_blocker_geometric_complex :
-public Skeleton_blocker_simplifiable_complex<SkeletonBlockerGeometricDS> {
+public Skeleton_blocker_complex<SkeletonBlockerGeometricDS> {
public:
typedef typename SkeletonBlockerGeometricDS::GT GT;
- typedef Skeleton_blocker_simplifiable_complex<SkeletonBlockerGeometricDS> SimplifiableSkeletonblocker;
+ typedef Skeleton_blocker_complex<SkeletonBlockerGeometricDS> SimplifiableSkeletonblocker;
typedef typename SimplifiableSkeletonblocker::Vertex_handle Vertex_handle;
typedef typename SimplifiableSkeletonblocker::Root_vertex_handle Root_vertex_handle;
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h
index db17fb28..163fb7e3 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h
+++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h
@@ -32,524 +32,634 @@ namespace Gudhi {
namespace skbl {
+///**
+// * \brief Class that allows simplification operation on a simplicial complex represented
+// * by a skeleton/blockers pair.
+// * \ingroup skbl
+// * @extends Skeleton_blocker_complex
+// */
+//template<typename SkeletonBlockerDS>
+//class Skeleton_blocker_complex : public Skeleton_blocker_complex<SkeletonBlockerDS> {
+// template<class ComplexType> friend class Skeleton_blocker_sub_complex;
+//
+//public:
+// typedef Skeleton_blocker_complex<SkeletonBlockerDS> SkeletonBlockerComplex;
+//
+// typedef typename SkeletonBlockerComplex::Graph_edge Graph_edge;
+//
+// typedef typename SkeletonBlockerComplex::boost_adjacency_iterator boost_adjacency_iterator;
+// typedef typename SkeletonBlockerComplex::Edge_handle Edge_handle;
+// typedef typename SkeletonBlockerComplex::boost_vertex_handle boost_vertex_handle;
+// typedef typename SkeletonBlockerComplex::Vertex_handle Vertex_handle;
+// typedef typename SkeletonBlockerComplex::Root_vertex_handle Root_vertex_handle;
+// typedef typename SkeletonBlockerComplex::Simplex_handle Simplex_handle;
+// typedef typename SkeletonBlockerComplex::Root_simplex_handle Root_simplex_handle;
+// typedef typename SkeletonBlockerComplex::Blocker_handle Blocker_handle;
+//
+//
+// typedef typename SkeletonBlockerComplex::Root_simplex_iterator Root_simplex_iterator;
+// typedef typename SkeletonBlockerComplex::Simplex_handle_iterator Simplex_handle_iterator;
+// typedef typename SkeletonBlockerComplex::BlockerMap BlockerMap;
+// typedef typename SkeletonBlockerComplex::BlockerPair BlockerPair;
+// typedef typename SkeletonBlockerComplex::BlockerMapIterator BlockerMapIterator;
+// typedef typename SkeletonBlockerComplex::BlockerMapConstIterator BlockerMapConstIterator;
+//
+// typedef typename SkeletonBlockerComplex::Visitor Visitor;
+//
+//
+// /** @name Constructors / Destructors / Initialization
+// */
+// //@{
+//
+// explicit Skeleton_blocker_complex(int num_vertices_ = 0, Visitor* visitor_ = NULL) :
+// Skeleton_blocker_complex<SkeletonBlockerDS>(num_vertices_, visitor_) { }
+//
+// /**
+// * @brief Constructor with a list of simplices
+// * @details The list of simplices must be the list
+// * of simplices of a simplicial complex, sorted with increasing dimension.
+// */
+// //soon deprecated
+// explicit Skeleton_blocker_complex(std::list<Simplex_handle>& simplices, Visitor* visitor_ = NULL) :
+// Skeleton_blocker_complex<SkeletonBlockerDS>(simplices, visitor_) { }
+//
+// /**
+// * @brief Constructor with a list of simplices
+// * @details The list of simplices must be the list of simplices of a simplicial complex.
+// */
+// template<typename SimpleHandleOutputIterator>
+// explicit Skeleton_blocker_complex(SimpleHandleOutputIterator simplex_begin,SimpleHandleOutputIterator simplex_end,bool is_flag_complex = false,Visitor* visitor_ = NULL) :
+// Skeleton_blocker_complex<SkeletonBlockerDS>(simplex_begin,simplex_end,is_flag_complex, visitor_) { }
+//
+//
+// virtual ~Skeleton_blocker_complex() { }
+//
+// //@}
+//
+// /**
+// * Returns true iff the blocker 'sigma' is popable.
+// * To define popable, let us call 'L' the complex that
+// * consists in the current complex without the blocker 'sigma'.
+// * A blocker 'sigma' is then "popable" if the link of 'sigma'
+// * in L is reducible.
+// *
+// */
+// bool is_popable_blocker(Blocker_handle sigma) const;
+//
+// /**
+// * Removes all the popable blockers of the complex and delete them.
+// * @returns the number of popable blockers deleted
+// */
+// void remove_popable_blockers();
+//
+// /**
+// * Removes all the popable blockers of the complex passing through v and delete them.
+// */
+// void remove_popable_blockers(Vertex_handle v);
+//
+// /**
+// * @brief Removes all the popable blockers of the complex passing through v and delete them.
+// * Also remove popable blockers in the neighborhood if they became popable.
+// *
+// */
+// void remove_all_popable_blockers(Vertex_handle v);
+//
+// /**
+// * Remove the star of the vertex 'v'
+// */
+// void remove_star(Vertex_handle v) ;
+//
+//private:
+// /**
+// * after removing the star of a simplex, blockers sigma that contains this simplex must be removed.
+// * Furthermore, all simplices tau of the form sigma \setminus simplex_to_be_removed must be added
+// * whenever the dimension of tau is at least 2.
+// */
+// void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed);
+//
+//public:
+// /**
+// * Remove the star of the edge connecting vertices a and b.
+// * @returns the number of blocker that have been removed
+// */
+// void remove_star(Vertex_handle a, Vertex_handle b) ;
+//
+// /**
+// * Remove the star of the edge 'e'.
+// */
+// void remove_star(Edge_handle e) ;
+//
+// /**
+// * Remove the star of the simplex 'sigma' which needs to belong to the complex
+// */
+// void remove_star(const Simplex_handle& sigma);
+//
+// /**
+// * @brief add a maximal simplex plus all its cofaces.
+// * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
+// */
+// void add_simplex(const Simplex_handle& sigma);
+//
+//private:
+// /**
+// * remove all blockers that contains sigma
+// */
+// void remove_blocker_containing_simplex(const Simplex_handle& sigma) ;
+//
+// /**
+// * remove all blockers that contains sigma
+// */
+// void remove_blocker_include_in_simplex(const Simplex_handle& sigma);
+//
+//public:
+// enum simplifiable_status {
+// NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
+// };
+//
+// simplifiable_status is_remove_star_homotopy_preserving(const Simplex_handle& simplex) {
+// // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of Skeleton_blocker_geometric_complex
+// // then call it there to build the link and return the value of link.is_contractible()
+// return MAYBE_HOMOTOPY_EQ;
+// }
+//
+// enum contractible_status {
+// NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
+// };
+//
+// /**
+// * @brief %Test if the complex is reducible using a strategy defined in the class
+// * (by default it tests if the complex is a cone)
+// * @details Note that NO could be returned if some invariant ensures that the complex
+// * is not a point (for instance if the euler characteristic is different from 1).
+// * This function will surely have to return MAYBE in some case because the
+// * associated problem is undecidable but it in practice, it can often
+// * be solved with the help of geometry.
+// */
+// virtual contractible_status is_contractible() const {
+// if (this->is_cone()) {
+// return CONTRACTIBLE;
+// } else {
+// return MAYBE_CONTRACTIBLE;
+// }
+// }
+//
+// /** @Edge contraction operations
+// */
+// //@{
+//
+// /**
+// * @return If ignore_popable_blockers is true
+// * then the result is true iff the link condition at edge ab is satisfied
+// * or equivalently iff no blocker contains ab.
+// * If ignore_popable_blockers is false then the
+// * result is true iff all blocker containing ab are popable.
+// */
+// bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const{
+// for (auto blocker : this->const_blocker_range(a))
+// if (blocker->contains(b)) {
+// // false if ignore_popable_blockers is false
+// // otherwise the blocker has to be popable
+// return ignore_popable_blockers && is_popable_blocker(blocker);
+// }
+// return true;
+//
+// }
+//
+// /**
+// * @return If ignore_popable_blockers is true
+// * then the result is true iff the link condition at edge ab is satisfied
+// * or equivalently iff no blocker contains ab.
+// * If ignore_popable_blockers is false then the
+// * result is true iff all blocker containing ab are popable.
+// */
+// bool link_condition(Edge_handle e, bool ignore_popable_blockers = false) const {
+// const Graph_edge& edge = (*this)[e];
+// assert(this->get_address(edge.first()));
+// assert(this->get_address(edge.second()));
+// Vertex_handle a(*this->get_address(edge.first()));
+// Vertex_handle b(*this->get_address(edge.second()));
+// return link_condition(a, b, ignore_popable_blockers);
+// }
+//
+//protected:
+// /**
+// * Compute simplices beta such that a.beta is an order 0 blocker
+// * that may be used to construct a new blocker after contracting ab.
+// * It requires that the link condition is satisfied.
+// */
+// void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const;
+//
+//private:
+// /**
+// * @brief "Replace" the edge 'bx' by the edge 'ax'.
+// * Assume that the edge 'bx' was present whereas 'ax' was not.
+// * Precisely, it does not replace edges, but remove 'bx' and then add 'ax'.
+// * The visitor 'on_swaped_edge' is called just after edge 'ax' had been added
+// * and just before edge 'bx' had been removed. That way, it can
+// * eventually access to information of 'ax'.
+// */
+// void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x);
+//
+//private:
+// /**
+// * @brief removes all blockers passing through the edge 'ab'
+// */
+// void delete_blockers_around_vertex(Vertex_handle v);
+//
+// /**
+// * @brief removes all blockers passing through the edge 'ab'
+// */
+// void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b);
+//
+//public:
+// /**
+// * Contracts the edge.
+// * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
+// * it removes first all blockers passing through 'ab'
+// */
+// void contract_edge(Edge_handle edge) {
+// contract_edge(this->first_vertex(edge), this->second_vertex(edge));
+// }
+//
+// /**
+// * Contracts the edge connecting vertices a and b.
+// * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
+// * it removes first all blockers passing through 'ab'
+// */
+// void contract_edge(Vertex_handle a, Vertex_handle b);
+//
+//private:
+// void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b, std::set<Simplex_handle>& blockers_to_add);
+//
+// /**
+// * delete all blockers that passes through a or b
+// */
+// void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b);
+// void update_edges_after_contraction(Vertex_handle a, Vertex_handle b) ;
+//
+// void notify_changed_edges(Vertex_handle a) ;
+// //@}
+//};
+
+
+
+template<typename SkeletonBlockerDS>
+bool Skeleton_blocker_complex<SkeletonBlockerDS>::is_popable_blocker(Blocker_handle sigma) const {
+ assert(this->contains_blocker(*sigma));
+ Skeleton_blocker_link_complex<Skeleton_blocker_complex> link_blocker_sigma;
+ build_link_of_blocker(*this, *sigma, link_blocker_sigma);
+
+ bool res = link_blocker_sigma.is_contractible() == CONTRACTIBLE;
+ return res;
+}
+
+
+/**
+ * Removes all the popable blockers of the complex and delete them.
+ * @returns the number of popable blockers deleted
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_popable_blockers() {
+ std::list<Vertex_handle> vertex_to_check;
+ for (auto v : this->vertex_range())
+ vertex_to_check.push_front(v);
+
+ while (!vertex_to_check.empty()) {
+ Vertex_handle v = vertex_to_check.front();
+ vertex_to_check.pop_front();
+
+ bool blocker_popable_found = true;
+ while (blocker_popable_found) {
+ blocker_popable_found = false;
+ for (auto block : this->blocker_range(v)) {
+ if (this->is_popable_blocker(block)) {
+ for (Vertex_handle nv : *block)
+ if (nv != v) vertex_to_check.push_back(nv);
+ this->delete_blocker(block);
+ blocker_popable_found = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Removes all the popable blockers of the complex passing through v and delete them.
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_popable_blockers(Vertex_handle v) {
+ bool blocker_popable_found = true;
+ while (blocker_popable_found) {
+ blocker_popable_found = false;
+ for (auto block : this->blocker_range(v)) {
+ if (is_popable_blocker(block)) {
+ this->delete_blocker(block);
+ blocker_popable_found = true;
+ }
+ }
+ }
+}
+
+/**
+ * @brief Removes all the popable blockers of the complex passing through v and delete them.
+ * Also remove popable blockers in the neighborhood if they became popable.
+ *
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_all_popable_blockers(Vertex_handle v) {
+ std::list<Vertex_handle> vertex_to_check;
+ vertex_to_check.push_front(v);
+
+ while (!vertex_to_check.empty()) {
+ Vertex_handle v = vertex_to_check.front();
+ vertex_to_check.pop_front();
+
+ bool blocker_popable_found = true;
+ while (blocker_popable_found) {
+ blocker_popable_found = false;
+ for (auto block : this->blocker_range(v)) {
+ if (this->is_popable_blocker(block)) {
+ for (Vertex_handle nv : *block)
+ if (nv != v) vertex_to_check.push_back(nv);
+ this->delete_blocker(block);
+ blocker_popable_found = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Vertex_handle v) {
+ // we remove the blockers that are not consistent anymore
+ update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(v));
+ while (this->degree(v) > 0) {
+ Vertex_handle w(* (adjacent_vertices(v.vertex, this->skeleton).first));
+ this->remove_edge(v, w);
+ }
+ this->remove_vertex(v);
+}
+
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed) {
+ std::list <Blocker_handle> blockers_to_update;
+ if (simplex_to_be_removed.empty()) return;
+
+ auto v0 = simplex_to_be_removed.first_vertex();
+ for (auto blocker : this->blocker_range(v0)) {
+ if (blocker->contains(simplex_to_be_removed))
+ blockers_to_update.push_back(blocker);
+ }
+
+ for (auto blocker_to_update : blockers_to_update) {
+ Simplex_handle sub_blocker_to_be_added;
+ bool sub_blocker_need_to_be_added =
+ (blocker_to_update->dimension() - simplex_to_be_removed.dimension()) >= 2;
+ if (sub_blocker_need_to_be_added) {
+ sub_blocker_to_be_added = *blocker_to_update;
+ sub_blocker_to_be_added.difference(simplex_to_be_removed);
+ }
+ this->delete_blocker(blocker_to_update);
+ if (sub_blocker_need_to_be_added)
+ this->add_blocker(sub_blocker_to_be_added);
+ }
+}
+
+
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Vertex_handle a, Vertex_handle b) {
+ update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(a, b));
+ // we remove the edge
+ this->remove_edge(a, b);
+}
+
+/**
+ * Remove the star of the edge 'e'.
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Edge_handle e) {
+ return remove_star(this->first_vertex(e), this->second_vertex(e));
+}
+
+
+
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(const Simplex_handle& sigma) {
+ assert(this->contains(sigma));
+ if (sigma.dimension() == 0) {
+ remove_star(sigma.first_vertex());
+ } else if (sigma.dimension() == 1) {
+ remove_star(sigma.first_vertex(), sigma.last_vertex());
+ } else {
+ remove_blocker_containing_simplex(sigma);
+ this->add_blocker(sigma);
+ }
+}
+
/**
- * \brief Class that allows simplification operation on a simplicial complex represented
- * by a skeleton/blockers pair.
- * \ingroup skbl
- * @extends Skeleton_blocker_complex
+ * @brief add a maximal simplex plus all its cofaces.
+ * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
*/
template<typename SkeletonBlockerDS>
-class Skeleton_blocker_simplifiable_complex : public Skeleton_blocker_complex<SkeletonBlockerDS> {
- template<class ComplexType> friend class Skeleton_blocker_sub_complex;
-
- public:
- typedef Skeleton_blocker_complex<SkeletonBlockerDS> SkeletonBlockerComplex;
-
- typedef typename SkeletonBlockerComplex::Graph_edge Graph_edge;
-
- typedef typename SkeletonBlockerComplex::boost_adjacency_iterator boost_adjacency_iterator;
- typedef typename SkeletonBlockerComplex::Edge_handle Edge_handle;
- typedef typename SkeletonBlockerComplex::boost_vertex_handle boost_vertex_handle;
- typedef typename SkeletonBlockerComplex::Vertex_handle Vertex_handle;
- typedef typename SkeletonBlockerComplex::Root_vertex_handle Root_vertex_handle;
- typedef typename SkeletonBlockerComplex::Simplex_handle Simplex_handle;
- typedef typename SkeletonBlockerComplex::Root_simplex_handle Root_simplex_handle;
- typedef typename SkeletonBlockerComplex::Blocker_handle Blocker_handle;
-
-
- typedef typename SkeletonBlockerComplex::Root_simplex_iterator Root_simplex_iterator;
- typedef typename SkeletonBlockerComplex::Simplex_handle_iterator Simplex_handle_iterator;
- typedef typename SkeletonBlockerComplex::BlockerMap BlockerMap;
- typedef typename SkeletonBlockerComplex::BlockerPair BlockerPair;
- typedef typename SkeletonBlockerComplex::BlockerMapIterator BlockerMapIterator;
- typedef typename SkeletonBlockerComplex::BlockerMapConstIterator BlockerMapConstIterator;
-
- typedef typename SkeletonBlockerComplex::Visitor Visitor;
-
-
- /** @name Constructors / Destructors / Initialization
- */
- //@{
-
- explicit Skeleton_blocker_simplifiable_complex(int num_vertices_ = 0, Visitor* visitor_ = NULL) :
- Skeleton_blocker_complex<SkeletonBlockerDS>(num_vertices_, visitor_) { }
-
- /**
- * @brief Constructor with a list of simplices
- * @details The list of simplices must be the list
- * of simplices of a simplicial complex, sorted with increasing dimension.
- */
- //soon deprecated
- explicit Skeleton_blocker_simplifiable_complex(std::list<Simplex_handle>& simplices, Visitor* visitor_ = NULL) :
- Skeleton_blocker_complex<SkeletonBlockerDS>(simplices, visitor_) { }
-
- /**
- * @brief Constructor with a list of simplices
- * @details The list of simplices must be the list of simplices of a simplicial complex.
- */
- template<typename SimpleHandleOutputIterator>
- explicit Skeleton_blocker_simplifiable_complex(SimpleHandleOutputIterator simplex_begin,SimpleHandleOutputIterator simplex_end,bool is_flag_complex = false,Visitor* visitor_ = NULL) :
- Skeleton_blocker_complex<SkeletonBlockerDS>(simplex_begin,simplex_end,is_flag_complex, visitor_) { }
-
-
- virtual ~Skeleton_blocker_simplifiable_complex() { }
-
- //@}
-
- /**
- * Returns true iff the blocker 'sigma' is popable.
- * To define popable, let us call 'L' the complex that
- * consists in the current complex without the blocker 'sigma'.
- * A blocker 'sigma' is then "popable" if the link of 'sigma'
- * in L is reducible.
- *
- */
- virtual bool is_popable_blocker(Blocker_handle sigma) const {
- assert(this->contains_blocker(*sigma));
- Skeleton_blocker_link_complex<Skeleton_blocker_simplifiable_complex> link_blocker_sigma;
- build_link_of_blocker(*this, *sigma, link_blocker_sigma);
-
- bool res = link_blocker_sigma.is_contractible() == CONTRACTIBLE;
- return res;
- }
-
- /**
- * Removes all the popable blockers of the complex and delete them.
- * @returns the number of popable blockers deleted
- */
- void remove_popable_blockers() {
- std::list<Vertex_handle> vertex_to_check;
- for (auto v : this->vertex_range())
- vertex_to_check.push_front(v);
-
- while (!vertex_to_check.empty()) {
- Vertex_handle v = vertex_to_check.front();
- vertex_to_check.pop_front();
-
- bool blocker_popable_found = true;
- while (blocker_popable_found) {
- blocker_popable_found = false;
- for (auto block : this->blocker_range(v)) {
- if (this->is_popable_blocker(block)) {
- for (Vertex_handle nv : *block)
- if (nv != v) vertex_to_check.push_back(nv);
- this->delete_blocker(block);
- blocker_popable_found = true;
- break;
- }
- }
- }
- }
- }
-
- /**
- * Removes all the popable blockers of the complex passing through v and delete them.
- */
- void remove_popable_blockers(Vertex_handle v) {
- bool blocker_popable_found = true;
- while (blocker_popable_found) {
- blocker_popable_found = false;
- for (auto block : this->blocker_range(v)) {
- if (is_popable_blocker(block)) {
- this->delete_blocker(block);
- blocker_popable_found = true;
- }
- }
- }
- }
-
- /**
- * @brief Removes all the popable blockers of the complex passing through v and delete them.
- * Also remove popable blockers in the neighborhood if they became popable.
- *
- */
- void remove_all_popable_blockers(Vertex_handle v) {
- std::list<Vertex_handle> vertex_to_check;
- vertex_to_check.push_front(v);
-
- while (!vertex_to_check.empty()) {
- Vertex_handle v = vertex_to_check.front();
- vertex_to_check.pop_front();
-
- bool blocker_popable_found = true;
- while (blocker_popable_found) {
- blocker_popable_found = false;
- for (auto block : this->blocker_range(v)) {
- if (this->is_popable_blocker(block)) {
- for (Vertex_handle nv : *block)
- if (nv != v) vertex_to_check.push_back(nv);
- this->delete_blocker(block);
- blocker_popable_found = true;
- break;
- }
- }
- }
- }
- }
-
- /**
- * Remove the star of the vertex 'v'
- */
- void remove_star(Vertex_handle v) {
- // we remove the blockers that are not consistent anymore
- update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(v));
- while (this->degree(v) > 0) {
- Vertex_handle w(* (adjacent_vertices(v.vertex, this->skeleton).first));
- this->remove_edge(v, w);
- }
- this->remove_vertex(v);
- }
-
- private:
- /**
- * after removing the star of a simplex, blockers sigma that contains this simplex must be removed.
- * Furthermore, all simplices tau of the form sigma \setminus simplex_to_be_removed must be added
- * whenever the dimension of tau is at least 2.
- */
- void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed) {
- std::list <Blocker_handle> blockers_to_update;
- if (simplex_to_be_removed.empty()) return;
-
- auto v0 = simplex_to_be_removed.first_vertex();
- for (auto blocker : this->blocker_range(v0)) {
- if (blocker->contains(simplex_to_be_removed))
- blockers_to_update.push_back(blocker);
- }
-
- for (auto blocker_to_update : blockers_to_update) {
- Simplex_handle sub_blocker_to_be_added;
- bool sub_blocker_need_to_be_added =
- (blocker_to_update->dimension() - simplex_to_be_removed.dimension()) >= 2;
- if (sub_blocker_need_to_be_added) {
- sub_blocker_to_be_added = *blocker_to_update;
- sub_blocker_to_be_added.difference(simplex_to_be_removed);
- }
- this->delete_blocker(blocker_to_update);
- if (sub_blocker_need_to_be_added)
- this->add_blocker(sub_blocker_to_be_added);
- }
- }
-
- public:
- /**
- * Remove the star of the edge connecting vertices a and b.
- * @returns the number of blocker that have been removed
- */
- void remove_star(Vertex_handle a, Vertex_handle b) {
- update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(a, b));
- // we remove the edge
- this->remove_edge(a, b);
- }
-
- /**
- * Remove the star of the edge 'e'.
- */
- void remove_star(Edge_handle e) {
- return remove_star(this->first_vertex(e), this->second_vertex(e));
- }
-
- /**
- * Remove the star of the simplex 'sigma' which needs to belong to the complex
- */
- void remove_star(const Simplex_handle& sigma) {
- assert(this->contains(sigma));
- if (sigma.dimension() == 0) {
- remove_star(sigma.first_vertex());
- } else if (sigma.dimension() == 1) {
- remove_star(sigma.first_vertex(), sigma.last_vertex());
- } else {
- remove_blocker_containing_simplex(sigma);
- this->add_blocker(sigma);
- }
- }
-
- /**
- * @brief add a maximal simplex plus all its cofaces.
- * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
- */
- void add_simplex(const Simplex_handle& sigma) {
- assert(!this->contains(sigma));
- assert(sigma.dimension() > 1);
- remove_blocker_include_in_simplex(sigma);
- }
-
- private:
- /**
- * remove all blockers that contains sigma
- */
- void remove_blocker_containing_simplex(const Simplex_handle& sigma) {
- std::vector <Blocker_handle> blockers_to_remove;
- for (auto blocker : this->blocker_range(sigma.first_vertex())) {
- if (blocker->contains(sigma))
- blockers_to_remove.push_back(blocker);
- }
- for (auto blocker_to_update : blockers_to_remove)
- this->delete_blocker(blocker_to_update);
- }
-
- /**
- * remove all blockers that contains sigma
- */
- void remove_blocker_include_in_simplex(const Simplex_handle& sigma) {
- std::vector <Blocker_handle> blockers_to_remove;
- for (auto blocker : this->blocker_range(sigma.first_vertex())) {
- if (sigma.contains(*blocker))
- blockers_to_remove.push_back(blocker);
- }
- for (auto blocker_to_update : blockers_to_remove)
- this->delete_blocker(blocker_to_update);
- }
-
- public:
- enum simplifiable_status {
- NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
- };
-
- simplifiable_status is_remove_star_homotopy_preserving(const Simplex_handle& simplex) {
- // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of Skeleton_blocker_geometric_complex
- // then call it there to build the link and return the value of link.is_contractible()
- return MAYBE_HOMOTOPY_EQ;
- }
-
- enum contractible_status {
- NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
- };
-
- /**
- * @brief %Test if the complex is reducible using a strategy defined in the class
- * (by default it tests if the complex is a cone)
- * @details Note that NO could be returned if some invariant ensures that the complex
- * is not a point (for instance if the euler characteristic is different from 1).
- * This function will surely have to return MAYBE in some case because the
- * associated problem is undecidable but it in practice, it can often
- * be solved with the help of geometry.
- */
- virtual contractible_status is_contractible() const {
- if (this->is_cone()) {
- return CONTRACTIBLE;
- } else {
- return MAYBE_CONTRACTIBLE;
- }
- }
-
- /** @Edge contraction operations
- */
- //@{
-
- /**
- * @return If ignore_popable_blockers is true
- * then the result is true iff the link condition at edge ab is satisfied
- * or equivalently iff no blocker contains ab.
- * If ignore_popable_blockers is false then the
- * result is true iff all blocker containing ab are popable.
- */
- bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const {
- for (auto blocker : this->const_blocker_range(a))
- if (blocker->contains(b)) {
- // false if ignore_popable_blockers is false
- // otherwise the blocker has to be popable
- return ignore_popable_blockers && is_popable_blocker(blocker);
- }
- return true;
- }
-
- /**
- * @return If ignore_popable_blockers is true
- * then the result is true iff the link condition at edge ab is satisfied
- * or equivalently iff no blocker contains ab.
- * If ignore_popable_blockers is false then the
- * result is true iff all blocker containing ab are popable.
- */
- bool link_condition(Edge_handle & e, bool ignore_popable_blockers = false) const {
- const Graph_edge& edge = (*this)[e];
- assert(this->get_address(edge.first()));
- assert(this->get_address(edge.second()));
- Vertex_handle a(*this->get_address(edge.first()));
- Vertex_handle b(*this->get_address(edge.second()));
- return link_condition(a, b, ignore_popable_blockers);
- }
-
- protected:
- /**
- * Compute simplices beta such that a.beta is an order 0 blocker
- * that may be used to construct a new blocker after contracting ab.
- * It requires that the link condition is satisfied.
- */
- void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const {
- for (auto const & blocker : this->const_blocker_range(a)) {
- Simplex_handle beta = (*blocker);
- beta.remove_vertex(a);
- buffer.push_back(beta);
- }
-
- Simplex_handle n;
- this->add_neighbours(b, n);
- this->remove_neighbours(a, n);
- n.remove_vertex(a);
-
-
- for (Vertex_handle y : n) {
- Simplex_handle beta;
- beta.add_vertex(y);
- buffer.push_back(beta);
- }
- }
-
- private:
- /**
- * @brief "Replace" the edge 'bx' by the edge 'ax'.
- * Assume that the edge 'bx' was present whereas 'ax' was not.
- * Precisely, it does not replace edges, but remove 'bx' and then add 'ax'.
- * The visitor 'on_swaped_edge' is called just after edge 'ax' had been added
- * and just before edge 'bx' had been removed. That way, it can
- * eventually access to information of 'ax'.
- */
- void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) {
- this->add_edge(a, x);
- if (this->visitor) this->visitor->on_swaped_edge(a, b, x);
- this->remove_edge(b, x);
- }
-
- private:
- /**
- * @brief removes all blockers passing through the edge 'ab'
- */
- void delete_blockers_around_vertex(Vertex_handle v) {
- std::list <Blocker_handle> blockers_to_delete;
- for (auto blocker : this->blocker_range(v)) {
- blockers_to_delete.push_back(blocker);
- }
- while (!blockers_to_delete.empty()) {
- this->remove_blocker(blockers_to_delete.back());
- blockers_to_delete.pop_back();
- }
- }
-
- /**
- * @brief removes all blockers passing through the edge 'ab'
- */
- void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b) {
- std::list<Blocker_handle> blocker_to_delete;
- for (auto blocker : this->blocker_range(a))
- if (blocker->contains(b)) blocker_to_delete.push_back(blocker);
- while (!blocker_to_delete.empty()) {
- this->delete_blocker(blocker_to_delete.back());
- blocker_to_delete.pop_back();
- }
- }
-
- public:
- /**
- * Contracts the edge.
- * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
- * it removes first all blockers passing through 'ab'
- */
- void contract_edge(Edge_handle edge) {
- contract_edge(this->first_vertex(edge), this->second_vertex(edge));
- }
-
- /**
- * Contracts the edge connecting vertices a and b.
- * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
- * it removes first all blockers passing through 'ab'
- */
- void contract_edge(Vertex_handle a, Vertex_handle b) {
- assert(this->contains_vertex(a));
- assert(this->contains_vertex(b));
- assert(this->contains_edge(a, b));
-
- // if some blockers passes through 'ab', we remove them.
- if (!link_condition(a, b))
- delete_blockers_around_edge(a, b);
-
- std::set<Simplex_handle> blockers_to_add;
-
- get_blockers_to_be_added_after_contraction(a, b, blockers_to_add);
-
- delete_blockers_around_vertices(a, b);
-
- update_edges_after_contraction(a, b);
-
- this->remove_vertex(b);
-
- notify_changed_edges(a);
-
- for (auto block : blockers_to_add)
- this->add_blocker(block);
-
- assert(this->contains_vertex(a));
- assert(!this->contains_vertex(b));
- }
-
- private:
- void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b, std::set<Simplex_handle>& blockers_to_add) {
- blockers_to_add.clear();
-
- typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex<SkeletonBlockerDS> > LinkComplexType;
-
- LinkComplexType link_a(*this, a);
- LinkComplexType link_b(*this, b);
-
- std::vector<Simplex_handle> vector_alpha, vector_beta;
-
- tip_blockers(a, b, vector_alpha);
- tip_blockers(b, a, vector_beta);
-
- for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha) {
- for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta) {
- Simplex_handle sigma = *alpha;
- sigma.union_vertices(*beta);
- Root_simplex_handle sigma_id = this->get_id(sigma);
- if (this->contains(sigma) &&
- proper_faces_in_union<SkeletonBlockerComplex>(sigma_id, link_a, link_b)) {
- // Blocker_handle blocker = new Simplex_handle(sigma);
- sigma.add_vertex(a);
- blockers_to_add.insert(sigma);
- }
- }
- }
- }
-
- /**
- * delete all blockers that passes through a or b
- */
- void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b) {
- std::vector<Blocker_handle> blocker_to_delete;
- for (auto bl : this->blocker_range(a))
- blocker_to_delete.push_back(bl);
- for (auto bl : this->blocker_range(b))
- blocker_to_delete.push_back(bl);
- while (!blocker_to_delete.empty()) {
- this->delete_blocker(blocker_to_delete.back());
- blocker_to_delete.pop_back();
- }
- }
-
- void update_edges_after_contraction(Vertex_handle a, Vertex_handle b) {
- // We update the set of edges
- this->remove_edge(a, b);
-
- // For all edges {b,x} incident to b,
- // we remove {b,x} and add {a,x} if not already there.
- while (this->degree(b) > 0) {
- Vertex_handle x(*(adjacent_vertices(b.vertex, this->skeleton).first));
- if (!this->contains_edge(a, x))
- // we 'replace' the edge 'bx' by the edge 'ax'
- this->swap_edge(a, b, x);
- else
- this->remove_edge(b, x);
- }
- }
-
- void notify_changed_edges(Vertex_handle a) {
- // We notify the visitor that all edges incident to 'a' had changed
- boost_adjacency_iterator v, v_end;
-
- for (tie(v, v_end) = adjacent_vertices(a.vertex, this->skeleton); v != v_end; ++v)
- if (this->visitor) this->visitor->on_changed_edge(a, Vertex_handle(*v));
- }
- //@}
-};
+void Skeleton_blocker_complex<SkeletonBlockerDS>::add_simplex(const Simplex_handle& sigma) {
+ assert(!this->contains(sigma));
+ assert(sigma.dimension() > 1);
+ remove_blocker_include_in_simplex(sigma);
+}
+
+
+/**
+ * remove all blockers that contains sigma
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_containing_simplex(const Simplex_handle& sigma) {
+ std::vector <Blocker_handle> blockers_to_remove;
+ for (auto blocker : this->blocker_range(sigma.first_vertex())) {
+ if (blocker->contains(sigma))
+ blockers_to_remove.push_back(blocker);
+ }
+ for (auto blocker_to_update : blockers_to_remove)
+ this->delete_blocker(blocker_to_update);
+}
+
+/**
+ * remove all blockers that contains sigma
+ */
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_include_in_simplex(const Simplex_handle& sigma) {
+ std::vector <Blocker_handle> blockers_to_remove;
+ for (auto blocker : this->blocker_range(sigma.first_vertex())) {
+ if (sigma.contains(*blocker))
+ blockers_to_remove.push_back(blocker);
+ }
+ for (auto blocker_to_update : blockers_to_remove)
+ this->delete_blocker(blocker_to_update);
+}
+
+
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const {
+ for (auto const & blocker : this->const_blocker_range(a)) {
+ Simplex_handle beta = (*blocker);
+ beta.remove_vertex(a);
+ buffer.push_back(beta);
+ }
+
+ Simplex_handle n;
+ this->add_neighbours(b, n);
+ this->remove_neighbours(a, n);
+ n.remove_vertex(a);
+
+
+ for (Vertex_handle y : n) {
+ Simplex_handle beta;
+ beta.add_vertex(y);
+ buffer.push_back(beta);
+ }
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) {
+ this->add_edge(a, x);
+ if (this->visitor) this->visitor->on_swaped_edge(a, b, x);
+ this->remove_edge(b, x);
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::delete_blockers_around_vertex(Vertex_handle v) {
+ std::list <Blocker_handle> blockers_to_delete;
+ for (auto blocker : this->blocker_range(v)) {
+ blockers_to_delete.push_back(blocker);
+ }
+ while (!blockers_to_delete.empty()) {
+ this->remove_blocker(blockers_to_delete.back());
+ blockers_to_delete.pop_back();
+ }
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::delete_blockers_around_edge(Vertex_handle a, Vertex_handle b) {
+ std::list<Blocker_handle> blocker_to_delete;
+ for (auto blocker : this->blocker_range(a))
+ if (blocker->contains(b)) blocker_to_delete.push_back(blocker);
+ while (!blocker_to_delete.empty()) {
+ this->delete_blocker(blocker_to_delete.back());
+ blocker_to_delete.pop_back();
+ }
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::contract_edge(Vertex_handle a, Vertex_handle b) {
+ assert(this->contains_vertex(a));
+ assert(this->contains_vertex(b));
+ assert(this->contains_edge(a, b));
+
+ // if some blockers passes through 'ab', we remove them.
+ if (!link_condition(a, b))
+ delete_blockers_around_edge(a, b);
+
+ std::set<Simplex_handle> blockers_to_add;
+
+ get_blockers_to_be_added_after_contraction(a, b, blockers_to_add);
+
+ delete_blockers_around_vertices(a, b);
+
+ update_edges_after_contraction(a, b);
+
+ this->remove_vertex(b);
+
+ notify_changed_edges(a);
+
+ for (auto block : blockers_to_add)
+ this->add_blocker(block);
+
+ assert(this->contains_vertex(a));
+ assert(!this->contains_vertex(b));
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b, std::set<Simplex_handle>& blockers_to_add) {
+ blockers_to_add.clear();
+
+ typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex<SkeletonBlockerDS> > LinkComplexType;
+
+ LinkComplexType link_a(*this, a);
+ LinkComplexType link_b(*this, b);
+
+ std::vector<Simplex_handle> vector_alpha, vector_beta;
+
+ tip_blockers(a, b, vector_alpha);
+ tip_blockers(b, a, vector_beta);
+
+ for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha) {
+ for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta) {
+ Simplex_handle sigma = *alpha;
+ sigma.union_vertices(*beta);
+ Root_simplex_handle sigma_id = this->get_id(sigma);
+ if (this->contains(sigma) &&
+ proper_faces_in_union<Skeleton_blocker_complex<SkeletonBlockerDS>>(sigma_id, link_a, link_b)) {
+ // Blocker_handle blocker = new Simplex_handle(sigma);
+ sigma.add_vertex(a);
+ blockers_to_add.insert(sigma);
+ }
+ }
+ }
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b) {
+ std::vector<Blocker_handle> blocker_to_delete;
+ for (auto bl : this->blocker_range(a))
+ blocker_to_delete.push_back(bl);
+ for (auto bl : this->blocker_range(b))
+ blocker_to_delete.push_back(bl);
+ while (!blocker_to_delete.empty()) {
+ this->delete_blocker(blocker_to_delete.back());
+ blocker_to_delete.pop_back();
+ }
+}
+
+
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::update_edges_after_contraction(Vertex_handle a, Vertex_handle b) {
+ // We update the set of edges
+ this->remove_edge(a, b);
+
+ // For all edges {b,x} incident to b,
+ // we remove {b,x} and add {a,x} if not already there.
+ while (this->degree(b) > 0) {
+ Vertex_handle x(*(adjacent_vertices(b.vertex, this->skeleton).first));
+ if (!this->contains_edge(a, x))
+ // we 'replace' the edge 'bx' by the edge 'ax'
+ this->swap_edge(a, b, x);
+ else
+ this->remove_edge(b, x);
+ }
+}
+
+template<typename SkeletonBlockerDS>
+void
+Skeleton_blocker_complex<SkeletonBlockerDS>::notify_changed_edges(Vertex_handle a){
+ // We notify the visitor that all edges incident to 'a' had changed
+ boost_adjacency_iterator v, v_end;
+
+ for (tie(v, v_end) = adjacent_vertices(a.vertex, this->skeleton); v != v_end; ++v)
+ if (this->visitor) this->visitor->on_changed_edge(a, Vertex_handle(*v));
+
+}
+
} // namespace skbl