• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

point.hh

00001 // Copyright (C) 2007, 2008, 2009, 2010, 2011 EPITA Research and
00002 // Development 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_CORE_POINT_HH
00028 # define MLN_CORE_POINT_HH
00029 
00038 
00039 # include <cmath>
00040 # include <mln/core/def/coord.hh>
00041 # include <mln/core/concept/proxy.hh>
00042 # include <mln/core/concept/gpoint.hh>
00043 # include <mln/core/internal/coord_impl.hh>
00044 # include <mln/fun/i2v/all_to.hh>
00045 
00046 # include <mln/metal/bool.hh>
00047 # include <mln/metal/is_not.hh>
00048 # include <mln/algebra/vec.hh>
00049 # include <mln/metal/converts_to.hh>
00050 # include <mln/algebra/h_vec.hh>
00051 # include <mln/util/yes.hh>
00052 
00053 
00054 namespace mln
00055 {
00056 
00058   template <typename G, typename C> struct  point;
00059   template <typename G, typename C> struct dpoint;
00060   namespace literal {
00061     struct zero_t;
00062     struct one_t;
00063     struct origin_t;
00064   }
00066 
00067 
00068   namespace convert
00069   {
00070 
00071     namespace over_load
00072     {
00073 
00074       template <typename G, typename C1, typename C2>
00075       void from_to_(const point<G,C1>& from, point<G,C2>& to);
00076 
00077       template <unsigned n, typename C1, typename G, typename C2>
00078       void
00079       from_to_(const mln::algebra::vec<n,C1>& from, point<G,C2>& to);
00080 
00081       template <unsigned n, typename C1, typename G>
00082       void
00083       from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to);
00084 
00085     } // end of namespace mln::convert::over_load
00086 
00087   } // end of namespace mln::convert
00088 
00089 
00090 
00091   namespace internal
00092   {
00093     // This is a hack so that g++-2.95 can compile the method
00094     // "point<G,C>::operator vec() const".
00095     template <typename G, typename C>
00096     struct vec_of_point
00097     {
00098       typedef mln::algebra::vec<G::dim, float> ret;
00099     };
00100 
00101   }
00102 
00107   template <typename G, typename C>
00108   struct point : public Gpoint< point<G,C> >,
00109                  public internal::mutable_coord_impl_< G::dim, C, point<G,C> >
00110   {
00111     // FIXME: Temporary hack.
00112     typedef point site;
00113     typedef point psite;
00114 
00115 
00119     enum { dim = G::dim };
00120 
00122     typedef G grid;
00123 
00125     typedef dpoint<G,C> delta;
00126 
00128     typedef dpoint<G,C> dpsite;
00129 
00131     typedef C coord;
00132 
00134     typedef mln::algebra::vec<G::dim, float> vec;
00135 
00137     typedef mln::algebra::h_vec<G::dim, float> h_vec;
00138 
00142     const C& operator[](unsigned i) const;
00143 
00147     C& operator[](unsigned i);
00148 
00149 
00151     const C& last_coord() const;
00152 
00154     C& last_coord();
00155 
00156 
00158     point();
00159 
00161     template <typename C2>
00162     point(const mln::algebra::vec<dim,C2>& v);
00163 
00164     point(const mln::algebra::vec<dim,C>& v);
00165 
00166 
00169     explicit point(C ind);
00170     point(C row, C col);
00171     point(C sli, C row, C col);
00173 
00175     point(const literal::origin_t&);
00176     point<G,C>& operator=(const literal::origin_t&);
00177     // Works only in 1D:
00178     point(const literal::zero_t&);
00179     point<G,C>& operator=(const literal::zero_t&);
00180     point(const literal::one_t&);
00181     point<G,C>& operator=(const literal::one_t&);
00183 
00185     template <typename F>
00186     point(const Function_v2v<F>& f);
00187 
00189     void set_all(C c);
00190 
00192     static const point<G,C> origin;
00193 
00195     point<G,C>& operator+=(const delta& dp);
00196 
00198     point<G,C>& operator-=(const delta& dp);
00199 
00200   /* FIXME: Seems highly non-generic!
00201      This (non documented change, even in ChangeLog) change was
00202      introduce by revision 1224, see
00203      https://trac.lrde.org/olena/changeset/1224#file2
00204      https://www.lrde.epita.fr/pipermail/olena-patches/2007-October/001592.html
00205   */
00206     operator typename internal::vec_of_point<G,C>::ret () const; // Hack to help g++-2.95.
00207 
00209     vec to_vec() const;
00210 
00212     h_vec to_h_vec() const;
00213 
00215     static const point<G,C>& plus_infty();
00216 
00218     static const point<G,C>& minus_infty();
00219 
00221     mln::algebra::vec<G::dim, C>& hook_coord_();
00222 
00223   protected:
00224     mln::algebra::vec<G::dim, C> coord_;
00225   };
00226 
00227   namespace internal
00228   {
00229 
00232 
00233     template <typename P, typename E>
00234     struct subject_point_impl;
00235 
00236     template <typename G, typename C, typename E>
00237     struct subject_point_impl< point<G,C>, E >
00238     {
00239       typename point<G,C>::vec to_vec() const;
00240       operator typename point<G,C>::vec () const; // Hack to help g++-2.95.
00241 
00242     private:
00243       const E& exact_() const;
00244     };
00245 
00247 
00248   } // end of namespace mln::internal
00249 
00250 
00252   template <typename G, typename C>
00253   const mln::algebra::vec<point<G,C>::dim - 1, C>& cut_(const point<G,C>& p);
00254 
00255   template <typename C>
00256   const util::yes& cut_(const point<grid::tick,C>& p);
00257 
00258 
00259 
00260 # ifndef MLN_INCLUDE_ONLY
00261 
00262 
00263   namespace internal
00264   {
00265 
00266     template <typename C, typename C2>
00267     inline
00268     C
00269     convert_data_(metal::bool_<false>, const C2& v)
00270     {
00271       return static_cast<C>(v);
00272     }
00273 
00274     template <typename C, typename C2>
00275     inline
00276     C
00277     convert_data_(metal::bool_<true>, const C2& v)
00278     {
00279       return static_cast<C>(round(v));
00280     }
00281 
00282     template <typename C, typename C2>
00283     inline
00284     C
00285     convert_data(const C2& v)
00286     {
00287       // If (C != float && C != double) && (C2 == float || C2 == double)
00288       // => We want to round the value.
00289       // Otherwise we can just statically cast.
00290       //
00291       return convert_data_<C>(
00292         typename mlc_and(
00293           mlc_and(mlc_is_not(C,float),
00294                   mlc_is_not(C,double)),
00295           mlc_or(mlc_is(C2,float),
00296                  mlc_is(C2, double)))::eval(), v);
00297     }
00298 
00299 
00300 
00301   } // end of namespace mln::internal
00302 
00303 
00304 
00305   namespace convert
00306   {
00307 
00308     namespace over_load
00309     {
00310 
00311       template <typename G, typename C1, typename C2>
00312       inline
00313       void
00314       from_to_(const point<G,C1>& from, point<G,C2>& to)
00315       {
00316         mlc_converts_to(C1,C2)::check();
00317         enum { dim = G::dim };
00318 
00319         for (unsigned i = 0; i < dim; ++i)
00320           to[i] = mln::internal::convert_data<C2>(from[i]);
00321       }
00322 
00323 
00324       template <unsigned n, typename C1, typename G, typename C2>
00325       inline
00326       void
00327       from_to_(const mln::algebra::vec<n,C1>& from, point<G,C2>& to)
00328       {
00329         mlc_converts_to(C1, C2)::check();
00330         enum { dim = G::dim };
00331         mlc_bool(G::dim == n)::check();
00332 
00333         unsigned j = 0;
00334         for (unsigned i = dim - 2; i < dim; ++i)
00335           to[i]   = mln::internal::convert_data<C2>(from[j++]);
00336         for (unsigned i = 2; i < dim; ++i, ++j)
00337           to[i-j] = mln::internal::convert_data<C2>(from[j]);
00338       }
00339 
00340       template <typename C1, typename G, typename C2>
00341       inline
00342       void
00343       from_to_(const mln::algebra::vec<1,C1>& from, point<G,C2>& to)
00344       {
00345         mlc_converts_to(C1, C2)::check();
00346         enum { dim = G::dim };
00347         mlc_bool(G::dim == 1)::check();
00348 
00349         to[0] = mln::internal::convert_data<C2>(from[0]);
00350       }
00351 
00352       template <unsigned n, typename C1, typename G>
00353       inline
00354       void
00355       from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to)
00356       {
00357         enum { dim = G::dim };
00358         mlc_bool(G::dim == n)::check();
00359 
00360         unsigned j = 0;
00361         for (unsigned i = dim - 2; i < dim; ++i)
00362           to[i]   = from[j++];
00363         for (unsigned i = 2; i < dim; ++i, ++j)
00364           to[i-j] = from[j];
00365       }
00366 
00367       template <typename C1, typename G>
00368       inline
00369       void
00370       from_to_(const mln::algebra::vec<1,C1>& from, point<G,C1>& to)
00371       {
00372         enum { dim = G::dim };
00373         mlc_bool(G::dim == 1)::check();
00374 
00375         to[0] = from[0];
00376       }
00377 
00378     } // end of namespace mln::convert::over_load
00379 
00380   } // end of namespace mln::convert
00381 
00382 
00383   template <typename G, typename C>
00384   inline
00385   const C& point<G,C>::operator[](unsigned i) const
00386   {
00387     assert(i < dim);
00388     return this->coord_[i];
00389   }
00390 
00391   template <typename G, typename C>
00392   inline
00393   C& point<G,C>::operator[](unsigned i)
00394   {
00395     assert(i < dim);
00396     return this->coord_[i];
00397   }
00398 
00399   template <typename G, typename C>
00400   inline
00401   const C&
00402   point<G,C>::last_coord() const
00403   {
00404     return this->coord_[dim - 1];
00405   }
00406 
00407   template <typename G, typename C>
00408   inline
00409   C&
00410   point<G,C>::last_coord()
00411   {
00412     return this->coord_[dim - 1];
00413   }
00414 
00415 
00416   // Constructors.
00417 
00418   template <typename G, typename C>
00419   inline
00420   point<G,C>::point()
00421   {
00422   }
00423 
00424   template <typename G, typename C>
00425   template <typename C2>
00426   inline
00427   point<G,C>::point(const mln::algebra::vec<dim,C2>& v)
00428   {
00429     convert::over_load::from_to_(v, *this);
00430   }
00431 
00432 
00433   template <typename G, typename C>
00434   inline
00435   point<G,C>::point(const mln::algebra::vec<dim,C>& v)
00436   {
00437     convert::over_load::from_to_(v, *this);
00438   }
00439 
00440 
00441   template <typename G, typename C>
00442   inline
00443   point<G,C>::point(C ind)
00444   {
00445     metal::bool_<(dim == 1)>::check();
00446     coord_[0] = ind;
00447   }
00448 
00449   template <typename G, typename C>
00450   inline
00451   point<G,C>::point(C row, C col)
00452   {
00453     metal::bool_<(dim == 2)>::check();
00454     coord_[0] = row;
00455     coord_[1] = col;
00456   }
00457 
00458   template <typename G, typename C>
00459   inline
00460   point<G,C>::point(C sli, C row, C col)
00461   {
00462     metal::bool_<(dim == 3)>::check();
00463     coord_[0] = sli;
00464     coord_[1] = row;
00465     coord_[2] = col;
00466   }
00467 
00468   template <typename G, typename C>
00469   template <typename F>
00470   inline
00471   point<G,C>::point(const Function_v2v<F>& f_)
00472   {
00473     mlc_converts_to(mln_result(F), C)::check();
00474     const F& f = exact(f_);
00475     for (unsigned i = 0; i < dim; ++i)
00476       coord_[i] = static_cast<C>( f(i) );
00477   }
00478 
00479   template <typename G, typename C>
00480   inline
00481   point<G,C>::point(const literal::origin_t&)
00482   {
00483     coord_.set_all(0);
00484   }
00485 
00486   template <typename G, typename C>
00487   inline
00488   point<G,C>&
00489   point<G,C>::operator=(const literal::origin_t&)
00490   {
00491     coord_.set_all(0);
00492     return *this;
00493   }
00494 
00495   template <typename G, typename C>
00496   inline
00497   point<G,C>::point(const literal::zero_t&)
00498   {
00499     metal::bool_<(dim == 1)>::check();
00500     coord_[0] = 1;
00501   }
00502 
00503   template <typename G, typename C>
00504   inline
00505   point<G,C>&
00506   point<G,C>::operator=(const literal::zero_t&)
00507   {
00508     metal::bool_<(dim == 1)>::check();
00509     coord_[0] = 1;
00510     return *this;
00511   }
00512 
00513   template <typename G, typename C>
00514   inline
00515   point<G,C>::point(const literal::one_t&)
00516   {
00517     metal::bool_<(dim == 1)>::check();
00518     coord_[0] = 1;
00519   }
00520 
00521   template <typename G, typename C>
00522   inline
00523   point<G,C>&
00524   point<G,C>::operator=(const literal::one_t&)
00525   {
00526     metal::bool_<(dim == 1)>::check();
00527     coord_[0] = 1;
00528     return *this;
00529   }
00530 
00531   template <typename G, typename C>
00532   inline
00533   void point<G,C>::set_all(C c)
00534   {
00535     coord_.set_all(c);
00536   }
00537 
00538   template <typename G, typename C>
00539   const point<G,C> point<G,C>::origin = all_to(0);
00540 
00541   template <typename G, typename C>
00542   inline
00543   point<G,C>&
00544   point<G,C>::operator+=(const delta& dp)
00545   {
00546     for (unsigned i = 0; i < dim; ++i)
00547       coord_[i] = static_cast<C>(coord_[i] + dp[i]);
00548     return *this;
00549   }
00550 
00551   template <typename G, typename C>
00552   inline
00553   point<G,C>&
00554   point<G,C>::operator-=(const delta& dp)
00555   {
00556     for (unsigned i = 0; i < dim; ++i)
00557       coord_[i] -= dp[i];
00558     return *this;
00559   }
00560 
00561   template <typename G, typename C>
00562   inline
00563   point<G,C>::operator typename internal::vec_of_point<G,C>::ret () const // Hack to help g++-2.95.
00564   {
00565     return to_vec();
00566   }
00567 
00568   template <typename G, typename C>
00569   inline
00570   typename point<G,C>::vec
00571   point<G,C>::to_vec() const
00572   {
00573     //FIXME: to be improved.
00574     if (dim > 2)
00575     {
00576       mln::algebra::vec<G::dim, float> tmp;
00577       unsigned j = 0;
00578       for (unsigned i = dim - 2; i < dim; ++i)
00579         tmp[j++] = mln::internal::convert_data<float>(coord_[i]);
00580       for (unsigned i = 2; i < dim; ++i, ++j)
00581         tmp[j] = mln::internal::convert_data<float>(coord_[i-j]);
00582 
00583       return tmp;
00584     }
00585 
00586     return coord_;
00587   }
00588 
00589   template <typename G, typename C>
00590   inline
00591   typename point<G,C>::h_vec
00592   point<G,C>::to_h_vec() const
00593   {
00594     mln::algebra::h_vec<G::dim, float> tmp;
00595 
00596     //FIXME: to be improved.
00597     if (dim == 1)
00598       tmp[0] = coord_[0];
00599     else
00600     {
00601       unsigned j = 0;
00602       for (unsigned i = dim - 2; i < dim; ++i)
00603         tmp[j++] = coord_[i];
00604 
00605       for (unsigned i = 2; i < dim; ++i, ++j)
00606         tmp[j] = coord_[i-j];
00607 
00608       tmp[G::dim] = 1;
00609     }
00610 
00611     return tmp;
00612   }
00613 
00614 
00615   template <typename G, typename C>
00616   inline
00617   const point<G,C>&
00618   point<G,C>::plus_infty()
00619   {
00620     static const point<G,C> the_(all_to(mln_max(C)));
00621     return the_;
00622   }
00623 
00624   template <typename G, typename C>
00625   inline
00626   const point<G,C>&
00627   point<G,C>::minus_infty()
00628   {
00629     static const point<G,C> the_(all_to(mln_min(C)));
00630     return the_;
00631   }
00632 
00633   template <typename G, typename C>
00634   inline
00635   mln::algebra::vec<G::dim, C>&
00636   point<G,C>::hook_coord_()
00637   {
00638     return coord_;
00639   }
00640 
00641   namespace internal
00642   {
00643 
00644     template <typename G, typename C, typename E>
00645     inline
00646     const E&
00647     subject_point_impl< point<G,C>, E >::exact_() const
00648     {
00649       return internal::force_exact<const E>(*this);
00650     }
00651 
00652     template <typename G, typename C, typename E>
00653     inline
00654     typename point<G,C>::vec
00655     subject_point_impl< point<G,C>, E >::to_vec() const
00656     {
00657       return exact_().get_subject().to_vec();
00658     }
00659 
00660     template <typename G, typename C, typename E>
00661     inline
00662     subject_point_impl< point<G,C>, E >::operator typename point<G,C>::vec () const // Hack to help g++-2.95.
00663     {
00664       return exact_().get_subject();
00665     }
00666 
00667   } // end of namespace mln::internal
00668 
00669   template <typename G, typename C>
00670   inline
00671   const mln::algebra::vec<point<G,C>::dim - 1, C>&
00672   cut_(const point<G,C>& p)
00673   {
00674     return *(mln::algebra::vec<point<G,C>::dim - 1, C>*)(& p.to_vec());
00675   }
00676 
00677   template <typename C>
00678   inline
00679   const util::yes&
00680   cut_(const point<grid::tick,C>& /* p */)
00681   {
00682     util::yes* the_;
00683     return *the_;
00684   }
00685 
00686 # endif // ! MLN_INCLUDE_ONLY
00687 
00688 
00689 } // end of namespace mln
00690 
00691 
00692 #endif // ! MLN_CORE_POINT_HH

Generated on Fri Sep 16 2011 16:33:50 for Milena (Olena) by  doxygen 1.7.1