Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
concept/window.hh
1 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_CORE_CONCEPT_WINDOW_HH
27 # define MLN_CORE_CONCEPT_WINDOW_HH
28 
36 
37 # include <mln/core/concept/object.hh>
38 # include <mln/core/concept/iterator.hh>
39 # include <mln/trait/windows.hh>
40 
41 # include <mln/core/site_set/p_array.hh>
42 # include <mln/core/internal/geom_bbox.hh> // For use in convert::from_to.
43 # include <mln/convert/from_to.hxx>
44 # include <mln/util/array.hh>
45 
46 
47 
48 # define mln_is_simple_window(W) \
49  \
50 mln::metal::and_< mlc_is(mln_trait_window_size(W), \
51  mln::trait::window::size::fixed), \
52  mln::metal::and_< mlc_is(mln_trait_window_support(W), \
53  mln::trait::window::support::regular), \
54  mlc_is(mln_trait_window_definition(W), \
55  mln::trait::window::definition::unique) > >
56 
57 
58 # define mln_is_fastest_IW(I, W) \
59  \
60 mlc_and(mlc_is(mln_trait_image_speed(I), \
61  trait::image::speed::fastest), \
62  mln_is_simple_window(W))
63 
64 
65 
66 namespace mln
67 {
68 
69  // Forward declarations.
70  template <typename E> struct Window;
71  template <typename E> struct Image;
72 
73 
74  // Window category flag type.
75  template <>
76  struct Window<void>
77  {
78  typedef Object<void> super;
79  };
80 
81 
86  template <typename E>
87  struct Window : public Object<E>
88  {
89  typedef Window<void> category;
90 
91  /*
92  typedef site;
93  typedef psite;
94  typedef dpsite;
95 
96  typedef qiter;
97  typedef fwd_qiter;
98  typedef bkd_qiter;
99  */
100 
101  protected:
102  Window();
103  };
104 
105 
106  template <typename Wl, typename Wr>
107  bool operator==(const Window<Wl>& lhs, const Window<Wr>& rhs);
108 
109 
110  template <typename W>
111  std::ostream& operator<<(std::ostream& ostr, const Window<W>& win);
112 
113 
114  // FIXME: Move as a method of Image?
115  template <typename I, typename W>
117  offsets_wrt(const Image<I>& ima, const Window<W>& win);
118 
119  template <typename I, typename W>
121  positive_offsets_wrt(const Image<I>& ima, const Window<W>& win);
122 
123  template <typename I, typename W>
125  negative_offsets_wrt(const Image<I>& ima, const Window<W>& win);
126 
127 
128 
129  namespace convert
130  {
131 
132  namespace over_load
133  {
134 
135  template <typename W, typename I>
136  void
137  from_to_(const Window<W>& from, Image<I>& to);
138 
139  } // end of namespace mln::convert::over_load
140 
141  } // end of namespace mln::convert
142 
143 
144 
145 # ifndef MLN_INCLUDE_ONLY
146 
147  namespace internal
148  {
149 
150  // size: fixed or unknown.
151 
152  template <typename trait_size, typename E>
153  struct window_size_check
154  {
155  static void run() { /* No requirement. */ }
156  };
157 
158  template <typename E>
159  struct window_size_check< mln::trait::window::size::fixed, E >
160  {
161  static void run()
162  {
163  unsigned (E::*m)() const = & E::size;
164  m = 0;
165  }
166  };
167 
168  // support: regular or irregular.
169 
170  template <typename trait_support, typename E>
171  struct window_support_check
172  {
173  static void run() { /* No requirement. */ }
174  };
175 
176  template <typename E>
177  struct window_support_check< mln::trait::window::support::regular, E >
178  {
179  static void run_extra()
180  {
181  // Associated type.
182  typedef mln_regular(E) regular;
183 
184  // Methods.
185  bool (E::*m1)() const = &E::is_centered;
186  m1 = 0;
187  bool (E::*m2)() const = &E::is_symmetric;
188  m2 = 0;
189  void (E::*m3)() = &E::sym;
190  m3 = 0;
191  unsigned (E::*m4)() const = &E::delta;
192  m4 = 0;
193  bool (E::*m5)() const = &E::is_valid;
194  m5 = 0;
195  }
196 
197  static void run(mln::trait::window::definition::unique)
198  {
199  typedef mln_dpsite(E) D;
200  const D& (E::*m1)(unsigned) const = &E::dp;
201  m1 = 0;
202  bool (E::*m2)(const D&) const = &E::has;
203  m2 = 0;
204  run_extra();
205  }
206 
207  static void run(mln::trait::window::definition::n_ary)
208  {
209  run_extra();
210  }
211 
212  static void run(mln::trait::window::definition::varying)
213  {
214  /* No requirement. */
215  }
216 
217  static void run()
218  {
219  run(mln_trait_window_definition(E)());
220  }
221  };
222 
223  // definition: unique, n_ary, or varying.
224 
225  template <typename trait_definition, typename E>
226  struct window_definition_check
227  {
228  static void run() { /* No requirement. */ }
229  };
230 
231  template <typename E>
232  struct window_definition_check< mln::trait::window::definition::multiple, E >
233  {
234  static void run()
235  {
236  typedef mln_element(E) W;
237  void (E::*m1)(unsigned, const W&) = &E::set_window;
238  m1 = 0;
239  const W& (E::*m2)(unsigned) const = &E::window;
240  m2 = 0;
241  unsigned (E::*m3)() const = &E::nwindows;
242  m3 = 0;
243  }
244  };
245 
246  } // end of namespace mln::internal
247 
248 
249  template <typename E>
250  inline
251  Window<E>::Window()
252  {
253  // Check properties.
254  mlc_not_equal( mln_trait_window_size(E), mln::trait::undef )::check();
255  mlc_not_equal( mln_trait_window_support(E), mln::trait::undef )::check();
256  mlc_not_equal( mln_trait_window_definition(E), mln::trait::undef )::check();
257 
258  // Check associated types.
259  typedef mln_site(E) site;
260  typedef mln_psite(E) psite;
261  typedef mln_dpsite(E) dpsite;
262  typedef mln_qiter(E) qiter;
263  typedef mln_fwd_qiter(E) fwd_qiter;
264  typedef mln_bkd_qiter(E) bkd_qiter;
265 
266  // Check methods depending upon properties.
267  internal::window_size_check < mln_trait_window_size(E), E >::run();
268  internal::window_support_check < mln_trait_window_support(E), E >::run();
269  internal::window_definition_check< mln_trait_window_definition(E), E >::run();
270  }
271 
272  template <typename Wl, typename Wr>
273  inline
274  bool operator==(const Window<Wl>& lhs, const Window<Wr>& rhs)
275  {
276  return exact(lhs).std_vector() == exact(rhs).std_vector();
277  }
278 
279 
280  // Operator <<.
281 
282  namespace internal
283  {
284 
285  template <typename W>
286  inline
287  void print(trait::window::definition::unique,
288  std::ostream& ostr, const W& win) // FIXME: Add Window<W> to win?
289  {
290  win.print(ostr);
291  }
292 
293  template <typename W>
294  inline
295  void print(trait::window::definition::multiple,
296  std::ostream& ostr, const W& win) // FIXME: Add Window<W> to win?
297  {
298  ostr << "[";
299  const unsigned nw = win.nwindows();
300  for (unsigned w = 0; w < nw; ++w)
301  {
302  ostr << " #" << w << ':';
303  win.window_(w).print(ostr);
304  }
305  ostr << " ]";
306  }
307 
308  } // end of namespace mln::internal
309 
310  template <typename W>
311  inline
312  std::ostream& operator<<(std::ostream& ostr, const Window<W>& win)
313  {
314  mlc_is(mln_trait_window_support(W),
315  trait::window::support::regular)::check();
316  mlc_is_not(mln_trait_window_definition(W),
317  trait::window::definition::varying)::check();
318  // FIXME: test on is_empty?
319  internal::print(mln_trait_window_definition(W)(),
320  ostr, exact(win));
321  return ostr;
322  }
323 
324 
325  template <typename I, typename W>
326  inline
327  util::array<int>
328  offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
329  {
330  mln_is_simple_window(W)::check();
331 
332  const I& ima = exact(ima_);
333  const W& win = exact(win_);
334  mln_precondition(ima.is_valid());
335  mln_precondition(win.is_valid());
336 
337  util::array<int> arr;
338  unsigned n = win.size();
339 
340  for (unsigned i = 0; i < n; ++i)
341  arr.append(ima.delta_index(win.dp(i)));
342 
343  return arr;
344  }
345 
346 
347  template <typename I, typename W>
348  inline
349  util::array<int>
350  positive_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
351  {
352  mln_is_simple_window(W)::check();
353 
354  const I& ima = exact(ima_);
355  const W& win = exact(win_);
356  mln_precondition(ima.is_valid());
357  mln_precondition(win.is_valid());
358 
359  util::array<int> arr;
360  unsigned n = win.size();
361 
362  for (unsigned i = 0; i < n; ++i)
363  {
364  int offset = ima.delta_index(win.dp(i));
365  if (offset > 0)
366  arr.append(offset);
367  }
368 
369  return arr;
370  }
371 
372 
373  template <typename I, typename W>
374  inline
375  util::array<int>
376  negative_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
377  {
378  mln_is_simple_window(W)::check();
379 
380  const I& ima = exact(ima_);
381  const W& win = exact(win_);
382  mln_precondition(ima.is_valid());
383  mln_precondition(win.is_valid());
384 
385  util::array<int> arr;
386  unsigned n = win.size();
387 
388  for (unsigned i = 0; i < n; ++i)
389  {
390  int offset = ima.delta_index(win.dp(i));
391  if (offset < 0)
392  arr.append(offset);
393  }
394 
395  return arr;
396  }
397 
398 
399  namespace convert
400  {
401 
402  namespace over_load
403  {
404 
405  template <typename W, typename I>
406  void
407  from_to_(const Window<W>& win_, Image<I>& ima_)
408  {
409  mln_is_simple_window(W)::check();
410  typedef mln_psite(I) P;
411  mlc_converts_to(mln_dpsite(W), mln_delta(P))::check();
412  mlc_equal(mln_value(I), bool)::check();
413 
414  const W& win = exact(win_);
415  I& ima = exact(ima_);
416 
417  mln_precondition(win.is_valid());
418  mln_precondition(! ima.is_valid());
419 
420  // Hack (below) to avoid circular dependency.
421  ima.init_(mln::internal::geom_bbox(win));
422  {
423  // data::fill(ima, false) is:
424  mln_piter(I) p(ima.domain());
425  for_all(p)
426  ima(p) = false;
427  }
428  unsigned n = win.size();
429  for (unsigned i = 0; i < n; ++i)
430  ima(convert::to<P>(win.dp(i))) = true;
431  }
432 
433  } // end of namespace mln::convert::over_load
434 
435  } // end of namespace mln::convert
436 
437 # endif // ! MLN_INCLUDE_ONLY
438 
439 } // end of namespace mln
440 
441 
442 #endif // ! MLN_CORE_CONCEPT_WINDOW_HH