Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
core/site_set/box.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_SITE_SET_BOX_HH
28 # define MLN_CORE_SITE_SET_BOX_HH
29 
35 
36 # include <mln/core/concept/box.hh>
37 # include <mln/core/internal/box_impl.hh>
38 # include <mln/core/point.hh>
39 # include <mln/literal/origin.hh>
40 
41 
42 namespace mln
43 {
44 
45  // Fwd decls.
46  template <typename P> class box;
47  template <typename P> class box_fwd_piter_;
48  template <typename P> class box_bkd_piter_;
49 
50 
51  namespace trait
52  {
53 
54  template <typename P>
55  struct site_set_< box<P> >
56  {
57  typedef trait::site_set::nsites::known nsites;
58  typedef trait::site_set::bbox::straight bbox;
59  typedef trait::site_set::contents::fixed contents;
60  typedef trait::site_set::arity::unique arity;
61  };
62 
63  template <typename P>
64  struct set_precise_unary_< op::ord, box<P> >
65  {
66  typedef set_precise_unary_< op::ord, box<P> > ret; // Itself.
67  bool strict(const box<P>& lhs, const box<P>& rhs) const;
68  };
69 
70  } // end of namespace mln::trait
71 
72 
79  //
80  template <typename P>
81  class box : public Box< box<P> >,
82  public internal::box_impl_< P::dim, mln_coord(P), box<P> >,
83  private mlc_is_unqualif(P)::check_t
84  {
85  public:
87  enum { dim = P::dim };
88 
90  typedef P element;
91 
93  typedef P psite;
94 
96  typedef P site;
97 
99  typedef box_fwd_piter_<P> fwd_piter;
100 
102  typedef fwd_piter piter;
103 
105  typedef box_bkd_piter_<P> bkd_piter;
106 
108  P pmin() const;
109 
111  P& pmin();
112 
114  P pmax() const;
115 
117  P& pmax();
118 
120  box();
121 
123  box(const site& pmin, const site& pmax);
124 
127  explicit box(mln_coord(P) ninds);
128  box(mln_coord(P) nrows, mln_coord(P) ncols);
129  box(mln_coord(P) nslis, mln_coord(P) nrows, mln_coord(P) ncols);
131 
136  bool has(const P& p) const;
137 
139  void enlarge(unsigned b);
140 
142  void enlarge(unsigned dim, unsigned b);
143 
145  box<P> to_larger(unsigned b) const;
146 
148  P pcenter() const;
149 
152  bool is_valid() const;
153 
155  void crop_wrt(const box<P>& b);
156 
158  void merge(const box<P>& b);
159 
161  std::size_t memory_size() const;
162 
163  protected:
164 
165  P pmin_, pmax_;
166  };
167 
168 
178  template <typename P>
179  std::ostream& operator<<(std::ostream& ostr, const box<P>& b);
180 
181 
183  template <typename P>
184  inline
185  box<P>
186  larger_than(const box<P> a, const box<P> b);
187 
188 
189 
190 # ifndef MLN_INCLUDE_ONLY
191 
192  template <typename P>
193  inline
194  bool
196  {
197  // Validity is: for all i, pmin_[i] <= pmax_[i].
198  // Nota bene: a one-point box is valid.
199  return util::ord_weak(pmin_, pmax_);
200  }
201 
202  template <typename P>
203  inline
204  void
206  {
207  if (pmin_.col() < ref.pmin().col())
208  pmin_.col() = ref.pmin().col();
209  if (pmin_.row() < ref.pmin().row())
210  pmin_.row() = ref.pmin().row();
211 
212  if (pmax_.col() > ref.pmax().col())
213  pmax_.col() = ref.pmax().col();
214  if (pmax_.row() > ref.pmax().row())
215  pmax_.row() = ref.pmax().row();
216  }
217 
218  template <typename P>
219  inline
220  void
222  {
223  mln_precondition(is_valid());
224  if (! b.is_valid())
225  {
226  // no-op
227  return;
228  }
229 
230  for (unsigned i = 0; i < P::dim; ++i)
231  {
232  if (b.pmin()[i] < pmin_[i])
233  pmin_[i] = b.pmin()[i];
234  if (b.pmax()[i] > pmax_[i])
235  pmax_[i] = b.pmax()[i];
236  }
237  }
238 
239  template <typename P>
240  inline
241  P
242  box<P>::pmin() const
243  {
244  mln_precondition(is_valid());
245  return pmin_;
246  }
247 
248  template <typename P>
249  inline
250  P&
252  {
253  return pmin_;
254  }
255 
256  template <typename P>
257  inline
258  P
259  box<P>::pmax() const
260  {
261  mln_precondition(is_valid());
262  return pmax_;
263  }
264 
265  template <typename P>
266  inline
267  P&
269  {
270  return pmax_;
271  }
272 
273  template <typename P>
274  inline
276  : pmin_(P::plus_infty()),
277  pmax_(P::minus_infty())
278  {
279  // FIXME: The code above can be slow; think about removing it...
280  }
281 
282  template <typename P>
283  inline
284  box<P>::box(const site& pmin, const site& pmax)
285  : pmin_(pmin),
286  pmax_(pmax)
287  {
288  mln_precondition(is_valid());
289  }
290 
291  template <typename P>
292  inline
293  box<P>::box(mln_coord(P) ninds)
294  {
295  metal::bool_<(dim == 1)>::check();
296  pmin_ = literal::origin;
297  pmax_ = P(ninds - 1);
298  }
299 
300  template <typename P>
301  inline
302  box<P>::box(mln_coord(P) nrows, mln_coord(P) ncols)
303  {
304  metal::bool_<(dim == 2)>::check();
305  mln_precondition(nrows != 0 && ncols != 0);
306 
307  pmin_ = literal::origin;
308  pmax_ = P(--nrows, --ncols);
309  mln_postcondition(is_valid());
310  }
311 
312  template <typename P>
313  inline
314  box<P>::box(mln_coord(P) nslis, mln_coord(P) nrows, mln_coord(P) ncols)
315  {
316  metal::bool_<(dim == 3)>::check();
317  pmin_ = literal::origin;
318  pmax_ = P(nslis - 1, nrows - 1, ncols - 1);
319  mln_postcondition(is_valid());
320  }
321 
322  template <typename P>
323  inline
324  bool
325  box<P>::has(const P& p) const
326  {
327  mln_precondition(is_valid());
328  for (unsigned i = 0; i < P::dim; ++i)
329  if (p[i] < pmin_[i] || p[i] > pmax_[i])
330  return false;
331  return true;
332  }
333 
334  template <typename P>
335  inline
336  void
337  box<P>::enlarge(unsigned b)
338  {
339  mln_precondition(is_valid());
340  for (unsigned i = 0; i < P::dim; ++i)
341  {
342  pmin_[i] = static_cast<mln_coord(P)>(pmin_[i] - b);
343  pmax_[i] = static_cast<mln_coord(P)>(pmax_[i] + b);
344  }
345  mln_postcondition(is_valid());
346  }
347 
348  template <typename P>
349  inline
350  void
351  box<P>::enlarge(unsigned dim, unsigned b)
352  {
353  mln_precondition(is_valid());
354  pmin_[dim] = static_cast<mln_coord(P)>(pmin_[dim] - b);
355  pmax_[dim] = static_cast<mln_coord(P)>(pmax_[dim] + b);
356  mln_postcondition(is_valid());
357  }
358 
359  template <typename P>
360  inline
361  box<P>
362  larger_than(const box<P> a, const box<P> b)
363  {
364  P pmin,pmax;
365 
366  for (unsigned i = 0; i < P::dim; i++)
367  {
368  pmin[i] = (a.pmin()[i] < b.pmin()[i]) ? a.pmin()[i] : b.pmin()[i];
369  pmax[i] = (a.pmax()[i] > b.pmax()[i]) ? a.pmax()[i] : b.pmax()[i];
370  }
371 
372  return box<P>(pmin, pmax);
373  }
374 
375  template <typename P>
376  inline
377  box<P>
378  box<P>::to_larger(unsigned b) const
379  {
380  mln_precondition(is_valid());
381  box<P> tmp(*this);
382 
383  for (unsigned i = 0; i < P::dim; ++i)
384  {
385  tmp.pmin_[i] = static_cast<mln_coord(P)>(tmp.pmin_[i] - b);
386  tmp.pmax_[i] = static_cast<mln_coord(P)>(tmp.pmax_[i] + b);
387  }
388  mln_postcondition(tmp.is_valid());
389  return tmp;
390  }
391 
392  template <typename P>
393  inline
394  P
396  {
397  mln_precondition(is_valid());
398  P center;
399  for (unsigned i = 0; i < P::dim; ++i)
400  center[i] = static_cast<mln_coord(P)>(pmin_[i] + ((pmax_[i] - pmin_[i]) / 2));
401  return center;
402  }
403 
404  template <typename P>
405  inline
406  std::size_t
408  {
409  return sizeof(*this);
410  }
411 
412  template <typename P>
413  inline
414  std::ostream& operator<<(std::ostream& ostr, const box<P>& b)
415  {
416  mln_precondition(b.is_valid());
417  return ostr << "[" << b.pmin() << ".." << b.pmax() << ']';
418  }
419 
420  namespace trait
421  {
422 
423  template <typename P>
424  inline
425  bool
426  set_precise_unary_< op::ord, box<P> >::strict(const box<P>& lhs, const box<P>& rhs) const
427  {
428  // Lexicographical over "pmin then pmax".
429  return util::ord_lexi_strict(lhs.pmin(), lhs.pmax(),
430  rhs.pmin(), rhs.pmax());
431  }
432 
433  } // end of namespace mln::trait
434 
435 # endif // ! MLN_INCLUDE_ONLY
436 
437 } // end of namespace mln
438 
439 
440 # include <mln/core/site_set/box_piter.hh>
441 
442 
443 #endif // ! MLN_CORE_SITE_SET_BOX_HH