$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
p_line2d.hh
1 // Copyright (C) 2007, 2008, 2009, 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_SITE_SET_P_LINE2D_HH
28 # define MLN_CORE_SITE_SET_P_LINE2D_HH
29 
34 
35 # include <mln/core/site_set/p_array.hh>
36 # include <mln/core/alias/box2d.hh>
37 
38 # include <mln/math/sign.hh>
39 # include <mln/math/abs.hh>
40 # include <mln/math/min.hh>
41 # include <mln/math/max.hh>
42 
43 
44 namespace mln
45 {
46 
47  // Forward declaration.
48  class p_line2d;
49 
50 
51 
52  namespace trait
53  {
54 
55  template <>
56  struct site_set_< p_line2d >
57  {
58  typedef trait::site_set::nsites::known nsites;
59  typedef trait::site_set::bbox::straight bbox;
60  typedef trait::site_set::contents::fixed contents;
61  typedef trait::site_set::arity::unique arity;
62  };
63 
64  template <>
65  struct set_precise_unary_< op::ord, p_line2d >
66  {
67  typedef set_precise_unary_< op::ord, p_line2d > ret; // Itself.
68  bool strict(const p_line2d& lhs, const p_line2d& rhs) const;
69  };
70 
71  } // end of namespace trait
72 
73 
74 
79  //
80  class p_line2d : public internal::site_set_base_< point2d, p_line2d >
81  {
82  typedef p_line2d self_;
83  public:
84 
86  typedef point2d element;
87 
90 
93 
96 
99 
100 
102  p_line2d();
103 
105  p_line2d(const point2d& beg, const point2d& end,
106  bool is_end_excluded = false);
107 
108 
110  bool has(const psite& p) const;
111 
113  bool has(const util::index& i) const;
114 
116  bool is_valid() const;
117 
118 
120  unsigned nsites() const;
121 
123  const point2d& begin() const;
124 
126  const point2d& end() const;
127 
129  const point2d& operator[](unsigned i) const;
130 
131 
133  typedef const box2d& q_box;
134 
136  const box2d& bbox() const;
137 
138 
140  std::size_t memory_size() const;
141 
143  const std::vector<point2d>& std_vector() const;
144 
145  // Return the corresponding algebra::vec.
147 
148  protected:
149 
152 
153  void compute_(const point2d& beg, const point2d& end,
154  bool is_end_excluded);
155  };
156 
157 
158 
159 # ifndef MLN_INCLUDE_ONLY
160 
161  inline
163  {
164  mln_postcondition(! is_valid());
165  }
166 
167  inline
168  p_line2d::p_line2d(const point2d& beg, const point2d& end,
169  bool is_end_excluded)
170  {
171  if (is_end_excluded)
172  mln_precondition(end != beg);
173  compute_(beg, end, is_end_excluded);
174  mln_postcondition(is_valid());
175  }
176 
177  inline
178  void
179  p_line2d::compute_(const point2d& beg, const point2d& end,
180  bool is_end_excluded)
181  {
182  if (is_end_excluded)
183  mln_precondition(end != beg);
184 
185  // Compute arr_.
186  dpoint2d dp = end - beg;
187  int
188  srow = math::sign(dp.row()), drow = math::abs(dp.row()), ddrow = 2 * drow,
189  scol = math::sign(dp.col()), dcol = math::abs(dp.col()), ddcol = 2 * dcol,
190  row = beg.row(),
191  col = beg.col();
192  if ( dcol > drow )
193  {
194  int e = ddrow - dcol;
195  for (int i = 0; i < dcol; ++i)
196  {
197  arr_.append(point2d(static_cast<def::coord>(row),
198  static_cast<def::coord>(col)));
199  while (e >= 0)
200  {
201  row += srow;
202  e -= ddcol;
203  }
204  col += scol;
205  e += ddrow;
206  }
207  }
208  else
209  {
210  int e = ddcol - drow;
211  for (int i = 0; i < drow; ++i)
212  {
213  arr_.append(point2d(static_cast<def::coord>(row),
214  static_cast<def::coord>(col)));
215  while (e >= 0)
216  {
217  col += scol;
218  e -= ddrow;
219  }
220  row += srow;
221  e += ddcol;
222  }
223  }
224  if (! is_end_excluded)
225  arr_.append(point2d(static_cast<def::coord>(row),
226  static_cast<def::coord>(col)));
227 
228  // Compute bb_.
229  point2d end_ = arr_[arr_.nsites() - 1];
230  bb_.pmin() = point2d(math::min(beg.row(), end_.row()),
231  math::min(beg.col(), end_.col()));
232  bb_.pmax() = point2d(math::max(beg.row(), end_.row()),
233  math::max(beg.col(), end_.col()));
234 
235  mln_postcondition(this->begin() == beg);
236  mln_postcondition(is_end_excluded == (this->end() != end));
237  }
238 
239  inline
240  bool
241  p_line2d::has(const psite& p) const
242  {
243  if (! has(p.index()))
244  return false;
245  mln_invariant(p.to_site() == (*this)[p.index()]);
246  return true;
247  }
248 
249  inline
250  bool
251  p_line2d::has(const util::index& i) const
252  {
253  return i >= 0 && unsigned(i) < nsites();
254  }
255 
256  inline
257  bool
258  p_line2d::is_valid() const
259  {
260  mln_invariant(implies(bb_.is_valid(), ! arr_.is_empty()));
261  return bb_.is_valid();
262  }
263 
264  inline
265  unsigned
266  p_line2d::nsites() const
267  {
268  return arr_.nsites();
269  }
270 
271  inline
272  const box2d&
273  p_line2d::bbox() const
274  {
275  mln_precondition(is_valid());
276  return bb_;
277  }
278 
279  inline
280  const std::vector<point2d>&
281  p_line2d::std_vector() const
282  {
283  return arr_.std_vector();
284  }
285 
286  // FIXME: make it more generic?
287  inline
288  algebra::vec<2, float>
289  p_line2d::to_vec() const
290  {
291  algebra::vec<2, float> res;
292  res[0] = float(end().row() - begin().row());
293  res[1] = float(end().col() - begin().col());
294  return res;
295  }
296 
297  inline
298  const point2d&
299  p_line2d::operator[](unsigned i) const
300  {
301  mln_precondition(i < nsites());
302  return arr_[i];
303  }
304 
305  inline
306  const point2d&
307  p_line2d::begin() const
308  {
309  mln_precondition(is_valid());
310  return arr_[0];
311  }
312 
313  inline
314  const point2d&
315  p_line2d::end() const
316  {
317  mln_precondition(is_valid());
318  return arr_[nsites() - 1];
319  }
320 
321  inline
322  std::size_t
323  p_line2d::memory_size() const
324  {
325  return arr_.memory_size() + sizeof(box2d);
326  }
327 
328 
329  namespace trait
330  {
331 
332  inline
333  bool
334  set_precise_unary_< op::ord, p_line2d >::strict(const p_line2d& lhs,
335  const p_line2d& rhs) const
336  {
337  return util::ord_lexi_strict(lhs.begin(), lhs.end(),
338  rhs.begin(), rhs.end());
339  }
340 
341  } // end of namespace mln::trait
342 
343 # endif // ! MLN_INCLUDE_ONLY
344 
345 } // end of namespace mln
346 
347 
348 #endif // ! MLN_CORE_SITE_SET_P_LINE2D_HH