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
00040 #ifndef OLENA_LRDE_UFMT_FIORIO_2_HH
00041 # define OLENA_LRDE_UFMT_FIORIO_2_HH
00042
00043 # include <algorithm>
00044
00045 # include <oln/core/image2d.hh>
00046 # include <oln/level/fill.hh>
00047
00048 namespace oln
00049 {
00050 namespace lrde
00051 {
00052 namespace ufmt
00053 {
00054
00055
00056 template <typename I>
00057 class fiorio
00058 {
00059 typedef oln_point_type(I) point;
00060 typedef oln_value_type(I) value;
00061 typedef oln_iter_type(I) piter;
00062 typedef typename mute<I, point>::ret parent_type;
00063
00064 public:
00065 fiorio(const abstract::image<I>& ima) :
00066 ima_(ima.exact().clone()), parent_(ima.size())
00067 , n_level_roots_cpt_(ima.npoints())
00068 {
00069
00070 piter p (parent_);
00071 for_all (p)
00072 parent_[p] = p;
00073 }
00074
00076 void go()
00077 {
00078 scan_line();
00079 }
00080
00081
00084 public:
00085 const I& ima() const
00086 {
00087 return ima_;
00088 }
00089
00090 const parent_type& parent() const
00091 {
00092 return parent_;
00093 }
00095
00096
00101 unsigned n_level_roots1() const
00102 {
00103 return n_level_roots_cpt_;
00104 }
00105
00108 unsigned n_level_roots2() const
00109 {
00110 unsigned n_level_roots = 0;
00111 oln_iter_type(parent_type) p(parent_);
00112 for_all (p)
00113 if (is_level_root(p))
00114 ++n_level_roots;
00115 return n_level_roots;
00116 }
00117
00119 typedef typename mute<parent_type, bool>::ret level_roots_image_type;
00120
00124 level_roots_image_type level_roots() const
00125 {
00126
00127 level_roots_image_type level_roots (ima_.size());
00128 oln_iter_type(parent_type) p(ima_);
00129 for_all (p)
00130 level_roots[p] = is_level_root(p);
00131 return level_roots;
00132 }
00134
00135
00136 protected:
00137
00138 void scan_line()
00139 {
00140
00141 build_tree_of_line(0);
00142 for (coord i = 1; i < ima_.nrows(); ++i)
00143 {
00144 build_tree_of_line(i);
00145
00146 merge_line(i);
00147 }
00148 }
00149
00150 void build_tree_of_line(coord row)
00151 {
00152
00153
00154 for (coord j = 1; j < ima_.ncols(); ++j)
00155 {
00156 point left = find_level_root(point(row, j - 1));
00157 point this_one = point(row, j);
00158 insert(this_one, left);
00159 }
00160 }
00161
00162 void merge_line(coord row)
00163 {
00164 precondition(row > 0);
00165
00166 for (coord col = 0; col < ima_.ncols(); ++col)
00167 {
00168 point p (row, col );
00169 point upper (row - 1, col );
00170
00171
00172
00173
00174 merge(p, upper);
00175 }
00176 }
00177
00179 void insert(const point& p, const point& n)
00180 {
00181 point r = find_ancestor(n, ima_[p]);
00182 if (ima_[r] <= ima_[p])
00183 {
00184 parent_[p] = r;
00185 if (ima_[r] == ima_[p])
00186
00187 --n_level_roots_cpt_;
00188 }
00189 else
00190 {
00191 if (not is_top(r))
00192 parent_[p] = parent_[r];
00193 parent_[r] = p;
00194 }
00195 }
00196
00199 void merge(const point& p, const point& q)
00200 {
00201
00202
00203 if (ima_[p] >= ima_[q])
00204 merge_(p, q);
00205 else
00206 merge_(q, p);
00207 }
00208
00209
00210 void merge_(const point& p, const point& q)
00211 {
00212 precondition (p != q);
00213 precondition (ima_[p] >= ima_[q]);
00214
00215 point r = find_ancestor(p, ima_[q]);
00216 point s = find_level_root(q);
00217
00218
00219
00220 if (r == s)
00221 return;
00222
00223 point t = parent_[s];
00224
00225 if (ima_[s] == ima_[r])
00226 {
00227 parent_[s] = r;
00228
00229 --n_level_roots_cpt_;
00230 }
00231 else
00232 {
00233 if (not is_top(r))
00234 parent_[s] = parent_[r];
00235 parent_[r] = s;
00236 }
00237 merge_(r, t);
00238 }
00239
00240
00241 #if 0
00242 void merge_(point p, point q)
00243 {
00244 precondition (p != q);
00245 precondition (ima_[p] >= ima_[q]);
00246
00247 point r = find_ancestor(p, ima_[q]);
00248 point s = find_level_root(q);
00249
00250
00251
00252 while (r != s)
00253 {
00254 invariant (p != q);
00255 invariant (ima_[p] >= ima_[q]);
00256
00257 point t = parent_[s];
00258 if (ima_[s] == ima_[r])
00259 {
00260 parent_[s] = r;
00261
00262 --n_level_roots_cpt_;
00263 }
00264 else
00265 {
00266 if (not is_top(r))
00267 parent_[s] = parent_[r];
00268 parent_[r] = s;
00269 }
00270 p = r;
00271 q = t;
00272 r = find_ancestor(p, ima_[q]);
00273 s = find_level_root(q);
00274 }
00275 }
00276 #endif
00277
00279 bool is_top(const point& p) const
00280 {
00281 return parent_[p] == p;
00282 }
00283
00284 bool is_level_root(const point& p) const
00285 {
00286 return
00287 is_top(p) ||
00288 (ima_[parent_[p]] != ima_[p]);
00289 }
00290
00293 point find_level_root(const point& p)
00294 {
00295
00296 if (is_level_root(p))
00297 return p;
00298 else
00299
00300 return parent_[p] = find_level_root(parent_[p]);
00301 }
00302
00305 point find_ancestor(point p, const value& level)
00306 {
00307 while (not is_top(p) and ima_[parent_[p]] >= level)
00308 p = find_level_root(parent_[p]);
00309 return p;
00310 }
00311
00312 protected:
00314 I ima_;
00316 parent_type parent_;
00317
00318 unsigned n_level_roots_cpt_;
00319
00320 };
00321
00322 }
00323
00324 }
00325
00326 }
00327
00328 #endif // ! OLENA_LRDE_UFMT_FIORIO_2_HH