00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef OLENA_ATTRIBUTE_UNION_FIND_HH
00029 # define OLENA_ATTRIBUTE_UNION_FIND_HH
00030
00031 #include <oln/level/fill.hh>
00032
00033 #include <ntg/bin.hh>
00034
00035 #include <vector>
00036 #include <oln/utils/histogram.hh>
00037 #include <oln/morpho/attributes.hh>
00038
00039 namespace oln {
00040 namespace morpho {
00041 namespace fast {
00042 namespace tarjan {
00043
00055 template<class T, class ATTRIBUTE, class Env = attr_env_type(ATTRIBUTE)>
00056 struct tarjan_set
00057 {
00058 typedef oln_point_type(T) point_type;
00059 typedef oln_value_type(T) data_type;
00060 typedef oln_concrete_type(T) image_type;
00061 typedef typename ATTRIBUTE::lambda_type lambda_type;
00062 typedef Env env_type;
00063
00069 tarjan_set(const image_type& ima, const env_type &env) : input_(ima),
00070 parent_(ima.size()),
00071 aux_data_(ima.size()),
00072 env_(env)
00073 {
00074 level::fill(parent_, INACTIVE());
00075 }
00076
00085 template<bool closing, class N>
00086 image_type
00087 get_comptute(const lambda_type & lambda,
00088 const abstract::neighborhood<N>& Ng)
00089 {
00090 lambda_ = λ
00091
00092 std::vector<point_type> I(input_.npoints());
00093
00094 oln::utils::select_distrib_sort<closing>()(input_, I);
00095
00096 level::fill(aux_data_, ntg_sup_val(lambda_type));
00097 aux_data_.border_adapt_assign(Ng.delta(), ntg_sup_val(lambda_type));
00098
00099
00100 for (unsigned int p = 0; p < I.size(); ++p)
00101 {
00102 point_type p_p = I[p];
00103 make_set(p_p);
00104 oln_neighb_type(N) Q_prime(Ng, p_p);
00105 for_all (Q_prime)
00106 if (is_proc(Q_prime))
00107 uni(Q_prime.cur(), p_p);
00108 }
00109
00110
00111 image_type output(input_.size());
00112 for (int p = I.size() - 1; p >= 0; --p)
00113 {
00114 point_type p_p = I[p];
00115 if ((parent_[p_p] == ACTIVE()) || (parent_[p_p] == INACTIVE()))
00116 output[p_p] = input_[p_p];
00117 else
00118 output[p_p] = output[parent_[p_p]];
00119
00120
00121
00122 }
00123 return output;
00124 }
00125
00126 protected:
00130 static const point_type&
00131 ACTIVE()
00132 {
00133 static struct foo_def
00134 {
00135 point_type elt;
00136 foo_def()
00137 {
00138 const unsigned dim = point_type::dim;
00139 for (unsigned i = 0; i < dim; ++i )
00140 elt.nth(i) = -1;
00141 }
00142 } tmp;
00143
00144 return tmp.elt;
00145 }
00146
00150 static const point_type&
00151 INACTIVE()
00152 {
00153 static struct foo_def
00154 {
00155 point_type elt;
00156 foo_def() {
00157 const unsigned dim = point_type::dim;
00158 for (unsigned i = 0; i < dim; ++i )
00159 elt.nth(i) = -2;
00160 }
00161 } tmp;
00162
00163 return tmp.elt;
00164 }
00165
00170 void
00171 make_set(const point_type& x)
00172 {
00173 precondition(parent_[x] == INACTIVE());
00174 parent_[x] = ACTIVE();
00175 aux_data_[x] = ATTRIBUTE(input_, x, env_);
00176 }
00177
00182 point_type
00183 find_root(const point_type& x)
00184 {
00185 if ((parent_[x] != ACTIVE()) && (parent_[x] != INACTIVE()))
00186 {
00187 parent_[x] = find_root(parent_[x]);
00188 return parent_[x];
00189 }
00190 else
00191 return x;
00192 }
00193
00199 bool
00200 criterion(const point_type& x, const point_type& y)
00201 {
00202 precondition((parent_[x] == ACTIVE()) || (parent_[x] == INACTIVE()));
00203 precondition((parent_[y] == ACTIVE()) || (parent_[y] == INACTIVE()));
00204 return ( (input_[x] == input_[y]) || (aux_data_[x] < *lambda_));
00205 }
00206
00212 void
00213 uni(const point_type& n, const point_type& p)
00214 {
00215 point_type r = find_root(n);
00216 if (r != p)
00217 if (criterion(r,p))
00218 {
00219 aux_data_[p] += aux_data_[r];
00220 parent_[r] = p;
00221 }
00222 else
00223 {
00224 aux_data_[p] = *lambda_;
00225 }
00226 }
00227
00231 bool is_proc(const point_type &p) const
00232 {
00233
00234
00235
00236
00237
00238 return aux_data_[p].operator!=(ntg_sup_val(lambda_type));
00239 };
00240
00241
00242 const image_type &input_;
00243 typename mute<T, point_type>::ret parent_;
00244 typename mute<T, ATTRIBUTE>::ret aux_data_;
00245 const lambda_type *lambda_;
00246 const env_type env_;
00247 };
00248 }
00249 }
00250 }
00251 }
00252 #endif