Milena (Olena)  User documentation 2.0a Id
line.hh
00001 // Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
00002 // Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 #ifndef MLN_ACCU_LINE_HH
00028 # define MLN_ACCU_LINE_HH
00029 
00035 
00036 # include <mln/core/concept/meta_accumulator.hh>
00037 # include <mln/core/concept/image.hh>
00038 
00039 
00040 
00041 namespace mln
00042 {
00043 
00044   namespace accu
00045   {
00046 
00047     // FIXME:
00048 
00063     template <typename Meta_Accu, unsigned Dir, // Free parameters.
00064               typename I, typename O>
00065     void
00066     line(const Image<I>& input,
00067          const mln_site(I)& p_start, def::coord len,
00068          def::coord half_length,
00069          Image<O>& output);
00070 
00071 
00072 
00073 # ifndef MLN_INCLUDE_ONLY
00074 
00075     namespace internal
00076     {
00077 
00078       template <typename Meta_Accu, unsigned Dir, // Free parameters.
00079                 typename I, typename O>
00080       void
00081       line_tests(const Image<I>& input_,
00082                  const mln_site(I)&, unsigned,
00083                  unsigned,
00084                  Image<O>& output_)
00085       {
00086         mlc_is_a(Meta_Accu, Meta_Accumulator)::check();
00087 
00088         typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00089         mlc_converts_to(mln_result(A), mln_value(O))::check();
00090 
00091         typedef mln_site(I) P;
00092         mlc_bool(Dir < P::dim)::check();
00093 
00094         mlc_is(mln_trait_image_value_io(O),
00095                mln::trait::image::value_io::read_write)::check();
00096 
00097         const I& input = exact(input_);
00098         O& output = exact(output_);
00099         mln_precondition(input.is_valid());
00100         mln_precondition(output.is_valid());
00101       }
00102 
00103     } // end of namespace mln::accu::internal
00104 
00105 
00106     namespace impl
00107     {
00108 
00109       namespace generic
00110       {
00111 
00112         template <typename Meta_Accu, unsigned Dir,
00113                   typename I, typename O>
00114         void
00115         line(const Image<I>& input_,
00116              const mln_site(I)& p_start, unsigned len_,
00117              unsigned half_length_,
00118              Image<O>& output_)
00119         {
00120           typedef mln_site(I) P;
00121           typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00122 
00123           const I& input = exact(input_);
00124           O& output = exact(output_);
00125 
00126           // Avoid warning in signed/unsigned comparison.
00127           const def::coord len = static_cast<def::coord>(len_);
00128           const def::coord half_length = static_cast<def::coord>(half_length_);
00129 
00130           // Checks and tests.
00131           internal::line_tests<Meta_Accu, Dir>(input,
00132                                                p_start, len,
00133                                                half_length,
00134                                                output);
00135 
00136           // Initialization.
00137           const def::coord start = p_start[Dir];
00138           const def::coord last = static_cast<def::coord>(start + len - 1);
00139           A a; // Accumulator.
00140           a.init();
00141           P p; // Current point.
00142 
00143           // Start (first line point).
00144           p = p_start;
00145           P q = p;
00146           for (def::coord c = 0; c <= half_length && c < len; ++c)
00147             {
00148               a.take(input(q));
00149               ++q[Dir];
00150             }
00151           output(p) = a;
00152 
00153           def::coord& cur = p[Dir];
00154           if (cur == last)
00155             return;
00156 
00157           // Begin of line.
00158 
00159           P p_plus = p_start;
00160           def::coord& plus = p_plus[Dir];
00161           plus = static_cast<def::coord>(plus + half_length);
00162 
00163           while (cur < start + half_length && cur < last)
00164             {
00165               ++cur;
00166               ++plus;
00167               if (plus <= last)
00168                 a.take(input(p_plus));
00169               output(p) = a;
00170             }
00171 
00172           if (cur == last)
00173             return;
00174 
00175           // Middle of line.
00176 
00177           P p_minus = p_start;
00178           def::coord& minus = p_minus[Dir];
00179           --minus;
00180 
00181           while (cur < last - half_length)
00182             {
00183               ++cur;
00184               ++plus;
00185               ++minus;
00186               mln_invariant(plus >= start && plus <= last);
00187               a.take(input(p_plus));
00188               mln_invariant(minus >= start && minus <= last);
00189               a.untake(input(p_minus));
00190               output(p) = a;
00191             }
00192 
00193           if (cur == last)
00194             return;
00195 
00196           // End of line.
00197 
00198           while (cur < last)
00199             {
00200               ++cur;
00201               ++minus;
00202               mln_invariant(minus >= start && minus <= last);
00203               a.untake(input(p_minus));
00204               output(p) = a;
00205             }
00206         }
00207 
00208       } // end of namespace mln::accu::impl::generic
00209 
00210 
00211 
00212       template <typename Meta_Accu, unsigned Dir,
00213                 typename I, typename O>
00214       void
00215       line_fastest(const Image<I>& input_,
00216                    const mln_site(I)& p_start, def::coord len,
00217                    def::coord half_length,
00218                    Image<O>& output_)
00219       {
00220         typedef mln_site(I)  P;
00221         typedef mln_value(I) V;
00222         typedef mln_accu_with(Meta_Accu, V) A;
00223 
00224         const I& input = exact(input_);
00225         O& output = exact(output_);
00226 
00227         // Checks and tests.
00228         internal::line_tests<Meta_Accu, Dir>(input,
00229                                              p_start, len,
00230                                              half_length,
00231                                              output);
00232 
00233         // Initialization.
00234 
00235         const def::coord start = p_start[Dir];
00236         const def::coord last = start + len - 1;
00237 
00238         const V* p_in    = & input(p_start);
00239         V* p_out   = & output(p_start);
00240 
00241         mln_delta(P) dp = literal::zero;
00242         dp[Dir] = 1;
00243         unsigned offset = input.delta_index(dp);
00244 
00245         A a; // Accumulator.
00246         a.init();
00247 
00248         // Start (first line point).
00249 
00250         const V* q = p_in;
00251         for (def::coord c = 0; c <= half_length && c < len; ++c)
00252           {
00253             a.take(*q);
00254             q += offset;
00255           }
00256         *p_out = a;
00257 
00258         def::coord cur = p_start[Dir];
00259         if (cur == last)
00260           return;
00261 
00262         // Begin of line.
00263 
00264         def::coord plus = start + half_length;
00265         const V* p_plus = p_in + half_length * offset;
00266 
00267         while (cur < start + half_length && cur < last)
00268           {
00269             ++cur;
00270             p_in += offset;
00271             ++plus;
00272             p_plus += offset;
00273             if (plus <= last)
00274               a.take(*p_plus);
00275             p_out += offset;
00276             *p_out = a;
00277           }
00278 
00279         if (cur == last)
00280           return;
00281 
00282         // Middle of line.
00283 
00284         def::coord minus = start - 1;
00285         const V* p_minus = p_in - offset;
00286 
00287         while (cur < last - half_length)
00288           {
00289             ++cur;
00290             p_in += offset;
00291             ++plus;
00292             p_plus += offset;
00293             ++minus;
00294             p_minus += offset;
00295             mln_invariant(plus >= start && plus <= last);
00296             a.take(*p_plus);
00297             mln_invariant(minus >= start && minus <= last);
00298             a.untake(*p_minus);
00299             p_out += offset;
00300             *p_out = a;
00301           }
00302 
00303         if (cur == last)
00304           return;
00305 
00306         // End of line.
00307 
00308         while (cur < last)
00309           {
00310             ++cur;
00311             p_in += offset;
00312             ++minus;
00313             p_minus += offset;
00314             mln_invariant(minus >= start && minus <= last);
00315             a.untake(*p_minus);
00316             p_out += offset;
00317             *p_out = a;
00318           }
00319 
00320       }
00321 
00322 
00323 
00324 
00325     } // end of namespace mln::accu::impl
00326 
00327 
00328     namespace internal
00329     {
00330 
00331       template <typename Meta_Accu, unsigned Dir, // Free parameters.
00332                 typename I, typename O>
00333       void
00334       line_dispatch(trait::image::speed::any,
00335                     const Image<I>& input,
00336                     const mln_site(I)& p_start, unsigned len,
00337                     unsigned half_length,
00338                     Image<O>& output)
00339       {
00340         impl::generic::line<Meta_Accu, Dir>(input,
00341                                             p_start, len,
00342                                             half_length,
00343                                             output);
00344       }
00345 
00346 //       template <typename Meta_Accu, unsigned Dir, // Free parameters.
00347 //              typename I, typename O>
00348 //       void
00349 //       line_dispatch(trait::image::speed::fastest,
00350 //                  const Image<I>& input,
00351 //                  const mln_site(I)& p_start, unsigned len,
00352 //                  unsigned half_length,
00353 //                  Image<O>& output)
00354 //       {
00355 //      impl::line_fastest<Meta_Accu, Dir>(input,
00356 //                                         p_start, len,
00357 //                                         half_length,
00358 //                                         output);
00359 //       }
00360 
00361       template <typename Meta_Accu, unsigned Dir, // Free parameters.
00362                 typename I, typename O>
00363       void
00364       line_dispatch(const Image<I>& input,
00365                     const mln_site(I)& p_start, unsigned len,
00366                     unsigned half_length,
00367                     Image<O>& output)
00368       {
00369         line_dispatch<Meta_Accu, Dir>(mln_trait_image_speed(I)(),
00370                                       input,
00371                                       p_start, len,
00372                                       half_length,
00373                                       output);
00374       }
00375 
00376     } // end of namespace mln::accu::internal
00377 
00378 
00379     template <typename Meta_Accu, unsigned Dir, // Free parameters.
00380               typename I, typename O>
00381     void
00382     line(const Image<I>& input,
00383          const mln_site(I)& p_start, unsigned len,
00384          unsigned half_length,
00385          Image<O>& output)
00386     {
00387       internal::line_tests<Meta_Accu, Dir>(input,
00388                                            p_start, len,
00389                                            half_length,
00390                                            output);
00391       internal::line_dispatch<Meta_Accu, Dir>(input,
00392                                               p_start, len,
00393                                               half_length,
00394                                               output);
00395     }
00396 
00397 # endif // ! MLN_INCLUDE_ONLY
00398 
00399   } // end of namespace mln::accu
00400 
00401 } // end of namespace mln
00402 
00403 
00404 #endif // ! MLN_ACCU_LINE_HH
 All Classes Namespaces Functions Variables Typedefs Enumerator