Subversion Repositories public iLand

Rev

Rev 45 | Rev 48 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1
 
15 Werner 2
#ifndef GRID_H
3
#define GRID_H
4
 
22 Werner 5
#include <QtCore>
15 Werner 6
 
7
 
8
#include <stdexcept>
9
 
10
/** Grid class (template).
11
 
12
  */
13
template <class T>
14
class Grid {
15
public:
16
 
17
    Grid();
18
    Grid(int cellsize, int sizex, int sizey) { mData=0; setup(cellsize, sizex, sizey); }
33 Werner 19
    // copy ctor
20
    Grid(const Grid<T>& toCopy);
15 Werner 21
    ~Grid() { if (mData) delete[] mData; }
22
 
18 Werner 23
    bool setup(const float cellsize, const int sizex, const int sizey);
22 Werner 24
    bool setup(const QRectF& rect, const double cellsize);
37 Werner 25
    void initialize(const T& value) {for( T *p = begin();p!=end(); ++p) *p=value; qDebug()<<"Grid initialize"<<end()-begin()<<"items.";}
15 Werner 26
 
27
    const int sizeX() const { return mSizeX; }
28
    const int sizeY() const { return mSizeY; }
29
    const float metricSizeX() const { return mSizeX*mCellsize; }
30
    const float metricSizeY() const { return mSizeY*mCellsize; }
31
    const float cellsize() const { return mCellsize; }
27 Werner 32
    const int count() const { return mCount; }
32 Werner 33
    // operations
15 Werner 34
    // query
33 Werner 35
    /// access (const) with index variables. use int.
36
    inline const T& operator()(const int ix, const int iy) const { return constValueAtIndex(ix, iy); }
37
    /// access (const) using metric variables. use float.
38
    inline const T& operator()(const float x, const float y) const { return constValueAt(x, y); }
45 Werner 39
    inline const T& operator[] (const QPointF &p) const { return constValueAtIndex(p); }
33 Werner 40
 
25 Werner 41
    T& valueAtIndex(const QPoint& pos); ///< value at position defined by indices (x,y)
33 Werner 42
    T& valueAtIndex(const int ix, const int iy) { return valueAtIndex(QPoint(ix,iy)); } ///< const value at position defined by indices (x,y)
43
 
44
    const T& constValueAtIndex(const QPoint& pos) const; ///< value at position defined by a (integer) QPoint
32 Werner 45
    const T& constValueAtIndex(const int ix, const int iy) const { return constValueAtIndex(QPoint(ix,iy)); }
33 Werner 46
 
47
    T& valueAt(const QPointF& posf); ///< value at position defined by metric coordinates (QPointF)
48
    const T& constValueAt(const QPointF& posf) const; ///< value at position defined by metric coordinates (QPointF)
49
 
50
    T& valueAt(const float x, const float y); ///< value at position defined by metric coordinates (x,y)
51
    const T& constValueAt(const float x, const float y) const; ///< value at position defined by metric coordinates (x,y)
52
 
27 Werner 53
    QPoint indexAt(const QPointF& pos) const { return QPoint(int((pos.x()-mOffset.x()) / mCellsize),  int((pos.y()-mOffset.y())/mCellsize)); } /// get index of value at position pos (metric)
54
    bool isIndexValid(const QPoint& pos) const { return (pos.x()>=0 && pos.x()<mSizeX && pos.y()>=0 && pos.y()<mSizeY); } /// get index of value at position pos (index)
55
    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.
32 Werner 56
    QPointF cellCoordinates(const QPoint &pos) { return QPointF( (pos.x()+0.5)*mCellsize+mOffset.x(), (pos.y()+0.5)*mCellsize + mOffset.y());} /// get metric coordinates of the cells center
27 Werner 57
    inline  T* begin() const { return mData; } ///< get "iterator" pointer
37 Werner 58
    inline  T* end() const { return mEnd; } ///< get iterator end-pointer
27 Werner 59
    QPoint indexOf(T* element) const; ///< retrieve index (x/y) of the pointer element. returns -1/-1 if element is not valid.
60
    // special queries
33 Werner 61
    T max() const; ///< retrieve the maximum value of a grid
62
    T sum() const; ///< retrieve the sum of the grid
63
    T avg() const; ///< retrieve the average value of a grid
64
    /// creates a grid with lower resolution and averaged cell values.
65
    /// @param factor factor by which grid size is reduced (e.g. 3 -> 3x3=9 pixels are averaged to 1 result pixel)
66
    /// @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)
67
    /// @return Grid with size sizeX()/factor x sizeY()/factor
68
    Grid<T> averaged(const int factor, const int offsetx=0, const int offsety=0) const;
69
    /// normalized returns a normalized grid, in a way that the sum()  = @param targetvalue.
70
    /// if the grid is empty or the sum is 0, no modifications are performed.
71
    Grid<T> normalized(const T targetvalue) const;
15 Werner 72
private:
73
    T* mData;
37 Werner 74
    T* mEnd; ///< pointer to 1 element behind the last
22 Werner 75
    QPointF mOffset;
36 Werner 76
    float mCellsize; ///< size of a cell in meter
77
    int mSizeX; ///< count of cells in x-direction
78
    int mSizeY; ///< count of cells in y-direction
79
    int mCount; ///< total number of cells in the grid
15 Werner 80
};
81
 
