CoordinateHandler.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 
32 #ifndef COORD_HANDLER_H_
33 #define COORD_HANDLER_H_
34 
35 #include <drain/image/CoordinatePolicy.h>
36 #include <drain/Log.h>
37 #include <ostream>
38 #include <stdexcept>
39 
40 #include "drain/util/Flags.h"
41 #include "drain/util/Frame.h"
42 #include "Geometry.h"
43 
44 #include "ImageFrame.h"
45 #include "Direction.h" //~ "Position.h", experimental
46 
47 namespace drain {
48 
49 
50 namespace image {
51 
52 
53 
54 
55 typedef drain::GlobalFlags<CoordinatePolicy> coord_overflow_flagger_t;
56 typedef drain::Flags::ivalue_t coord_overflow_t;
57 //enum coord_overflow_t {UNCHANGED=0, X_OVERFLOW=1, X_UNDERFLOW=2, Y_OVERFLOW=4, Y_UNDERFLOW=8, IRREVERSIBLE=128};
58 
59 //template <>
60 //const drain::SingleFlagger<coord_overflow_t>::dict_t drain::SingleFlagger<coord_overflow_t>::dict;
61 
62 class CoordinateHandler2D { //: protected CoordinatePolicy {
63 
64 public:
65 
66  static const drain::FlaggerBase<size_t>::dict_t dict;
67 
68  static const coord_overflow_t UNCHANGED = 0; // = 0;
69  static const coord_overflow_t X_OVERFLOW = 1; // = 1;
70  static const coord_overflow_t X_UNDERFLOW = 2; // = 2;
71  static const coord_overflow_t Y_OVERFLOW = 4; // = 4;
72  static const coord_overflow_t Y_UNDERFLOW = 8; // 8;
74  static const coord_overflow_t IRREVERSIBLE = 128; // = 128;
75 
76 
77 
78  CoordinatePolicy policy;
80 
81 
83  inline
85  set(area, policy);
86  }
87 
88  // Copy constructor
89  inline
91  // setLimits(handler.xRange.min, handler.yRange.min, handler.xRange.max+1, handler.yRange.max+1); // +1
92  // setLimits(handler.xRange.min, handler.yRange.min, handler.xRange.max+1, handler.yRange.max+1); // +1
93  xRange.set(handler.getXRange());
94  yRange.set(handler.getYRange());
95  area.set(handler.area);
96  setPolicy(handler.getPolicy());
97  }
98 
99  //
100  inline
101  CoordinateHandler2D(const ImageFrame & src){
102  set(src.getGeometry().area, src.getCoordinatePolicy());
103  }
104 
105 
107 
111  inline
112  CoordinateHandler2D(int xUpperLimit, int yUpperLimit, const CoordinatePolicy &policy = CoordinatePolicy()){
113  setLimits(xUpperLimit, yUpperLimit);
114  setPolicy(policy);
115  }
116 
117  inline virtual
118  ~CoordinateHandler2D(){};
119 
120 
121  inline
122  void set(const drain::image::ImageConf & src){
123  setLimits(src.getWidth(), src.getHeight());
124  setPolicy(src.getCoordinatePolicy());
125  }
126 
127  inline
128  void set(const drain::image::AreaGeometry & area = AreaGeometry(), const CoordinatePolicy &p = CoordinatePolicy()){
129  setLimits(area.getWidth(), area.getHeight());
130  setPolicy(p);
131  }
132 
134  inline
135  void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit){
136  xRange.set(xMin, xUpperLimit - 1);
137  yRange.set(yMin, yUpperLimit - 1);
138  area.set(xUpperLimit, yUpperLimit);
139  }
140 
142  void setLimits(int xUpperLimit,int yUpperLimit){
143  setLimits(0, 0, xUpperLimit, yUpperLimit);
144  }
145 
146 
147  inline
148  const Range<int> & getXRange() const {
149  return xRange;
150  }
151 
152  inline
153  const Range<int> & getYRange() const {
154  return yRange;
155  }
156 
157 
159  inline
160  void setPolicy(const CoordinatePolicy &p) {
161  setPolicy(p.xUnderFlowPolicy, p.yUnderFlowPolicy, p.xOverFlowPolicy, p.yOverFlowPolicy);
162  };
163 
165  void setPolicy(EdgePolicy::index_t xUnderFlowPolicy, EdgePolicy::index_t yUnderFlowPolicy, EdgePolicy::index_t xOverFlowPolicy, EdgePolicy::index_t yOverFlowPolicy);
166 
168  inline
169  void setPolicy(EdgePolicy::index_t p){
170  setPolicy(p, p, p, p);
171  }
172 
173 
174  inline
175  const CoordinatePolicy & getPolicy() const {
176  return policy; //*this;
177  }
178 
179 
181 
189  virtual inline
190  coord_overflow_t handle(int &x,int &y) const {
191 
192  result = 0;
193 
194  if (x < xRange.min)
195  result |= (this->*handleXUnderFlow)(x,y);
196 
197  if (x >= area.width)
198  result |= (this->*handleXOverFlow)(x,y);
199 
200  if (y < yRange.min)
201  result |= (this->*handleYUnderFlow)(x,y);
202 
203  if (y >= area.height)
204  result |= (this->*handleYOverFlow)(x,y);
205 
206  return result;
207 
208  }
209 
211  inline
212  coord_overflow_t handle(Point2D<int> &p) const {
213  return handle(p.x, p.y);
214  }
215 
216  inline // NEW
217  coord_overflow_t handle(Position &p) const {
218  return handle(p.i, p.j);
219  }
220 
222  inline
223  bool validate(Point2D<int> &p) const {
224  return (handle(p.x, p.y) & CoordinateHandler2D::IRREVERSIBLE) == 0;
225  }
226 
228  inline
229  bool validate(int &x, int &y) const {
230  return (handle(x, y) & CoordinateHandler2D::IRREVERSIBLE) == 0;
231  }
232 
233 private:
234 
235  mutable coord_overflow_t result;
236 
237 protected:
238 
239  //CoordinatePolicy policy;
240  drain::Range<int> xRange;
241  drain::Range<int> yRange;
242 
243  coord_overflow_t (CoordinateHandler2D::*handleXUnderFlow)(int &x, int &y) const;
244  coord_overflow_t (CoordinateHandler2D::*handleXOverFlow)(int &x, int &y) const;
245  coord_overflow_t (CoordinateHandler2D::*handleYUnderFlow)(int &x, int &y) const;
246  coord_overflow_t (CoordinateHandler2D::*handleYOverFlow)(int &x, int &y) const;
247 
248 
250  coord_overflow_t skipUndefined(int &x, int &y) const {
251  return 0;
252  };
253 
254  // LIMIT
256  coord_overflow_t limitXUnderFlow( int &x, int &y) const {
257  x = xRange.min;
258  return X_UNDERFLOW | IRREVERSIBLE;
259  };
260 
262  coord_overflow_t limitYUnderFlow( int &x, int &y) const {
263  y = yRange.min;
264  return Y_UNDERFLOW | IRREVERSIBLE;
265  };
266 
267  coord_overflow_t limitXOverFlow( int &x, int &y) const {
268  x = xRange.max;
269  return X_OVERFLOW | IRREVERSIBLE;
270  };
271 
272  coord_overflow_t limitYOverFlow( int &x, int &y) const {
273  y = yRange.max;
274  return Y_OVERFLOW | IRREVERSIBLE;
275  };
276 
277  // WRAP
279  coord_overflow_t wrapXUnderFlow( int &x, int &y) const {
280  // Assuming minValue = 0
281  x = x % area.width + area.width;
282  return X_UNDERFLOW;
283  };
284 
286  coord_overflow_t wrapYUnderFlow( int &x, int &y) const {
287  // Assuming minValue = 0
288  y = y % area.height + area.height;
289  return Y_UNDERFLOW;
290  };
291 
293  coord_overflow_t wrapXOverFlow( int &x, int &y) const {
294  // Assuming minValue = 0
295  x = x % area.width;
296  return X_OVERFLOW;
297  };
298 
300  coord_overflow_t wrapYOverFlow( int &x, int &y) const {
301  // Assuming minValue = 0
302  y = y % area.height;
303  return Y_OVERFLOW;
304  };
305 
306  // MIRROR
308  coord_overflow_t mirrorXUnderFlow( int &x, int &y) const {
309  x = xRange.min-x;
310  return X_UNDERFLOW;
311  };
312 
314  coord_overflow_t mirrorYUnderFlow( int &x, int &y) const {
315  y = yRange.min-y;
316  return Y_UNDERFLOW;
317  };
318 
320  coord_overflow_t mirrorXOverFlow( int &x, int &y) const {
321  x = 2*xRange.max - x;
322  return X_OVERFLOW;
323  };
324 
326  coord_overflow_t mirrorYOverFlow( int &x, int &y) const {
327  y = 2*yRange.max - y;
328  return Y_OVERFLOW;
329  };
330 
331  // POLAR
333 
337  coord_overflow_t polarXUnderFlow( int &x, int &y) const {
338  x = xRange.min - x - 1;
339  y = (y + area.height/2) % area.height;
340  //std::cout << "handleXUnderFlow_Polar ";
341  return X_UNDERFLOW; // ??
342  };
343 
345 
349  coord_overflow_t polarYUnderFlow( int &x, int &y) const {
350  y = yRange.min - y - 1;
351  x = (x + area.width/2) % area.width;
352  return Y_UNDERFLOW; // ??
353  };
354 
356  coord_overflow_t polarXOverFlow( int &x, int &y) const {
357  x = 2*xRange.max - x + 1;
358  y = (y + area.height/2) % area.height;
359  return X_OVERFLOW; // ??
360  };
361 
363  coord_overflow_t polarYOverFlow( int &x, int &y) const {
364  y = 2*yRange.max - y + 1;
365  x = (x + area.width/2) % area.width;
366  return X_OVERFLOW; // ??
367  };
368 
369  /*
370  Alternative approach would be to coord in dependent have:
371  coord_overflow_t handleAUnderFlow_Limit(const int &a,const int &b,
372  const int &aMin, const int &aMax,
373  const int &bMin, const int &bMax )
374  */
375 
376 
377  // etc.
378 
379 };
380 
381 // using namespace std;
382 
383 // std::ostream & operator<<(std::ostream & ostr, const CoordinatePolicy & policy);
384 
385 
386 std::ostream & operator<<(std::ostream & ostr, const CoordinateHandler2D & handler);
387 
388 } // image
389 
390 } // drain
391 #endif
392 
393 // Drain
Flags using a global dictionary.
Definition: GlobalFlags.h:81
Definition: CoordinateHandler.h:62
bool validate(int &x, int &y) const
Handles the coordinate, returning true if the position is reversible.
Definition: CoordinateHandler.h:229
void setPolicy(EdgePolicy::index_t p)
Set the same policy in all the directions.
Definition: CoordinateHandler.h:169
CoordinateHandler2D(int xUpperLimit, int yUpperLimit, const CoordinatePolicy &policy=CoordinatePolicy())
Constructor.
Definition: CoordinateHandler.h:112
static const coord_overflow_t IRREVERSIBLE
Equal move in inverse direction would not result original position.
Definition: CoordinateHandler.h:74
coord_overflow_t polarXUnderFlow(int &x, int &y) const
Definition: CoordinateHandler.h:337
coord_overflow_t polarYUnderFlow(int &x, int &y) const
Definition: CoordinateHandler.h:349
coord_overflow_t handle(Point2D< int > &p) const
Calls handle(int &x,int &y)
Definition: CoordinateHandler.h:212
void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit)
Sets minimum values and outer upper limits for x and y.
Definition: CoordinateHandler.h:135
coord_overflow_t skipUndefined(int &x, int &y) const
Does nothing to the coordinates.
Definition: CoordinateHandler.h:250
virtual coord_overflow_t handle(int &x, int &y) const
Ensures the validity of the coordinates. If inside limits, arguments (x,y) remain intact and 0 is ret...
Definition: CoordinateHandler.h:190
CoordinateHandler2D(const drain::image::AreaGeometry &area=AreaGeometry(), const CoordinatePolicy &policy=CoordinatePolicy())
Default constructor.
Definition: CoordinateHandler.h:84
bool validate(Point2D< int > &p) const
Handles the coordinate, returning true if the position is reversible.
Definition: CoordinateHandler.h:223
void setPolicy(const CoordinatePolicy &p)
Assigns internal function pointers.
Definition: CoordinateHandler.h:160
void setLimits(int xUpperLimit, int yUpperLimit)
Sets outer upper limits for x and y.
Definition: CoordinateHandler.h:142
Policies for coordinate underflows and overflows.
Definition: CoordinatePolicy.h:106
Struct for image (excluding data)
Definition: ImageConf.h:333
Image with static geometry.
Definition: ImageFrame.h:67
const CoordinatePolicy & getCoordinatePolicy() const
Coord policy.
Definition: ImageLike.h:167
Definition: DataSelector.cpp:1277
Definition: Direction.h:46