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 #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
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
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
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
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
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
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
00341
00342
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
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 }
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 }
00478
00479 }
00480
00481
00482 #endif // ! MLN_ACCU_TRANSFORM_SNAKE_HH