$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
accu/line.hh
1 // Copyright (C) 2007, 2008, 2009, 2011, 2012 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_ACCU_LINE_HH
28 # define MLN_ACCU_LINE_HH
29 
35 
36 # include <mln/core/concept/meta_accumulator.hh>
37 # include <mln/core/concept/image.hh>
38 
39 
40 
41 namespace mln
42 {
43 
44  namespace accu
45  {
46 
47  // FIXME:
48 
63  template <typename Meta_Accu, unsigned Dir, // Free parameters.
64  typename I, typename O>
65  void
66  line(const Image<I>& input,
67  const mln_site(I)& p_start, def::coord len,
68  def::coord half_length,
69  Image<O>& output);
70 
71 
72 
73 # ifndef MLN_INCLUDE_ONLY
74 
75  namespace internal
76  {
77 
78  template <typename Meta_Accu, unsigned Dir, // Free parameters.
79  typename I, typename O>
80  void
81  line_tests(const Image<I>& input_,
82  const mln_site(I)&, unsigned,
83  unsigned,
84  Image<O>& output_)
85  {
86  mlc_is_a(Meta_Accu, Meta_Accumulator)::check();
87 
88  typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
89  mlc_converts_to(mln_result(A), mln_value(O))::check();
90 
91  typedef mln_site(I) P;
92  mlc_bool(Dir < P::dim)::check();
93 
94  mlc_is(mln_trait_image_value_io(O),
95  mln::trait::image::value_io::read_write)::check();
96 
97  const I& input = exact(input_);
98  O& output = exact(output_);
99  mln_precondition(input.is_valid());
100  mln_precondition(output.is_valid());
101  }
102 
103  } // end of namespace mln::accu::internal
104 
105 
106  namespace impl
107  {
108 
109  namespace generic
110  {
111 
112  template <typename Meta_Accu, unsigned Dir,
113  typename I, typename O>
114  void
115  line(const Image<I>& input_,
116  const mln_site(I)& p_start, unsigned len_,
117  unsigned half_length_,
118  Image<O>& output_)
119  {
120  typedef mln_site(I) P;
121  typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
122 
123  const I& input = exact(input_);
124  O& output = exact(output_);
125 
126  // Avoid warning in signed/unsigned comparison.
127  const def::coord len = static_cast<def::coord>(len_);
128  const def::coord half_length = static_cast<def::coord>(half_length_);
129 
130  // Checks and tests.
131  internal::line_tests<Meta_Accu, Dir>(input,
132  p_start, len,
133  half_length,
134  output);
135 
136  // Initialization.
137  const def::coord start = p_start[Dir];
138  const def::coord last = static_cast<def::coord>(start + len - 1);
139  A a; // Accumulator.
140  a.init();
141  P p; // Current point.
142 
143  // Start (first line point).
144  p = p_start;
145  P q = p;
146  for (def::coord c = 0; c <= half_length && c < len; ++c)
147  {
148  a.take(input(q));
149  ++q[Dir];
150  }
151  output(p) = a;
152 
153  def::coord& cur = p[Dir];
154  if (cur == last)
155  return;
156 
157  // Begin of line.
158 
159  P p_plus = p_start;
160  def::coord& plus = p_plus[Dir];
161  plus = static_cast<def::coord>(plus + half_length);
162 
163  while (cur < start + half_length && cur < last)
164  {
165  ++cur;
166  ++plus;
167  if (plus <= last)
168  a.take(input(p_plus));
169  output(p) = a;
170  }
171 
172  if (cur == last)
173  return;
174 
175  // Middle of line.
176 
177  P p_minus = p_start;
178  def::coord& minus = p_minus[Dir];
179  --minus;
180 
181  while (cur < last - half_length)
182  {
183  ++cur;
184  ++plus;
185  ++minus;
186  mln_invariant(plus >= start && plus <= last);
187  a.take(input(p_plus));
188  mln_invariant(minus >= start && minus <= last);
189  a.untake(input(p_minus));
190  output(p) = a;
191  }
192 
193  if (cur == last)
194  return;
195 
196  // End of line.
197 
198  while (cur < last)
199  {
200  ++cur;
201  ++minus;
202  mln_invariant(minus >= start && minus <= last);
203  a.untake(input(p_minus));
204  output(p) = a;
205  }
206  }
207 
208  } // end of namespace mln::accu::impl::generic
209 
210 
211 
212  template <typename Meta_Accu, unsigned Dir,
213  typename I, typename O>
214  void
215  line_fastest(const Image<I>& input_,
216  const mln_site(I)& p_start, def::coord len,
217  def::coord half_length,
218  Image<O>& output_)
219  {
220  typedef mln_site(I) P;
221  typedef mln_value(I) V;
222  typedef mln_accu_with(Meta_Accu, V) A;
223 
224  const I& input = exact(input_);
225  O& output = exact(output_);
226 
227  // Checks and tests.
228  internal::line_tests<Meta_Accu, Dir>(input,
229  p_start, len,
230  half_length,
231  output);
232 
233  // Initialization.
234 
235  const def::coord start = p_start[Dir];
236  const def::coord last = start + len - 1;
237 
238  const V* p_in = & input(p_start);
239  V* p_out = & output(p_start);
240 
241  mln_delta(P) dp = literal::zero;
242  dp[Dir] = 1;
243  unsigned offset = input.delta_offset(dp);
244 
245  A a; // Accumulator.
246  a.init();
247 
248  // Start (first line point).
249 
250  const V* q = p_in;
251  for (def::coord c = 0; c <= half_length && c < len; ++c)
252  {
253  a.take(*q);
254  q += offset;
255  }
256  *p_out = a;
257 
258  def::coord cur = p_start[Dir];
259  if (cur == last)
260  return;
261 
262  // Begin of line.
263 
264  def::coord plus = start + half_length;
265  const V* p_plus = p_in + half_length * offset;
266 
267  while (cur < start + half_length && cur < last)
268  {
269  ++cur;
270  p_in += offset;
271  ++plus;
272  p_plus += offset;
273  if (plus <= last)
274  a.take(*p_plus);
275  p_out += offset;
276  *p_out = a;
277  }
278 
279  if (cur == last)
280  return;
281 
282  // Middle of line.
283 
284  def::coord minus = start - 1;
285  const V* p_minus = p_in - offset;
286 
287  while (cur < last - half_length)
288  {
289  ++cur;
290  p_in += offset;
291  ++plus;
292  p_plus += offset;
293  ++minus;
294  p_minus += offset;
295  mln_invariant(plus >= start && plus <= last);
296  a.take(*p_plus);
297  mln_invariant(minus >= start && minus <= last);
298  a.untake(*p_minus);
299  p_out += offset;
300  *p_out = a;
301  }
302 
303  if (cur == last)
304  return;
305 
306  // End of line.
307 
308  while (cur < last)
309  {
310  ++cur;
311  p_in += offset;
312  ++minus;
313  p_minus += offset;
314  mln_invariant(minus >= start && minus <= last);
315  a.untake(*p_minus);
316  p_out += offset;
317  *p_out = a;
318  }
319 
320  }
321 
322 
323 
324 
325  } // end of namespace mln::accu::impl
326 
327 
328  namespace internal
329  {
330 
331  template <typename Meta_Accu, unsigned Dir, // Free parameters.
332  typename I, typename O>
333  void
334  line_dispatch(trait::image::speed::any,
335  const Image<I>& input,
336  const mln_site(I)& p_start, unsigned len,
337  unsigned half_length,
338  Image<O>& output)
339  {
340  impl::generic::line<Meta_Accu, Dir>(input,
341  p_start, len,
342  half_length,
343  output);
344  }
345 
346 // template <typename Meta_Accu, unsigned Dir, // Free parameters.
347 // typename I, typename O>
348 // void
349 // line_dispatch(trait::image::speed::fastest,
350 // const Image<I>& input,
351 // const mln_site(I)& p_start, unsigned len,
352 // unsigned half_length,
353 // Image<O>& output)
354 // {
355 // impl::line_fastest<Meta_Accu, Dir>(input,
356 // p_start, len,
357 // half_length,
358 // output);
359 // }
360 
361  template <typename Meta_Accu, unsigned Dir, // Free parameters.
362  typename I, typename O>
363  void
364  line_dispatch(const Image<I>& input,
365  const mln_site(I)& p_start, unsigned len,
366  unsigned half_length,
367  Image<O>& output)
368  {
369  line_dispatch<Meta_Accu, Dir>(mln_trait_image_speed(I)(),
370  input,
371  p_start, len,
372  half_length,
373  output);
374  }
375 
376  } // end of namespace mln::accu::internal
377 
378 
379  template <typename Meta_Accu, unsigned Dir, // Free parameters.
380  typename I, typename O>
381  void
382  line(const Image<I>& input,
383  const mln_site(I)& p_start, unsigned len,
384  unsigned half_length,
385  Image<O>& output)
386  {
387  internal::line_tests<Meta_Accu, Dir>(input,
388  p_start, len,
389  half_length,
390  output);
391  internal::line_dispatch<Meta_Accu, Dir>(input,
392  p_start, len,
393  half_length,
394  output);
395  }
396 
397 # endif // ! MLN_INCLUDE_ONLY
398 
399  } // end of namespace mln::accu
400 
401 } // end of namespace mln
402 
403 
404 #endif // ! MLN_ACCU_LINE_HH