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