Subversion Repositories public iLand

Rev

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