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
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 }
00086
00087 }
00088
00089
00090
00091 namespace internal
00092 {
00093
00094
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
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
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
00201
00202
00203
00204
00205
00206 operator typename internal::vec_of_point<G,C>::ret () const;
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;
00241
00242 private:
00243 const E& exact_() const;
00244 };
00245
00247
00248 }
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
00288
00289
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 }
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
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
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 }
00369
00370 }
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
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
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
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
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
00653 {
00654 return exact_().get_subject();
00655 }
00656
00657 }
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 }
00680
00681
00682 #endif // ! MLN_CORE_POINT_HH