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_LINE_HH
00027 # define MLN_ACCU_LINE_HH
00028 
00034 
00035 # include <mln/core/concept/meta_accumulator.hh>
00036 # include <mln/core/concept/image.hh>
00037 
00038 
00039 
00040 namespace mln
00041 {
00042 
00043   namespace accu
00044   {
00045 
00046     
00047 
00062     template <typename Meta_Accu, unsigned Dir, 
00063               typename I, typename O>
00064     void
00065     line(const Image<I>& input,
00066          const mln_site(I)& p_start, unsigned len,
00067          unsigned half_length,
00068          Image<O>& output);
00069 
00070 
00071 
00072 # ifndef MLN_INCLUDE_ONLY
00073 
00074     namespace internal
00075     {
00076 
00077       template <typename Meta_Accu, unsigned Dir, 
00078                 typename I, typename O>
00079       void
00080       line_tests(const Image<I>& input_,
00081                  const mln_site(I)&, unsigned,
00082                  unsigned,
00083                  Image<O>& output_)
00084       {
00085         mlc_is_a(Meta_Accu, Meta_Accumulator)::check();
00086 
00087         typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00088         mlc_converts_to(mln_result(A), mln_value(O))::check();
00089 
00090         typedef mln_site(I) P;
00091         mlc_bool(Dir < P::dim)::check();
00092 
00093         mlc_is(mln_trait_image_value_io(O),
00094                mln::trait::image::value_io::read_write)::check();
00095 
00096         const I& input = exact(input_);
00097         O& output = exact(output_);
00098         mln_precondition(input.is_valid());
00099         mln_precondition(output.is_valid());
00100       }
00101       
00102     } 
00103 
00104 
00105     namespace impl
00106     {
00107 
00108       namespace generic
00109       {
00110         
00111         template <typename Meta_Accu, unsigned Dir,
00112                   typename I, typename O>
00113         void
00114         line(const Image<I>& input_,
00115              const mln_site(I)& p_start, unsigned len_,
00116              unsigned half_length_,
00117              Image<O>& output_)
00118         {
00119           typedef mln_site(I) P;
00120           typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00121 
00122           const I& input = exact(input_);
00123           O& output = exact(output_);
00124 
00125           
00126           const def::coord len = static_cast<def::coord>(len_);
00127           const def::coord half_length = static_cast<def::coord>(half_length_);
00128 
00129           
00130           internal::line_tests<Meta_Accu, Dir>(input,
00131                                                p_start, len,
00132                                                half_length,
00133                                                output);
00134 
00135           
00136           const def::coord start = p_start[Dir];
00137           const def::coord last = static_cast<def::coord>(start + len - 1);
00138           A a; 
00139           a.init();
00140           P p; 
00141 
00142           
00143           p = p_start;
00144           P q = p;
00145           for (def::coord c = 0; c <= half_length && c < len; ++c)
00146             {
00147               a.take(input(q));
00148               ++q[Dir];
00149             }
00150           output(p) = a;
00151 
00152           def::coord& cur = p[Dir];
00153           if (cur == last)
00154             return;
00155 
00156           
00157 
00158           P p_plus = p_start;
00159           def::coord& plus = p_plus[Dir];
00160           plus = static_cast<def::coord>(plus + half_length);
00161 
00162           while (cur < start + half_length && cur < last)
00163             {
00164               ++cur;
00165               ++plus;
00166               if (plus <= last)
00167                 a.take(input(p_plus));
00168               output(p) = a;
00169             }
00170 
00171           if (cur == last)
00172             return;
00173 
00174           
00175 
00176           P p_minus = p_start;
00177           def::coord& minus = p_minus[Dir];
00178           --minus;
00179 
00180           while (cur < last - half_length)
00181             {
00182               ++cur;
00183               ++plus;
00184               ++minus;
00185               mln_invariant(plus >= start && plus <= last);
00186               a.take(input(p_plus));
00187               mln_invariant(minus >= start && minus <= last);
00188               a.untake(input(p_minus));
00189               output(p) = a;
00190             }
00191 
00192           if (cur == last)
00193             return;
00194 
00195           
00196 
00197           while (cur < last)
00198             {
00199               ++cur;
00200               ++minus;
00201               mln_invariant(minus >= start && minus <= last);
00202               a.untake(input(p_minus));
00203               output(p) = a;
00204             }
00205         }
00206 
00207       } 
00208 
00209 
00210 
00211       template <typename Meta_Accu, unsigned Dir,
00212                 typename I, typename O>
00213       void
00214       line_fastest(const Image<I>& input_,
00215                    const mln_site(I)& p_start, unsigned len,
00216                    unsigned half_length,
00217                    Image<O>& output_)
00218       {
00219         typedef mln_site(I)  P;
00220         typedef mln_value(I) V;
00221         typedef mln_accu_with(Meta_Accu, V) A;
00222 
00223         const I& input = exact(input_);
00224         O& output = exact(output_);
00225 
00226         
00227         internal::line_tests<Meta_Accu, Dir>(input,
00228                                              p_start, len,
00229                                              half_length,
00230                                              output);
00231 
00232         
00233 
00234         const def::coord start = p_start[Dir];
00235         const def::coord last = start + len - 1;
00236 
00237         const V* p_in    = & input(p_start);
00238         V* p_out   = & output(p_start);
00239 
00240         mln_delta(P) dp = literal::zero;
00241         dp[Dir] = 1;
00242         unsigned offset = input.delta_index(dp);
00243 
00244         A a; 
00245         a.init();
00246 
00247         
00248 
00249         const V* q = p_in;
00250         for (def::coord c = 0; c <= half_length && c < len; ++c)
00251           {
00252             a.take(*q);
00253             q += offset;
00254           }
00255         *p_out = a;
00256 
00257         def::coord cur = p_start[Dir];
00258         if (cur == last)
00259           return;
00260 
00261         
00262 
00263         def::coord plus = start + half_length;
00264         const V* p_plus = p_in + half_length * offset;
00265 
00266         while (cur < start + half_length && cur < last)
00267           {
00268             ++cur;
00269             p_in += offset;
00270             ++plus;
00271             p_plus += offset;
00272             if (plus <= last)
00273               a.take(*p_plus);
00274             p_out += offset;
00275             *p_out = a;
00276           }
00277 
00278         if (cur == last)
00279           return;
00280 
00281         
00282 
00283         def::coord minus = start - 1;
00284         const V* p_minus = p_in - offset;
00285 
00286         while (cur < last - half_length)
00287           {
00288             ++cur;
00289             p_in += offset;
00290             ++plus;
00291             p_plus += offset;
00292             ++minus;
00293             p_minus += offset;
00294             mln_invariant(plus >= start && plus <= last);
00295             a.take(*p_plus);
00296             mln_invariant(minus >= start && minus <= last);
00297             a.untake(*p_minus);
00298             p_out += offset;
00299             *p_out = a;
00300           }
00301 
00302         if (cur == last)
00303           return;
00304 
00305         
00306 
00307         while (cur < last)
00308           {
00309             ++cur;
00310             p_in += offset;
00311             ++minus;
00312             p_minus += offset;
00313             mln_invariant(minus >= start && minus <= last);
00314             a.untake(*p_minus);
00315             p_out += offset;
00316             *p_out = a;
00317           }
00318 
00319       }
00320 
00321 
00322 
00323 
00324     } 
00325 
00326 
00327     namespace internal
00328     {
00329 
00330       template <typename Meta_Accu, unsigned Dir, 
00331                 typename I, typename O>
00332       void
00333       line_dispatch(trait::image::speed::any,
00334                     const Image<I>& input,
00335                     const mln_site(I)& p_start, unsigned len,
00336                     unsigned half_length,
00337                     Image<O>& output)
00338       {
00339         impl::generic::line<Meta_Accu, Dir>(input,
00340                                             p_start, len,
00341                                             half_length,
00342                                             output);
00343       }
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360       template <typename Meta_Accu, unsigned Dir, 
00361                 typename I, typename O>
00362       void
00363       line_dispatch(const Image<I>& input,
00364                     const mln_site(I)& p_start, unsigned len,
00365                     unsigned half_length,
00366                     Image<O>& output)
00367       {
00368         line_dispatch<Meta_Accu, Dir>(mln_trait_image_speed(I)(),
00369                                       input,
00370                                       p_start, len,
00371                                       half_length,
00372                                       output);
00373       }
00374       
00375     } 
00376 
00377 
00378     template <typename Meta_Accu, unsigned Dir, 
00379               typename I, typename O>
00380     void
00381     line(const Image<I>& input,
00382          const mln_site(I)& p_start, unsigned len,
00383          unsigned half_length,
00384          Image<O>& output)
00385     {
00386       internal::line_tests<Meta_Accu, Dir>(input,
00387                                            p_start, len,
00388                                            half_length,
00389                                            output);
00390       internal::line_dispatch<Meta_Accu, Dir>(input,
00391                                               p_start, len,
00392                                               half_length,
00393                                               output);
00394     }
00395 
00396 # endif // ! MLN_INCLUDE_ONLY
00397 
00398   } 
00399 
00400 } 
00401 
00402 
00403 #endif // ! MLN_ACCU_LINE_HH