26 #ifndef MLN_ACCU_TRANSFORM_SNAKE_HH
27 # define MLN_ACCU_TRANSFORM_SNAKE_HH
39 # include <mln/core/concept/image.hh>
40 # include <mln/core/concept/meta_accumulator.hh>
41 # include <mln/core/alias/window2d.hh>
42 # include <mln/win/diff.hh>
43 # include <mln/win/shift.hh>
44 # include <mln/geom/delta.hh>
45 # include <mln/extension/adjust.hh>
47 # include <mln/canvas/browsing/snake_fwd.hh>
48 # include <mln/canvas/browsing/snake_generic.hh>
59 template <
typename A,
typename I,
typename W>
60 mln_ch_value(I, mln_result(A))
61 transform_snake(const Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
64 template <typename A, typename I, typename W>
65 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
66 transform_snake(const Meta_Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
70 # ifndef MLN_INCLUDE_ONLY
76 template <
typename I,
typename W>
77 void transform_snake_tests(
const Image<I>& input_,
const Window<W>& win_)
79 const I& input =
exact(input_);
80 const W& win =
exact(win_);
82 mln_precondition(input.is_valid());
83 mln_precondition(win.is_valid());
84 mln_precondition(! win.is_empty());
93 template <
typename I,
typename W,
typename A>
94 struct transform_snake_functor
96 typedef transform_snake_functor<I,W, A>
self;
97 typedef void (
self::*move_fun)();
104 mln_ch_value(I, mln_result(A)) output;
128 std::vector<move_fun> moves;
129 std::vector<dpsite> dps;
131 transform_snake_functor(const Image<I>& input, const Window<W>& win, const Accumulator<A>& a)
132 : input(
exact(input)),
136 win_left_fwd(win::shift(win, mln::
left) - win),
137 win_right_fwd(win - win::shift(win, mln::
left)),
138 win_left_bkd(win::shift(win_left_fwd, mln::
right)),
139 win_right_bkd(win::shift(win_right_fwd, mln::right)),
141 win_bot_up(win::shift(win, mln::
down) - win),
142 win_top_up(win - win::shift(win, mln::
down)),
143 win_bot_down(win::shift(win_bot_up, mln::
up)),
144 win_top_down(win::shift(win_top_up, mln::up)),
146 q_l_fwd(win_left_fwd, p),
147 q_r_fwd(win_right_fwd, p),
148 q_l_bkd(win_left_bkd, p),
149 q_r_bkd(win_right_bkd, p),
151 q_top_up(win_top_up, p),
152 q_bot_up(win_bot_up, p),
153 q_top_down(win_top_down, p),
154 q_bot_down(win_bot_down, p),
159 if (win_bot_up.size() + win_top_up.size() +
160 win_bot_down.size() + win_top_down.size() <
161 win_left_fwd.size() + win_right_fwd.size() +
162 win_left_bkd.size() + win_right_bkd.size())
188 p = input.domain().pmin() - dps[0];
189 mln_qiter(W) q(win, p);
193 p = input.domain().pmin();
199 if (input.has(q_l_fwd))
200 accu.untake(input(q_l_fwd));
202 if (input.has(q_r_fwd))
203 accu.
take(input(q_r_fwd));
210 if (input.has(q_r_bkd))
211 accu.untake(input(q_r_bkd));
213 if (input.has(q_l_bkd))
214 accu.
take(input(q_l_bkd));
221 if (input.has(q_top_down))
222 accu.untake(input(q_top_down));
224 if (input.has(q_bot_down))
225 accu.
take(input(q_bot_down));
232 if (input.has(q_bot_up))
233 accu.untake(input(q_bot_up));
235 if (input.has(q_top_up))
236 accu.
take(input(q_top_up));
246 template <typename I, typename W, typename A>
247 struct transform_snake_fastest_functor
249 typedef transform_snake_fastest_functor<I,W,A>
self;
250 typedef void (
self::*move_fun)();
257 mln_ch_value(I, mln_result(A)) output;
271 mln_qixter(const I, window2d)
282 std::vector<move_fun> moves;
283 std::vector<dpsite> dps;
285 transform_snake_fastest_functor(const I& input, const W& win, const A& a)
290 win_left_fwd(win::shift(win, mln::left) - win),
291 win_right_fwd(win - win::shift(win, mln::left)),
292 win_left_bkd(win::shift(win_left_fwd, mln::right)),
293 win_right_bkd(win::shift(win_right_fwd, mln::right)),
295 win_bot_up(win::shift(win, mln::down) - win),
296 win_top_up(win - win::shift(win, mln::down)),
297 win_bot_down(win::shift(win_bot_up, mln::up)),
298 win_top_down(win::shift(win_top_up, mln::up)),
300 q_l_fwd(input, win_left_fwd, p),
301 q_r_fwd(input, win_right_fwd, p),
302 q_l_bkd(input, win_left_bkd, p),
303 q_r_bkd(input, win_right_bkd, p),
305 q_top_up(input, win_top_up, p),
306 q_bot_up(input, win_bot_up, p),
307 q_top_down(input, win_top_down, p),
308 q_bot_down(input, win_bot_down, p),
313 if (win_bot_up.size() + win_top_up.size() +
314 win_bot_down.size() + win_top_down.size() <
315 win_left_fwd.size() + win_right_fwd.size() +
316 win_left_bkd.size() + win_right_bkd.size())
345 p = input.domain().pmin() - dps[0];
346 mln_qixter(
const I, W) q(input, win, p);
349 p = input.domain().pmin();
355 accu.untake(q_l_fwd.val());
357 accu.
take(q_r_fwd.val());
364 accu.untake(q_r_bkd.val());
366 accu.
take(q_l_bkd.val());
373 accu.untake(q_top_down.val());
375 accu.
take(q_bot_down.val());
382 accu.untake(q_bot_up.val());
384 accu.
take(q_top_up.val());
393 template <typename A, typename I, typename W>
395 mln_ch_value(I, mln_result(A))
396 transform_snake_dispatch(metal::false_,
397 const Accumulator<A>& a,
398 const Image<I>& input, const Window<W>& win)
400 typedef transform_snake_functor<I, W, A> F;
406 template <
typename A,
typename I,
typename W>
408 mln_ch_value(I, mln_result(A))
409 transform_snake_dispatch(metal::true_,
410 const Accumulator<A>& a,
411 const Image<I>& input, const Window<W>& win)
413 typedef transform_snake_fastest_functor<I, W, A> F;
419 template <
typename A,
typename I,
typename W>
421 mln_ch_value(I, mln_result(A))
422 transform_snake_dispatch(const Accumulator<A>& a,
423 const Image<I>& input, const Window<W>& win)
425 return transform_snake_dispatch(mln_is_fastest_IW(I, W)(),
434 template <
typename A,
typename I,
typename W>
436 mln_ch_value(I, mln_result(A))
438 const Image<I>& input, const Window<W>& win)
440 mln_trace(
"accu::transform_snake");
442 internal::transform_snake_tests(input, win);
445 mln_ch_value(I, mln_result(A)) output;
446 output = internal::transform_snake_dispatch(a, input, win);
452 template <typename A, typename I, typename W>
454 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
456 const Image<I>& input, const Window<W>& win)
458 mln_trace(
"accu::transform_snake");
460 internal::transform_snake_tests(input, win);
462 typedef mln_accu_with(A, mln_value(I)) A_;
466 mln_ch_value(I, mln_result(A_)) output;
467 output = internal::transform_snake_dispatch(a_, input, win);
473 # endif // ! MLN_INCLUDE_ONLY
480 #endif // ! MLN_ACCU_TRANSFORM_SNAKE_HH