• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

transform_snake.hh

00001 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00026 #ifndef MLN_ACCU_TRANSFORM_SNAKE_HH
00027 # define MLN_ACCU_TRANSFORM_SNAKE_HH
00028 
00038 
00039 # include <mln/core/concept/image.hh>
00040 # include <mln/core/concept/meta_accumulator.hh>
00041 # include <mln/core/alias/window2d.hh>
00042 # include <mln/win/diff.hh>
00043 # include <mln/win/shift.hh>
00044 # include <mln/geom/delta.hh>
00045 # include <mln/extension/adjust.hh>
00046 
00047 # include <mln/canvas/browsing/snake_fwd.hh>
00048 # include <mln/canvas/browsing/snake_generic.hh>
00049 
00050 
00051 
00052 namespace mln
00053 {
00054 
00055   namespace accu
00056   {
00057 
00058 
00059     template <typename A, typename I, typename W>
00060     mln_ch_value(I, mln_result(A))
00061     transform_snake(const Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
00062 
00063 
00064     template <typename A, typename I, typename W>
00065     mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00066     transform_snake(const Meta_Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
00067 
00068 
00069 
00070 # ifndef MLN_INCLUDE_ONLY
00071 
00072     namespace internal
00073     {
00074 
00075 
00076       template <typename I, typename W>
00077       void transform_snake_tests(const Image<I>& input_, const Window<W>& win_)
00078       {
00079         const I& input = exact(input_);
00080         const W& win   = exact(win_);
00081 
00082         mln_precondition(input.is_valid());
00083         mln_precondition(win.is_valid());
00084         mln_precondition(! win.is_empty());
00085 
00086         (void) input;
00087         (void) win;
00088       }
00089 
00090 
00091       // Functor.
00092 
00093       template <typename I, typename W, typename A>
00094       struct transform_snake_functor
00095       {
00096         typedef transform_snake_functor<I,W, A> self;
00097         typedef void (self::*move_fun)();
00098         typedef mln_deduce(I, psite, delta) dpsite;
00099 
00100         const I& input;
00101         const W& win;
00102         A accu;
00103 
00104         mln_ch_value(I, mln_result(A)) output;
00105 
00106         mln_psite(I) p;
00107 
00108         window2d
00109         win_left_fwd,
00110           win_right_fwd,
00111           win_left_bkd,
00112           win_right_bkd,
00113           win_bot_up,
00114           win_top_up,
00115           win_bot_down,
00116           win_top_down;
00117 
00118         mln_qiter(window2d)
00119         q_l_fwd,
00120           q_r_fwd,
00121           q_l_bkd,
00122           q_r_bkd,
00123           q_top_up,
00124           q_bot_up,
00125           q_top_down,
00126           q_bot_down;
00127 
00128         std::vector<move_fun> moves;
00129         std::vector<dpsite> dps;
00130 
00131         transform_snake_functor(const Image<I>& input, const Window<W>& win, const Accumulator<A>& a)
00132           : input(exact(input)),
00133             win(exact(win)),
00134             accu(exact(a)),
00135 
00136             win_left_fwd(win::shift(win, mln::left) - win),
00137             win_right_fwd(win - win::shift(win, mln::left)),
00138             win_left_bkd(win::shift(win_left_fwd, mln::right)),
00139             win_right_bkd(win::shift(win_right_fwd, mln::right)),
00140 
00141             win_bot_up(win::shift(win, mln::down) - win),
00142             win_top_up(win - win::shift(win, mln::down)),
00143             win_bot_down(win::shift(win_bot_up, mln::up)),
00144             win_top_down(win::shift(win_top_up, mln::up)),
00145 
00146             q_l_fwd(win_left_fwd, p),
00147             q_r_fwd(win_right_fwd, p),
00148             q_l_bkd(win_left_bkd, p),
00149             q_r_bkd(win_right_bkd, p),
00150 
00151             q_top_up(win_top_up, p),
00152             q_bot_up(win_bot_up, p),
00153             q_top_down(win_top_down, p),
00154             q_bot_down(win_bot_down, p),
00155 
00156             moves(3),
00157             dps(3)
00158         {
00159           if (win_bot_up.size()   + win_top_up.size() +
00160               win_bot_down.size() + win_top_down.size() <
00161               win_left_fwd.size() + win_right_fwd.size() +
00162               win_left_bkd.size() + win_right_bkd.size())
00163             {
00164               // Vertical snake
00165               dps[0] = mln::right;
00166               dps[1] = mln::down;
00167               dps[2] = mln::up;
00168               moves[0] = &self::right;
00169               moves[1] = &self::down;
00170               moves[2] = &self::up;
00171             }
00172           else
00173             {
00174               // Horizontal snake
00175               dps[0] = mln::down;
00176               dps[1] = mln::right;
00177               dps[2] = mln::left;
00178               moves[0] = &self::down;
00179               moves[1] = &self::right;
00180               moves[2] = &self::left;
00181             }
00182         }
00183 
00184         void init()
00185         {
00186           initialize(output, input);
00187           accu.init();
00188           p = input.domain().pmin() - dps[0];
00189           mln_qiter(W) q(win, p);
00190           for_all(q)
00191             if (input.has(q))
00192               accu.take(input(q));
00193           p = input.domain().pmin();
00194         }
00195 
00196         void right()
00197         {
00198           for_all(q_l_fwd)
00199             if (input.has(q_l_fwd))
00200               accu.untake(input(q_l_fwd));
00201           for_all(q_r_fwd)
00202             if (input.has(q_r_fwd))
00203               accu.take(input(q_r_fwd));
00204           output(p) = accu;
00205         }
00206 
00207         void left()
00208         {
00209           for_all(q_r_bkd)
00210             if (input.has(q_r_bkd))
00211               accu.untake(input(q_r_bkd));
00212           for_all(q_l_bkd)
00213             if (input.has(q_l_bkd))
00214               accu.take(input(q_l_bkd));
00215           output(p) = accu;
00216         }
00217 
00218         void down()
00219         {
00220           for_all(q_top_down)
00221             if (input.has(q_top_down))
00222               accu.untake(input(q_top_down));
00223           for_all(q_bot_down)
00224             if (input.has(q_bot_down))
00225               accu.take(input(q_bot_down));
00226           output(p) = accu;
00227         }
00228 
00229         void up()
00230         {
00231           for_all(q_bot_up)
00232             if (input.has(q_bot_up))
00233               accu.untake(input(q_bot_up));
00234           for_all(q_top_up)
00235             if (input.has(q_top_up))
00236               accu.take(input(q_top_up));
00237           output(p) = accu;
00238         }
00239 
00240       };
00241 
00242 
00243 
00244       // Functor (fastest version).
00245 
00246       template <typename I, typename W, typename A>
00247       struct transform_snake_fastest_functor
00248       {
00249         typedef transform_snake_fastest_functor<I,W,A> self;
00250         typedef void (self::*move_fun)();
00251         typedef mln_deduce(I, psite, delta) dpsite;
00252 
00253         const I& input;
00254         const W& win;
00255         A accu;
00256 
00257         mln_ch_value(I, mln_result(A)) output;
00258 
00259         mln_psite(I) p;
00260 
00261         window2d
00262         win_left_fwd,
00263           win_right_fwd,
00264           win_left_bkd,
00265           win_right_bkd,
00266           win_bot_up,
00267           win_top_up,
00268           win_bot_down,
00269           win_top_down;
00270 
00271         mln_qixter(const I, window2d)
00272         q_l_fwd,
00273           q_r_fwd,
00274           q_l_bkd,
00275           q_r_bkd,
00276           q_top_up,
00277           q_bot_up,
00278           q_top_down,
00279           q_bot_down;
00280 
00281 
00282         std::vector<move_fun> moves;
00283         std::vector<dpsite> dps;
00284 
00285         transform_snake_fastest_functor(const I& input, const W& win, const A& a)
00286           : input(input),
00287             win(win),
00288             accu(a),
00289 
00290             win_left_fwd(win::shift(win, mln::left) - win),
00291             win_right_fwd(win - win::shift(win, mln::left)),
00292             win_left_bkd(win::shift(win_left_fwd, mln::right)),
00293             win_right_bkd(win::shift(win_right_fwd, mln::right)),
00294 
00295             win_bot_up(win::shift(win, mln::down) - win),
00296             win_top_up(win - win::shift(win, mln::down)),
00297             win_bot_down(win::shift(win_bot_up, mln::up)),
00298             win_top_down(win::shift(win_top_up, mln::up)),
00299 
00300             q_l_fwd(input, win_left_fwd, p),
00301             q_r_fwd(input, win_right_fwd, p),
00302             q_l_bkd(input, win_left_bkd, p),
00303             q_r_bkd(input, win_right_bkd, p),
00304 
00305             q_top_up(input, win_top_up, p),
00306             q_bot_up(input, win_bot_up, p),
00307             q_top_down(input, win_top_down, p),
00308             q_bot_down(input, win_bot_down, p),
00309 
00310             moves(3),
00311             dps(3)
00312         {
00313           if (win_bot_up.size()   + win_top_up.size() +
00314               win_bot_down.size() + win_top_down.size() <
00315               win_left_fwd.size() + win_right_fwd.size() +
00316               win_left_bkd.size() + win_right_bkd.size())
00317           {
00318             // Vertical snake
00319             dps[0] = mln::right;
00320             dps[1] = mln::down;
00321             dps[2] = mln::up;
00322             moves[0] = &self::right;
00323             moves[1] = &self::down;
00324             moves[2] = &self::up;
00325           }
00326           else
00327           {
00328             // Horizontal snake
00329             dps[0] = mln::down;
00330             dps[1] = mln::right;
00331             dps[2] = mln::left;
00332             moves[0] = &self::down;
00333             moves[1] = &self::right;
00334             moves[2] = &self::left;
00335           }
00336         }
00337 
00338         void init()
00339         {
00340           // extension::adjust_fill is performed in the routine
00341           // because it has to be done before the initialization of
00342           // the fast iterators (q_*).
00343           initialize(output, input);
00344           accu.init();
00345           p = input.domain().pmin() - dps[0];
00346           mln_qixter(const I, W) q(input, win, p);
00347           for_all(q)
00348             accu.take(q.val());
00349           p = input.domain().pmin();
00350         }
00351 
00352         void right()
00353         {
00354           for_all(q_l_fwd)
00355             accu.untake(q_l_fwd.val());
00356           for_all(q_r_fwd)
00357             accu.take(q_r_fwd.val());
00358           output(p) = accu;
00359         }
00360 
00361         void left()
00362         {
00363           for_all(q_r_bkd)
00364             accu.untake(q_r_bkd.val());
00365           for_all(q_l_bkd)
00366             accu.take(q_l_bkd.val());
00367           output(p) = accu;
00368         }
00369 
00370         void down()
00371         {
00372           for_all(q_top_down)
00373             accu.untake(q_top_down.val());
00374           for_all(q_bot_down)
00375             accu.take(q_bot_down.val());
00376           output(p) = accu;
00377         }
00378 
00379         void up()
00380         {
00381           for_all(q_bot_up)
00382             accu.untake(q_bot_up.val());
00383           for_all(q_top_up)
00384             accu.take(q_top_up.val());
00385           output(p) = accu;
00386         }
00387 
00388       };
00389 
00390 
00391       // Both dispatch and implementation (hum...)
00392 
00393       template <typename A, typename I, typename W>
00394       inline
00395       mln_ch_value(I, mln_result(A))
00396       transform_snake_dispatch(metal::false_,
00397                                const Accumulator<A>& a,
00398                                const Image<I>& input, const Window<W>& win)
00399       {
00400         typedef transform_snake_functor<I, W, A> F;
00401         F f(exact(input), exact(win), exact(a));
00402         canvas::browsing::snake_generic(f);
00403         return f.output;
00404       }
00405 
00406       template <typename A, typename I, typename W>
00407       inline
00408       mln_ch_value(I, mln_result(A))
00409       transform_snake_dispatch(metal::true_,
00410                                const Accumulator<A>& a,
00411                                const Image<I>& input, const Window<W>& win)
00412       {
00413         typedef transform_snake_fastest_functor<I, W, A> F;
00414         F f(exact(input), exact(win), exact(a));
00415         canvas::browsing::snake_generic(f);
00416         return f.output;
00417       }
00418 
00419       template <typename A, typename I, typename W>
00420       inline
00421       mln_ch_value(I, mln_result(A))
00422       transform_snake_dispatch(const Accumulator<A>& a,
00423                                const Image<I>& input, const Window<W>& win)
00424       {
00425         return transform_snake_dispatch(mln_is_fastest_IW(I, W)(),
00426                                         a, input, win);
00427       }
00428 
00429     } // end of namespace mln::accu::internal
00430 
00431 
00432 
00433 
00434     template <typename A, typename I, typename W>
00435     inline
00436     mln_ch_value(I, mln_result(A))
00437     transform_snake(const Accumulator<A>& a,
00438                     const Image<I>& input, const Window<W>& win)
00439     {
00440       trace::entering("accu::transform_snake");
00441 
00442       internal::transform_snake_tests(input, win);
00443 
00444       extension::adjust(input, geom::delta(win) + 1);
00445       mln_ch_value(I, mln_result(A)) output;
00446       output = internal::transform_snake_dispatch(a, input, win);
00447 
00448       trace::exiting("accu::transform_snake");
00449       return output;
00450     }
00451 
00452 
00453     template <typename A, typename I, typename W>
00454     inline
00455                  mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00456     transform_snake(const Meta_Accumulator<A>& a,
00457                     const Image<I>& input, const Window<W>& win)
00458     {
00459       trace::entering("accu::transform_snake");
00460 
00461       internal::transform_snake_tests(input, win);
00462 
00463       typedef mln_accu_with(A, mln_value(I)) A_;
00464       A_ a_ = accu::unmeta(exact(a), mln_value(I)());
00465 
00466       extension::adjust(input, geom::delta(win) + 1);
00467       mln_ch_value(I, mln_result(A_)) output;
00468       output = internal::transform_snake_dispatch(a_, input, win);
00469 
00470       trace::exiting("accu::transform_snake");
00471       return output;
00472     }
00473 
00474 
00475 # endif // ! MLN_INCLUDE_ONLY
00476 
00477   } // end of namespace mln::accu
00478 
00479 } // end of namespace mln
00480 
00481 
00482 #endif // ! MLN_ACCU_TRANSFORM_SNAKE_HH

Generated on Tue Oct 4 2011 15:24:44 for Milena (Olena) by  doxygen 1.7.1