37 #ifndef VIGRA_UNION_FIND_HXX 
   38 #define VIGRA_UNION_FIND_HXX 
   46 #include "array_vector.hxx" 
   47 #include "iteratoradapter.hxx" 
   53 template <
class T, 
class IsSigned = VigraFalseType>
 
   54 struct UnionFindAccessorImpl
 
   56     static const T max_label = NumericTraits<T>::maxConst >> 1;
 
   57     static const T anchor_bit = ~max_label;
 
   64     static T deletedAnchor()
 
   66         return NumericTraits<T>::maxConst;
 
   69     static bool isAnchor(T 
const & t)
 
   71         return (t & anchor_bit) != 0;
 
   74     static bool isValidAnchor(T 
const & t)
 
   76         return isAnchor(t) && t != deletedAnchor();
 
   79     static bool notAnchor(T 
const & t)
 
   81         return (t & anchor_bit) == 0;
 
   84     static T toAnchor(T 
const & t)
 
   86         return t | anchor_bit;
 
   89     static T fromAnchor(T 
const & t)
 
   96 struct UnionFindAccessorImpl<T, VigraTrueType>
 
  100         return NumericTraits<T>::max();
 
  103     static T deletedAnchor()
 
  105         return NumericTraits<T>::min();
 
  108     static bool isAnchor(T 
const & t)
 
  113     static bool isValidAnchor(T 
const & t)
 
  115         return isAnchor(t) && t != deletedAnchor();
 
  118     static bool notAnchor(T 
const & t)
 
  123     static T toAnchor(T 
const & t)
 
  128     static T fromAnchor(T 
const & t)
 
  134 template <
class Array, 
class LabelAccessor>
 
  135 class UnionFindIteratorPolicy
 
  138     typedef UnionFindIteratorPolicy                BaseType;
 
  139     typedef typename Array::difference_type        value_type;
 
  140     typedef typename Array::difference_type        difference_type;
 
  141     typedef value_type 
const &                     reference;
 
  142     typedef value_type 
const &                     index_reference;
 
  143     typedef value_type 
const *                     pointer;
 
  144     typedef typename std::forward_iterator_tag     iterator_category;
 
  146     Array 
const & array_;
 
  149     UnionFindIteratorPolicy(Array 
const & array, value_type index=0)
 
  154     static void initialize(BaseType & d) 
 
  159     static reference dereference(BaseType 
const & d)
 
  164     static bool equal(BaseType 
const & d1, BaseType 
const & d2)
 
  166         return d1.index_ == d2.index_;
 
  169     static bool less(BaseType 
const & d1, BaseType 
const & d2)
 
  171         return d1.index_ < d2.index_;
 
  174     static void increment(BaseType & d)
 
  180     static void advanceToAnchor(BaseType & d)
 
  182         while(d.index_ < (value_type)d.array_.size()-1 && 
 
  183               !LabelAccessor::isValidAnchor(d.array_[d.index_]))
 
  195     typedef ArrayVector<T>                                             LabelArray;
 
  196     typedef typename LabelArray::difference_type                       IndexType;
 
  197     typedef detail::UnionFindAccessorImpl<T, 
 
  198                           typename NumericTraits<T>::isSigned>         LabelAccessor;
 
  199     typedef detail::UnionFindIteratorPolicy<LabelArray, LabelAccessor> IteratorPolicy;
 
  200     typedef IteratorAdaptor<IteratorPolicy>                            iterator;
 
  201     typedef iterator                                                   const_iterator;
 
  203     mutable ArrayVector<T> labels_;
 
  206     UnionFindArray(T next_free_label = 1)
 
  208         vigra_precondition(next_free_label <= LabelAccessor::max(),
 
  209            "UnionFindArray(): Need more labels than can be represented" 
  210            "in the destination type.");
 
  212         for(T k=0; k < next_free_label; ++k)
 
  213             labels_.push_back(LabelAccessor::toAnchor(k));
 
  214         labels_.push_back(LabelAccessor::toAnchor(next_free_label));
 
  217     const_iterator begin(
unsigned int start_at=0)
 const 
  219         return const_iterator(IteratorPolicy(labels_, start_at));
 
  222     const_iterator end()
 const 
  224         return const_iterator(IteratorPolicy(labels_, labels_.size()-1));
 
  227     T nextFreeIndex()
 const 
  229         return T(labels_.size() - 1);
 
  232     T findIndex(T index)
 const 
  234         IndexType root = index;
 
  235         while(LabelAccessor::notAnchor(labels_[root]))
 
  236             root = (IndexType)labels_[root];
 
  238         while((IndexType)index != root)
 
  240             T next = labels_[(IndexType)index];
 
  241             labels_[(IndexType)index] = root;
 
  247     T findLabel(T index)
 const 
  249         return LabelAccessor::fromAnchor(labels_[findIndex(index)]);
 
  252     void deleteIndex(T index)
 
  254         labels_[findIndex(index)] = LabelAccessor::deletedAnchor();
 
  258     T makeUnion(T l1, T l2)
 
  260         IndexType i1 = findIndex(l1);
 
  261         IndexType i2 = findIndex(l2);
 
  278     T finalizeIndex(T index)
 
  280         if(index == (T)labels_.size()-1)
 
  283             vigra_invariant(index < LabelAccessor::max(),
 
  284                     "connected components: Need more labels than can be represented in the destination type.");
 
  286             labels_.push_back(LabelAccessor::toAnchor((T)labels_.size()));
 
  291             labels_.back() = LabelAccessor::toAnchor((T)labels_.size()-1);
 
  298         T index = LabelAccessor::fromAnchor(labels_.back());
 
  299         vigra_invariant(index < LabelAccessor::max(),
 
  300           "connected components: Need more labels than can be represented in the destination type.");
 
  301         labels_.push_back(LabelAccessor::toAnchor((T)labels_.size()));
 
  305     unsigned int makeContiguous()
 
  308         unsigned int count = 0; 
 
  309         for(IndexType i=0; i<(IndexType)(labels_.size()-1); ++i)
 
  311             if(LabelAccessor::isValidAnchor(labels_[i]))
 
  313                     labels_[i] = LabelAccessor::toAnchor((T)count++);
 
  317                     labels_[i] = findIndex(i);  
 
  326 #endif // VIGRA_UNION_FIND_HXX