flat-zone.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
00002 // Laboratory
00003 //
00004 // This  file is  part of  the Olena  Library.  This  library  is free
00005 // software; you can redistribute it  and/or modify it under the terms
00006 // of the  GNU General  Public License version  2 as published  by the
00007 // Free Software Foundation.
00008 //
00009 // This library is distributed in the hope that it will be useful, but
00010 // WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
00011 // MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have  received a copy of the  GNU General Public License
00015 // along with  this library; see the  file COPYING.  If  not, write to
00016 // the Free Software Foundation, 59  Temple Place - Suite 330, Boston,
00017 // MA 02111-1307, USA.
00018 //
00019 // As a  special exception, you  may use this  file as part of  a free
00020 // software library without restriction.  Specifically, if other files
00021 // instantiate templates  or use macros or inline  functions from this
00022 // file, or  you compile  this file  and link it  with other  files to
00023 // produce  an executable,  this file  does  not by  itself cause  the
00024 // resulting  executable  to be  covered  by  the  GNU General  Public
00025 // License.   This exception  does  not however  invalidate any  other
00026 // reasons why the executable file might be covered by the GNU General
00027 // Public License.
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)) // first merge of p component
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             // Compute cc map
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               // bottom-right corner -> bottom-left corner
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               // bottom-right corner -> top-right corner
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               // top-right corner -> top-left corner - 1
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               // bottom-left corner -> top-left corner - 1
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             // Compute label map
00303             {
00304               typename image_type::fwd_iter_type p(input);
00305 
00306               // Push_back because no label = 0;
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             // merge
00368             cc.uni(root_l2, root_l1);
00369             // update our tables
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       } // end of namespace obsolete
00386 
00387     } // end of namespace tarjan
00388 
00389   } // end of namespace topo
00390 
00391 } // end of namespace oln
00392 
00393 #endif // ! OLENA_TOPO_TARJAN_FLAT_ZONE_HH

Generated on Thu Apr 15 20:13:09 2004 for Olena by doxygen 1.3.6-20040222