Milena (Olena)
User documentation 2.0a Id
|
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