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
00029 #ifndef OLENA_TOPO_TARJAN_FLAT_ZONE_HH
00030 # define OLENA_TOPO_TARJAN_FLAT_ZONE_HH
00031
00032 # include <oln/basics.hh>
00033 # include <oln/topo/tarjan/tarjan_with_attr.hh>
00034 # include <oln/topo/tarjan/union.hh>
00035 # include <oln/morpho/attributes.hh>
00036 # include <map>
00037
00038 namespace oln {
00039
00040 namespace topo {
00041
00042 namespace tarjan {
00043
00071 template<class T,
00072 class DestType = unsigned,
00073 class A = oln::morpho::attr::card_type<>,
00074 class Exact = mlc::final>
00075 struct flat_zone:
00076 public abstract::tarjan_with_attr<typename mlc::exact_vt<flat_zone<T, DestType, A, Exact>,
00077 Exact>::ret>
00078 {
00079
00080 typedef oln_point_type(T) point_type;
00081 typedef oln_value_type(T) data_type;
00082 typedef oln_concrete_type(T) image_type;
00083
00084 typedef DestType comp_type;
00085
00086 typedef flat_zone<T, DestType, A, Exact> self_type;
00087 typedef mlc_exact_vt_type(self_type, Exact) exact_type;
00088 typedef abstract::tarjan_with_attr<exact_type> super_type;
00089
00090 friend class super_type;
00091 friend class abstract::tarjan<exact_type>;
00098 flat_zone(const image_type &ima,
00099 const attr_env_type(A) &env = attr_env_type(A)()): super_type(ima, env)
00100 {
00101 }
00102
00103 std::vector<point_type>
00104 get_processing_order_impl()
00105 {
00106 std::vector<point_type> res;
00107 oln_iter_type(image_type) it(input_);
00108
00109 res.reserve(input_.npoints());
00110 for_all(it)
00111 res.push_back(it);
00112 return res;
00113 }
00114
00115 protected:
00116
00124 void
00125 mark_set_impl(const point_type &x)
00126 {
00127 if (parent_.size() == parent_.capacity())
00128 {
00129 capacity = parent_.capacity() + capacity_chunk;
00130 parent_.reserve(capacity);
00131 comp_value_.reserve(capacity);
00132 }
00133 to_comp_[x] = ncomps_ + 1;
00134 data_.push_back(A(input_, x, env_));
00135 parent_.push_back(ncomps_ + 1);
00136 comp_value_.push_back(ncomps_ + 1);
00137 }
00138
00147 void
00148 uni_impl(const point_type& n, const point_type& p)
00149 {
00150 comp_type r = find_root(to_comp_[n]);
00151 precondition(to_comp_[n] <= ncomps_);
00152 precondition(to_comp_[p] <= (ncomps_ + 1));
00153 if (r != to_comp_[p])
00154 if (input_[n] == input_[p])
00155 {
00156 if (to_comp_[p] == (ncomps_ + 1))
00157 {
00158 precondition(r < comp_value_.capacity());
00159 data_[r] += data_[to_comp_[p]];
00160 precondition(r <= ncomps_);
00161 to_comp_[p] = r;
00162 }
00163 else
00164 {
00165 precondition(r < parent_.capacity());
00166 data_[parent_[to_comp_[p]]] += data_[parent_[r]];
00167 parent_[r] = parent_[to_comp_[p]];
00168
00169 }
00170 }
00171 }
00172 };
00173
00182 template <typename T, typename DestType, typename A, typename Exact>
00183 struct tarjan_traits<flat_zone<T, DestType, A, Exact> >
00184 {
00185 typedef T input_type;
00186 typedef typename mute<T, DestType>::ret output_type;
00187 typedef A attr_type;
00188 };
00189
00193 namespace obsolete {
00218 template <class I>
00219 struct flat_zone
00220 {
00221 typedef oln_point_type(I) point_type;
00222 typedef oln_value_type(I) data_type;
00223 typedef oln_concrete_type(I) image_type;
00224
00225 typedef tarjan::tarjan_set<image_type, tarjan::empty_class> tarjan_cc;
00226
00227 const image_type &input;
00228 tarjan_cc cc;
00230 image2d<unsigned> label;
00231
00232 std::vector<point_type> look_up_table;
00233
00234 image2d< std::vector<oln::point2d> > ima_region;
00235
00236 unsigned nlabels_;
00241 flat_zone(const image_type& input_) : input(input_), cc(input_),
00242 label(input_.size()),
00243 ima_region(input_.size()),
00244 nlabels_(0)
00245 {
00246 doit();
00247 }
00249 void
00250 doit()
00251 {
00252
00253 {
00254 window2d c4;
00255 c4.add(0,1).add(1,0);
00256 typename image_type::bkd_iter_type p(input);
00257 for_all(p)
00258 {
00259 cc.make_set(p);
00260 window2d::neighb_type p_prime(c4, p);
00261 for_all (p_prime) if (input.hold(p_prime))
00262 if (input[p] == input[p_prime])
00263 cc.uni(p_prime.cur(), p);
00264 }
00265
00266 cc.make_set(point_type(input.nrows(), input.ncols()));
00267
00268
00269 for (int j = input.ncols() - 1; j >= 0; --j)
00270 {
00271 cc.make_set(point_type(input.nrows(), j));
00272 cc.uni(point_type(input.nrows(), j + 1), point_type(input.nrows(), j));
00273 }
00274
00275
00276 for (int i = input.nrows() - 1; i >= 0; --i)
00277 {
00278 cc.make_set(point_type(i, input.ncols()));
00279 cc.uni(point_type(i + 1, input.ncols()), point_type(i, input.ncols()));
00280 }
00281
00282
00283 for (int j = input.ncols() - 1; j > 0; --j)
00284 {
00285 cc.make_set(point_type(-1, j));
00286 cc.uni(point_type(-1, j + 1), point_type(-1, j));
00287 }
00288
00289
00290 for (int i = input.nrows() - 1; i > 0; --i)
00291 {
00292 cc.make_set(point_type(i, -1));
00293 cc.uni(point_type(i + 1, -1), point_type(i, -1));
00294 }
00295
00296 cc.make_set(point_type(-1, -1));
00297
00298 cc.uni(point_type(-1, 0), point_type(-1, -1));
00299 cc.uni(point_type(0, -1), point_type(-1, -1));
00300 }
00301
00302
00303 {
00304 typename image_type::fwd_iter_type p(input);
00305
00306
00307 look_up_table.push_back(point_type());
00308
00309 label.border_adapt_assign(1, ++nlabels_);
00310
00311 look_up_table.push_back(cc.find_root(point_type(-1, -1)));
00312
00313 for_all(p)
00314 {
00315 if (cc.is_root(p))
00316 {
00317 label[p] = ++nlabels_;
00318 look_up_table.push_back(p);
00319 }
00320 else
00321 label[p] = label[cc.parent[p]];
00322 }
00323
00324 {
00325 typename image_type::fwd_iter_type p(input);
00326 for_all(p)
00327 {
00328 if (cc.is_root(p))
00329 ima_region[p].push_back(p);
00330 else
00331 ima_region[cc.parent[p]].push_back(p);
00332 }
00333 }
00334
00335 }
00336 }
00338 const unsigned
00339 get_label(const point_type & p) const
00340 {
00341 return label[p];
00342 }
00344 const point_type&
00345 get_root(unsigned l) const
00346 {
00347 return look_up_table[l];
00348 }
00350 const unsigned
00351 nlabels() const
00352 {
00353 return nlabels_;
00354 }
00355
00360 void
00361 merge(const int l1, const int l2)
00362 {
00363 point_type root_l1 = look_up_table[l1];
00364 point_type root_l2 = look_up_table[l2];
00365 assertion(cc.is_root(root_l1));
00366 assertion(cc.is_root(root_l2));
00367
00368 cc.uni(root_l2, root_l1);
00369
00370 look_up_table[l2] = root_l1;
00371 for (typename std::vector<point_type>::iterator
00372 i = ima_region[root_l2].begin();
00373 i != ima_region[root_l2].end(); ++i)
00374 label[*i] = l1;
00375 ima_region[root_l1].insert(ima_region[root_l1].end(),
00376 ima_region[root_l1].begin(),
00377 ima_region[root_l1].end());
00378 ima_region[root_l2].clear();
00379
00380 --nlabels_;
00381 }
00382
00383 };
00384
00385 }
00386
00387 }
00388
00389 }
00390
00391 }
00392
00393 #endif // ! OLENA_TOPO_TARJAN_FLAT_ZONE_HH