Milena (Olena)
User documentation 2.0a Id
|
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 (void) p; 00683 util::yes* the_; 00684 return *the_; 00685 } 00686 00687 # endif // ! MLN_INCLUDE_ONLY 00688 00689 00690 } // end of namespace mln 00691 00692 00693 #endif // ! MLN_CORE_POINT_HH