17#ifndef __algo_neighbourhooditerator_h__
18#define __algo_neighbourhooditerator_h__
43 template <
class IteratorType>
48 pos_orig (iter.ndim()),
51 assert (iter.ndim() == extent.size());
52 pos.resize(iter.ndim());
53 for (
size_t i = 0; i < iter.ndim(); ++i){
54 ext[i] = (ext[i]-1) / 2;
55 offset[i] = iter.index(i);
57 pos[i] = (offset[i] - ext[i] < 0) ? 0 : offset[i] - ext[i];
60 auto high = (offset[i] + ext[i] >= iter.size(i)) ? iter.size(i) - 1 : offset[i] + ext[i];
61 dim[i] = high - pos[i] + 1;
65 size_t ndim ()
const {
return dim.size(); }
66 ssize_t size (
size_t axis)
const {
return dim[
axis]; }
68 const ssize_t& index (
size_t axis)
const {
return pos[
axis]; }
69 ssize_t& index (
size_t axis) {
return pos[
axis]; }
71 const Eigen::Matrix< ssize_t, 1, Eigen::Dynamic > get_pos()
const {
return pos; }
73 const ssize_t& extent (
size_t axis)
const {
return dim[
axis]; }
74 const ssize_t& centre (
size_t axis)
const {
return offset[
axis]; }
79 if (not this->has_next_){
80 this->has_next_ =
true;
81 for (
auto axis = dim.size();
axis-- != 0; )
85 for (
auto axis = dim.size();
axis-- != 0; ) {
91 this->has_next_ =
false;
96 stream <<
"neighbourhood iterator, position [ ";
97 for (
size_t n = 0; n < V.ndim(); ++n)
98 stream << V.index(n) <<
" ";
99 stream <<
"], extent [ ";
100 for (
size_t n = 0; n < V.ndim(); ++n)
101 stream << V.extent(n) <<
" ";
102 stream <<
"], centre [ ";
103 for (
size_t n = 0; n < V.ndim(); ++n)
104 stream << V.centre(n) <<
" ";
112 Eigen::Matrix< ssize_t, 1, Eigen::Dynamic > pos;
115 void value ()
const { assert (0); }
a dummy image to iterate over a certain neighbourhood, useful for multi-threaded looping.
friend std::ostream & operator<<(std::ostream &stream, const NeighbourhoodIterator &V)