00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef MLN_ACCU_LINE_HH
00027 # define MLN_ACCU_LINE_HH
00028
00034
00035 # include <mln/core/concept/meta_accumulator.hh>
00036 # include <mln/core/concept/image.hh>
00037
00038
00039
00040 namespace mln
00041 {
00042
00043 namespace accu
00044 {
00045
00046
00047
00062 template <typename Meta_Accu, unsigned Dir,
00063 typename I, typename O>
00064 void
00065 line(const Image<I>& input,
00066 const mln_site(I)& p_start, unsigned len,
00067 unsigned half_length,
00068 Image<O>& output);
00069
00070
00071
00072 # ifndef MLN_INCLUDE_ONLY
00073
00074 namespace internal
00075 {
00076
00077 template <typename Meta_Accu, unsigned Dir,
00078 typename I, typename O>
00079 void
00080 line_tests(const Image<I>& input_,
00081 const mln_site(I)&, unsigned,
00082 unsigned,
00083 Image<O>& output_)
00084 {
00085 mlc_is_a(Meta_Accu, Meta_Accumulator)::check();
00086
00087 typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00088 mlc_converts_to(mln_result(A), mln_value(O))::check();
00089
00090 typedef mln_site(I) P;
00091 mlc_bool(Dir < P::dim)::check();
00092
00093 mlc_is(mln_trait_image_value_io(O),
00094 mln::trait::image::value_io::read_write)::check();
00095
00096 const I& input = exact(input_);
00097 O& output = exact(output_);
00098 mln_precondition(input.is_valid());
00099 mln_precondition(output.is_valid());
00100 }
00101
00102 }
00103
00104
00105 namespace impl
00106 {
00107
00108 namespace generic
00109 {
00110
00111 template <typename Meta_Accu, unsigned Dir,
00112 typename I, typename O>
00113 void
00114 line(const Image<I>& input_,
00115 const mln_site(I)& p_start, unsigned len_,
00116 unsigned half_length_,
00117 Image<O>& output_)
00118 {
00119 typedef mln_site(I) P;
00120 typedef mln_accu_with(Meta_Accu, mln_value(I)) A;
00121
00122 const I& input = exact(input_);
00123 O& output = exact(output_);
00124
00125
00126 const def::coord len = static_cast<def::coord>(len_);
00127 const def::coord half_length = static_cast<def::coord>(half_length_);
00128
00129
00130 internal::line_tests<Meta_Accu, Dir>(input,
00131 p_start, len,
00132 half_length,
00133 output);
00134
00135
00136 const def::coord start = p_start[Dir];
00137 const def::coord last = static_cast<def::coord>(start + len - 1);
00138 A a;
00139 a.init();
00140 P p;
00141
00142
00143 p = p_start;
00144 P q = p;
00145 for (def::coord c = 0; c <= half_length && c < len; ++c)
00146 {
00147 a.take(input(q));
00148 ++q[Dir];
00149 }
00150 output(p) = a;
00151
00152 def::coord& cur = p[Dir];
00153 if (cur == last)
00154 return;
00155
00156
00157
00158 P p_plus = p_start;
00159 def::coord& plus = p_plus[Dir];
00160 plus = static_cast<def::coord>(plus + half_length);
00161
00162 while (cur < start + half_length && cur < last)
00163 {
00164 ++cur;
00165 ++plus;
00166 if (plus <= last)
00167 a.take(input(p_plus));
00168 output(p) = a;
00169 }
00170
00171 if (cur == last)
00172 return;
00173
00174
00175
00176 P p_minus = p_start;
00177 def::coord& minus = p_minus[Dir];
00178 --minus;
00179
00180 while (cur < last - half_length)
00181 {
00182 ++cur;
00183 ++plus;
00184 ++minus;
00185 mln_invariant(plus >= start && plus <= last);
00186 a.take(input(p_plus));
00187 mln_invariant(minus >= start && minus <= last);
00188 a.untake(input(p_minus));
00189 output(p) = a;
00190 }
00191
00192 if (cur == last)
00193 return;
00194
00195
00196
00197 while (cur < last)
00198 {
00199 ++cur;
00200 ++minus;
00201 mln_invariant(minus >= start && minus <= last);
00202 a.untake(input(p_minus));
00203 output(p) = a;
00204 }
00205 }
00206
00207 }
00208
00209
00210
00211 template <typename Meta_Accu, unsigned Dir,
00212 typename I, typename O>
00213 void
00214 line_fastest(const Image<I>& input_,
00215 const mln_site(I)& p_start, unsigned len,
00216 unsigned half_length,
00217 Image<O>& output_)
00218 {
00219 typedef mln_site(I) P;
00220 typedef mln_value(I) V;
00221 typedef mln_accu_with(Meta_Accu, V) A;
00222
00223 const I& input = exact(input_);
00224 O& output = exact(output_);
00225
00226
00227 internal::line_tests<Meta_Accu, Dir>(input,
00228 p_start, len,
00229 half_length,
00230 output);
00231
00232
00233
00234 const def::coord start = p_start[Dir];
00235 const def::coord last = start + len - 1;
00236
00237 const V* p_in = & input(p_start);
00238 V* p_out = & output(p_start);
00239
00240 mln_delta(P) dp = literal::zero;
00241 dp[Dir] = 1;
00242 unsigned offset = input.delta_index(dp);
00243
00244 A a;
00245 a.init();
00246
00247
00248
00249 const V* q = p_in;
00250 for (def::coord c = 0; c <= half_length && c < len; ++c)
00251 {
00252 a.take(*q);
00253 q += offset;
00254 }
00255 *p_out = a;
00256
00257 def::coord cur = p_start[Dir];
00258 if (cur == last)
00259 return;
00260
00261
00262
00263 def::coord plus = start + half_length;
00264 const V* p_plus = p_in + half_length * offset;
00265
00266 while (cur < start + half_length && cur < last)
00267 {
00268 ++cur;
00269 p_in += offset;
00270 ++plus;
00271 p_plus += offset;
00272 if (plus <= last)
00273 a.take(*p_plus);
00274 p_out += offset;
00275 *p_out = a;
00276 }
00277
00278 if (cur == last)
00279 return;
00280
00281
00282
00283 def::coord minus = start - 1;
00284 const V* p_minus = p_in - offset;
00285
00286 while (cur < last - half_length)
00287 {
00288 ++cur;
00289 p_in += offset;
00290 ++plus;
00291 p_plus += offset;
00292 ++minus;
00293 p_minus += offset;
00294 mln_invariant(plus >= start && plus <= last);
00295 a.take(*p_plus);
00296 mln_invariant(minus >= start && minus <= last);
00297 a.untake(*p_minus);
00298 p_out += offset;
00299 *p_out = a;
00300 }
00301
00302 if (cur == last)
00303 return;
00304
00305
00306
00307 while (cur < last)
00308 {
00309 ++cur;
00310 p_in += offset;
00311 ++minus;
00312 p_minus += offset;
00313 mln_invariant(minus >= start && minus <= last);
00314 a.untake(*p_minus);
00315 p_out += offset;
00316 *p_out = a;
00317 }
00318
00319 }
00320
00321
00322
00323
00324 }
00325
00326
00327 namespace internal
00328 {
00329
00330 template <typename Meta_Accu, unsigned Dir,
00331 typename I, typename O>
00332 void
00333 line_dispatch(trait::image::speed::any,
00334 const Image<I>& input,
00335 const mln_site(I)& p_start, unsigned len,
00336 unsigned half_length,
00337 Image<O>& output)
00338 {
00339 impl::generic::line<Meta_Accu, Dir>(input,
00340 p_start, len,
00341 half_length,
00342 output);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 template <typename Meta_Accu, unsigned Dir,
00361 typename I, typename O>
00362 void
00363 line_dispatch(const Image<I>& input,
00364 const mln_site(I)& p_start, unsigned len,
00365 unsigned half_length,
00366 Image<O>& output)
00367 {
00368 line_dispatch<Meta_Accu, Dir>(mln_trait_image_speed(I)(),
00369 input,
00370 p_start, len,
00371 half_length,
00372 output);
00373 }
00374
00375 }
00376
00377
00378 template <typename Meta_Accu, unsigned Dir,
00379 typename I, typename O>
00380 void
00381 line(const Image<I>& input,
00382 const mln_site(I)& p_start, unsigned len,
00383 unsigned half_length,
00384 Image<O>& output)
00385 {
00386 internal::line_tests<Meta_Accu, Dir>(input,
00387 p_start, len,
00388 half_length,
00389 output);
00390 internal::line_dispatch<Meta_Accu, Dir>(input,
00391 p_start, len,
00392 half_length,
00393 output);
00394 }
00395
00396 # endif // ! MLN_INCLUDE_ONLY
00397
00398 }
00399
00400 }
00401
00402
00403 #endif // ! MLN_ACCU_LINE_HH