Subversion Repositories public iLand

Rev

Rev 406 | Rev 410 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 406 Rev 407
Line 41... Line 41...
41
    mOpacity=mFoliageMass=mWoodyMass=mCoarseRootMass=mFineRootMass=mLeafArea=0.;
41
    mOpacity=mFoliageMass=mWoodyMass=mCoarseRootMass=mFineRootMass=mLeafArea=0.;
42
    mDbhDelta=mNPPReserve=mLRI=mStressIndex=0.;
42
    mDbhDelta=mNPPReserve=mLRI=mStressIndex=0.;
43
    mLightResponse = 0.;
43
    mLightResponse = 0.;
44
    mId = m_nextId++;
44
    mId = m_nextId++;
45
    m_statCreated++;
45
    m_statCreated++;
-
 
46
}
-
 
47
-
 
48
float Tree::crownRadius() const
-
 
49
{
-
 
50
    Q_ASSERT(mStamp!=0);
-
 
51
    return mStamp->crownRadius();
46
}
52
}
47
53
48
void Tree::setGrid(FloatGrid* gridToStamp, Grid<HeightGridValue> *dominanceGrid)
54
void Tree::setGrid(FloatGrid* gridToStamp, Grid<HeightGridValue> *dominanceGrid)
49
{
55
{
50
    mGrid = gridToStamp; mHeightGrid = dominanceGrid;
56
    mGrid = gridToStamp; mHeightGrid = dominanceGrid;
Line 120... Line 126...
120
    float value, z, z_zstar;
126
    float value, z, z_zstar;
121
    int gr_stamp = mStamp->size();
127
    int gr_stamp = mStamp->size();
122
    int grid_x, grid_y;
128
    int grid_x, grid_y;
123
    float *grid_value_ptr;
129
    float *grid_value_ptr;
124
    if (!mGrid->isIndexValid(pos) || !mGrid->isIndexValid(pos+QPoint(gr_stamp, gr_stamp))) {
130
    if (!mGrid->isIndexValid(pos) || !mGrid->isIndexValid(pos+QPoint(gr_stamp, gr_stamp))) {
125
        // todo: in this case we should use another algorithm!!!
-
 
-
 
131
        // this should not happen because of the buffer
126
        return;
132
        return;
127
    }
133
    }
128
    grid_y = pos.y();
134
    grid_y = pos.y();
129
    for (y=0;y<gr_stamp; ++y) {
135
    for (y=0;y<gr_stamp; ++y) {
130
136
Line 184... Line 190...
184
    float *grid_value;
190
    float *grid_value;
185
    if (!mGrid->isIndexValid(pos) || !mGrid->isIndexValid(pos+QPoint(gr_stamp, gr_stamp))) {
191
    if (!mGrid->isIndexValid(pos) || !mGrid->isIndexValid(pos+QPoint(gr_stamp, gr_stamp))) {
186
        // todo: in this case we should use another algorithm!!! necessary????
192
        // todo: in this case we should use another algorithm!!! necessary????
187
        return;
193
        return;
188
    }
194
    }
189
-
 
-
 
195
    float z, z_zstar;
190
    int xt, yt; // wraparound coordinates
196
    int xt, yt; // wraparound coordinates
191
    for (y=0;y<gr_stamp; ++y) {
197
    for (y=0;y<gr_stamp; ++y) {
192
        grid_y = pos.y() + y;
198
        grid_y = pos.y() + y;
193
        yt = torusIndex(grid_y, cPxPerRU,bufferOffset, ru_offset.y()); // 50 cells per 100m
199
        yt = torusIndex(grid_y, cPxPerRU,bufferOffset, ru_offset.y()); // 50 cells per 100m
194
        for (x=0;x<gr_stamp;++x) {
200
        for (x=0;x<gr_stamp;++x) {
195
            // suppose there is no stamping outside
201
            // suppose there is no stamping outside
196
            grid_x = pos.x() + x;
202
            grid_x = pos.x() + x;
197
            xt = torusIndex(grid_x,cPxPerRU,bufferOffset, ru_offset.x());
203
            xt = torusIndex(grid_x,cPxPerRU,bufferOffset, ru_offset.x());
198
204
199
            local_dom = mHeightGrid->valueAtIndex(xt/cPxPerHeight,yt/cPxPerHeight).height;
205
            local_dom = mHeightGrid->valueAtIndex(xt/cPxPerHeight,yt/cPxPerHeight).height;
-
 
206
-
 
207
            z = std::max(mHeight - (*mStamp).distanceToCenter(x,y), 0.f); // distance to center = height (45° line)
-
 
208
            z_zstar = (z>=local_dom)?1.f:z/local_dom;
200
            value = (*mStamp)(x,y); // stampvalue
209
            value = (*mStamp)(x,y); // stampvalue
201
            value = 1. - value*mOpacity / local_dom; // calculated value
-
 
-
 
210
            value = 1. - value*mOpacity * z_zstar; // calculated value
-
 
211
            // old: value = 1. - value*mOpacity / local_dom; // calculated value
202
            value = qMax(value, 0.02f); // limit value
212
            value = qMax(value, 0.02f); // limit value
203
213
204
            grid_value = mGrid->ptr(xt, yt); // use wraparound coordinates
214
            grid_value = mGrid->ptr(xt, yt); // use wraparound coordinates
205
            *grid_value *= value;
215
            *grid_value *= value;
206
        }
216
        }
Line 271... Line 281...
271
//        for (iy=-ringcount; iy<=+ringcount; iy++) {
281
//        for (iy=-ringcount; iy<=+ringcount; iy++) {
272
//        ring = qMax(abs(ix), abs(iy));
282
//        ring = qMax(abs(ix), abs(iy));
273
//        QPoint pos(ix+p.x(), iy+p.y());
283
//        QPoint pos(ix+p.x(), iy+p.y());
274
//        if (mHeightGrid->isIndexValid(pos)) {
284
//        if (mHeightGrid->isIndexValid(pos)) {
275
//            float &rHGrid = mHeightGrid->valueAtIndex(pos).height;
285
//            float &rHGrid = mHeightGrid->valueAtIndex(pos).height;
-
 
286
//            if (rHGrid > mHeight) // skip calculation if grid is higher than tree
-
 
287
//                continue;
-
 
288
//            int direction = 4 + (ix?(ix<0?-3:3):0) + (iy?(iy<0?-1:1):0); // 4 + 3*sgn(x) + sgn(y)
-
 
289
//            hdom = mHeight - dist[direction];
-
 
290
//            if (ring>1)
-
 
291
//                hdom -= (ring-1)*10;
-
 
292
//
-
 
293
//            rHGrid = qMax(rHGrid, hdom); // write value
-
 
294
//        } // is valid
-
 
295
//    } // for (y)
-
 
296
}
-
 
297
-
 
298
void Tree::heightGrid_torus()
-
 
299
{
-
 
300
    // height of Z*
-
 
301
-
 
302
    QPoint p = QPoint(mPositionIndex.x()/cPxPerHeight, mPositionIndex.y()/cPxPerHeight); // pos of tree on height grid
-
 
303
    int bufferOffset = mHeightGrid->indexAt(QPointF(0.,0.)).x(); // offset of buffer (i.e.: size of buffer in height-pixels)
-
 
304
    p.setX((p.x()-bufferOffset)%10 + bufferOffset); // 10: 10 x 10m pixeln in 100m
-
 
305
    p.setY((p.y()-bufferOffset)%10 + bufferOffset);
-
 
306
-
 
307
-
 
308
    // torus coordinates: ru_offset = coords of lower left corner of 1ha patch
-
 
309
    QPoint ru_offset =QPoint(mPositionIndex.x()/cPxPerHeight - p.x(), mPositionIndex.y()/cPxPerHeight - p.y());
-
 
310
-
 
311
    // count trees that are on height-grid cells (used for stockable area)
-
 
312
    HeightGridValue &v = mHeightGrid->valueAtIndex(torusIndex(p.x(),10,bufferOffset,ru_offset.x()),
-
 
313
                                                   torusIndex(p.y(),10,bufferOffset,ru_offset.y()));
-
 
314
    v.increaseCount();
-
 
315
    v.height = qMax(v.height, mHeight);
-
 
316
-
 
317
-
 
318
    int r = mStamp->reader()->offset(); // distance between edge and the center pixel. e.g.: if r = 2 -> stamp=5x5
-
 
319
    int index_eastwest = mPositionIndex.x() % cPxPerHeight; // 4: very west, 0 east edge
-
 
320
    int index_northsouth = mPositionIndex.y() % cPxPerHeight; // 4: northern edge, 0: southern edge
-
 
321
    if (index_eastwest - r < 0) { // east
-
 
322
        HeightGridValue &v = mHeightGrid->valueAtIndex(torusIndex(p.x()-1,10,bufferOffset,ru_offset.x()),
-
 
323
                                                       torusIndex(p.y(),10,bufferOffset,ru_offset.y()));
-
 
324
        v.height = qMax(v.height, mHeight-5);
-
 
325
    }
-
 
326
    if (index_eastwest + r >= cPxPerHeight) {  // west
-
 
327
        HeightGridValue &v = mHeightGrid->valueAtIndex(torusIndex(p.x()+1,10,bufferOffset,ru_offset.x()),
-
 
328
                                                       torusIndex(p.y(),10,bufferOffset,ru_offset.y()));
-
 
329
        v.height = qMax(v.height, mHeight-5);
-
 
330
    }
-
 
331
    if (index_northsouth - r < 0) {  // south
-
 
332
        HeightGridValue &v = mHeightGrid->valueAtIndex(torusIndex(p.x(),10,bufferOffset,ru_offset.x()),
-
 
333
                                                       torusIndex(p.y()-1,10,bufferOffset,ru_offset.y()));
-
 
334
        v.height = qMax(v.height, mHeight-5);
-
 
335
    }
-
 
336
    if (index_northsouth + r >= cPxPerHeight) {  // north
-
 
337
        HeightGridValue &v = mHeightGrid->valueAtIndex(torusIndex(p.x(),10,bufferOffset,ru_offset.x()),
-
 
338
                                                       torusIndex(p.y()+1,10,bufferOffset,ru_offset.y()));
-
 
339
        v.height = qMax(v.height, mHeight-5);
-
 
340
    }
-
 
341
-
 
342
-
 
343
-
 
344
-
 
345
//    int index_eastwest = mPositionIndex.x() % cPxPerHeight; // 4: very west, 0 east edge
-
 
346
//    int index_northsouth = mPositionIndex.y() % cPxPerHeight; // 4: northern edge, 0: southern edge
-
 
347
//    int dist[9];
-
 
348
//    dist[3] = index_northsouth * 2 + 1; // south
-
 
349
//    dist[1] = index_eastwest * 2 + 1; // west
-
 
350
//    dist[5] = 10 - dist[3]; // north
-
 
351
//    dist[7] = 10 - dist[1]; // east
-
 
352
//    dist[8] = qMax(dist[5], dist[7]); // north-east
-
 
353
//    dist[6] = qMax(dist[3], dist[7]); // south-east
-
 
354
//    dist[0] = qMax(dist[3], dist[1]); // south-west
-
 
355
//    dist[2] = qMax(dist[5], dist[1]); // north-west
-
 
356
//    dist[4] = 0; // center cell
-
 
357
//    /* the scheme of indices is as follows:  if sign(ix)= -1, if ix<0, 0 for ix=0, 1 for ix>0 (detto iy), then:
-
 
358
//       index = 4 + 3*sign(ix) + sign(iy) transforms combinations of directions to unique ids (0..8), which are used above.
-
 
359
//        e.g.: sign(ix) = -1, sign(iy) = 1 (=north-west) -> index = 4 + -3 + 1 = 2
-
 
360
//    */
-
 
361
//
-
 
362
//
-
 
363
//    int ringcount = int(floor(mHeight / cellsize)) + 1;
-
 
364
//    int ix, iy;
-
 
365
//    int ring;
-
 
366
//    float hdom;
-
 
367
//    for (ix=-ringcount;ix<=ringcount;ix++)
-
 
368
//        for (iy=-ringcount; iy<=+ringcount; iy++) {
-
 
369
//        ring = qMax(abs(ix), abs(iy));
-
 
370
//        QPoint pos(ix+p.x(), iy+p.y());
-
 
371
//        QPoint p_torus(torusIndex(pos.x(),10,bufferOffset,ru_offset.x()),
-
 
372
//                       torusIndex(pos.y(),10,bufferOffset,ru_offset.y()));
-
 
373
//        if (mHeightGrid->isIndexValid(p_torus)) {
-
 
374
//            float &rHGrid = mHeightGrid->valueAtIndex(p_torus.x(),p_torus.y()).height;
276
//            if (rHGrid > mHeight) // skip calculation if grid is higher than tree
375
//            if (rHGrid > mHeight) // skip calculation if grid is higher than tree
277
//                continue;
376
//                continue;
278
//            int direction = 4 + (ix?(ix<0?-3:3):0) + (iy?(iy<0?-1:1):0); // 4 + 3*sgn(x) + sgn(y)
377
//            int direction = 4 + (ix?(ix<0?-3:3):0) + (iy?(iy<0?-1:1):0); // 4 + 3*sgn(x) + sgn(y)
279
//            hdom = mHeight - dist[direction];
378
//            hdom = mHeight - dist[direction];
280
//            if (ring>1)
379
//            if (ring>1)
Line 348... Line 447...
348
    mRU->addWLA(mLeafArea, mLRI);
447
    mRU->addWLA(mLeafArea, mLRI);
349
448
350
449
351
    //qDebug() << "Tree #"<< id() << "value" << sum << "Impact" << mImpact;
450
    //qDebug() << "Tree #"<< id() << "value" << sum << "Impact" << mImpact;
352
    //mRU->addWLA(mLRI*mLeafArea, mLeafArea);
451
    //mRU->addWLA(mLRI*mLeafArea, mLeafArea);
353
}
-
 
354
-
 
355
void Tree::heightGrid_torus()
-
 
356
{
-
 
357
    // height of Z*
-
 
358
    const float cellsize = mHeightGrid->cellsize();
-
 
359
-
 
360
    QPoint p = QPoint(mPositionIndex.x()/cPxPerHeight, mPositionIndex.y()/cPxPerHeight); // pos of tree on height grid
-
 
361
    int bufferOffset = mHeightGrid->indexAt(QPointF(0.,0.)).x(); // offset of buffer
-
 
362
-
 
363
    // count trees that are on height-grid cells (used for stockable area)
-
 
364
    mHeightGrid->valueAtIndex(p).increaseCount();
-
 
365
-
 
366
    // torus coordinates
-
 
367
    p.setX((p.x()-bufferOffset)%10 + bufferOffset);
-
 
368
    p.setY((p.y()-bufferOffset)%10 + bufferOffset);
-
 
369
    QPoint ru_offset =QPoint(mPositionIndex.x()/cPxPerHeight - p.x(), mPositionIndex.y()/cPxPerHeight - p.y());
-
 
370
-
 
371
    int index_eastwest = mPositionIndex.x() % cPxPerHeight; // 4: very west, 0 east edge
-
 
372
    int index_northsouth = mPositionIndex.y() % cPxPerHeight; // 4: northern edge, 0: southern edge
-
 
373
    int dist[9];
-
 
374
    dist[3] = index_northsouth * 2 + 1; // south
-
 
375
    dist[1] = index_eastwest * 2 + 1; // west
-
 
376
    dist[5] = 10 - dist[3]; // north
-
 
377
    dist[7] = 10 - dist[1]; // east
-
 
378
    dist[8] = qMax(dist[5], dist[7]); // north-east
-
 
379
    dist[6] = qMax(dist[3], dist[7]); // south-east
-
 
380
    dist[0] = qMax(dist[3], dist[1]); // south-west
-
 
381
    dist[2] = qMax(dist[5], dist[1]); // north-west
-
 
382
    dist[4] = 0; // center cell
-
 
383
    /* the scheme of indices is as follows:  if sign(ix)= -1, if ix<0, 0 for ix=0, 1 for ix>0 (detto iy), then:
-
 
384
       index = 4 + 3*sign(ix) + sign(iy) transforms combinations of directions to unique ids (0..8), which are used above.
-
 
385
        e.g.: sign(ix) = -1, sign(iy) = 1 (=north-west) -> index = 4 + -3 + 1 = 2
-
 
386
    */
-
 
387
-
 
388
-
 
389
    int ringcount = int(floor(mHeight / cellsize)) + 1;
-
 
390
    int ix, iy;
-
 
391
    int ring;
-
 
392
    float hdom;
-
 
393
    for (ix=-ringcount;ix<=ringcount;ix++)
-
 
394
        for (iy=-ringcount; iy<=+ringcount; iy++) {
-
 
395
        ring = qMax(abs(ix), abs(iy));
-
 
396
        QPoint pos(ix+p.x(), iy+p.y());
-
 
397
        QPoint p_torus(torusIndex(pos.x(),10,bufferOffset,ru_offset.x()),
-
 
398
                       torusIndex(pos.y(),10,bufferOffset,ru_offset.y()));
-
 
399
        if (mHeightGrid->isIndexValid(p_torus)) {
-
 
400
            float &rHGrid = mHeightGrid->valueAtIndex(p_torus.x(),p_torus.y()).height;
-
 
401
            if (rHGrid > mHeight) // skip calculation if grid is higher than tree
-
 
402
                continue;
-
 
403
            int direction = 4 + (ix?(ix<0?-3:3):0) + (iy?(iy<0?-1:1):0); // 4 + 3*sgn(x) + sgn(y)
-
 
404
            hdom = mHeight - dist[direction];
-
 
405
            if (ring>1)
-
 
406
                hdom -= (ring-1)*10;
-
 
407
-
 
408
            rHGrid = qMax(rHGrid, hdom); // write value
-
 
409
        } // is valid
-
 
410
    } // for (y)
-
 
411
}
452
}
412
453
413
/// Torus version of read stamp (glued edges)
454
/// Torus version of read stamp (glued edges)
414
void Tree::readLIF_torus()
455
void Tree::readLIF_torus()
415
{
456
{
Line 434... Line 475...
434
475
435
    int x,y;
476
    int x,y;
436
    double sum=0.;
477
    double sum=0.;
437
    double value, own_value;
478
    double value, own_value;
438
    float *grid_value;
479
    float *grid_value;
-
 
480
    float z, z_zstar;
439
    int reader_size = reader->size();
481
    int reader_size = reader->size();
440
    int rx = pos_reader.x();
482
    int rx = pos_reader.x();
441
    int ry = pos_reader.y();
483
    int ry = pos_reader.y();
442
    int xt, yt; // wrapped coords
484
    int xt, yt; // wrapped coords
443
485
444
    for (y=0;y<reader_size; ++y) {
486
    for (y=0;y<reader_size; ++y) {
445
        yt = torusIndex(ry+y,cPxPerRU, bufferOffset, ru_offset.y());
487
        yt = torusIndex(ry+y,cPxPerRU, bufferOffset, ru_offset.y());
446
        for (x=0;x<reader_size;++x) {
488
        for (x=0;x<reader_size;++x) {
447
            xt = torusIndex(rx+x,cPxPerRU, bufferOffset, ru_offset.x());
489
            xt = torusIndex(rx+x,cPxPerRU, bufferOffset, ru_offset.x());
448
            grid_value = mGrid->ptr(xt,yt);
490
            grid_value = mGrid->ptr(xt,yt);
449
            //p = pos_reader + QPoint(x,y);
-
 
450
            //if (m_grid->isIndexValid(p)) {
-
 
-
 
491
451
            local_dom = mHeightGrid->valueAtIndex(xt/cPxPerHeight, yt/cPxPerHeight).height; // ry: gets ++ed in outer loop, rx not
492
            local_dom = mHeightGrid->valueAtIndex(xt/cPxPerHeight, yt/cPxPerHeight).height; // ry: gets ++ed in outer loop, rx not
452
            //local_dom = m_dominanceGrid->valueAt( m_grid->cellCoordinates(p) );
-
 
-
 
493
            z = std::max(mHeight - reader->distanceToCenter(x,y), 0.f); // distance to center = height (45° line)
-
 
494
            z_zstar = (z>=local_dom)?1.f:z/local_dom;
453
495
454
            own_value = 1. - mStamp->offsetValue(x,y,d_offset)*mOpacity / local_dom; // old: dom_height;
-
 
-
 
496
            own_value = 1. - mStamp->offsetValue(x,y,d_offset)*mOpacity * z_zstar;
-
 
497
            // old: own_value = 1. - mStamp->offsetValue(x,y,d_offset)*mOpacity / local_dom; // old: dom_height;
455
            own_value = qMax(own_value, 0.02);
498
            own_value = qMax(own_value, 0.02);
456
            value =  *grid_value / own_value; // remove impact of focal tree
-
 
-
 
499
            value =  *grid_value++ / own_value; // remove impact of focal tree
-
 
500
457
            // debug for one tree in HJA
501
            // debug for one tree in HJA
458
            //if (id()==178020)
502
            //if (id()==178020)
459
            //    qDebug() << x << y << xt << yt << *grid_value << local_dom << own_value << value << (*reader)(x,y);
503
            //    qDebug() << x << y << xt << yt << *grid_value << local_dom << own_value << value << (*reader)(x,y);
460
            //if (_isnan(value))
504
            //if (_isnan(value))
461
            //    qDebug() << "isnan" << id();
505
            //    qDebug() << "isnan" << id();