Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
p_line2d.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_SITE_SET_P_LINE2D_HH
27 # define MLN_CORE_SITE_SET_P_LINE2D_HH
28 
33 
34 # include <mln/core/site_set/p_array.hh>
35 # include <mln/core/alias/box2d.hh>
36 
37 # include <mln/math/sign.hh>
38 # include <mln/math/abs.hh>
39 # include <mln/math/min.hh>
40 # include <mln/math/max.hh>
41 
42 
43 namespace mln
44 {
45 
46  // Forward declaration.
47  class p_line2d;
48 
49 
50 
51  namespace trait
52  {
53 
54  template <>
55  struct site_set_< p_line2d >
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 <>
64  struct set_precise_unary_< op::ord, p_line2d >
65  {
66  typedef set_precise_unary_< op::ord, p_line2d > ret; // Itself.
67  bool strict(const p_line2d& lhs, const p_line2d& rhs) const;
68  };
69 
70  } // end of namespace trait
71 
72 
73 
78  //
79  class p_line2d : public internal::site_set_base_< point2d, p_line2d >
80  {
81  typedef p_line2d self_;
82  public:
83 
85  typedef point2d element;
86 
89 
92 
95 
98 
99 
101  p_line2d();
102 
104  p_line2d(const point2d& beg, const point2d& end,
105  bool is_end_excluded = false);
106 
107 
109  bool has(const psite& p) const;
110 
112  bool has(const util::index& i) const;
113 
115  bool is_valid() const;
116 
117 
119  unsigned nsites() const;
120 
122  const point2d& begin() const;
123 
125  const point2d& end() const;
126 
128  const point2d& operator[](unsigned i) const;
129 
130 
132  typedef const box2d& q_box;
133 
135  const box2d& bbox() const;
136 
137 
139  std::size_t memory_size() const;
140 
142  const std::vector<point2d>& std_vector() const;
143 
144  // Return the corresponding algebra::vec.
145  algebra::vec<2, float> to_vec() const;
146 
147  protected:
148 
149  p_array<point2d> arr_;
150  box2d bb_;
151 
152  void compute_(const point2d& beg, const point2d& end,
153  bool is_end_excluded);
154  };
155 
156 
157 
158 # ifndef MLN_INCLUDE_ONLY
159 
160  inline
162  {
163  mln_postcondition(! is_valid());
164  }
165 
166  inline
167  p_line2d::p_line2d(const point2d& beg, const point2d& end,
168  bool is_end_excluded)
169  {
170  if (is_end_excluded)
171  mln_precondition(end != beg);
172  compute_(beg, end, is_end_excluded);
173  mln_postcondition(is_valid());
174  }
175 
176  inline
177  void
178  p_line2d::compute_(const point2d& beg, const point2d& end,
179  bool is_end_excluded)
180  {
181  if (is_end_excluded)
182  mln_precondition(end != beg);
183 
184  // Compute arr_.
185  dpoint2d dp = end - beg;
186  int
187  srow = math::sign(dp.row()), drow = math::abs(dp.row()), ddrow = 2 * drow,
188  scol = math::sign(dp.col()), dcol = math::abs(dp.col()), ddcol = 2 * dcol,
189  row = beg.row(),
190  col = beg.col();
191  if ( dcol > drow )
192  {
193  int e = ddrow - dcol;
194  for (int i = 0; i < dcol; ++i)
195  {
196  arr_.append(point2d(static_cast<def::coord>(row),
197  static_cast<def::coord>(col)));
198  while (e >= 0)
199  {
200  row += srow;
201  e -= ddcol;
202  }
203  col += scol;
204  e += ddrow;
205  }
206  }
207  else
208  {
209  int e = ddcol - drow;
210  for (int i = 0; i < drow; ++i)
211  {
212  arr_.append(point2d(static_cast<def::coord>(row),
213  static_cast<def::coord>(col)));
214  while (e >= 0)
215  {
216  col += scol;
217  e -= ddrow;
218  }
219  row += srow;
220  e += ddcol;
221  }
222  }
223  if (! is_end_excluded)
224  arr_.append(point2d(static_cast<def::coord>(row),
225  static_cast<def::coord>(col)));
226 
227  // Compute bb_.
228  point2d end_ = arr_[arr_.nsites() - 1];
229  bb_.pmin() = point2d(math::min(beg.row(), end_.row()),
230  math::min(beg.col(), end_.col()));
231  bb_.pmax() = point2d(math::max(beg.row(), end_.row()),
232  math::max(beg.col(), end_.col()));
233 
234  mln_postcondition(this->begin() == beg);
235  mln_postcondition(is_end_excluded == (this->end() != end));
236  }
237 
238  inline
239  bool
240  p_line2d::has(const psite& p) const
241  {
242  mln_precondition(p.target_() == this); // FIXME: Refine.
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
259  {
260  mln_invariant(implies(bb_.is_valid(), ! arr_.is_empty()));
261  return bb_.is_valid();
262  }
263 
264  inline
265  unsigned
267  {
268  return arr_.nsites();
269  }
270 
271  inline
272  const box2d&
274  {
275  mln_precondition(is_valid());
276  return bb_;
277  }
278 
279  inline
280  const std::vector<point2d>&
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&
308  {
309  mln_precondition(is_valid());
310  return arr_[0];
311  }
312 
313  inline
314  const point2d&
316  {
317  mln_precondition(is_valid());
318  return arr_[nsites() - 1];
319  }
320 
321  inline
322  std::size_t
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