Subversion Repositories public iLand

Rev

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

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