Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
point.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 2011 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_CORE_POINT_HH
28 # define MLN_CORE_POINT_HH
29 
38 
39 # include <cmath>
40 # include <mln/core/def/coord.hh>
41 # include <mln/core/concept/proxy.hh>
42 # include <mln/core/concept/gpoint.hh>
43 # include <mln/core/internal/coord_impl.hh>
44 # include <mln/fun/i2v/all_to.hh>
45 
46 # include <mln/metal/bool.hh>
47 # include <mln/metal/is_not.hh>
48 # include <mln/algebra/vec.hh>
49 # include <mln/metal/converts_to.hh>
50 # include <mln/algebra/h_vec.hh>
51 # include <mln/util/yes.hh>
52 
53 
54 namespace mln
55 {
56 
58  template <typename G, typename C> struct point;
59  template <typename G, typename C> struct dpoint;
60  namespace literal {
61  struct zero_t;
62  struct one_t;
63  struct origin_t;
64  }
66 
67 
68  namespace convert
69  {
70 
71  namespace over_load
72  {
73 
74  template <typename G, typename C1, typename C2>
75  void from_to_(const point<G,C1>& from, point<G,C2>& to);
76 
77  template <unsigned n, typename C1, typename G, typename C2>
78  void
79  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C2>& to);
80 
81  template <unsigned n, typename C1, typename G>
82  void
83  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to);
84 
85  } // end of namespace mln::convert::over_load
86 
87  } // end of namespace mln::convert
88 
89 
90 
91  namespace internal
92  {
93  // This is a hack so that g++-2.95 can compile the method
94  // "point<G,C>::operator vec() const".
95  template <typename G, typename C>
96  struct vec_of_point
97  {
98  typedef mln::algebra::vec<G::dim, float> ret;
99  };
100 
101  }
102 
107  template <typename G, typename C>
108  struct point : public Gpoint< point<G,C> >,
109  public internal::mutable_coord_impl_< G::dim, C, point<G,C> >
110  {
111  // FIXME: Temporary hack.
112  typedef point site;
113  typedef point psite;
114 
115 
119  enum { dim = G::dim };
120 
122  typedef G grid;
123 
126 
129 
131  typedef C coord;
132 
134  typedef mln::algebra::vec<G::dim, float> vec;
135 
138 
142  const C& operator[](unsigned i) const;
143 
147  C& operator[](unsigned i);
148 
149 
151  const C& last_coord() const;
152 
154  C& last_coord();
155 
156 
158  point();
159 
161  template <typename C2>
162  point(const mln::algebra::vec<dim,C2>& v);
163 
164  point(const mln::algebra::vec<dim,C>& v);
165 
166 
169  explicit point(C ind);
170  point(C row, C col);
171  point(C sli, C row, C col);
173 
175  point(const literal::origin_t&);
176  point<G,C>& operator=(const literal::origin_t&);
177  // Works only in 1D:
178  point(const literal::zero_t&);
179  point<G,C>& operator=(const literal::zero_t&);
180  point(const literal::one_t&);
181  point<G,C>& operator=(const literal::one_t&);
183 
185  template <typename F>
186  point(const Function_v2v<F>& f);
187 
189  void set_all(C c);
190 
192  static const point<G,C> origin;
193 
195  point<G,C>& operator+=(const delta& dp);
196 
198  point<G,C>& operator-=(const delta& dp);
199 
200  /* FIXME: Seems highly non-generic!
201  This (non documented change, even in ChangeLog) change was
202  introduce by revision 1224, see
203  https://trac.lrde.org/olena/changeset/1224#file2
204  https://www.lrde.epita.fr/pipermail/olena-patches/2007-October/001592.html
205  */
206  operator typename internal::vec_of_point<G,C>::ret () const; // Hack to help g++-2.95.
207 
209  vec to_vec() const;
210 
212  h_vec to_h_vec() const;
213 
215  static const point<G,C>& plus_infty();
216 
218  static const point<G,C>& minus_infty();
219 
221  mln::algebra::vec<G::dim, C>& hook_coord_();
222 
223  protected:
224  mln::algebra::vec<G::dim, C> coord_;
225  };
226 
227  namespace internal
228  {
229 
232 
233  template <typename P, typename E>
235 
236  template <typename G, typename C, typename E>
237  struct subject_point_impl< point<G,C>, E >
238  {
239  typename point<G,C>::vec to_vec() const;
240  operator typename point<G,C>::vec () const; // Hack to help g++-2.95.
241 
242  private:
243  const E& exact_() const;
244  };
245 
247 
248  } // end of namespace mln::internal
249 
250 
252  template <typename G, typename C>
253  const mln::algebra::vec<point<G,C>::dim - 1, C>& cut_(const point<G,C>& p);
254 
255  template <typename C>
256  const util::yes& cut_(const point<grid::tick,C>& p);
257 
258 
259 
260 # ifndef MLN_INCLUDE_ONLY
261 
262 
263  namespace internal
264  {
265 
266  template <typename C, typename C2>
267  inline
268  C
269  convert_data_(metal::bool_<false>, const C2& v)
270  {
271  return static_cast<C>(v);
272  }
273 
274  template <typename C, typename C2>
275  inline
276  C
277  convert_data_(metal::bool_<true>, const C2& v)
278  {
279  return static_cast<C>(round(v));
280  }
281 
282  template <typename C, typename C2>
283  inline
284  C
285  convert_data(const C2& v)
286  {
287  // If (C != float && C != double) && (C2 == float || C2 == double)
288  // => We want to round the value.
289  // Otherwise we can just statically cast.
290  //
291  return convert_data_<C>(
292  typename mlc_and(
293  mlc_and(mlc_is_not(C,float),
294  mlc_is_not(C,double)),
295  mlc_or(mlc_is(C2,float),
296  mlc_is(C2, double)))::eval(), v);
297  }
298 
299 
300 
301  } // end of namespace mln::internal
302 
303 
304 
305  namespace convert
306  {
307 
308  namespace over_load
309  {
310 
311  template <typename G, typename C1, typename C2>
312  inline
313  void
314  from_to_(const point<G,C1>& from, point<G,C2>& to)
315  {
316  mlc_converts_to(C1,C2)::check();
317  enum { dim = G::dim };
318 
319  for (unsigned i = 0; i < dim; ++i)
320  to[i] = mln::internal::convert_data<C2>(from[i]);
321  }
322 
323 
324  template <unsigned n, typename C1, typename G, typename C2>
325  inline
326  void
327  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C2>& to)
328  {
329  mlc_converts_to(C1, C2)::check();
330  enum { dim = G::dim };
331  mlc_bool(G::dim == n)::check();
332 
333  unsigned j = 0;
334  for (unsigned i = dim - 2; i < dim; ++i)
335  to[i] = mln::internal::convert_data<C2>(from[j++]);
336  for (unsigned i = 2; i < dim; ++i, ++j)
337  to[i-j] = mln::internal::convert_data<C2>(from[j]);
338  }
339 
340  template <typename C1, typename G, typename C2>
341  inline
342  void
343  from_to_(const mln::algebra::vec<1,C1>& from, point<G,C2>& to)
344  {
345  mlc_converts_to(C1, C2)::check();
346  enum { dim = G::dim };
347  mlc_bool(G::dim == 1)::check();
348 
349  to[0] = mln::internal::convert_data<C2>(from[0]);
350  }
351 
352  template <unsigned n, typename C1, typename G>
353  inline
354  void
355  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to)
356  {
357  enum { dim = G::dim };
358  mlc_bool(G::dim == n)::check();
359 
360  unsigned j = 0;
361  for (unsigned i = dim - 2; i < dim; ++i)
362  to[i] = from[j++];
363  for (unsigned i = 2; i < dim; ++i, ++j)
364  to[i-j] = from[j];
365  }
366 
367  template <typename C1, typename G>
368  inline
369  void
370  from_to_(const mln::algebra::vec<1,C1>& from, point<G,C1>& to)
371  {
372  enum { dim = G::dim };
373  mlc_bool(G::dim == 1)::check();
374 
375  to[0] = from[0];
376  }
377 
378  } // end of namespace mln::convert::over_load
379 
380  } // end of namespace mln::convert
381 
382 
383  template <typename G, typename C>
384  inline
385  const C& point<G,C>::operator[](unsigned i) const
386  {
387  assert(i < dim);
388  return this->coord_[i];
389  }
390 
391  template <typename G, typename C>
392  inline
393  C& point<G,C>::operator[](unsigned i)
394  {
395  assert(i < dim);
396  return this->coord_[i];
397  }
398 
399  template <typename G, typename C>
400  inline
401  const C&
403  {
404  return this->coord_[dim - 1];
405  }
406 
407  template <typename G, typename C>
408  inline
409  C&
411  {
412  return this->coord_[dim - 1];
413  }
414 
415 
416  // Constructors.
417 
418  template <typename G, typename C>
419  inline
421  {
422  }
423 
424  template <typename G, typename C>
425  template <typename C2>
426  inline
427  point<G,C>::point(const mln::algebra::vec<dim,C2>& v)
428  {
429  convert::over_load::from_to_(v, *this);
430  }
431 
432 
433  template <typename G, typename C>
434  inline
435  point<G,C>::point(const mln::algebra::vec<dim,C>& v)
436  {
437  convert::over_load::from_to_(v, *this);
438  }
439 
440 
441  template <typename G, typename C>
442  inline
444  {
445  metal::bool_<(dim == 1)>::check();
446  coord_[0] = ind;
447  }
448 
449  template <typename G, typename C>
450  inline
451  point<G,C>::point(C row, C col)
452  {
453  metal::bool_<(dim == 2)>::check();
454  coord_[0] = row;
455  coord_[1] = col;
456  }
457 
458  template <typename G, typename C>
459  inline
460  point<G,C>::point(C sli, C row, C col)
461  {
462  metal::bool_<(dim == 3)>::check();
463  coord_[0] = sli;
464  coord_[1] = row;
465  coord_[2] = col;
466  }
467 
468  template <typename G, typename C>
469  template <typename F>
470  inline
472  {
473  mlc_converts_to(mln_result(F), C)::check();
474  const F& f = exact(f_);
475  for (unsigned i = 0; i < dim; ++i)
476  coord_[i] = static_cast<C>( f(i) );
477  }
478 
479  template <typename G, typename C>
480  inline
482  {
483  coord_.set_all(0);
484  }
485 
486  template <typename G, typename C>
487  inline
488  point<G,C>&
490  {
491  coord_.set_all(0);
492  return *this;
493  }
494 
495  template <typename G, typename C>
496  inline
497  point<G,C>::point(const literal::zero_t&)
498  {
499  metal::bool_<(dim == 1)>::check();
500  coord_[0] = 1;
501  }
502 
503  template <typename G, typename C>
504  inline
505  point<G,C>&
506  point<G,C>::operator=(const literal::zero_t&)
507  {
508  metal::bool_<(dim == 1)>::check();
509  coord_[0] = 1;
510  return *this;
511  }
512 
513  template <typename G, typename C>
514  inline
515  point<G,C>::point(const literal::one_t&)
516  {
517  metal::bool_<(dim == 1)>::check();
518  coord_[0] = 1;
519  }
520 
521  template <typename G, typename C>
522  inline
523  point<G,C>&
524  point<G,C>::operator=(const literal::one_t&)
525  {
526  metal::bool_<(dim == 1)>::check();
527  coord_[0] = 1;
528  return *this;
529  }
530 
531  template <typename G, typename C>
532  inline
534  {
535  coord_.set_all(c);
536  }
537 
538  template <typename G, typename C>
539  const point<G,C> point<G,C>::origin = all_to(0);
540 
541  template <typename G, typename C>
542  inline
543  point<G,C>&
545  {
546  for (unsigned i = 0; i < dim; ++i)
547  coord_[i] = static_cast<C>(coord_[i] + dp[i]);
548  return *this;
549  }
550 
551  template <typename G, typename C>
552  inline
553  point<G,C>&
555  {
556  for (unsigned i = 0; i < dim; ++i)
557  coord_[i] -= dp[i];
558  return *this;
559  }
560 
561  template <typename G, typename C>
562  inline
563  point<G,C>::operator typename internal::vec_of_point<G,C>::ret () const // Hack to help g++-2.95.
564  {
565  return to_vec();
566  }
567 
568  template <typename G, typename C>
569  inline
570  typename point<G,C>::vec
572  {
573  //FIXME: to be improved.
574  if (dim > 2)
575  {
576  mln::algebra::vec<G::dim, float> tmp;
577  unsigned j = 0;
578  for (unsigned i = dim - 2; i < dim; ++i)
579  tmp[j++] = mln::internal::convert_data<float>(coord_[i]);
580  for (unsigned i = 2; i < dim; ++i, ++j)
581  tmp[j] = mln::internal::convert_data<float>(coord_[i-j]);
582 
583  return tmp;
584  }
585 
586  return coord_;
587  }
588 
589  template <typename G, typename C>
590  inline
591  typename point<G,C>::h_vec
593  {
595 
596  //FIXME: to be improved.
597  if (dim == 1)
598  tmp[0] = coord_[0];
599  else
600  {
601  unsigned j = 0;
602  for (unsigned i = dim - 2; i < dim; ++i)
603  tmp[j++] = coord_[i];
604 
605  for (unsigned i = 2; i < dim; ++i, ++j)
606  tmp[j] = coord_[i-j];
607 
608  tmp[G::dim] = 1;
609  }
610 
611  return tmp;
612  }
613 
614 
615  template <typename G, typename C>
616  inline
617  const point<G,C>&
619  {
620  static const point<G,C> the_(all_to(mln_max(C)));
621  return the_;
622  }
623 
624  template <typename G, typename C>
625  inline
626  const point<G,C>&
628  {
629  static const point<G,C> the_(all_to(mln_min(C)));
630  return the_;
631  }
632 
633  template <typename G, typename C>
634  inline
635  mln::algebra::vec<G::dim, C>&
637  {
638  return coord_;
639  }
640 
641  namespace internal
642  {
643 
644  template <typename G, typename C, typename E>
645  inline
646  const E&
647  subject_point_impl< point<G,C>, E >::exact_() const
648  {
649  return internal::force_exact<const E>(*this);
650  }
651 
652  template <typename G, typename C, typename E>
653  inline
654  typename point<G,C>::vec
655  subject_point_impl< point<G,C>, E >::to_vec() const
656  {
657  return exact_().get_subject().to_vec();
658  }
659 
660  template <typename G, typename C, typename E>
661  inline
662  subject_point_impl< point<G,C>, E >::operator typename point<G,C>::vec () const // Hack to help g++-2.95.
663  {
664  return exact_().get_subject();
665  }
666 
667  } // end of namespace mln::internal
668 
669  template <typename G, typename C>
670  inline
671  const mln::algebra::vec<point<G,C>::dim - 1, C>&
672  cut_(const point<G,C>& p)
673  {
674  return *(mln::algebra::vec<point<G,C>::dim - 1, C>*)(& p.to_vec());
675  }
676 
677  template <typename C>
678  inline
679  const util::yes&
680  cut_(const point<grid::tick,C>& p)
681  {
682  (void) p;
683  util::yes* the_;
684  return *the_;
685  }
686 
687 # endif // ! MLN_INCLUDE_ONLY
688 
689 
690 } // end of namespace mln
691 
692 
693 #endif // ! MLN_CORE_POINT_HH