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/utils/qsort.hh>
00038 #include <oln/morpho/attributes.hh>
00039
00040 namespace oln {
00041 namespace morpho {
00042 namespace fast {
00043 namespace tarjan {
00044
00056 template<class T, class ATTRIBUTE, class Env = attr_env_type(ATTRIBUTE)>
00057 struct tarjan_set
00058 {
00059 typedef oln_point_type(T) point_type;
00060 typedef oln_value_type(T) data_type;
00061 typedef oln_concrete_type(T) image_type;
00062 typedef typename ATTRIBUTE::lambda_type lambda_type;
00063 typedef Env env_type;
00064
00070 tarjan_set(const image_type& ima, const env_type &env) : input_(ima),
00071 parent_(ima.size()),
00072 aux_data_(ima.size()),
00073 env_(env)
00074 {
00075 level::fill(parent_, INACTIVE());
00076 }
00077
00086 template<bool closing, class N>
00087 image_type
00088 get_comptute(const lambda_type & lambda,
00089 const abstract::neighborhood<N>& Ng)
00090 {
00091 lambda_ = λ
00092
00093 std::vector<point_type> I;
00094
00095
00096
00097 oln::utils::select_q_sort<closing>()(input_, I);
00098
00099 level::fill(aux_data_, ntg_sup_val(lambda_type));
00100 aux_data_.border_adapt_assign(Ng.delta(), ntg_sup_val(lambda_type));
00101
00102
00103 for (unsigned int p = 0; p < I.size(); ++p)
00104 {
00105 point_type p_p = I[p];
00106 make_set(p_p);
00107 oln_neighb_type(N) Q_prime(Ng, p_p);
00108 for_all (Q_prime)
00109 if (is_proc(Q_prime))
00110 uni(Q_prime.cur(), p_p);
00111 }
00112
00113
00114 image_type output(input_.size());
00115 for (int p = I.size() - 1; p >= 0; --p)
00116 {
00117 point_type p_p = I[p];
00118 if ((parent_[p_p] == ACTIVE()) || (parent_[p_p] == INACTIVE()))
00119 output[p_p] = input_[p_p];
00120 else
00121 output[p_p] = output[parent_[p_p]];
00122
00123
00124
00125 }
00126 return output;
00127 }
00128
00129 protected:
00133 static const point_type&
00134 ACTIVE()
00135 {
00136 static struct foo_def
00137 {
00138 point_type elt;
00139 foo_def()
00140 {
00141 const unsigned dim = point_type::dim;
00142 for (unsigned i = 0; i < dim; ++i )
00143 elt.nth(i) = -1;
00144 }
00145 } tmp;
00146
00147 return tmp.elt;
00148 }
00149
00153 static const point_type&
00154 INACTIVE()
00155 {
00156 static struct foo_def
00157 {
00158 point_type elt;
00159 foo_def() {
00160 const unsigned dim = point_type::dim;
00161 for (unsigned i = 0; i < dim; ++i )
00162 elt.nth(i) = -2;
00163 }
00164 } tmp;
00165
00166 return tmp.elt;
00167 }
00168
00173 void
00174 make_set(const point_type& x)
00175 {
00176 precondition(parent_[x] == INACTIVE());
00177 parent_[x] = ACTIVE();
00178 aux_data_[x] = ATTRIBUTE(input_, x, env_);
00179 }
00180
00185 point_type
00186 find_root(const point_type& x)
00187 {
00188 if ((parent_[x] != ACTIVE()) && (parent_[x] != INACTIVE()))
00189 {
00190 parent_[x] = find_root(parent_[x]);
00191 return parent_[x];
00192 }
00193 else
00194 return x;
00195 }
00196
00202 bool
00203 criterion(const point_type& x, const point_type& y)
00204 {
00205 precondition((parent_[x] == ACTIVE()) || (parent_[x] == INACTIVE()));
00206 precondition((parent_[y] == ACTIVE()) || (parent_[y] == INACTIVE()));
00207 return ( (input_[x] == input_[y]) || (aux_data_[x] < *lambda_));
00208 }
00209
00215 void
00216 uni(const point_type& n, const point_type& p)
00217 {
00218 point_type r = find_root(n);
00219 if (r != p)
00220 if (criterion(r,p))
00221 {
00222 aux_data_[p] += aux_data_[r];
00223 parent_[r] = p;
00224 }
00225 else
00226 {
00227 aux_data_[p] = *lambda_;
00228 }
00229 }
00230
00234 bool is_proc(const point_type &p) const
00235 {
00236
00237
00238
00239
00240
00241 return aux_data_[p].operator!=(ntg_sup_val(lambda_type));
00242 };
00243
00244
00245 const image_type &input_;
00246 typename mute<T, point_type>::ret parent_;
00247 typename mute<T, ATTRIBUTE>::ret aux_data_;
00248 const lambda_type *lambda_;
00249 const env_type env_;
00250 };
00251 }
00252 }
00253 }
00254 }
00255 #endif