Subversion Repositories public iLand

Rev

Rev 1221 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1221 Rev 1222
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/grid.h':
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/grid.h':
2
/********************************************************************************************
2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
6
**
7
**    This program is free software: you can redistribute it and/or modify
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
10
**    (at your option) any later version.
11
**
11
**
12
**    This program is distributed in the hope that it will be useful,
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
15
**    GNU General Public License for more details.
16
**
16
**
17
**    You should have received a copy of the GNU General Public License
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
19
********************************************************************************************/
20
20
21
#ifndef GRID_H
21
#ifndef GRID_H
22
#define GRID_H
22
#define GRID_H
23
23
24
#include <QtCore>
24
#include <QtCore>
25
25
26
26
27
#include <stdexcept>
27
#include <stdexcept>
28
#include <limits>
28
#include <limits>
29
#include <cstring>
29
#include <cstring>
30
30
31
#include "global.h"
31
#include "global.h"
32
32
33
/** Grid class (template).
33
/** Grid class (template).
34
@ingroup tools
34
@ingroup tools
35
Orientation
35
Orientation
36
The grid is oriented as typically coordinates on the northern hemisphere: higher y-values -> north, higher x-values-> east.
36
The grid is oriented as typically coordinates on the northern hemisphere: higher y-values -> north, higher x-values-> east.
37
The projection is reversed for drawing on screen (Viewport).
37
The projection is reversed for drawing on screen (Viewport).
38
          N
38
          N
39
  (0/2) (1/2) (2/2)
39
  (0/2) (1/2) (2/2)
40
W (0/1) (1/1) (2/1)  E
40
W (0/1) (1/1) (2/1)  E
41
  (0/0) (1/0) (2/0)
41
  (0/0) (1/0) (2/0)
42
          S
42
          S
43
*/
43
*/
44
template <class T>
44
template <class T>
45
class Grid {
45
class Grid {
46
public:
46
public:
47
47
48
    Grid();
48
    Grid();
49
    Grid(float cellsize, int sizex, int sizey) { mData=0; setup(cellsize, sizex, sizey); }
49
    Grid(float cellsize, int sizex, int sizey) { mData=0; setup(cellsize, sizex, sizey); }
50
    /// create from a metric rect
50
    /// create from a metric rect
51
    Grid(const QRectF rect_metric, const float cellsize) { mData=0; setup(rect_metric,cellsize); }
51
    Grid(const QRectF rect_metric, const float cellsize) { mData=0; setup(rect_metric,cellsize); }
52
    // copy ctor
52
    // copy ctor
53
    Grid(const Grid<T>& toCopy);
53
    Grid(const Grid<T>& toCopy);
54
    ~Grid() { clear(); }
54
    ~Grid() { clear(); }
55
    void clear() { if (mData) delete[] mData; mData=0; }
55
    void clear() { if (mData) delete[] mData; mData=0; }
56
56
57
    bool setup(const float cellsize, const int sizex, const int sizey);
57
    bool setup(const float cellsize, const int sizex, const int sizey);
58
    bool setup(const QRectF& rect, const double cellsize);
58
    bool setup(const QRectF& rect, const double cellsize);
59
    bool setup(const Grid<T>& source) { clear();  mRect = source.mRect; return setup(source.mRect, source.mCellsize); }
59
    bool setup(const Grid<T>& source) { clear();  mRect = source.mRect; return setup(source.mRect, source.mCellsize); }
60
    void initialize(const T& value) {for( T *p = begin();p!=end(); ++p) *p=value; }
60
    void initialize(const T& value) {for( T *p = begin();p!=end(); ++p) *p=value; }
61
    void wipe(); ///< write 0-bytes with memcpy to the whole area
61
    void wipe(); ///< write 0-bytes with memcpy to the whole area
62
    void wipe(const T value); ///< overwrite the whole area with "value" size of T must be the size of "int" ERRORNOUS!!!
62
    void wipe(const T value); ///< overwrite the whole area with "value" size of T must be the size of "int" ERRORNOUS!!!
63
    /// copies the content of the source grid to this grid.
63
    /// copies the content of the source grid to this grid.
64
    /// no operation, if the grids are not of the same size.
64
    /// no operation, if the grids are not of the same size.
65
    void copy(const Grid<T> source) { if (source.count()==count()) memcpy(mData, source.mData, count()*sizeof(T)); }
65
    void copy(const Grid<T> source) { if (source.count()==count()) memcpy(mData, source.mData, count()*sizeof(T)); }
66
    /// create a double grid (same size as this grid) and convert this grid to double values.
66
    /// create a double grid (same size as this grid) and convert this grid to double values.
67
    /// NOTE: caller is responsible for freeing memory!
67
    /// NOTE: caller is responsible for freeing memory!
68
    Grid<double> *toDouble() const;
68
    Grid<double> *toDouble() const;
69
69
70
    // get the number of cells in x and y direction
70
    // get the number of cells in x and y direction
71
    int sizeX() const { return mSizeX; }
71
    int sizeX() const { return mSizeX; }
72
    int sizeY() const { return mSizeY; }
72
    int sizeY() const { return mSizeY; }
73
    // get the size of the grid in metric coordinates (x and y direction)
73
    // get the size of the grid in metric coordinates (x and y direction)
74
    float metricSizeX() const { return mSizeX*mCellsize; }
74
    float metricSizeX() const { return mSizeX*mCellsize; }
75
    float metricSizeY() const { return mSizeY*mCellsize; }
75
    float metricSizeY() const { return mSizeY*mCellsize; }
76
    /// get the metric rectangle of the grid
76
    /// get the metric rectangle of the grid
77
    QRectF metricRect() const { return mRect; }
77
    QRectF metricRect() const { return mRect; }
78
    /// get the rectangle of the grid in terms of indices
78
    /// get the rectangle of the grid in terms of indices
79
    QRect rectangle() const { return QRect(QPoint(0,0), QPoint(sizeX(), sizeY())); }
79
    QRect rectangle() const { return QRect(QPoint(0,0), QPoint(sizeX(), sizeY())); }
80
    /// get the length of one pixel of the grid
80
    /// get the length of one pixel of the grid
81
    float cellsize() const { return mCellsize; }
81
    float cellsize() const { return mCellsize; }
82
    int count() const { return mCount; } ///< returns the number of elements of the grid
82
    int count() const { return mCount; } ///< returns the number of elements of the grid
83
    bool isEmpty() const { return mData==NULL; } ///< returns false if the grid was not setup
83
    bool isEmpty() const { return mData==NULL; } ///< returns false if the grid was not setup
84
    // operations
84
    // operations
85
    // query
85
    // query
86
    /// access (const) with index variables. use int.
86
    /// access (const) with index variables. use int.
87
    inline const T& operator()(const int ix, const int iy) const { return constValueAtIndex(ix, iy); }
87
    inline const T& operator()(const int ix, const int iy) const { return constValueAtIndex(ix, iy); }
88
    /// access (const) using metric variables. use float.
88
    /// access (const) using metric variables. use float.
89
    inline const T& operator()(const float x, const float y) const { return constValueAt(x, y); }
89
    inline const T& operator()(const float x, const float y) const { return constValueAt(x, y); }
90
    /// access value of grid with a QPoint
90
    /// access value of grid with a QPoint
91
    inline const T& operator[](const QPoint &p) const { return constValueAtIndex(p); }
91
    inline const T& operator[](const QPoint &p) const { return constValueAtIndex(p); }
92
    /// use the square brackets to access by index
92
    /// use the square brackets to access by index
93
    inline T& operator[](const int idx) const { return mData[idx]; }
93
    inline T& operator[](const int idx) const { return mData[idx]; }
94
    /// use the square bracket to access by QPointF
94
    /// use the square bracket to access by QPointF
95
    inline T& operator[] (const QPointF &p) { return valueAt(p); }
95
    inline T& operator[] (const QPointF &p) { return valueAt(p); }
96
96
97
    inline T& valueAtIndex(const QPoint& pos) {return valueAtIndex(pos.x(), pos.y());}  ///< value at position defined by a QPoint defining the two indices (x,y)
97
    inline T& valueAtIndex(const QPoint& pos) {return valueAtIndex(pos.x(), pos.y());}  ///< value at position defined by a QPoint defining the two indices (x,y)
98
    T& valueAtIndex(const int ix, const int iy) { return mData[iy*mSizeX + ix];  } ///< const value at position defined by indices (x,y)
98
    T& valueAtIndex(const int ix, const int iy) { return mData[iy*mSizeX + ix];  } ///< const value at position defined by indices (x,y)
99
    T& valueAtIndex(const int index) {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
99
    T& valueAtIndex(const int index) {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
100
    inline int index(const int ix, const int iy) { return iy*mSizeX + ix; } ///< get the 0-based index of the cell with indices ix and iy.
100
    inline int index(const int ix, const int iy) { return iy*mSizeX + ix; } ///< get the 0-based index of the cell with indices ix and iy.
101
    inline int index(const QPoint &pos) { return pos.y()*mSizeX + pos.x(); } ///< get the 0-based index of the cell at 'pos'.
101
    inline int index(const QPoint &pos) { return pos.y()*mSizeX + pos.x(); } ///< get the 0-based index of the cell at 'pos'.
102
    /// value at position defined by a (integer) QPoint
102
    /// value at position defined by a (integer) QPoint
103
    inline const T& constValueAtIndex(const QPoint& pos) const {return constValueAtIndex(pos.x(), pos.y()); }
103
    inline const T& constValueAtIndex(const QPoint& pos) const {return constValueAtIndex(pos.x(), pos.y()); }
104
    /// value at position defined by a pair of integer coordinates
104
    /// value at position defined by a pair of integer coordinates
105
    inline const T& constValueAtIndex(const int ix, const int iy) const { return mData[iy*mSizeX + ix];  }
105
    inline const T& constValueAtIndex(const int ix, const int iy) const { return mData[iy*mSizeX + ix];  }
106
    /// value at position defined by the index within the grid
106
    /// value at position defined by the index within the grid
107
    const T& constValueAtIndex(const int index) const {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
107
    const T& constValueAtIndex(const int index) const {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
108
108
109
    T& valueAt(const QPointF& posf); ///< value at position defined by metric coordinates (QPointF)
109
    T& valueAt(const QPointF& posf); ///< value at position defined by metric coordinates (QPointF)
110
    const T& constValueAt(const QPointF& posf) const; ///< value at position defined by metric coordinates (QPointF)
110
    const T& constValueAt(const QPointF& posf) const; ///< value at position defined by metric coordinates (QPointF)
111
111
112
    T& valueAt(const float x, const float y); ///< value at position defined by metric coordinates (x,y)
112
    T& valueAt(const float x, const float y); ///< value at position defined by metric coordinates (x,y)
113
    const T& constValueAt(const float x, const float y) const; ///< value at position defined by metric coordinates (x,y)
113
    const T& constValueAt(const float x, const float y) const; ///< value at position defined by metric coordinates (x,y)
114
114
115
115
116
    bool coordValid(const float x, const float y) const { return x>=mRect.left() && x<mRect.right()  && y>=mRect.top() && y<mRect.bottom(); }
116
    bool coordValid(const float x, const float y) const { return x>=mRect.left() && x<mRect.right()  && y>=mRect.top() && y<mRect.bottom(); }
117
    bool coordValid(const QPointF &pos) const { return coordValid(pos.x(), pos.y()); }
117
    bool coordValid(const QPointF &pos) const { return coordValid(pos.x(), pos.y()); }
118
118
119
    QPoint indexAt(const QPointF& pos) const { return QPoint(int((pos.x()-mRect.left()) / mCellsize),  int((pos.y()-mRect.top())/mCellsize)); } ///< get index of value at position pos (metric)
119
    QPoint indexAt(const QPointF& pos) const { return QPoint(int((pos.x()-mRect.left()) / mCellsize),  int((pos.y()-mRect.top())/mCellsize)); } ///< get index of value at position pos (metric)
120
    /// get index (x/y) of the (linear) index 'index' (0..count-1)
120
    /// get index (x/y) of the (linear) index 'index' (0..count-1)
121
    QPoint indexOf(const int index) const {return QPoint(index % mSizeX,  index / mSizeX); }
121
    QPoint indexOf(const int index) const {return QPoint(index % mSizeX,  index / mSizeX); }
122
    bool isIndexValid(const QPoint& pos) const { return (pos.x()>=0 && pos.x()<mSizeX && pos.y()>=0 && pos.y()<mSizeY); } ///< return true, if position is within the grid
122
    bool isIndexValid(const QPoint& pos) const { return (pos.x()>=0 && pos.x()<mSizeX && pos.y()>=0 && pos.y()<mSizeY); } ///< return true, if position is within the grid
123
    bool isIndexValid(const int x, const int y) const {return (x>=0 && x<mSizeX && y>=0 && y<mSizeY); } ///< return true, if index is within the grid
123
    bool isIndexValid(const int x, const int y) const {return (x>=0 && x<mSizeX && y>=0 && y<mSizeY); } ///< return true, if index is within the grid
124
124
125
    /// returns the index of an aligned grid (with the same size and matching origin) with the double cell size (e.g. to scale from a 10m grid to a 20m grid)
125
    /// returns the index of an aligned grid (with the same size and matching origin) with the double cell size (e.g. to scale from a 10m grid to a 20m grid)
126
    int index2(int idx) const {return ((idx/mSizeX)/2)*(mSizeX/2) + (idx%mSizeX)/2; }
126
    int index2(int idx) const {return ((idx/mSizeX)/2)*(mSizeX/2) + (idx%mSizeX)/2; }
127
    /// returns the index of an aligned grid (the same size) with the 5 times bigger cells (e.g. to scale from a 2m grid to a 10m grid)
127
    /// returns the index of an aligned grid (the same size) with the 5 times bigger cells (e.g. to scale from a 2m grid to a 10m grid)
128
    int index5(int idx) const {return ((idx/mSizeX)/5)*(mSizeX/5) + (idx%mSizeX)/5; }
128
    int index5(int idx) const {return ((idx/mSizeX)/5)*(mSizeX/5) + (idx%mSizeX)/5; }
129
    /// returns the index of an aligned grid (the same size) with the 10 times bigger cells (e.g. to scale from a 2m grid to a 20m grid)
129
    /// returns the index of an aligned grid (the same size) with the 10 times bigger cells (e.g. to scale from a 2m grid to a 20m grid)
130
    int index10(int idx) const {return ((idx/mSizeX)/10)*(mSizeX/10) + (idx%mSizeX)/10; }
130
    int index10(int idx) const {return ((idx/mSizeX)/10)*(mSizeX/10) + (idx%mSizeX)/10; }
131
131
132
    /// force @param pos to contain valid indices with respect to this grid.
132
    /// force @param pos to contain valid indices with respect to this grid.
133
    void validate(QPoint &pos) const{ pos.setX( qMax(qMin(pos.x(), mSizeX-1), 0) );  pos.setY( qMax(qMin(pos.y(), mSizeY-1), 0) );} ///< ensure that "pos" is a valid key. if out of range, pos is set to minimum/maximum values.
133
    void validate(QPoint &pos) const{ pos.setX( qMax(qMin(pos.x(), mSizeX-1), 0) );  pos.setY( qMax(qMin(pos.y(), mSizeY-1), 0) );} ///< ensure that "pos" is a valid key. if out of range, pos is set to minimum/maximum values.
134
    /// get the (metric) centerpoint of cell with index @p pos
134
    /// get the (metric) centerpoint of cell with index @p pos
135
    QPointF cellCenterPoint(const QPoint &pos) const { return QPointF( (pos.x()+0.5)*mCellsize+mRect.left(), (pos.y()+0.5)*mCellsize + mRect.top());} ///< get metric coordinates of the cells center
135
    QPointF cellCenterPoint(const QPoint &pos) const { return QPointF( (pos.x()+0.5)*mCellsize+mRect.left(), (pos.y()+0.5)*mCellsize + mRect.top());} ///< get metric coordinates of the cells center
136
    /// get the metric cell center point of the cell given by index 'index'
136
    /// get the metric cell center point of the cell given by index 'index'
137
    QPointF cellCenterPoint(const int &index) const { QPoint pos=indexOf(index); return QPointF( (pos.x()+0.5)*mCellsize+mRect.left(), (pos.y()+0.5)*mCellsize + mRect.top());}
137
    QPointF cellCenterPoint(const int &index) const { QPoint pos=indexOf(index); return QPointF( (pos.x()+0.5)*mCellsize+mRect.left(), (pos.y()+0.5)*mCellsize + mRect.top());}
138
    /// get the metric rectangle of the cell with index @pos
138
    /// get the metric rectangle of the cell with index @pos
139
    QRectF cellRect(const QPoint &pos) const { QRectF r( QPointF(mRect.left() + mCellsize*pos.x(), mRect.top() + pos.y()*mCellsize),
139
    QRectF cellRect(const QPoint &pos) const { QRectF r( QPointF(mRect.left() + mCellsize*pos.x(), mRect.top() + pos.y()*mCellsize),
140
                                                   QSizeF(mCellsize, mCellsize)); return r; } ///< return coordinates of rect given by @param pos.
140
                                                   QSizeF(mCellsize, mCellsize)); return r; } ///< return coordinates of rect given by @param pos.
141
141
142
    inline  T* begin() const { return mData; } ///< get "iterator" pointer
142
    inline  T* begin() const { return mData; } ///< get "iterator" pointer
143
    inline  T* end() const { return mEnd; } ///< get iterator end-pointer
143
    inline  T* end() const { return mEnd; } ///< get iterator end-pointer
144
    inline QPoint indexOf(const T* element) const; ///< retrieve index (x/y) of the pointer element. returns -1/-1 if element is not valid.
144
    inline QPoint indexOf(const T* element) const; ///< retrieve index (x/y) of the pointer element. returns -1/-1 if element is not valid.
145
    // special queries
145
    // special queries
146
    T max() const; ///< retrieve the maximum value of a grid
146
    T max() const; ///< retrieve the maximum value of a grid
147
    T sum() const; ///< retrieve the sum of the grid
147
    T sum() const; ///< retrieve the sum of the grid
148
    T avg() const; ///< retrieve the average value of a grid
148
    T avg() const; ///< retrieve the average value of a grid
149
    // modifying operations
149
    // modifying operations
150
    void add(const T& summand);
150
    void add(const T& summand);
151
    void multiply(const T& factor);
151
    void multiply(const T& factor);
152
    /// limit each cell value to (including) min_value and (including) max_value
152
    /// limit each cell value to (including) min_value and (including) max_value
153
    void limit(const T min_value, const T max_value);
153
    void limit(const T min_value, const T max_value);
154
154
155
    /// creates a grid with lower resolution and averaged cell values.
155
    /// creates a grid with lower resolution and averaged cell values.
156
    /// @param factor factor by which grid size is reduced (e.g. 3 -> 3x3=9 pixels are averaged to 1 result pixel)
156
    /// @param factor factor by which grid size is reduced (e.g. 3 -> 3x3=9 pixels are averaged to 1 result pixel)
157
    /// @param offsetx, offsety: start averaging with an offset from 0/0 (e.g.: x=1, y=2, factor=3: -> 1/2-3/4 -> 0/0)
157
    /// @param offsetx, offsety: start averaging with an offset from 0/0 (e.g.: x=1, y=2, factor=3: -> 1/2-3/4 -> 0/0)
158
    /// @return Grid with size sizeX()/factor x sizeY()/factor
158
    /// @return Grid with size sizeX()/factor x sizeY()/factor
159
    Grid<T> averaged(const int factor, const int offsetx=0, const int offsety=0) const;
159
    Grid<T> averaged(const int factor, const int offsetx=0, const int offsety=0) const;
160
    /// normalized returns a normalized grid, in a way that the sum()  = @param targetvalue.
160
    /// normalized returns a normalized grid, in a way that the sum()  = @param targetvalue.
161
    /// if the grid is empty or the sum is 0, no modifications are performed.
161
    /// if the grid is empty or the sum is 0, no modifications are performed.
162
    Grid<T> normalized(const T targetvalue) const;
162
    Grid<T> normalized(const T targetvalue) const;
163
    T* ptr(int x, int y) { return &(mData[y*mSizeX + x]); } ///< get a pointer to the element indexed by "x" and "y"
163
    T* ptr(int x, int y) { return &(mData[y*mSizeX + x]); } ///< get a pointer to the element indexed by "x" and "y"
164
    inline double distance(const QPoint &p1, const QPoint &p2); ///< distance (metric) between p1 and p2
164
    inline double distance(const QPoint &p1, const QPoint &p2); ///< distance (metric) between p1 and p2
165
    const QPoint randomPosition() const; ///< returns a (valid) random position within the grid
165
    const QPoint randomPosition() const; ///< returns a (valid) random position within the grid
166
private:
166
private:
167
167
168
    T* mData;
168
    T* mData;
169
    T* mEnd; ///< pointer to 1 element behind the last
169
    T* mEnd; ///< pointer to 1 element behind the last
170
    QRectF mRect;
170
    QRectF mRect;
171
    float mCellsize; ///< size of a cell in meter
171
    float mCellsize; ///< size of a cell in meter
172
    int mSizeX; ///< count of cells in x-direction
172
    int mSizeX; ///< count of cells in x-direction
173
    int mSizeY; ///< count of cells in y-direction
173
    int mSizeY; ///< count of cells in y-direction
174
    int mCount; ///< total number of cells in the grid
174
    int mCount; ///< total number of cells in the grid
175
};
175
};
176
176
177
177
178
typedef Grid<float> FloatGrid;
178
typedef Grid<float> FloatGrid;
179
179
180
enum GridViewType { GridViewRainbow=0, GridViewRainbowReverse=1, GridViewGray=2, GridViewGrayReverse=3, GridViewHeat=4,
180
enum GridViewType { GridViewRainbow=0, GridViewRainbowReverse=1, GridViewGray=2, GridViewGrayReverse=3, GridViewHeat=4,
181
                    GridViewGreens=5, GridViewReds=6, GridViewBlues=7,
181
                    GridViewGreens=5, GridViewReds=6, GridViewBlues=7,
182
                    GridViewBrewerDiv=10, GridViewBrewerQual=11, GridViewTerrain=12, GridViewCustom=14  };
182
                    GridViewBrewerDiv=10, GridViewBrewerQual=11, GridViewTerrain=12, GridViewCustom=14  };
183
183
184
/** @class GridRunner is a helper class to iterate over a rectangular fraction of a grid
184
/** @class GridRunner is a helper class to iterate over a rectangular fraction of a grid
185
*/
185
*/
186
template <class T>
186
template <class T>
187
class GridRunner {
187
class GridRunner {
188
public:
188
public:
189
    // constructors with a QRectF (metric coordinates)
189
    // constructors with a QRectF (metric coordinates)
190
    GridRunner(Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
190
    GridRunner(Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
191
    GridRunner(const Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
191
    GridRunner(const Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
192
    GridRunner(Grid<T> *target_grid, const QRectF &rectangle) {setup(target_grid, rectangle);}
192
    GridRunner(Grid<T> *target_grid, const QRectF &rectangle) {setup(target_grid, rectangle);}
193
    // constructors with a QRect (indices within the grid)
193
    // constructors with a QRect (indices within the grid)
194
    GridRunner(Grid<T> &target_grid, const QRect &rectangle) {setup(&target_grid, rectangle);}
194
    GridRunner(Grid<T> &target_grid, const QRect &rectangle) {setup(&target_grid, rectangle);}
195
    GridRunner(const Grid<T> &target_grid, const QRect &rectangle) {setup(&target_grid, rectangle);}
195
    GridRunner(const Grid<T> &target_grid, const QRect &rectangle) {setup(&target_grid, rectangle);}
196
    GridRunner(Grid<T> *target_grid, const QRect &rectangle) {setup(target_grid, rectangle);}
196
    GridRunner(Grid<T> *target_grid, const QRect &rectangle) {setup(target_grid, rectangle);}
197
    GridRunner(Grid<T> *target_grid) {setup(target_grid, target_grid->rectangle()); }
197
    GridRunner(Grid<T> *target_grid) {setup(target_grid, target_grid->rectangle()); }
198
    T* next(); ///< to to next element, return NULL if finished
198
    T* next(); ///< to to next element, return NULL if finished
199
    /// return the current element, or NULL
199
    /// return the current element, or NULL
200
    T* current() const { return mCurrent; }
200
    T* current() const { return mCurrent; }
201
    /// return the first element
201
    /// return the first element
202
    T* first() const { return mFirst; }
202
    T* first() const { return mFirst; }
203
    /// return the last element (not one element behind the last element!)
203
    /// return the last element (not one element behind the last element!)
204
    T* last() const { return mLast; }
204
    T* last() const { return mLast; }
205
    /// checks if the state of the GridRunner is valid, returns false if out of scope
205
    /// checks if the state of the GridRunner is valid, returns false if out of scope
206
    bool isValid() const {return mCurrent>=mFirst && mCurrent<=mLast; }
206
    bool isValid() const {return mCurrent>=mFirst && mCurrent<=mLast; }
207
    /// return the (index) - coordinates of the current position in the grid
207
    /// return the (index) - coordinates of the current position in the grid
208
    QPoint currentIndex() const { return mGrid->indexOf(mCurrent); }
208
    QPoint currentIndex() const { return mGrid->indexOf(mCurrent); }
209
    /// return the coordinates of the cell center point of the current position in the grid.
209
    /// return the coordinates of the cell center point of the current position in the grid.
210
    QPointF currentCoord() const {return mGrid->cellCenterPoint(mGrid->indexOf(mCurrent));}
210
    QPointF currentCoord() const {return mGrid->cellCenterPoint(mGrid->indexOf(mCurrent));}
211
    void reset() { mCurrent = mFirst-1; mCurrentCol = -1; }
211
    void reset() { mCurrent = mFirst-1; mCurrentCol = -1; }
212
    /// set the internal pointer to the pixel at index 'new_index'. The index is relative to the base grid!
212
    /// set the internal pointer to the pixel at index 'new_index'. The index is relative to the base grid!
213
    void setPosition(QPoint new_index) { if (mGrid->isIndexValid(new_index)) mCurrent = const_cast<Grid<T> *>(mGrid)->ptr(new_index.x(), new_index.y()); else mCurrent=0; }
213
    void setPosition(QPoint new_index) { if (mGrid->isIndexValid(new_index)) mCurrent = const_cast<Grid<T> *>(mGrid)->ptr(new_index.x(), new_index.y()); else mCurrent=0; }
214
    // helpers
214
    // helpers
215
    /// fill array with pointers to neighbors (north, east, west, south)
215
    /// fill array with pointers to neighbors (north, east, west, south)
216
    /// or Null-pointers if out of range.
216
    /// or Null-pointers if out of range.
217
    /// the target array (rArray) is not checked and must be valid!
217
    /// the target array (rArray) is not checked and must be valid!
218
    void neighbors4(T** rArray);
218
    void neighbors4(T** rArray);
219
    void neighbors8(T** rArray);
219
    void neighbors8(T** rArray);
220
private:
220
private:
221
    void setup(const Grid<T> *target_grid, const QRectF &rectangle);
221
    void setup(const Grid<T> *target_grid, const QRectF &rectangle);
222
    void setup(const Grid<T> *target_grid, const QRect &rectangle);
222
    void setup(const Grid<T> *target_grid, const QRect &rectangle);
223
    const Grid<T> *mGrid;
223
    const Grid<T> *mGrid;
224
    T* mFirst; // points to the first element of the grid
224
    T* mFirst; // points to the first element of the grid
225
    T* mLast; // points to the last element of the grid
225
    T* mLast; // points to the last element of the grid
226
    T* mCurrent;
226
    T* mCurrent;
227
    size_t mLineLength;
227
    size_t mLineLength;
228
    size_t mCols;
228
    size_t mCols;
229
    int mCurrentCol;
229
    int mCurrentCol;
230
};
230
};
231
231
232
/** @class Vector3D is a simple 3d vector.
232
/** @class Vector3D is a simple 3d vector.
233
  QVector3D (from Qt) is in QtGui so we needed a replacement.
233
  QVector3D (from Qt) is in QtGui so we needed a replacement.
234
*/
234
*/
235
class Vector3D
235
class Vector3D
236
{
236
{
237
 public:
237
 public:
238
    Vector3D(): mX(0.), mY(0.), mZ(0.) {}
238
    Vector3D(): mX(0.), mY(0.), mZ(0.) {}
239
    Vector3D(const double x, const double y, const double z): mX(x), mY(y), mZ(z) {}
239
    Vector3D(const double x, const double y, const double z): mX(x), mY(y), mZ(z) {}
240
    double x() const { return mX; } ///< get x-coordinate
240
    double x() const { return mX; } ///< get x-coordinate
241
    double y() const { return mY; } ///< get y-coordinate
241
    double y() const { return mY; } ///< get y-coordinate
242
    double z() const { return mZ; } ///< get z-coordinate
242
    double z() const { return mZ; } ///< get z-coordinate
243
    // set variables
243
    // set variables
244
    void setX(const double x) { mX=x; } ///< set value of the x-coordinate
244
    void setX(const double x) { mX=x; } ///< set value of the x-coordinate
245
    void setY(const double y) { mY=y; } ///< set value of the y-coordinate
245
    void setY(const double y) { mY=y; } ///< set value of the y-coordinate
246
    void setZ(const double z) { mZ=z; } ///< set value of the z-coordinate
246
    void setZ(const double z) { mZ=z; } ///< set value of the z-coordinate
247
private:
247
private:
248
    double mX;
248
    double mX;
249
    double mY;
249
    double mY;
250
    double mZ;
250
    double mZ;
251
};
251
};
252
252
253
// copy constructor
253
// copy constructor
254
template <class T>
254
template <class T>
255
Grid<T>::Grid(const Grid<T>& toCopy)
255
Grid<T>::Grid(const Grid<T>& toCopy)
256
{
256
{
257
    mData = 0;
257
    mData = 0;
258
    mRect = toCopy.mRect;
258
    mRect = toCopy.mRect;
259
    setup(toCopy.metricRect(), toCopy.cellsize());
259
    setup(toCopy.metricRect(), toCopy.cellsize());
260
    //setup(toCopy.cellsize(), toCopy.sizeX(), toCopy.sizeY());
260
    //setup(toCopy.cellsize(), toCopy.sizeX(), toCopy.sizeY());
261
    const T* end = toCopy.end();
261
    const T* end = toCopy.end();
262
    T* ptr = begin();
262
    T* ptr = begin();
263
    for (T* i= toCopy.begin(); i!=end; ++i, ++ptr)
263
    for (T* i= toCopy.begin(); i!=end; ++i, ++ptr)
264
       *ptr = *i;
264
       *ptr = *i;
265
}
265
}
266
266
267
// normalize function
267
// normalize function
268
template <class T>
268
template <class T>
269
Grid<T> Grid<T>::normalized(const T targetvalue) const
269
Grid<T> Grid<T>::normalized(const T targetvalue) const
270
{
270
{
271
    Grid<T> target(*this);
271
    Grid<T> target(*this);
272
    T total = sum();
272
    T total = sum();
273
    T multiplier;
273
    T multiplier;
274
    if (total)
274
    if (total)
275
        multiplier = targetvalue / total;
275
        multiplier = targetvalue / total;
276
    else
276
    else
277
        return target;
277
        return target;
278
    for (T* p=target.begin();p!=target.end();++p)
278
    for (T* p=target.begin();p!=target.end();++p)
279
        *p *= multiplier;
279
        *p *= multiplier;
280
    return target;
280
    return target;
281
}
281
}
282
282
283
283
284
template <class T>
284
template <class T>
285
Grid<T> Grid<T>::averaged(const int factor, const int offsetx, const int offsety) const
285
Grid<T> Grid<T>::averaged(const int factor, const int offsetx, const int offsety) const
286
{
286
{
287
    Grid<T> target;
287
    Grid<T> target;
288
    target.setup(cellsize()*factor, sizeX()/factor, sizeY()/factor);
288
    target.setup(cellsize()*factor, sizeX()/factor, sizeY()/factor);
289
    int x,y;
289
    int x,y;
290
    T sum=0;
290
    T sum=0;
291
    target.initialize(sum);
291
    target.initialize(sum);
292
    // sum over array of 2x2, 3x3, 4x4, ...
292
    // sum over array of 2x2, 3x3, 4x4, ...
293
    for (x=offsetx;x<mSizeX;x++)
293
    for (x=offsetx;x<mSizeX;x++)
294
        for (y=offsety;y<mSizeY;y++) {
294
        for (y=offsety;y<mSizeY;y++) {
295
            target.valueAtIndex((x-offsetx)/factor, (y-offsety)/factor) += constValueAtIndex(x,y);
295
            target.valueAtIndex((x-offsetx)/factor, (y-offsety)/factor) += constValueAtIndex(x,y);
296
        }
296
        }
297
    // divide
297
    // divide
298
    double fsquare = factor*factor;
298
    double fsquare = factor*factor;
299
    for (T* p=target.begin();p!=target.end();++p)
299
    for (T* p=target.begin();p!=target.end();++p)
300
        *p /= fsquare;
300
        *p /= fsquare;
301
    return target;
301
    return target;
302
}
302
}
303
303
304
304
305
template <class T>
305
template <class T>
306
T&  Grid<T>::valueAt(const float x, const float y)
306
T&  Grid<T>::valueAt(const float x, const float y)
307
{
307
{
308
    return valueAtIndex( indexAt(QPointF(x,y)) );
308
    return valueAtIndex( indexAt(QPointF(x,y)) );
309
}
309
}
310
310
311
template <class T>
311
template <class T>
312
const T&  Grid<T>::constValueAt(const float x, const float y) const
312
const T&  Grid<T>::constValueAt(const float x, const float y) const
313
{
313
{
314
    return constValueAtIndex( indexAt(QPointF(x,y)) );
314
    return constValueAtIndex( indexAt(QPointF(x,y)) );
315
}
315
}
316
316
317
template <class T>
317
template <class T>
318
T&  Grid<T>::valueAt(const QPointF& posf)
318
T&  Grid<T>::valueAt(const QPointF& posf)
319
{
319
{
320
    return valueAtIndex( indexAt(posf) );
320
    return valueAtIndex( indexAt(posf) );
321
}
321
}
322
322
323
template <class T>
323
template <class T>
324
const T&  Grid<T>::constValueAt(const QPointF& posf) const
324
const T&  Grid<T>::constValueAt(const QPointF& posf) const
325
{
325
{
326
    return constValueAtIndex( indexAt(posf) );
326
    return constValueAtIndex( indexAt(posf) );
327
}
327
}
328
328
329
template <class T>
329
template <class T>
330
Grid<T>::Grid()
330
Grid<T>::Grid()
331
{
331
{
332
    mData = 0; mCellsize=0.f;
332
    mData = 0; mCellsize=0.f;
333
    mEnd = 0;
333
    mEnd = 0;
334
    mSizeX=0; mSizeY=0; mCount=0;
334
    mSizeX=0; mSizeY=0; mCount=0;
335
}
335
}
336
336
337
template <class T>
337
template <class T>
338
bool Grid<T>::setup(const float cellsize, const int sizex, const int sizey)
338
bool Grid<T>::setup(const float cellsize, const int sizex, const int sizey)
339
{
339
{
340
    mSizeX=sizex; mSizeY=sizey;
340
    mSizeX=sizex; mSizeY=sizey;
341
    if (mRect.isNull()) // only set rect if not set before (e.g. by call to setup(QRectF, double))
341
    if (mRect.isNull()) // only set rect if not set before (e.g. by call to setup(QRectF, double))
342
        mRect.setCoords(0., 0., cellsize*sizex, cellsize*sizey);
342
        mRect.setCoords(0., 0., cellsize*sizex, cellsize*sizey);
343
343
344
    if (mData) {
344
    if (mData) {
345
        // test if we can re-use the allocated memory.
345
        // test if we can re-use the allocated memory.
346
        if (mSizeX*mSizeY > mCount || mCellsize != cellsize) {
346
        if (mSizeX*mSizeY > mCount || mCellsize != cellsize) {
347
            // we cannot re-use the memory - create new data
347
            // we cannot re-use the memory - create new data
348
            delete[] mData; mData=NULL;
348
            delete[] mData; mData=NULL;
349
        }
349
        }
350
    }
350
    }
351
    mCellsize=cellsize;
351
    mCellsize=cellsize;
352
    mCount = mSizeX*mSizeY;
352
    mCount = mSizeX*mSizeY;
353
    if (mCount==0)
353
    if (mCount==0)
354
        return false;
354
        return false;
355
    if (mData==NULL)
355
    if (mData==NULL)
356
        mData = new T[mCount];
356
        mData = new T[mCount];
357
    mEnd = &(mData[mCount]);
357
    mEnd = &(mData[mCount]);
358
    return true;
358
    return true;
359
}
359
}
360
360
361
template <class T>
361
template <class T>
362
bool Grid<T>::setup(const QRectF& rect, const double cellsize)
362
bool Grid<T>::setup(const QRectF& rect, const double cellsize)
363
{
363
{
364
    mRect = rect;
364
    mRect = rect;
365
    int dx = int(rect.width()/cellsize);
365
    int dx = int(rect.width()/cellsize);
366
    if (mRect.left()+cellsize*dx<rect.right())
366
    if (mRect.left()+cellsize*dx<rect.right())
367
        dx++;
367
        dx++;
368
    int dy = int(rect.height()/cellsize);
368
    int dy = int(rect.height()/cellsize);
369
    if (mRect.top()+cellsize*dy<rect.bottom())
369
    if (mRect.top()+cellsize*dy<rect.bottom())
370
        dy++;
370
        dy++;
371
    return setup(cellsize, dx, dy);
371
    return setup(cellsize, dx, dy);
372
}
372
}
373
373
374
/** retrieve from the index from an element reversely from a pointer to that element.
374
/** retrieve from the index from an element reversely from a pointer to that element.
375
    The internal memory layout is (for dimx=6, dimy=3):
375
    The internal memory layout is (for dimx=6, dimy=3):
376
0  1  2  3  4  5
376
0  1  2  3  4  5
377
6  7  8  9  10 11
377
6  7  8  9  10 11
378
12 13 14 15 16 17
378
12 13 14 15 16 17
379
Note: north and south are reversed, thus the item with index 0 is located in the south-western edge of the grid! */
379
Note: north and south are reversed, thus the item with index 0 is located in the south-western edge of the grid! */
380
template <class T> inline
380
template <class T> inline
381
QPoint Grid<T>::indexOf(const T* element) const
381
QPoint Grid<T>::indexOf(const T* element) const
382
{
382
{
383
//    QPoint result(-1,-1);
383
//    QPoint result(-1,-1);
384
    if (element==NULL || element<mData || element>=end())
384
    if (element==NULL || element<mData || element>=end())
385
        return QPoint(-1, -1);
385
        return QPoint(-1, -1);
386
    int idx = element - mData;
386
    int idx = element - mData;
387
    return QPoint(idx % mSizeX,  idx / mSizeX);
387
    return QPoint(idx % mSizeX,  idx / mSizeX);
388
//    result.setX( idx % mSizeX);
388
//    result.setX( idx % mSizeX);
389
//    result.setY( idx / mSizeX);
389
//    result.setY( idx / mSizeX);
390
//    return result;
390
//    return result;
391
}
391
}
392
392
393
template <class T>
393
template <class T>
394
T  Grid<T>::max() const
394
T  Grid<T>::max() const
395
{
395
{
396
    T maxv = -std::numeric_limits<T>::max();
396
    T maxv = -std::numeric_limits<T>::max();
397
    T* p;
397
    T* p;
398
    T* pend = end();
398
    T* pend = end();
399
    for (p=begin(); p!=pend;++p)
399
    for (p=begin(); p!=pend;++p)
400
       maxv = std::max(maxv, *p);
400
       maxv = std::max(maxv, *p);
401
    return maxv;
401
    return maxv;
402
}
402
}
403
403
404
template <class T>
404
template <class T>
405
T  Grid<T>::sum() const
405
T  Grid<T>::sum() const
406
{
406
{
407
    T* pend = end();
407
    T* pend = end();
408
    T total = 0;
408
    T total = 0;
409
    for (T *p=begin(); p!=pend;++p)
409
    for (T *p=begin(); p!=pend;++p)
410
       total += *p;
410
       total += *p;
411
    return total;
411
    return total;
412
}
412
}
413
413
414
template <class T>
414
template <class T>
415
T  Grid<T>::avg() const
415
T  Grid<T>::avg() const
416
{
416
{
417
    if (count())
417
    if (count())
418
        return sum() / T(count());
418
        return sum() / T(count());
419
    else return 0;
419
    else return 0;
420
}
420
}
421
421
422
template <class T>
422
template <class T>
423
void Grid<T>::add(const T& summand)
423
void Grid<T>::add(const T& summand)
424
{
424
{
425
    T* pend = end();
425
    T* pend = end();
426
    for (T *p=begin(); p!=pend;*p+=summand,++p)
426
    for (T *p=begin(); p!=pend;*p+=summand,++p)
427
       ;
427
       ;
428
}
428
}
429
429
430
template <class T>
430
template <class T>
431
void Grid<T>::multiply(const T& factor)
431
void Grid<T>::multiply(const T& factor)
432
{
432
{
433
    T* pend = end();
433
    T* pend = end();
434
    for (T *p=begin(); p!=pend;*p*=factor,++p)
434
    for (T *p=begin(); p!=pend;*p*=factor,++p)
435
        ;
435
        ;
436
}
436
}
437
437
438
template <class T>
438
template <class T>
439
void Grid<T>::limit(const T min_value, const T max_value)
439
void Grid<T>::limit(const T min_value, const T max_value)
440
{
440
{
441
    T* pend = end();
441
    T* pend = end();
442
    for (T *p=begin(); p!=pend;++p)
442
    for (T *p=begin(); p!=pend;++p)
443
        *p = *p < min_value ? min_value : (*p>max_value? max_value : *p);
443
        *p = *p < min_value ? min_value : (*p>max_value? max_value : *p);
444
}
444
}
445
445
446
446
447
447
448
template <class T>
448
template <class T>
449
void  Grid<T>::wipe()
449
void  Grid<T>::wipe()
450
{
450
{
451
    memset(mData, 0, mCount*sizeof(T));
451
    memset(mData, 0, mCount*sizeof(T));
452
}
452
}
453
template <class T>
453
template <class T>
454
void  Grid<T>::wipe(const T value)
454
void  Grid<T>::wipe(const T value)
455
{
455
{
456
    /* this does not work properly !!! */
456
    /* this does not work properly !!! */
457
    if (sizeof(T)==sizeof(int)) {
457
    if (sizeof(T)==sizeof(int)) {
458
        float temp = value;
458
        float temp = value;
459
        float *pf = &temp;
459
        float *pf = &temp;
460
460
461
        memset(mData, *((int*)pf), mCount*sizeof(T));
461
        memset(mData, *((int*)pf), mCount*sizeof(T));
462
    } else
462
    } else
463
        initialize(value);
463
        initialize(value);
464
}
464
}
465
465
466
template <class T>
466
template <class T>
467
Grid<double> *Grid<T>::toDouble() const
467
Grid<double> *Grid<T>::toDouble() const
468
{
468
{
469
    Grid<double> *g = new Grid<double>();
469
    Grid<double> *g = new Grid<double>();
470
    g->setup(metricRect(), cellsize());
470
    g->setup(metricRect(), cellsize());
471
    if (g->isEmpty())
471
    if (g->isEmpty())
472
        return g;
472
        return g;
473
    double *dp = g->begin();
473
    double *dp = g->begin();
474
    for (T *p=begin(); p!=end(); ++p, ++dp)
474
    for (T *p=begin(); p!=end(); ++p, ++dp)
475
        *dp = *p;
475
        *dp = *p;
476
    return g;
476
    return g;
477
}
477
}
478
478
479
template <class T>
479
template <class T>
480
double Grid<T>::distance(const QPoint &p1, const QPoint &p2)
480
double Grid<T>::distance(const QPoint &p1, const QPoint &p2)
481
{
481
{
482
    QPointF fp1=cellCenterPoint(p1);
482
    QPointF fp1=cellCenterPoint(p1);
483
    QPointF fp2=cellCenterPoint(p2);
483
    QPointF fp2=cellCenterPoint(p2);
484
    double distance = sqrt( (fp1.x()-fp2.x())*(fp1.x()-fp2.x()) + (fp1.y()-fp2.y())*(fp1.y()-fp2.y()));
484
    double distance = sqrt( (fp1.x()-fp2.x())*(fp1.x()-fp2.x()) + (fp1.y()-fp2.y())*(fp1.y()-fp2.y()));
485
    return distance;
485
    return distance;
486
}
486
}
487
487
488
template <class T>
488
template <class T>
489
const QPoint Grid<T>::randomPosition() const
489
const QPoint Grid<T>::randomPosition() const
490
{
490
{
491
    return QPoint(irandom(0,mSizeX), irandom(0, mSizeY));
491
    return QPoint(irandom(0,mSizeX), irandom(0, mSizeY));
492
}
492
}
493
493
494
////////////////////////////////////////////////////////////
494
////////////////////////////////////////////////////////////
495
// grid runner
495
// grid runner
496
////////////////////////////////////////////////////////////
496
////////////////////////////////////////////////////////////
497
template <class T>
497
template <class T>
498
void GridRunner<T>::setup(const Grid<T> *target_grid, const QRect &rectangle)
498
void GridRunner<T>::setup(const Grid<T> *target_grid, const QRect &rectangle)
499
{
499
{
500
    QPoint upper_left = rectangle.topLeft();
500
    QPoint upper_left = rectangle.topLeft();
501
    // due to the strange behavior of QRect::bottom() and right():
501
    // due to the strange behavior of QRect::bottom() and right():
502
    QPoint lower_right = rectangle.bottomRight();
502
    QPoint lower_right = rectangle.bottomRight();
503
    mCurrent = const_cast<Grid<T> *>(target_grid)->ptr(upper_left.x(), upper_left.y());
503
    mCurrent = const_cast<Grid<T> *>(target_grid)->ptr(upper_left.x(), upper_left.y());
504
    mFirst = mCurrent;
504
    mFirst = mCurrent;
505
    mCurrent--; // point to first element -1
505
    mCurrent--; // point to first element -1
506
    mLast = const_cast<Grid<T> *>(target_grid)->ptr(lower_right.x()-1, lower_right.y()-1);
506
    mLast = const_cast<Grid<T> *>(target_grid)->ptr(lower_right.x()-1, lower_right.y()-1);
507
    mCols = lower_right.x() - upper_left.x(); //
507
    mCols = lower_right.x() - upper_left.x(); //
508
    mLineLength =  target_grid->sizeX() - mCols;
508
    mLineLength =  target_grid->sizeX() - mCols;
509
    mCurrentCol = -1;
509
    mCurrentCol = -1;
510
    mGrid = target_grid;
510
    mGrid = target_grid;
511
//    qDebug() << "GridRunner: rectangle:" << rectangle
511
//    qDebug() << "GridRunner: rectangle:" << rectangle
512
//             << "upper_left:" << target_grid.cellCenterPoint(target_grid.indexOf(mCurrent))
512
//             << "upper_left:" << target_grid.cellCenterPoint(target_grid.indexOf(mCurrent))
513
//             << "lower_right:" << target_grid.cellCenterPoint(target_grid.indexOf(mLast));
513
//             << "lower_right:" << target_grid.cellCenterPoint(target_grid.indexOf(mLast));
514
}
514
}
515
515
516
template <class T>
516
template <class T>
517
void GridRunner<T>::setup(const Grid<T> *target_grid, const QRectF &rectangle_metric)
517
void GridRunner<T>::setup(const Grid<T> *target_grid, const QRectF &rectangle_metric)
518
{
518
{
519
    QRect rect(target_grid->indexAt(rectangle_metric.topLeft()),
519
    QRect rect(target_grid->indexAt(rectangle_metric.topLeft()),
520
               target_grid->indexAt(rectangle_metric.bottomRight()) );
520
               target_grid->indexAt(rectangle_metric.bottomRight()) );
521
    setup (target_grid, rect);
521
    setup (target_grid, rect);
522
}
522
}
523
523
524
template <class T>
524
template <class T>
525
T* GridRunner<T>::next()
525
T* GridRunner<T>::next()
526
{
526
{
527
    if (mCurrent>mLast)
527
    if (mCurrent>mLast)
528
        return NULL;
528
        return NULL;
529
    mCurrent++;
529
    mCurrent++;
530
    mCurrentCol++;
530
    mCurrentCol++;
531
531
532
    if (mCurrentCol >= int(mCols)) {
532
    if (mCurrentCol >= int(mCols)) {
533
        mCurrent += mLineLength; // skip to next line
533
        mCurrent += mLineLength; // skip to next line
534
        mCurrentCol = 0;
534
        mCurrentCol = 0;
535
    }
535
    }
536
    if (mCurrent>mLast)
536
    if (mCurrent>mLast)
537
        return NULL;
537
        return NULL;
538
    else
538
    else
539
        return mCurrent;
539
        return mCurrent;
540
}
540
}
541
541
542
template <class T>
542
template <class T>
543
/// get pointers the the 4-neighborhood
543
/// get pointers the the 4-neighborhood
544
/// north, east, west, south
544
/// north, east, west, south
545
/// 0-pointers are returned for edge pixels.
545
/// 0-pointers are returned for edge pixels.
546
void GridRunner<T>::neighbors4(T** rArray)
546
void GridRunner<T>::neighbors4(T** rArray)
547
{
547
{
548
    // north:
548
    // north:
549
    rArray[0] = mCurrent + mCols + mLineLength > mLast?0: mCurrent + mCols + mLineLength;
549
    rArray[0] = mCurrent + mCols + mLineLength > mLast?0: mCurrent + mCols + mLineLength;
550
    // south:
550
    // south:
551
    rArray[3] = mCurrent - (mCols + mLineLength) < mFirst?0: mCurrent -  (mCols + mLineLength);
551
    rArray[3] = mCurrent - (mCols + mLineLength) < mFirst?0: mCurrent -  (mCols + mLineLength);
552
    // east / west
552
    // east / west
553
    rArray[1] = mCurrentCol+1<int(mCols)? mCurrent + 1 : 0;
553
    rArray[1] = mCurrentCol+1<int(mCols)? mCurrent + 1 : 0;
554
    rArray[2] = mCurrentCol>0? mCurrent-1 : 0;
554
    rArray[2] = mCurrentCol>0? mCurrent-1 : 0;
555
}
555
}
556
556
557
/// get pointers to the 8-neighbor-hood
557
/// get pointers to the 8-neighbor-hood
558
/// north/east/west/south/NE/NW/SE/SW
558
/// north/east/west/south/NE/NW/SE/SW
559
/// 0-pointers are returned for edge pixels.
559
/// 0-pointers are returned for edge pixels.
560
template <class T>
560
template <class T>
561
void GridRunner<T>::neighbors8(T** rArray)
561
void GridRunner<T>::neighbors8(T** rArray)
562
{
562
{
563
    neighbors4(rArray);
563
    neighbors4(rArray);
564
    // north-east
564
    // north-east
565
    rArray[4] = rArray[0] && rArray[1]? rArray[0]+1: 0;
565
    rArray[4] = rArray[0] && rArray[1]? rArray[0]+1: 0;
566
    // north-west
566
    // north-west
567
    rArray[5] = rArray[0] && rArray[2]? rArray[0]-1: 0;
567
    rArray[5] = rArray[0] && rArray[2]? rArray[0]-1: 0;
568
    // south-east
568
    // south-east
569
    rArray[6] = rArray[3] && rArray[1]? rArray[3]+1: 0;
569
    rArray[6] = rArray[3] && rArray[1]? rArray[3]+1: 0;
570
    // south-west
570
    // south-west
571
    rArray[7] = rArray[3] && rArray[2]? rArray[3]-1: 0;
571
    rArray[7] = rArray[3] && rArray[2]? rArray[3]-1: 0;
572
572
573
}
573
}
574
574
575
////////////////////////////////////////////////////////////
575
////////////////////////////////////////////////////////////
576
// global functions
576
// global functions
577
////////////////////////////////////////////////////////////
577
////////////////////////////////////////////////////////////
578
578
579
/// dumps a FloatGrid to a String.
579
/// dumps a FloatGrid to a String.
580
/// rows will be y-lines, columns x-values. (see grid.cpp)
580
/// rows will be y-lines, columns x-values. (see grid.cpp)
581
QString gridToString(const FloatGrid &grid, const QChar sep=QChar(';'), const int newline_after=-1);
581
QString gridToString(const FloatGrid &grid, const QChar sep=QChar(';'), const int newline_after=-1);
582
582
583
/// creates and return a QImage from Grid-Data.
583
/// creates and return a QImage from Grid-Data.
584
/// @param black_white true: max_value = white, min_value = black, false: color-mode: uses a HSV-color model from blue (min_value) to red (max_value), default: color mode (false)
584
/// @param black_white true: max_value = white, min_value = black, false: color-mode: uses a HSV-color model from blue (min_value) to red (max_value), default: color mode (false)
585
/// @param min_value, max_value min/max bounds for color calcuations. values outside bounds are limited to these values. defaults: min=0, max=1
585
/// @param min_value, max_value min/max bounds for color calcuations. values outside bounds are limited to these values. defaults: min=0, max=1
586
/// @param reverse if true, color ramps are inversed (to: min_value = white (black and white mode) or red (color mode). default = false.
586
/// @param reverse if true, color ramps are inversed (to: min_value = white (black and white mode) or red (color mode). default = false.
587
/// @return a QImage with the Grids size of pixels. Pixel coordinates relate to the index values of the grid.
587
/// @return a QImage with the Grids size of pixels. Pixel coordinates relate to the index values of the grid.
588
QImage gridToImage(const FloatGrid &grid,
588
QImage gridToImage(const FloatGrid &grid,
589
                   bool black_white=false,
589
                   bool black_white=false,
590
                   double min_value=0., double max_value=1.,
590
                   double min_value=0., double max_value=1.,
591
                   bool reverse=false);
591
                   bool reverse=false);
592
592
593
593
594
/** load into 'rGrid' the content of the image pointed at by 'fileName'.
594
/** load into 'rGrid' the content of the image pointed at by 'fileName'.
595
    Pixels are converted to grey-scale and then transformend to a value ranging from 0..1 (black..white).
595
    Pixels are converted to grey-scale and then transformend to a value ranging from 0..1 (black..white).
596
  */
596
  */
597
bool loadGridFromImage(const QString &fileName, FloatGrid &rGrid);
597
bool loadGridFromImage(const QString &fileName, FloatGrid &rGrid);
598
598
599
/// template version for non-float grids (see also version for FloatGrid)
599
/// template version for non-float grids (see also version for FloatGrid)
600
/// @param sep string separator
600
/// @param sep string separator
601
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
601
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
602
template <class T>
602
template <class T>
603
        QString gridToString(const Grid<T> &grid, const QChar sep=QChar(';'), const int newline_after=-1)
603
        QString gridToString(const Grid<T> &grid, const QChar sep=QChar(';'), const int newline_after=-1)
604
{
604
{
605
    QString res;
605
    QString res;
606
    QTextStream ts(&res);
606
    QTextStream ts(&res);
607
607
608
    int newl_counter = newline_after;
608
    int newl_counter = newline_after;
609
    for (int y=grid.sizeY()-1;y>=0;--y){
609
    for (int y=grid.sizeY()-1;y>=0;--y){
610
        for (int x=0;x<grid.sizeX();x++){
610
        for (int x=0;x<grid.sizeX();x++){
611
            ts << grid.constValueAtIndex(x,y) << sep;
611
            ts << grid.constValueAtIndex(x,y) << sep;
612
            if (--newl_counter==0) {
612
            if (--newl_counter==0) {
613
                ts << "\r\n";
613
                ts << "\r\n";
614
                newl_counter = newline_after;
614
                newl_counter = newline_after;
615
            }
615
            }
616
        }
616
        }
617
        ts << "\r\n";
617
        ts << "\r\n";
618
    }
618
    }
619
619
620
    return res;
620
    return res;
621
}
621
}
622
622
623
/// template version for non-float grids (see also version for FloatGrid)
623
/// template version for non-float grids (see also version for FloatGrid)
624
/// @param valueFunction pointer to a function with the signature: QString func(const T&) : this should return a QString
624
/// @param valueFunction pointer to a function with the signature: QString func(const T&) : this should return a QString
625
/// @param sep string separator
625
/// @param sep string separator
626
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
626
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
627
template <class T>
627
template <class T>
628
        QString gridToString(const Grid<T> &grid, QString (*valueFunction)(const T& value), const QChar sep=QChar(';'), const int newline_after=-1 )
628
        QString gridToString(const Grid<T> &grid, QString (*valueFunction)(const T& value), const QChar sep=QChar(';'), const int newline_after=-1 )
629
        {
629
        {
630
            QString res;
630
            QString res;
631
            QTextStream ts(&res);
631
            QTextStream ts(&res);
632
632
633
            int newl_counter = newline_after;
633
            int newl_counter = newline_after;
634
            for (int y=grid.sizeY()-1;y>=0;--y){
634
            for (int y=grid.sizeY()-1;y>=0;--y){
635
                for (int x=0;x<grid.sizeX();x++){
635
                for (int x=0;x<grid.sizeX();x++){
636
                    ts << (*valueFunction)(grid.constValueAtIndex(x,y)) << sep;
636
                    ts << (*valueFunction)(grid.constValueAtIndex(x,y)) << sep;
637
637
638
                    if (--newl_counter==0) {
638
                    if (--newl_counter==0) {
639
                        ts << "\r\n";
639
                        ts << "\r\n";
640
                        newl_counter = newline_after;
640
                        newl_counter = newline_after;
641
                    }
641
                    }
642
                }
642
                }
643
                ts << "\r\n";
643
                ts << "\r\n";
644
            }
644
            }
645
645
646
            return res;
646
            return res;
647
        }
647
        }
648
void modelToWorld(const Vector3D &From, Vector3D &To);
648
void modelToWorld(const Vector3D &From, Vector3D &To);
649
649
650
template <class T>
650
template <class T>
651
    QString gridToESRIRaster(const Grid<T> &grid, QString (*valueFunction)(const T& value) )
651
    QString gridToESRIRaster(const Grid<T> &grid, QString (*valueFunction)(const T& value) )
652
{
652
{
653
        Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
653
        Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
654
        Vector3D world;
654
        Vector3D world;
655
        modelToWorld(model, world);
655
        modelToWorld(model, world);
656
        QString result = QString("ncols %1\r\nnrows %2\r\nxllcorner %3\r\nyllcorner %4\r\ncellsize %5\r\nNODATA_value %6\r\n")
656
        QString result = QString("ncols %1\r\nnrows %2\r\nxllcorner %3\r\nyllcorner %4\r\ncellsize %5\r\nNODATA_value %6\r\n")
657
                                .arg(grid.sizeX())
657
                                .arg(grid.sizeX())
658
                                .arg(grid.sizeY())
658
                                .arg(grid.sizeY())
659
                                .arg(world.x(),0,'f').arg(world.y(),0,'f')
659
                                .arg(world.x(),0,'f').arg(world.y(),0,'f')
660
                                .arg(grid.cellsize()).arg(-9999);
660
                                .arg(grid.cellsize()).arg(-9999);
661
        QString line =  gridToString(grid, valueFunction, QChar(' ')); // for special grids
661
        QString line =  gridToString(grid, valueFunction, QChar(' ')); // for special grids
662
        return result + line;
662
        return result + line;
663
}
663
}
664
664
665
    template <class T>
665
    template <class T>
666
        QString gridToESRIRaster(const Grid<T> &grid )
666
        QString gridToESRIRaster(const Grid<T> &grid )
667
{
667
{
668
            Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
668
            Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
669
            Vector3D world;
669
            Vector3D world;
670
            modelToWorld(model, world);
670
            modelToWorld(model, world);
671
            QString result = QString("ncols %1\r\nnrows %2\r\nxllcorner %3\r\nyllcorner %4\r\ncellsize %5\r\nNODATA_value %6\r\n")
671
            QString result = QString("ncols %1\r\nnrows %2\r\nxllcorner %3\r\nyllcorner %4\r\ncellsize %5\r\nNODATA_value %6\r\n")
672
                    .arg(grid.sizeX())
672
                    .arg(grid.sizeX())
673
                    .arg(grid.sizeY())
673
                    .arg(grid.sizeY())
674
                    .arg(world.x(),0,'f').arg(world.y(),0,'f')
674
                    .arg(world.x(),0,'f').arg(world.y(),0,'f')
675
                    .arg(grid.cellsize()).arg(-9999);
675
                    .arg(grid.cellsize()).arg(-9999);
676
            QString line = gridToString(grid, QChar(' ')); // for normal grids (e.g. float)
676
            QString line = gridToString(grid, QChar(' ')); // for normal grids (e.g. float)
677
            return result + line;
677
            return result + line;
678
}
678
}
679
679
680
#endif // GRID_H
680
#endif // GRID_H
681
 
681