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

point.hh

00001 // Copyright (C) 2007, 2008, 2009, 2010 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_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         //FIXME: to be improved while adding a conversion routine.
00335         if (dim < 3)
00336           to.hook_coord_() = from;
00337         else
00338         {
00339           for (unsigned i = dim - 2; i < dim; ++i)
00340             to[i]   = mln::internal::convert_data<C2>(from[j++]);
00341           for (unsigned i = 2; i < dim; ++i, ++j)
00342             to[i-j] = mln::internal::convert_data<C2>(from[j]);
00343         }
00344       }
00345 
00346       template <unsigned n, typename C1, typename G>
00347       inline
00348       void
00349       from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to)
00350       {
00351         enum { dim = G::dim };
00352         mlc_bool(G::dim == n)::check();
00353 
00354         unsigned j = 0;
00355         //FIXME: to be improved while adding a conversion routine.
00356         if (dim < 3)
00357           to.hook_coord_() = from;
00358         else
00359         {
00360           for (unsigned i = dim - 2; i < dim; ++i)
00361             to[i]   = from[j++];
00362           for (unsigned i = 2; i < dim; ++i, ++j)
00363             to[i-j] = from[j];
00364         }
00365       }
00366 
00367 
00368     } // end of namespace mln::convert::over_load
00369 
00370   } // end of namespace mln::convert
00371 
00372 
00373   template <typename G, typename C>
00374   inline
00375   const C& point<G,C>::operator[](unsigned i) const
00376   {
00377     assert(i < dim);
00378     return this->coord_[i];
00379   }
00380 
00381   template <typename G, typename C>
00382   inline
00383   C& point<G,C>::operator[](unsigned i)
00384   {
00385     assert(i < dim);
00386     return this->coord_[i];
00387   }
00388 
00389   template <typename G, typename C>
00390   inline
00391   const C&
00392   point<G,C>::last_coord() const
00393   {
00394     return this->coord_[dim - 1];
00395   }
00396 
00397   template <typename G, typename C>
00398   inline
00399   C&
00400   point<G,C>::last_coord()
00401   {
00402     return this->coord_[dim - 1];
00403   }
00404 
00405 
00406   // Constructors.
00407 
00408   template <typename G, typename C>
00409   inline
00410   point<G,C>::point()
00411   {
00412   }
00413 
00414   template <typename G, typename C>
00415   template <typename C2>
00416   inline
00417   point<G,C>::point(const mln::algebra::vec<dim,C2>& v)
00418   {
00419     convert::over_load::from_to_(v, *this);
00420   }
00421 
00422 
00423   template <typename G, typename C>
00424   inline
00425   point<G,C>::point(const mln::algebra::vec<dim,C>& v)
00426   {
00427     convert::over_load::from_to_(v, *this);
00428   }
00429 
00430 
00431   template <typename G, typename C>
00432   inline
00433   point<G,C>::point(C ind)
00434   {
00435     metal::bool_<(dim == 1)>::check();
00436     coord_[0] = ind;
00437   }
00438 
00439   template <typename G, typename C>
00440   inline
00441   point<G,C>::point(C row, C col)
00442   {
00443     metal::bool_<(dim == 2)>::check();
00444     coord_[0] = row;
00445     coord_[1] = col;
00446   }
00447 
00448   template <typename G, typename C>
00449   inline
00450   point<G,C>::point(C sli, C row, C col)
00451   {
00452     metal::bool_<(dim == 3)>::check();
00453     coord_[0] = sli;
00454     coord_[1] = row;
00455     coord_[2] = col;
00456   }
00457 
00458   template <typename G, typename C>
00459   template <typename F>
00460   inline
00461   point<G,C>::point(const Function_v2v<F>& f_)
00462   {
00463     mlc_converts_to(mln_result(F), C)::check();
00464     const F& f = exact(f_);
00465     for (unsigned i = 0; i < dim; ++i)
00466       coord_[i] = static_cast<C>( f(i) );
00467   }
00468 
00469   template <typename G, typename C>
00470   inline
00471   point<G,C>::point(const literal::origin_t&)
00472   {
00473     coord_.set_all(0);
00474   }
00475 
00476   template <typename G, typename C>
00477   inline
00478   point<G,C>&
00479   point<G,C>::operator=(const literal::origin_t&)
00480   {
00481     coord_.set_all(0);
00482     return *this;
00483   }
00484 
00485   template <typename G, typename C>
00486   inline
00487   point<G,C>::point(const literal::zero_t&)
00488   {
00489     metal::bool_<(dim == 1)>::check();
00490     coord_[0] = 1;
00491   }
00492 
00493   template <typename G, typename C>
00494   inline
00495   point<G,C>&
00496   point<G,C>::operator=(const literal::zero_t&)
00497   {
00498     metal::bool_<(dim == 1)>::check();
00499     coord_[0] = 1;
00500     return *this;
00501   }
00502 
00503   template <typename G, typename C>
00504   inline
00505   point<G,C>::point(const literal::one_t&)
00506   {
00507     metal::bool_<(dim == 1)>::check();
00508     coord_[0] = 1;
00509   }
00510 
00511   template <typename G, typename C>
00512   inline
00513   point<G,C>&
00514   point<G,C>::operator=(const literal::one_t&)
00515   {
00516     metal::bool_<(dim == 1)>::check();
00517     coord_[0] = 1;
00518     return *this;
00519   }
00520 
00521   template <typename G, typename C>
00522   inline
00523   void point<G,C>::set_all(C c)
00524   {
00525     coord_.set_all(c);
00526   }
00527 
00528   template <typename G, typename C>
00529   const point<G,C> point<G,C>::origin = all_to(0);
00530 
00531   template <typename G, typename C>
00532   inline
00533   point<G,C>&
00534   point<G,C>::operator+=(const delta& dp)
00535   {
00536     for (unsigned i = 0; i < dim; ++i)
00537       coord_[i] = static_cast<C>(coord_[i] + dp[i]);
00538     return *this;
00539   }
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] -= dp[i];
00548     return *this;
00549   }
00550 
00551   template <typename G, typename C>
00552   inline
00553   point<G,C>::operator typename internal::vec_of_point<G,C>::ret () const // Hack to help g++-2.95.
00554   {
00555     return to_vec();
00556   }
00557 
00558   template <typename G, typename C>
00559   inline
00560   typename point<G,C>::vec
00561   point<G,C>::to_vec() const
00562   {
00563     //FIXME: to be improved.
00564     if (dim > 2)
00565     {
00566       mln::algebra::vec<G::dim, float> tmp;
00567       unsigned j = 0;
00568       for (unsigned i = dim - 2; i < dim; ++i)
00569         tmp[j++] = coord_[i];
00570       for (unsigned i = 2; i < dim; ++i, ++j)
00571         tmp[j] = coord_[i-j];
00572 
00573       return tmp;
00574     }
00575 
00576     return coord_;
00577   }
00578 
00579   template <typename G, typename C>
00580   inline
00581   typename point<G,C>::h_vec
00582   point<G,C>::to_h_vec() const
00583   {
00584     mln::algebra::h_vec<G::dim, float> tmp;
00585 
00586     //FIXME: to be improved.
00587     if (dim == 1)
00588       tmp[0] = coord_[0];
00589     else
00590     {
00591       unsigned j = 0;
00592       for (unsigned i = dim - 2; i < dim; ++i)
00593         tmp[j++] = coord_[i];
00594 
00595       for (unsigned i = 2; i < dim; ++i, ++j)
00596         tmp[j] = coord_[i-j];
00597 
00598       tmp[G::dim] = 1;
00599     }
00600 
00601     return tmp;
00602   }
00603 
00604 
00605   template <typename G, typename C>
00606   inline
00607   const point<G,C>&
00608   point<G,C>::plus_infty()
00609   {
00610     static const point<G,C> the_(all_to(mln_max(C)));
00611     return the_;
00612   }
00613 
00614   template <typename G, typename C>
00615   inline
00616   const point<G,C>&
00617   point<G,C>::minus_infty()
00618   {
00619     static const point<G,C> the_(all_to(mln_min(C)));
00620     return the_;
00621   }
00622 
00623   template <typename G, typename C>
00624   inline
00625   mln::algebra::vec<G::dim, C>&
00626   point<G,C>::hook_coord_()
00627   {
00628     return coord_;
00629   }
00630 
00631   namespace internal
00632   {
00633 
00634     template <typename G, typename C, typename E>
00635     inline
00636     const E&
00637     subject_point_impl< point<G,C>, E >::exact_() const
00638     {
00639       return internal::force_exact<const E>(*this);
00640     }
00641 
00642     template <typename G, typename C, typename E>
00643     inline
00644     typename point<G,C>::vec
00645     subject_point_impl< point<G,C>, E >::to_vec() const
00646     {
00647       return exact_().get_subject().to_vec();
00648     }
00649 
00650     template <typename G, typename C, typename E>
00651     inline
00652     subject_point_impl< point<G,C>, E >::operator typename point<G,C>::vec () const // Hack to help g++-2.95.
00653     {
00654       return exact_().get_subject();
00655     }
00656 
00657   } // end of namespace mln::internal
00658 
00659   template <typename G, typename C>
00660   inline
00661   const mln::algebra::vec<point<G,C>::dim - 1, C>&
00662   cut_(const point<G,C>& p)
00663   {
00664     return *(mln::algebra::vec<point<G,C>::dim - 1, C>*)(& p.to_vec());
00665   }
00666 
00667   template <typename C>
00668   inline
00669   const util::yes&
00670   cut_(const point<grid::tick,C>& p)
00671   {
00672     util::yes* the_;
00673     return *the_;
00674   }
00675 
00676 # endif // ! MLN_INCLUDE_ONLY
00677 
00678 
00679 } // end of namespace mln
00680 
00681 
00682 #endif // ! MLN_CORE_POINT_HH

Generated on Fri Oct 19 2012 04:16:11 for Milena (Olena) by  doxygen 1.7.1