Subversion Repositories public iLand

Rev

Rev 643 | Rev 650 | 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
 
373 werner 12
#include "global.h"
13
 
247 werner 14
/** Grid class (template).
15 Werner 15
 
74 Werner 16
Orientation
490 werner 17
The grid is oriented as typically coordinates on the northern hemisphere: higher y-values -> north, higher x-values-> west.
18
The projection is reversed for drawing on screen (Viewport).
74 Werner 19
          N
490 werner 20
  (0/2) (1/2) (2/2)
21
E (0/1) (1/1) (2/1)  W
74 Werner 22
  (0/0) (1/0) (2/0)
23
          S
24
*/
15 Werner 25
template <class T>
26
class Grid {
27
public:
28
 
29
    Grid();
30
    Grid(int cellsize, int sizex, int sizey) { mData=0; setup(cellsize, sizex, sizey); }
58 Werner 31
    Grid(const QRectF rect_metric, const float cellsize) { mData=0; setup(rect_metric,cellsize); }
33 Werner 32
    // copy ctor
33
    Grid(const Grid<T>& toCopy);
105 Werner 34
    ~Grid() { clear(); }
35
    void clear() { if (mData) delete[] mData; mData=0; }
15 Werner 36
 
18 Werner 37
    bool setup(const float cellsize, const int sizex, const int sizey);
22 Werner 38
    bool setup(const QRectF& rect, const double cellsize);
453 werner 39
    bool setup(Grid<T>& source) {     mData = 0;  mRect = source.mRect; return setup(source.cellsize(), source.sizeX(), source.sizeY()); }
75 Werner 40
    void initialize(const T& value) {for( T *p = begin();p!=end(); ++p) *p=value; }
150 iland 41
    void wipe(); ///< write 0-bytes with memcpy to the whole area
154 werner 42
    void wipe(const T value); ///< overwrite the whole area with "value" size of T must be the size of "int" ERRORNOUS!!!
15 Werner 43
 
145 Werner 44
    int sizeX() const { return mSizeX; }
45
    int sizeY() const { return mSizeY; }
46
    float metricSizeX() const { return mSizeX*mCellsize; }
47
    float metricSizeY() const { return mSizeY*mCellsize; }
49 Werner 48
    QRectF metricRect() const { return mRect; }
145 Werner 49
    float cellsize() const { return mCellsize; }
373 werner 50
    int count() const { return mCount; } ///< returns the number of elements of the grid
51
    bool isEmpty() const { return mData==NULL; } ///< returns false if the grid was not setup
32 Werner 52
    // operations
15 Werner 53
    // query
33 Werner 54
    /// access (const) with index variables. use int.
55
    inline const T& operator()(const int ix, const int iy) const { return constValueAtIndex(ix, iy); }
56
    /// access (const) using metric variables. use float.
57
    inline const T& operator()(const float x, const float y) const { return constValueAt(x, y); }
48 Werner 58
    inline const T& operator[] (const QPointF &p) const { return constValueAt(p); }
33 Werner 59
 
77 Werner 60
    inline T& valueAtIndex(const QPoint& pos); ///< value at position defined by indices (x,y)
33 Werner 61
    T& valueAtIndex(const int ix, const int iy) { return valueAtIndex(QPoint(ix,iy)); } ///< const value at position defined by indices (x,y)
285 werner 62
    T& valueAtIndex(const int index) {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
33 Werner 63
 
64
    const T& constValueAtIndex(const QPoint& pos) const; ///< value at position defined by a (integer) QPoint
32 Werner 65
    const T& constValueAtIndex(const int ix, const int iy) const { return constValueAtIndex(QPoint(ix,iy)); }
549 werner 66
    const T& constValueAtIndex(const int index) const {return mData[index]; } ///< get a ref ot value at (one-dimensional) index 'index'.
33 Werner 67
 
68
    T& valueAt(const QPointF& posf); ///< value at position defined by metric coordinates (QPointF)
69
    const T& constValueAt(const QPointF& posf) const; ///< value at position defined by metric coordinates (QPointF)
70
 
71
    T& valueAt(const float x, const float y); ///< value at position defined by metric coordinates (x,y)
72
    const T& constValueAt(const float x, const float y) const; ///< value at position defined by metric coordinates (x,y)
73
 
105 Werner 74
    bool coordValid(const float x, const float y) const { return x>=mRect.left() && x<mRect.right()  && y>=mRect.top() && y<mRect.bottom(); }
49 Werner 75
    bool coordValid(const QPointF &pos) const { return coordValid(pos.x(), pos.y()); }
75 Werner 76
 
55 Werner 77
    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 78
    /// get index (x/y) of the (linear) index 'index' (0..count-1)
79
    QPoint indexOf(const int index) const {return QPoint(index % mSizeX,  index / mSizeX); }
373 werner 80
    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
81
    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
75 Werner 82
    /// force @param pos to contain valid indices with respect to this grid.
55 Werner 83
    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 84
    /// get the (metric) centerpoint of cell with index @p pos
549 werner 85
    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
105 Werner 86
    /// get the metric rectangle of the cell with index @pos
439 werner 87
    QRectF cellRect(const QPoint &pos) const { QRectF r( QPointF(mRect.left() + mCellsize*pos.x(), mRect.top() + pos.y()*mCellsize),
55 Werner 88
                                                   QSizeF(mCellsize, mCellsize)); return r; } ///< return coordinates of rect given by @param pos.
105 Werner 89
 
27 Werner 90
    inline  T* begin() const { return mData; } ///< get "iterator" pointer
37 Werner 91
    inline  T* end() const { return mEnd; } ///< get iterator end-pointer
487 werner 92
    inline QPoint indexOf(T* element) const; ///< retrieve index (x/y) of the pointer element. returns -1/-1 if element is not valid.
27 Werner 93
    // special queries
33 Werner 94
    T max() const; ///< retrieve the maximum value of a grid
95
    T sum() const; ///< retrieve the sum of the grid
96
    T avg() const; ///< retrieve the average value of a grid
391 werner 97
    // modifying operations
98
    void add(const T& summand);
99
    void multiply(const T& factor);
33 Werner 100
    /// creates a grid with lower resolution and averaged cell values.
101
    /// @param factor factor by which grid size is reduced (e.g. 3 -> 3x3=9 pixels are averaged to 1 result pixel)
102
    /// @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)
103
    /// @return Grid with size sizeX()/factor x sizeY()/factor
104
    Grid<T> averaged(const int factor, const int offsetx=0, const int offsety=0) const;
105
    /// normalized returns a normalized grid, in a way that the sum()  = @param targetvalue.
106
    /// if the grid is empty or the sum is 0, no modifications are performed.
107
    Grid<T> normalized(const T targetvalue) const;
373 werner 108
    T* ptr(int x, int y) { return &(mData[y*mSizeX + x]); } ///< get a pointer to the element denoted by "x" and "y"
109
    inline double distance(const QPoint &p1, const QPoint &p2); ///< distance (metric) between p1 and p2
110
    const QPoint randomPosition() const; ///< returns a (valid) random position within the grid
15 Werner 111
private:
77 Werner 112
 
15 Werner 113
    T* mData;
37 Werner 114
    T* mEnd; ///< pointer to 1 element behind the last
49 Werner 115
    QRectF mRect;
36 Werner 116
    float mCellsize; ///< size of a cell in meter
117
    int mSizeX; ///< count of cells in x-direction
118
    int mSizeY; ///< count of cells in y-direction
119
    int mCount; ///< total number of cells in the grid
15 Werner 120
};
121
 
122
typedef Grid<float> FloatGrid;
123
 
643 werner 124
enum GridViewType { GridViewRainbow, GridViewRainbowReverse, GridViewGray, GridViewGrayReverse };
125
 
438 werner 126
/** @class GridRunner is a helper class to iterate over a rectangular fraction of a grid
127
*/
128
template <class T>
129
class GridRunner {
130
public:
617 werner 131
    GridRunner(Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
132
    GridRunner(const Grid<T> &target_grid, const QRectF &rectangle) {setup(&target_grid, rectangle);}
133
    GridRunner(Grid<T> *target_grid, const QRectF &rectangle) {setup(target_grid, rectangle);}
438 werner 134
    T* next(); ///< to to next element, return NULL if finished
574 werner 135
    T* current() { return mCurrent; }
438 werner 136
private:
617 werner 137
    void setup(const Grid<T> *target_grid, const QRectF &rectangle);
438 werner 138
    T* mLast;
139
    T* mCurrent;
140
    size_t mLineLength;
141
    size_t mCols;
142
    size_t mCurrentCol;
143
};
144
 
646 werner 145
/** @class Vector3D is a simple 3d vector.
146
  QVector3D (from Qt) is in QtGui so we needed a replacement.
147
*/
148
class Vector3D
149
{
150
 public:
151
    Vector3D(): mX(0.), mY(0.), mZ(0.) {}
152
    Vector3D(const double x, const double y, const double z): mX(x), mY(y), mZ(z) {}
153
    double x() const { return mX; } ///< get x-coordinate
154
    double y() const { return mY; } ///< get y-coordinate
155
    double z() const { return mZ; } ///< get z-coordinate
156
    // set variables
157
    void setX(const double x) { mX=x; } ///< set value of the x-coordinate
158
    void setY(const double y) { mY=y; } ///< set value of the y-coordinate
159
    void setZ(const double z) { mZ=z; } ///< set value of the z-coordinate
160
private:
161
    double mX;
162
    double mY;
163
    double mZ;
164
};
438 werner 165
 
33 Werner 166
// copy constructor
167
template <class T>
168
Grid<T>::Grid(const Grid<T>& toCopy)
169
{
40 Werner 170
    mData = 0;
50 Werner 171
    mRect = toCopy.mRect;
33 Werner 172
    setup(toCopy.cellsize(), toCopy.sizeX(), toCopy.sizeY());
173
    const T* end = toCopy.end();
174
    T* ptr = begin();
175
    for (T* i= toCopy.begin(); i!=end; ++i, ++ptr)
176
       *ptr = *i;
177
}
22 Werner 178
 
33 Werner 179
// normalize function
32 Werner 180
template <class T>
33 Werner 181
Grid<T> Grid<T>::normalized(const T targetvalue) const
32 Werner 182
{
33 Werner 183
    Grid<T> target(*this);
184
    T total = sum();
185
    T multiplier;
186
    if (total)
187
        multiplier = targetvalue / total;
188
    else
189
        return target;
190
    for (T* p=target.begin();p!=target.end();++p)
191
        *p *= multiplier;
40 Werner 192
    return target;
33 Werner 193
}
194
 
195
 
196
template <class T>
197
Grid<T> Grid<T>::averaged(const int factor, const int offsetx, const int offsety) const
198
{
32 Werner 199
    Grid<T> target;
200
    target.setup(cellsize()*factor, sizeX()/factor, sizeY()/factor);
201
    int x,y;
202
    T sum=0;
203
    target.initialize(sum);
204
    // sum over array of 2x2, 3x3, 4x4, ...
205
    for (x=offsetx;x<mSizeX;x++)
206
        for (y=offsety;y<mSizeY;y++) {
207
            target.valueAtIndex((x-offsetx)/factor, (y-offsety)/factor) += constValueAtIndex(x,y);
208
        }
209
    // divide
210
    double fsquare = factor*factor;
211
    for (T* p=target.begin();p!=target.end();++p)
212
        *p /= fsquare;
213
    return target;
214
}
22 Werner 215
 
15 Werner 216
template <class T>
22 Werner 217
T&  Grid<T>::valueAtIndex(const QPoint& pos)
218
{
75 Werner 219
    //if (isIndexValid(pos)) {
77 Werner 220
        return mData[pos.y()*mSizeX + pos.x()];
75 Werner 221
    //}
222
    //qCritical("Grid::valueAtIndex. invalid: %d/%d", pos.x(), pos.y());
223
    //return mData[0];
22 Werner 224
}
36 Werner 225
 
27 Werner 226
template <class T>
227
const T&  Grid<T>::constValueAtIndex(const QPoint& pos) const
228
{
75 Werner 229
    //if (isIndexValid(pos)) {
77 Werner 230
        return mData[pos.y()*mSizeX + pos.x()];
75 Werner 231
    //}
232
    //qCritical("Grid::constValueAtIndex. invalid: %d/%d", pos.x(), pos.y());
233
    //return mData[0];
27 Werner 234
}
22 Werner 235
 
236
template <class T>
33 Werner 237
T&  Grid<T>::valueAt(const float x, const float y)
238
{
239
    return valueAtIndex( indexAt(QPointF(x,y)) );
240
}
36 Werner 241
 
33 Werner 242
template <class T>
243
const T&  Grid<T>::constValueAt(const float x, const float y) const
244
{
245
    return constValueAtIndex( indexAt(QPointF(x,y)) );
246
}
36 Werner 247
 
33 Werner 248
template <class T>
22 Werner 249
T&  Grid<T>::valueAt(const QPointF& posf)
250
{
251
    return valueAtIndex( indexAt(posf) );
252
}
36 Werner 253
 
33 Werner 254
template <class T>
255
const T&  Grid<T>::constValueAt(const QPointF& posf) const
256
{
257
    return constValueAtIndex( indexAt(posf) );
258
}
22 Werner 259
 
260
template <class T>
15 Werner 261
Grid<T>::Grid()
262
{
37 Werner 263
    mData = 0; mCellsize=0.f;
264
    mEnd = 0;
15 Werner 265
}
266
 
267
template <class T>
18 Werner 268
bool Grid<T>::setup(const float cellsize, const int sizex, const int sizey)
15 Werner 269
{
37 Werner 270
    mSizeX=sizex; mSizeY=sizey; mCellsize=cellsize;
50 Werner 271
    if (mRect.isNull()) // only set rect if not set before
272
        mRect.setCoords(0., 0., cellsize*sizex, cellsize*sizey);
15 Werner 273
    mCount = mSizeX*mSizeY;
37 Werner 274
    if (mData) {
275
         delete[] mData; mData=NULL;
276
     }
15 Werner 277
   if (mCount>0)
37 Werner 278
        mData = new T[mCount];
279
   mEnd = &(mData[mCount]);
15 Werner 280
   return true;
281
}
282
 
283
template <class T>
22 Werner 284
bool Grid<T>::setup(const QRectF& rect, const double cellsize)
15 Werner 285
{
49 Werner 286
    mRect = rect;
22 Werner 287
    int dx = int(rect.width()/cellsize);
49 Werner 288
    if (mRect.left()+cellsize*dx<rect.right())
22 Werner 289
        dx++;
290
    int dy = int(rect.height()/cellsize);
49 Werner 291
    if (mRect.top()+cellsize*dy<rect.bottom())
22 Werner 292
        dy++;
293
    return setup(cellsize, dx, dy);
15 Werner 294
}
295
 
261 werner 296
/** retrieve from the index from an element reversely from a pointer to that element.
297
    The internal memory layout is (for dimx=6, dimy=3):
298
 
299
6  7  8  9  10 11
300
12 13 14 15 16 17
301
Note: north and south are reversed, thus the item with index 0 is located in the south-western edge of the grid! */
487 werner 302
template <class T> inline
27 Werner 303
QPoint Grid<T>::indexOf(T* element) const
25 Werner 304
{
487 werner 305
//    QPoint result(-1,-1);
25 Werner 306
    if (element==NULL || element<mData || element>=end())
487 werner 307
        return QPoint(-1, -1);
25 Werner 308
    int idx = element - mData;
487 werner 309
    return QPoint(idx % mSizeX,  idx / mSizeX);
310
//    result.setX( idx % mSizeX);
311
//    result.setY( idx / mSizeX);
312
//    return result;
25 Werner 313
}
22 Werner 314
 
27 Werner 315
template <class T>
316
T  Grid<T>::max() const
317
{
143 Werner 318
    T maxv = -std::numeric_limits<T>::max();
27 Werner 319
    T* p;
320
    T* pend = end();
321
    for (p=begin(); p!=pend;++p)
322
       maxv = std::max(maxv, *p);
323
    return maxv;
324
}
325
 
33 Werner 326
template <class T>
327
T  Grid<T>::sum() const
328
{
329
    T* pend = end();
330
    T total = 0;
331
    for (T *p=begin(); p!=pend;++p)
332
       total += *p;
333
    return total;
334
}
335
 
336
template <class T>
337
T  Grid<T>::avg() const
338
{
339
    if (count())
340
        return sum() / T(count());
341
    else return 0;
342
}
343
 
150 iland 344
template <class T>
391 werner 345
void Grid<T>::add(const T& summand)
346
{
347
    T* pend = end();
348
    for (T *p=begin(); p!=pend;*p+=summand,++p)
349
       ;
350
}
351
 
352
template <class T>
353
void Grid<T>::multiply(const T& factor)
354
{
355
    T* pend = end();
356
    for (T *p=begin(); p!=pend;*p*=factor,++p)
357
       ;
358
}
359
 
360
 
361
 
362
template <class T>
150 iland 363
void  Grid<T>::wipe()
364
{
365
    memset(mData, 0, mCount*sizeof(T));
366
}
367
template <class T>
368
void  Grid<T>::wipe(const T value)
369
{
154 werner 370
    /* this does not work properly !!! */
153 werner 371
    if (sizeof(T)==sizeof(int)) {
372
        float temp = value;
373
        float *pf = &temp;
374
 
375
        memset(mData, *((int*)pf), mCount*sizeof(T));
376
    } else
150 iland 377
        initialize(value);
378
}
379
 
373 werner 380
template <class T>
381
double Grid<T>::distance(const QPoint &p1, const QPoint &p2)
382
{
383
    QPointF fp1=cellCenterPoint(p1);
384
    QPointF fp2=cellCenterPoint(p2);
385
    double distance = sqrt( (fp1.x()-fp2.x())*(fp1.x()-fp2.x()) + (fp1.y()-fp2.y())*(fp1.y()-fp2.y()));
386
    return distance;
387
}
388
 
389
template <class T>
390
const QPoint Grid<T>::randomPosition() const
391
{
392
    return QPoint(irandom(0,mSizeX-1), irandom(0, mSizeY-1));
393
}
438 werner 394
 
373 werner 395
////////////////////////////////////////////////////////////
438 werner 396
// grid runner
397
////////////////////////////////////////////////////////////
398
template <class T>
617 werner 399
void GridRunner<T>::setup(const Grid<T> *target_grid, const QRectF &rectangle)
438 werner 400
{
617 werner 401
    QPoint upper_left = target_grid->indexAt(rectangle.topLeft());
402
    QPoint lower_right = target_grid->indexAt(rectangle.bottomRight());
403
    mCurrent = const_cast<Grid<T> *>(target_grid)->ptr(upper_left.x(), upper_left.y());
585 werner 404
    mCurrent--; // point to first element -1
617 werner 405
    mLast = const_cast<Grid<T> *>(target_grid)->ptr(lower_right.x()-1, lower_right.y()-1);
438 werner 406
    mCols = lower_right.x() - upper_left.x(); //
617 werner 407
    mLineLength =  target_grid->sizeX() - mCols;
585 werner 408
    mCurrentCol = -1;
409
//    qDebug() << "GridRunner: rectangle:" << rectangle
410
//             << "upper_left:" << target_grid.cellCenterPoint(target_grid.indexOf(mCurrent))
411
//             << "lower_right:" << target_grid.cellCenterPoint(target_grid.indexOf(mLast));
438 werner 412
}
413
 
414
template <class T>
415
T* GridRunner<T>::next()
416
{
417
    if (mCurrent>mLast)
418
        return NULL;
419
    mCurrent++;
420
    mCurrentCol++;
585 werner 421
 
438 werner 422
    if (mCurrentCol >= mCols) {
423
        mCurrent += mLineLength; // skip to next line
424
        mCurrentCol = 0;
425
    }
585 werner 426
    if (mCurrent>mLast)
427
        return NULL;
428
    else
429
        return mCurrent;
438 werner 430
}
431
 
432
////////////////////////////////////////////////////////////
36 Werner 433
// global functions
373 werner 434
////////////////////////////////////////////////////////////
36 Werner 435
 
436
/// dumps a FloatGrid to a String.
46 Werner 437
/// rows will be y-lines, columns x-values. (see grid.cpp)
599 werner 438
QString gridToString(const FloatGrid &grid, const QChar sep=QChar(';'), const int newline_after=-1);
36 Werner 439
 
440
/// creates and return a QImage from Grid-Data.
441
/// @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)
442
/// @param min_value, max_value min/max bounds for color calcuations. values outside bounds are limited to these values. defaults: min=0, max=1
443
/// @param reverse if true, color ramps are inversed (to: min_value = white (black and white mode) or red (color mode). default = false.
444
/// @return a QImage with the Grids size of pixels. Pixel coordinates relate to the index values of the grid.
445
QImage gridToImage(const FloatGrid &grid,
446
                   bool black_white=false,
447
                   double min_value=0., double max_value=1.,
448
                   bool reverse=false);
449
 
556 werner 450
 
285 werner 451
/** load into 'rGrid' the content of the image pointed at by 'fileName'.
452
    Pixels are converted to grey-scale and then transformend to a value ranging from 0..1 (black..white).
453
  */
454
bool loadGridFromImage(const QString &fileName, FloatGrid &rGrid);
455
 
46 Werner 456
/// template version for non-float grids (see also version for FloatGrid)
599 werner 457
/// @param sep string separator
458
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
36 Werner 459
template <class T>
599 werner 460
        QString gridToString(const Grid<T> &grid, const QChar sep=QChar(';'), const int newline_after=-1)
36 Werner 461
{
462
    QString res;
463
    QTextStream ts(&res);
464
 
599 werner 465
    int newl_counter = newline_after;
46 Werner 466
    for (int y=0;y<grid.sizeY();y++){
467
        for (int x=0;x<grid.sizeX();x++){
599 werner 468
            ts << grid.constValueAtIndex(x,y) << sep;
469
            if (--newl_counter==0) {
470
                ts << "\r\n";
471
                newl_counter = newline_after;
472
            }
36 Werner 473
        }
474
        ts << "\r\n";
475
    }
476
 
477
    return res;
478
}
46 Werner 479
 
599 werner 480
/// template version for non-float grids (see also version for FloatGrid)
481
/// @param valueFunction pointer to a function with the signature: QString func(const T&) : this should return a QString
482
/// @param sep string separator
483
/// @param newline_after if <>-1 a newline is added after every 'newline_after' data values
484
template <class T>
485
        QString gridToString(const Grid<T> &grid, QString (*valueFunction)(const T& value), const QChar sep=QChar(';'), const int newline_after=-1 )
486
{
487
    QString res;
488
    QTextStream ts(&res);
489
 
490
    int newl_counter = newline_after;
491
    for (int y=0;y<grid.sizeY();y++){
492
        for (int x=0;x<grid.sizeX();x++){
493
            ts << (*valueFunction)(grid.constValueAtIndex(x,y)) << sep;
494
 
495
            if (--newl_counter==0) {
496
                ts << "\r\n";
497
                newl_counter = newline_after;
498
            }
499
        }
500
        ts << "\r\n";
501
    }
502
 
503
    return res;
504
}
646 werner 505
void modelToWorld(const Vector3D &From, Vector3D &To);
599 werner 506
 
507
template <class T>
508
    QString gridToESRIRaster(const Grid<T> &grid, QString (*valueFunction)(const T& value) )
509
{
646 werner 510
        Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
511
        Vector3D world;
599 werner 512
        modelToWorld(model, world);
607 werner 513
        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 514
                                .arg(grid.sizeX())
515
                                .arg(grid.sizeY())
600 werner 516
                                .arg(world.x(),0,'f').arg(world.y(),0,'f')
599 werner 517
                                .arg(grid.cellsize()).arg(-9999);
600 werner 518
        QString line =  gridToString(grid, valueFunction, QChar(' '), grid.sizeX()); // for special grids
519
        QStringList lines = line.split("\r\n");
520
        for (int i=lines.count()-1; i>=0; --i)
521
            result+=lines[i];
599 werner 522
        return result;
523
 
524
}
525
    template <class T>
526
        QString gridToESRIRaster(const Grid<T> &grid )
527
{
646 werner 528
            Vector3D model(grid.metricRect().left(), grid.metricRect().top(), 0.);
529
            Vector3D world;
599 werner 530
            modelToWorld(model, world);
531
            QString result = QString("ncols %1\r\nnrows %2\r\nxllcorner %3\r\n yllcorner %4\r\ncellsize %5\r\nNODATA_value %6\r\n")
532
                    .arg(grid.sizeX())
533
                    .arg(grid.sizeY())
534
                    .arg(world.x()).arg(world.y())
535
                    .arg(grid.cellsize()).arg(-9999);
600 werner 536
            QString line = gridToString(grid, QChar(' '), grid.sizeX()); // for normal grids (e.g. float)
537
            QStringList lines = line.split("\r\n");
538
            for (int i=lines.count()-1; i>=0; --i)
539
                result+=lines[i];
599 werner 540
            return result;
541
 
542
}
543
 
15 Werner 544
#endif // GRID_H