82
typedef Grid<float> FloatGrid;
83
 
33 Werner 84
// copy constructor
85
template <class T>
86
Grid<T>::Grid(const Grid<T>& toCopy)
87
{
40 Werner 88
    mData = 0;
33 Werner 89
    setup(toCopy.cellsize(), toCopy.sizeX(), toCopy.sizeY());
90
    const T* end = toCopy.end();
91
    T* ptr = begin();
92
    for (T* i= toCopy.begin(); i!=end; ++i, ++ptr)
93
       *ptr = *i;
94
}
22 Werner 95
 
33 Werner 96
// normalize function
32 Werner 97
template <class T>
33 Werner 98
Grid<T> Grid<T>::normalized(const T targetvalue) const
32 Werner 99
{
33 Werner 100
    Grid<T> target(*this);
101
    T total = sum();
102
    T multiplier;
103
    if (total)
104
        multiplier = targetvalue / total;
105
    else
106
        return target;
107
    for (T* p=target.begin();p!=target.end();++p)
108
        *p *= multiplier;
40 Werner 109
    return target;
33 Werner 110
}
111
 
112
 
113
template <class T>
114
Grid<T> Grid<T>::averaged(const int factor, const int offsetx, const int offsety) const
115
{
32 Werner 116
    Grid<T> target;
117
    target.setup(cellsize()*factor, sizeX()/factor, sizeY()/factor);
118
    int x,y;
119
    T sum=0;
120
    target.initialize(sum);
121
    // sum over array of 2x2, 3x3, 4x4, ...
122
    for (x=offsetx;x<mSizeX;x++)
123
        for (y=offsety;y<mSizeY;y++) {
124
            target.valueAtIndex((x-offsetx)/factor, (y-offsety)/factor) += constValueAtIndex(x,y);
125
        }
126
    // divide
127
    double fsquare = factor*factor;
128
    for (T* p=target.begin();p!=target.end();++p)
129
        *p /= fsquare;
130
    return target;
131
}
22 Werner 132
 
15 Werner 133
template <class T>
22 Werner 134
T&  Grid<T>::valueAtIndex(const QPoint& pos)
135
{
136
    if (isIndexValid(pos)) {
37 Werner 137
        return mData[pos.x()*mSizeY + pos.y()];
22 Werner 138
    }
40 Werner 139
    qCritical("Grid::valueAtIndex. invalid: %d/%d", pos.x(), pos.y());
140
    return mData[0];
22 Werner 141
}
36 Werner 142
 
27 Werner 143
template <class T>
144
const T&  Grid<T>::constValueAtIndex(const QPoint& pos) const
145
{
146
    if (isIndexValid(pos)) {
37 Werner 147
        return mData[pos.x()*mSizeY + pos.y()];
27 Werner 148
    }
40 Werner 149
    qCritical("Grid::constValueAtIndex. invalid: %d/%d", pos.x(), pos.y());
150
    return mData[0];
27 Werner 151
}
22 Werner 152
 
153
template <class T>
33 Werner 154
T&  Grid<T>::valueAt(const float x, const float y)
155
{
156
    return valueAtIndex( indexAt(QPointF(x,y)) );
157
}
36 Werner 158
 
33 Werner 159
template <class T>
160
const T&  Grid<T>::constValueAt(const float x, const float y) const
161
{
162
    return constValueAtIndex( indexAt(QPointF(x,y)) );
163
}
36 Werner 164
 
33 Werner 165
template <class T>
22 Werner 166
T&  Grid<T>::valueAt(const QPointF& posf)
167
{
168
    return valueAtIndex( indexAt(posf) );
169
}
36 Werner 170
 
