$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
mln/core/image/complex_image.hh
1 // Copyright (C) 2008, 2009, 2012, 2013 EPITA Research and Development
2 // 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_IMAGE_COMPLEX_IMAGE_HH
28 # define MLN_CORE_IMAGE_COMPLEX_IMAGE_HH
29 
33 
34 # include <vector>
35 
36 # include <mln/trait/images.hh>
37 
38 # include <mln/core/internal/image_primary.hh>
39 # include <mln/metal/vec.hh>
40 # include <mln/core/site_set/p_complex.hh>
41 # include <mln/core/site_set/complex_psite.hh>
42 # include <mln/value/set.hh>
43 
44 // FIXME: Move this elsewhere.
45 // Working around std::vector<bool>'s (forced) specialization.
46 
47 # define mlc_unbool(V) \
48  typename mln::internal::unbool<V>::ret
49 
50 namespace mln
51 {
52 
53  namespace internal
54  {
55 
60  struct bool_proxy
61  {
62  public:
64  bool_proxy(bool b) : b_(b) {}
65  bool& operator=(bool b) { b_ = b; return *this; }
66 
67  operator bool&() { return b_; }
68  operator const bool&() const { return b_; }
69 
70  bool operator==(const bool_proxy& rhs) { return b_ == rhs.b_; }
71  bool operator< (const bool_proxy& rhs) { return b_ < rhs.b_; }
72 
73  private:
75  bool b_;
76  };
77 
78  template <typename V> struct unbool { typedef V ret; };
79  template <> struct unbool<bool> { typedef bool_proxy ret; };
80 
81  } // end of namespace mln::internal
82 
83 }
84 
85 
86 
87 /* FIXME: In the current implementation, the type of values on faces
88  of different dimensions is necessarily the same (V). We should
89  allow different data types for vertices and edges. */
90 
91 
92 namespace mln
93 {
94 
95  // Forward declaration.
96  template <unsigned D, typename G, typename V> class complex_image;
97 
98  namespace internal
99  {
100 
104  template <unsigned D, typename G, typename V>
105  struct data< complex_image<D, G, V> >
106  {
107  data(const p_complex<D, G>& pc,
108  const metal::vec< D + 1, std::vector<V> >& values);
109 
110  metal::vec< D + 1, std::vector< mlc_unbool(V) > > values_;
111  const p_complex<D, G> pc_;
112  };
113 
114  } // end of namespace mln::internal
115 
116 
117  namespace trait
118  {
119 
120  template <unsigned D, typename G, typename V>
121  struct image_< complex_image<D, G, V> >
122  : default_image_< V, complex_image<D, G, V> >
123  {
124  typedef trait::image::category::primary category;
125 
126  // FIXME: Is that right?
127  typedef trait::image::speed::fast speed;
128  typedef trait::image::size::regular size;
129 
130  // Value.
131  typedef trait::image::value_access::direct value_access;
132  // FIXME: This image is value wise read_write, and provides
133  // an access to its values throught a multi-set,
134  // but we need to add the corresponding interface in the class.
135  typedef trait::image::vw_io::none vw_io;
136  typedef trait::image::vw_set::none vw_set;
137  typedef trait::image::value_storage::disrupted value_storage;
138  typedef trait::image::value_browsing::site_wise_only value_browsing;
139  typedef trait::image::value_alignment::irrelevant value_alignment;
140  typedef trait::image::value_io::read_write value_io;
141 
142  // Site / domain.
143  typedef trait::image::pw_io::read_write pw_io;
144  typedef trait::image::localization::space localization;
145  /* FIXME: Depends on G. We could use
146  `trait::image::space_from_point<mln_site(G)>::ret' in most
147  cases (i.e., when G's site is a Point), but would not be
148  generic. */
149  typedef typename trait::image::dimension::none dimension;
150 
151  // Extended domain.
152  typedef trait::image::ext_domain::none ext_domain;
153  typedef trait::image::ext_value::irrelevant ext_value;
154  typedef trait::image::ext_io::irrelevant ext_io;
155  };
156 
157  } // end of namespace mln::trait
158 
159 
169  template <unsigned D, typename G, typename V>
171  : public internal::image_primary< V, p_complex<D, G>,
172  complex_image<D, G, V> >
173  {
174  public:
176  static const unsigned dim = D;
178  typedef G geom;
180  typedef V value;
181 
183  typedef V& lvalue;
184 
186  typedef const V& rvalue;
187 
189  typedef complex_image< D, tag::psite_<G>, tag::value_<V> > skeleton;
190 
191  public:
194  complex_image();
195  complex_image(const p_complex<D, G>& pc);
196  complex_image(const p_complex<D, G>& pc,
197  const metal::vec< D + 1, std::vector<V> >& values);
199 
202  void init_(const p_complex<D, G>& pc,
203  const metal::vec< D + 1, std::vector<V> >& values);
205 
207  rvalue operator()(const complex_psite<D, G>& p) const;
210 
214  const p_complex<D, G>& domain() const;
215 
217  const metal::vec<D + 1, std::vector< mlc_unbool(V) > >& values() const;
219  };
220 
222  // Fwd decl.
223  template <unsigned D, typename G, typename V, typename W>
224  void init_(tag::image_t,
225  complex_image<D, G, V>& target,
226  const complex_image<D, G, W>& model);
228 
229 # ifndef MLN_INCLUDE_ONLY
230 
231  /*-----------------.
232  | Initialization. |
233  `-----------------*/
234 
235  template <unsigned D, typename G, typename V, typename W>
236  inline
237  void init_(tag::image_t,
238  complex_image<D, G, V>& target,
239  const complex_image<D, G, W>& model)
240  {
241  metal::vec<D + 1, std::vector<V> > values;
242  for (unsigned i = 0; i <= D; ++i)
243  values[i].resize(model.domain().nfaces_of_dim(i));
244  target.init_(model.domain(), values);
245  }
246 
247  /*-------.
248  | Data. |
249  `-------*/
250 
251  namespace internal
252  {
253  template <unsigned D, typename G, typename V>
254  inline
255  data< complex_image<D, G, V> >::data(const p_complex<D, G>& pc,
256  const metal::vec< D + 1, std::vector<V> >& values)
257  : pc_(pc)
258  {
259  // We cannot use the initialization list for values_ (it
260  // would not work when V = bool).
261  for (unsigned i = 0; i <= D; ++i)
262  {
263  values_[i].reserve(values[i].size());
264  values_[i].insert(values_[i].begin(),
265  values[i].begin(), values[i].end());
266  }
267 
268  // Ensure the complex is consistent with the values.
269  /* FIXME: We need additional macros in mln/core/contract.hh for
270  big blocks of preconditions like this one. */
271 # ifndef NDEBUG
272  for (unsigned i = 0; i < D; ++i)
273  mln_precondition(pc.nfaces_of_dim(i) == values[i].size());
274 # endif // !NDEBUG
275  }
276 
277  } // end of namespace mln::internal
278 
279  /*---------------.
280  | Construction. |
281  `---------------*/
282 
283  template <unsigned D, typename G, typename V>
284  inline
285  complex_image<D, G, V>::complex_image()
286  {
287  }
288 
289  template <unsigned D, typename G, typename V>
290  inline
291  complex_image<D, G, V>::complex_image(const p_complex<D, G>& pc)
292  {
293  metal::vec<D + 1, std::vector<V> > values;
294  for (unsigned i = 0; i <= D; ++i)
295  values[i].resize(pc.nfaces_of_dim(i));
296  init_(pc, values);
297  }
298 
299  template <unsigned D, typename G, typename V>
300  inline
301  complex_image<D, G, V>::complex_image(const p_complex<D, G>& pc,
302  const metal::vec< D + 1,
303  std::vector<V> >& values)
304  {
305  init_(pc, values);
306  }
307 
308  template <unsigned D, typename G, typename V>
309  inline
310  void
311  complex_image<D, G, V>::init_(const p_complex<D, G>& pc,
312  const metal::vec< D + 1, std::vector<V> >& values)
313  {
314  mln_precondition(! this->is_valid());
315  this->data_ =
316  new internal::data< complex_image<D, G, V> >(pc, values);
317  }
318 
319  /*---------------.
320  | Manipulation. |
321  `---------------*/
322 
323  template <unsigned D, typename G, typename V>
324  inline
325  typename complex_image<D, G, V>::rvalue
326  complex_image<D, G, V>::operator()(const complex_psite<D, G>& p) const
327  {
328  mln_precondition(this->data_->pc_.has(p));
329  return this->data_->values_[p.n()][p.face_id()];
330  }
331 
332  template <unsigned D, typename G, typename V>
333  inline
334  typename complex_image<D, G, V>::lvalue
335  complex_image<D, G, V>::operator()(const complex_psite<D, G>& p)
336  {
337  mln_precondition(this->data_->pc_.has(p));
338  return this->data_->values_[p.n()][p.face_id()];
339  }
340 
341  template <unsigned D, typename G, typename V>
342  inline
343  const metal::vec< D + 1, std::vector< mlc_unbool(V) > >&
344  complex_image<D, G, V>::values() const
345  {
346  return this->data_->values_;
347  }
348 
349  template <unsigned D, typename G, typename V>
350  inline
351  const p_complex<D, G>&
352  complex_image<D, G, V>::domain() const
353  {
354  mln_precondition(this->is_valid());
355  return this->data_->pc_;
356  }
357 
358 # endif // ! MLN_INCLUDE_ONLY
359 
360 } // end of namespace mln
361 
362 # undef mlc_unbool
363 
364 #endif // ! MLN_CORE_IMAGE_COMPLEX_IMAGE_HH