00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef GIL_ITERATOR_FROM_2D_H
00013 #define GIL_ITERATOR_FROM_2D_H
00014
00023
00024 #include <cassert>
00025 #include <boost/iterator/iterator_facade.hpp>
00026 #include "gil_concept.hpp"
00027 #include "gil_config.hpp"
00028 #include "pixel_iterator.hpp"
00029 #include "locator.hpp"
00030
00031 namespace boost { namespace gil {
00032
00038
00039
00043
00044
00050
00051 template <typename Loc2>
00052 class iterator_from_2d : public iterator_facade<iterator_from_2d<Loc2>,
00053 typename Loc2::value_type,
00054 random_access_traversal_tag,
00055 typename Loc2::reference,
00056 typename Loc2::coord_t> {
00057 GIL_CLASS_REQUIRE(Loc2, boost::gil, PixelLocatorConcept)
00058 public:
00059 typedef iterator_facade<iterator_from_2d<Loc2>,
00060 typename Loc2::value_type,
00061 random_access_traversal_tag,
00062 typename Loc2::reference,
00063 typename Loc2::coord_t> parent_t;
00064 typedef typename parent_t::reference reference;
00065 typedef typename parent_t::difference_type difference_type;
00066 typedef typename Loc2::x_iterator x_iterator;
00067 typedef typename Loc2::point_t point_t;
00068
00069 int width() const { return _width; }
00070 int x_pos() const { return _coords.x; }
00071 int y_pos() const { return _coords.y; }
00072
00075 reference operator[](difference_type d) const { return *(*this+d); }
00076
00077 bool is_1d_traversable() const { return _p.is_1d_traversable(width()); }
00078 x_iterator& x() { return _p.x(); }
00079
00080 iterator_from_2d(){}
00081 iterator_from_2d(const Loc2& p, int width, int x=0, int y=0) : _coords(x,y), _width(width), _p(p) {}
00082 iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {}
00083 template <typename Loc> iterator_from_2d(const iterator_from_2d<Loc>& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {}
00084
00085 private:
00086 template <typename Loc> friend class iterator_from_2d;
00087 friend class boost::iterator_core_access;
00088 reference dereference() const { return *_p; }
00089 void increment() {
00090 ++_coords.x;
00091 ++_p.x();
00092 if (_coords.x>=_width) {
00093 _coords.x=0;
00094 ++_coords.y;
00095 _p+=point_t(-_width,1);
00096 }
00097 }
00098 void decrement() {
00099 --_coords.x;
00100 --_p.x();
00101 if (_coords.x<0) {
00102 _coords.x=_width-1;
00103 --_coords.y;
00104 _p+=point_t(_width,-1);
00105 }
00106 }
00107
00108 GIL_FORCEINLINE void advance(difference_type d) {
00109 if (_width==0) return;
00110 point_t delta;
00111 if (_coords.x+d>=0) {
00112 delta.x=(_coords.x+(int)d)%_width - _coords.x;
00113 delta.y=(_coords.x+(int)d)/_width;
00114 } else {
00115 delta.x=(_coords.x+(int)d*(1-_width))%_width -_coords.x;
00116 delta.y=-(_width-_coords.x-(int)d-1)/_width;
00117 }
00118 _p+=delta;
00119 _coords.x+=delta.x;
00120 _coords.y+=delta.y;
00121 }
00122
00123 difference_type distance_to(const iterator_from_2d& it) const {
00124 if (_width==0) return 0;
00125 return (it.y_pos()-_coords.y)*_width + (it.x_pos()-_coords.x);
00126 }
00127
00128 bool equal(const iterator_from_2d& it) const {
00129 assert(_width==it.width());
00130 return _coords==it._coords && _p==it._p;
00131 }
00132
00133 point2<int> _coords;
00134 int _width;
00135 Loc2 _p;
00136 };
00137
00138 template <typename Loc>
00139 struct const_iterator_type<iterator_from_2d<Loc> > {
00140 typedef iterator_from_2d<typename Loc::const_t> type;
00141 };
00142
00143 template <typename Loc>
00144 struct iterator_is_mutable<iterator_from_2d<Loc> > : public iterator_is_mutable<typename Loc::x_iterator> {};
00145
00146
00148
00150
00151 template <typename Loc>
00152 struct dynamic_x_step_type<iterator_from_2d<Loc> > {
00153 typedef iterator_from_2d<typename dynamic_x_step_type<Loc>::type> type;
00154 };
00155
00156
00158
00160
00161 template <typename Loc>
00162 struct color_space_type<iterator_from_2d<Loc> > : public color_space_type<Loc> {};
00163
00164 template <typename Loc>
00165 struct channel_mapping_type<iterator_from_2d<Loc> > : public channel_mapping_type<Loc> {};
00166
00167 template <typename Loc>
00168 struct is_planar<iterator_from_2d<Loc> > : public is_planar<Loc> {};
00169
00170 template <typename Loc>
00171 struct channel_type<iterator_from_2d<Loc> > : public channel_type<Loc> {};
00172
00173 } }
00174
00175 #endif