33 Werner 171
template <class T>
172
const T&  Grid<T>::constValueAt(const QPointF& posf) const
173
{
174
    return constValueAtIndex( indexAt(posf) );
175
}
22 Werner 176
 
177
template <class T>
15 Werner 178
Grid<T>::Grid()
179
{
37 Werner 180
    mData = 0; mCellsize=0.f;
181
    mEnd = 0;
15 Werner 182
}
183
 
184
template <class T>
18 Werner 185
bool Grid<T>::setup(const float cellsize, const int sizex, const int sizey)
15 Werner 186
{
37 Werner 187
    mSizeX=sizex; mSizeY=sizey; mCellsize=cellsize;
15 Werner 188
    mCount = mSizeX*mSizeY;
37 Werner 189
    if (mData) {
190
         delete[] mData; mData=NULL;
191
     }
15 Werner 192
   if (mCount>0)
37 Werner 193
        mData = new T[mCount];
194
   mEnd = &(mData[mCount]);
15 Werner 195
   return true;
196
}
197
 
198
template <class T>
22 Werner 199
bool Grid<T>::setup(const QRectF& rect, const double cellsize)
15 Werner 200
{
22 Werner 201
    mOffset.setX(rect.left());
202
    mOffset.setY(rect.top());
203
    int dx = int(rect.width()/cellsize);
204
    if (mOffset.x()+cellsize*dx<rect.right())
205
        dx++;
206
    int dy = int(rect.height()/cellsize);
207
    if (mOffset.y()+cellsize*dy<rect.bottom())
208
        dy++;
209
    return setup(cellsize, dx, dy);
15 Werner 210
}
211
 
25 Werner 212
template <class T>
27 Werner 213
QPoint Grid<T>::indexOf(T* element) const
25 Werner 214
{
215
    QPoint result(-1,-1);
216
    if (element==NULL || element<mData || element>=end())
217
        return result;
218
    int idx = element - mData;
41 Werner 219
    result.setX( idx % mSizeY);
220
    result.setY( idx / mSizeY);
25 Werner 221
    return result;
222
}
22 Werner 223
 
27 Werner 224
template <class T>
225
T  Grid<T>::max() const
226
{
227
    T maxv = std::numeric_limits<T>::min();
228
    T* p;
229
    T* pend = end();
230
    for (p=begin(); p!=pend;++p)
231
       maxv = std::max(maxv, *p);
232
    return maxv;
233
}
234
 
33 Werner 235
template <class T>
236
T  Grid<T>::sum() const
237
{
238
    T* pend = end();
239
    T total = 0;
240
    for (T *p=begin(); p!=pend;++p)
241
       total += *p;
242
    return total;
243
}
244
 
245
template <class T>
246
T  Grid<T>::avg() const
247
{
248
    if (count())
249
        return sum() / T(count());
250
    else return 0;
251
}
252
 
36 Werner 253
////////////////////////////////////////////////////////////7
254
// global functions
255
////////////////////////////////////////////////////////////7
256
 
257
/// dumps a FloatGrid to a String.
46 Werner 258
/// rows will be y-lines, columns x-values. (see grid.cpp)
36 Werner 259
QString gridToString(const FloatGrid &grid);
260
 
261
/// creates and return a QImage from Grid-Data.
262
/// @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)
263
/// @param min_value, max_value min/max bounds for color calcuations. values outside bounds are limited to these values. defaults: min=0, max=1
264
/// @param reverse if true, color ramps are inversed (to: min_value = white (black and white mode) or red (color mode). default = false.
265
/// @return a QImage with the Grids size of pixels. Pixel coordinates relate to the index values of the grid.
266
QImage gridToImage(const FloatGrid &grid,
267
                   bool black_white=false,
268
                   double min_value=0., double max_value=1.,
269
                   bool reverse=false);
270
 
46 Werner 271
/// template version for non-float grids (see also version for FloatGrid)
36 Werner 272
template <class T>
46 Werner 273
        QString gridToString(const Grid<T> &grid)
36 Werner 274
{
275
    QString res;
276
    QTextStream ts(&res);
277
 
46 Werner 278
    for (int y=0;y<grid.sizeY();y++){
279
        for (int x=0;x<grid.sizeX();x++){
36 Werner 280
            ts << grid.constValueAtIndex(x,y) << ";";
281
        }
282
        ts << "\r\n";
283
    }
284
 
285
    return res;
286
}
46 Werner 287
 
15 Werner 288
#endif // GRID_H