Loading...
Searching...
No Matches
CoordinateHandler.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood 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
47namespace drain {
48
49
50namespace 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/*
63enum 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
72template <>
73const drain::EnumDict<coord_overflow_t>::dict_t drain::EnumDict<coord_overflow_t>::dict;
74*/
75typedef unsigned int coord_overflow_t;
76
77class CoordinateHandler2D { //: protected CoordinatePolicy {
78
79public:
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
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
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
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
248private:
249
250 mutable coord_overflow_t result;
251 //mutable int result;
252
253protected:
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
402std::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
Something that has width and height.
Definition Frame.h:53
Definition Range.h:52
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 Point.h:48
Definition Direction.h:46