Subversion Repositories public iLand

Rev

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