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 
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 /*
63 enum coord_overflow_t {
64  UNCHANGED = 0,
65  X_OVERFLOW = 1,
66  X_UNDERFLOW = 2,
67  Y_OVERFLOW = 4,
68  Y_UNDERFLOW = 8,
69  IRREVERSIBLE = 128, /// Equal move in inverse direction would not result original position.
70 };
71 
72 template <>
73 const drain::EnumDict<coord_overflow_t>::dict_t drain::EnumDict<coord_overflow_t>::dict;
74 */
75 typedef unsigned int coord_overflow_t;
76 
77 class CoordinateHandler2D { //: protected CoordinatePolicy {
78 
79 public:
80 
82 
83 
84  static const coord_overflow_t UNCHANGED = 0; // = 0;
85  static const coord_overflow_t X_OVERFLOW = 1; // = 1;
86  static const coord_overflow_t X_UNDERFLOW = 2; // = 2;
87  static const coord_overflow_t Y_OVERFLOW = 4; // = 4;
88  static const coord_overflow_t Y_UNDERFLOW = 8; // 8;
90  static const coord_overflow_t IRREVERSIBLE = 128; // = 128;
91 
92 
93  CoordinatePolicy policy;
95 
96 
98  inline
100  set(area, policy);
101  }
102 
103  // Copy constructor
104  inline
106  // setLimits(handler.xRange.min, handler.yRange.min, handler.xRange.max+1, handler.yRange.max+1); // +1
107  // setLimits(handler.xRange.min, handler.yRange.min, handler.xRange.max+1, handler.yRange.max+1); // +1
108  xRange.set(handler.getXRange());
109  yRange.set(handler.getYRange());
110  area.set(handler.area);
111  setPolicy(handler.getPolicy());
112  }
113 
114  //
115  inline
116  CoordinateHandler2D(const ImageFrame & src){
117  set(src.getGeometry().area, src.getCoordinatePolicy());
118  }
119 
120 
122 
126  inline
127  CoordinateHandler2D(int xUpperLimit, int yUpperLimit, const CoordinatePolicy &policy = CoordinatePolicy()){
128  setLimits(xUpperLimit, yUpperLimit);
129  setPolicy(policy);
130  }
131 
132  inline virtual
133  ~CoordinateHandler2D(){};
134 
135 
136  inline
137  void set(const drain::image::ImageConf & src){
138  setLimits(src.getWidth(), src.getHeight());
139  setPolicy(src.getCoordinatePolicy());
140  }
141 
142  inline
143  void set(const drain::image::AreaGeometry & area = AreaGeometry(), const CoordinatePolicy &p = CoordinatePolicy()){
144  setLimits(area.getWidth(), area.getHeight());
145  setPolicy(p);
146  }
147 
149  inline
150  void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit){
151  xRange.set(xMin, xUpperLimit - 1);
152  yRange.set(yMin, yUpperLimit - 1);
153  area.set(xUpperLimit, yUpperLimit);
154  }
155 
157  void setLimits(int xUpperLimit,int yUpperLimit){
158  setLimits(0, 0, xUpperLimit, yUpperLimit);
159  }
160 
161 
162  inline
163  const Range<int> & getXRange() const {
164  return xRange;
165  }
166 
167  inline
168  const Range<int> & getYRange() const {
169  return yRange;
170  }
171 
172 
174  inline
175  void setPolicy(const CoordinatePolicy &p) {
176  setPolicy(p.xUnderFlowPolicy, p.yUnderFlowPolicy, p.xOverFlowPolicy, p.yOverFlowPolicy);
177  };
178 
180  void setPolicy(EdgePolicy::index_t xUnderFlowPolicy, EdgePolicy::index_t yUnderFlowPolicy, EdgePolicy::index_t xOverFlowPolicy, EdgePolicy::index_t yOverFlowPolicy);
181 
183  inline
184  void setPolicy(EdgePolicy::index_t p){
185  setPolicy(p, p, p, p);
186  }
187 
188 
189  inline
190  const CoordinatePolicy & getPolicy() const {
191  return policy; //*this;
192  }
193 
194 
196 
204  virtual inline
205  coord_overflow_t handle(int &x,int &y) const {
206 
207  result = 0;
208 
209  if (x < xRange.min)
210  result |= (this->*handleXUnderFlow)(x,y);
211 
212  if (x >= area.width)
213  result |= (this->*handleXOverFlow)(x,y);
214 
215  if (y < yRange.min)
216  result |= (this->*handleYUnderFlow)(x,y);
217 
218  if (y >= area.height)
219  result |= (this->*handleYOverFlow)(x,y);
220 
221  return result;
222 
223  }
224 
226  inline
228  return handle(p.x, p.y);
229  }
230 
231  inline // NEW
232  coord_overflow_t handle(Position &p) const {
233  return handle(p.i, p.j);
234  }
235 
237  inline
238  bool validate(Point2D<int> &p) const {
239  return (handle(p.x, p.y) & CoordinateHandler2D::IRREVERSIBLE) == 0;
240  }
241 
243  inline
244  bool validate(int &x, int &y) const {
245  return (handle(x, y) & CoordinateHandler2D::IRREVERSIBLE) == 0;
246  }
247 
248 private:
249 
250  mutable coord_overflow_t result;
251  //mutable int result;
252 
253 protected:
254 
255  //CoordinatePolicy policy;
256  drain::Range<int> xRange;
257  drain::Range<int> yRange;
258 
259  coord_overflow_t (CoordinateHandler2D::*handleXUnderFlow)(int &x, int &y) const;
260  coord_overflow_t (CoordinateHandler2D::*handleXOverFlow)(int &x, int &y) const;
261  coord_overflow_t (CoordinateHandler2D::*handleYUnderFlow)(int &x, int &y) const;
262  coord_overflow_t (CoordinateHandler2D::*handleYOverFlow)(int &x, int &y) const;
263 
264 
266  coord_overflow_t skipUndefined(int &x, int &y) const {
267  return 0;
268  };
269 
270  // LIMIT
272  coord_overflow_t limitXUnderFlow( int &x, int &y) const {
273  x = xRange.min;
274  return X_UNDERFLOW | IRREVERSIBLE;
275  };
276 
278  coord_overflow_t limitYUnderFlow( int &x, int &y) const {
279  y = yRange.min;
280  return Y_UNDERFLOW | IRREVERSIBLE;
281  };
282 
283  coord_overflow_t limitXOverFlow( int &x, int &y) const {
284  x = xRange.max;
285  return X_OVERFLOW | IRREVERSIBLE;
286  };
287 
288  coord_overflow_t limitYOverFlow( int &x, int &y) const {
289  y = yRange.max;
290  return Y_OVERFLOW | IRREVERSIBLE;
291  };
292 
293  // WRAP
295  coord_overflow_t wrapXUnderFlow( int &x, int &y) const {
296  // Assuming minValue = 0
297  x = x % area.width + area.width;
298  return X_UNDERFLOW;
299  };
300 
302  coord_overflow_t wrapYUnderFlow( int &x, int &y) const {
303  // Assuming minValue = 0
304  y = y % area.height + area.height;
305  return Y_UNDERFLOW;
306  };
307 
309  coord_overflow_t wrapXOverFlow( int &x, int &y) const {
310  // Assuming minValue = 0
311  x = x % area.width;
312  return X_OVERFLOW;
313  };
314 
316  coord_overflow_t wrapYOverFlow( int &x, int &y) const {
317  // Assuming minValue = 0
318  y = y % area.height;
319  return Y_OVERFLOW;
320  };
321 
322  // MIRROR
324  coord_overflow_t mirrorXUnderFlow( int &x, int &y) const {
325  x = xRange.min-x;
326  return X_UNDERFLOW;
327  };
328 
330  coord_overflow_t mirrorYUnderFlow( int &x, int &y) const {
331  y = yRange.min-y;
332  return Y_UNDERFLOW;
333  };
334 
336  coord_overflow_t mirrorXOverFlow( int &x, int &y) const {
337  x = 2*xRange.max - x;
338  return X_OVERFLOW;
339  };
340 
342  coord_overflow_t mirrorYOverFlow( int &x, int &y) const {
343  y = 2*yRange.max - y;
344  return Y_OVERFLOW;
345  };
346 
347  // POLAR
349 
353  coord_overflow_t polarXUnderFlow( int &x, int &y) const {
354  x = xRange.min - x - 1;
355  y = (y + area.height/2) % area.height;
356  //std::cout << "handleXUnderFlow_Polar ";
357  return X_UNDERFLOW; // ??
358  };
359 
361 
365  coord_overflow_t polarYUnderFlow( int &x, int &y) const {
366  y = yRange.min - y - 1;
367  x = (x + area.width/2) % area.width;
368  return Y_UNDERFLOW; // ??
369  };
370 
372  coord_overflow_t polarXOverFlow( int &x, int &y) const {
373  x = 2*xRange.max - x + 1;
374  y = (y + area.height/2) % area.height;
375  return X_OVERFLOW; // ??
376  };
377 
379  coord_overflow_t polarYOverFlow( int &x, int &y) const {
380  y = 2*yRange.max - y + 1;
381  x = (x + area.width/2) % area.width;
382  return X_OVERFLOW; // ??
383  };
384 
385  /*
386  Alternative approach would be to coord in dependent have:
387  coord_overflow_t handleAUnderFlow_Limit(const int &a,const int &b,
388  const int &aMin, const int &aMax,
389  const int &bMin, const int &bMax )
390  */
391 
392 
393  // etc.
394 
395 };
396 
397 // using namespace std;
398 
399 // std::ostream & operator<<(std::ostream & ostr, const CoordinatePolicy & policy);
400 
401 
402 std::ostream & operator<<(std::ostream & ostr, const CoordinateHandler2D & handler);
403 
404 } // image
405 
406 } // drain
407 #endif
408 
409 // Drain
Two-way mapping between strings and objects of template class T.
Definition: Dictionary.h:63
Definition: CoordinateHandler.h:77
bool validate(int &x, int &y) const
Handles the coordinate, returning true if the position is reversible.
Definition: CoordinateHandler.h:244
void setPolicy(EdgePolicy::index_t p)
Set the same policy in all the directions.
Definition: CoordinateHandler.h:184
CoordinateHandler2D(int xUpperLimit, int yUpperLimit, const CoordinatePolicy &policy=CoordinatePolicy())
Constructor.
Definition: CoordinateHandler.h:127
static const coord_overflow_t IRREVERSIBLE
Equal move in inverse direction would not result original position.
Definition: CoordinateHandler.h:90
coord_overflow_t polarXUnderFlow(int &x, int &y) const
Definition: CoordinateHandler.h:353
coord_overflow_t polarYUnderFlow(int &x, int &y) const
Definition: CoordinateHandler.h:365
coord_overflow_t handle(Point2D< int > &p) const
Calls handle(int &x,int &y)
Definition: CoordinateHandler.h:227
void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit)
Sets minimum values and outer upper limits for x and y.
Definition: CoordinateHandler.h:150
coord_overflow_t skipUndefined(int &x, int &y) const
Does nothing to the coordinates.
Definition: CoordinateHandler.h:266
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:205
CoordinateHandler2D(const drain::image::AreaGeometry &area=AreaGeometry(), const CoordinatePolicy &policy=CoordinatePolicy())
Default constructor.
Definition: CoordinateHandler.h:99
bool validate(Point2D< int > &p) const
Handles the coordinate, returning true if the position is reversible.
Definition: CoordinateHandler.h:238
void setPolicy(const CoordinatePolicy &p)
Assigns internal function pointers.
Definition: CoordinateHandler.h:175
void setLimits(int xUpperLimit, int yUpperLimit)
Sets outer upper limits for x and y.
Definition: CoordinateHandler.h:157
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
unsigned int coord_overflow_t
typedef drain::GlobalFlags<CoordinatePolicy> coord_overflow_flagger_t;
Definition: CoordinateHandler.h:75
Definition: DataSelector.cpp:1277
Definition: Direction.h:46