Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
3 Werner 2
 
3
#include "tree.h"
16 Werner 4
#include "core/grid.h"
30 Werner 5
#include "imagestamp.h"
3 Werner 6
 
38 Werner 7
#include "core/stamp.h"
8
#include "treespecies.h"
9
 
61 Werner 10
 
39 Werner 11
FloatGrid *Tree::m_grid = 0;
45 Werner 12
FloatGrid *Tree::m_dominanceGrid = 0;
40 Werner 13
int Tree::m_statPrint=0;
48 Werner 14
int Tree::m_statAboveZ=0;
40 Werner 15
int Tree::m_nextId=0;
53 Werner 16
float Tree::lafactor = 1.;
58 Werner 17
int Tree::m_debugid = -1;
40 Werner 18
 
3 Werner 19
Tree::Tree()
20
{
38 Werner 21
    m_Dbh = 0;
22
    m_Height = 0;
23
    m_species = 0;
40 Werner 24
    m_id = m_nextId++;
3 Werner 25
}
38 Werner 26
 
15 Werner 27
/** get distance and direction between two points.
38 Werner 28
  returns the distance (m), and the angle between PStart and PEnd (radians) in referenced param rAngle. */
3 Werner 29
float dist_and_direction(const QPointF &PStart, const QPointF &PEnd, float &rAngle)
30
{
31
    float dx = PEnd.x() - PStart.x();
32
    float dy = PEnd.y() - PStart.y();
33
    float d = sqrt(dx*dx + dy*dy);
34
    // direction:
35
    rAngle = atan2(dx, dy);
36
    return d;
37
}
38
 
39
 
38 Werner 40
void Tree::setup()
41
{
42
    if (m_Dbh<=0 || m_Height<=0)
43
        return;
44
    // check stamp
45
   Q_ASSERT_X(m_species!=0, "Tree::setup()", "species is NULL");
46
   m_stamp = m_species->stamp(m_Dbh, m_Height);
47
}
39 Werner 48
 
49
void Tree::applyStamp()
50
{
51
    Q_ASSERT(m_grid!=0);
52
    if (!m_stamp)
53
        return;
54
 
40 Werner 55
    QPoint pos = m_grid->indexAt(m_Position);
56
    int offset = m_stamp->offset();
57
    pos-=QPoint(offset, offset);
58
    QPoint p;
59
 
60 Werner 60
    float local_dom; // height of Z* on the current position
40 Werner 61
    int x,y;
58 Werner 62
    float value;
51 Werner 63
    QPoint dbg(10,20);
40 Werner 64
    for (x=0;x<m_stamp->size();++x) {
65
        for (y=0;y<m_stamp->size(); ++y) {
66
           p = pos + QPoint(x,y);
51 Werner 67
           // debug pixel
61 Werner 68
           //if (p==dbg)
69
           //    qDebug() << "#" << id() << "value;"<<(*m_stamp)(x,y)<<"domH"<<dom;
51 Werner 70
 
71
           if (m_grid->isIndexValid(p)) {
72
               // mulitplicative:
53 Werner 73
               //m_grid->valueAtIndex(p)*=(*m_stamp)(x,y);
51 Werner 74
               // additiv:
58 Werner 75
               // multiplicatie, v2
60 Werner 76
               local_dom = m_dominanceGrid->valueAt( m_grid->cellCoordinates(p) ); // todo: could be done more effectively (here 2 transormations are performed)...
77
               if (local_dom<=0.f) {
61 Werner 78
                   //qDebug() << "invalid height at " << m_grid->cellCoordinates(p) << "of" << local_dom;
79
                   local_dom = 2.;
60 Werner 80
               }
81
               value = (*m_stamp)(x,y);
82
               value = 1. - value*lafactor / local_dom;
59 Werner 83
               value = qMax(value, 0.02f);
58 Werner 84
               m_grid->valueAtIndex(p)*= value;
51 Werner 85
           }
40 Werner 86
        }
87
    }
58 Werner 88
 
89
    m_statPrint++; // count # of stamp applications...
90
}
91
 
62 Werner 92
/** heightGrid()
93
  This function calculates the "dominant height field". This grid is coarser as the fine-scaled light-grid.
94
 
95
*/
58 Werner 96
void Tree::heightGrid()
97
{
59 Werner 98
    // height of Z*
99
    float cellsize = m_dominanceGrid->cellsize();
62 Werner 100
    if (m_Height < cellsize/2.) {
59 Werner 101
        float &dom = m_dominanceGrid->valueAt(m_Position); // modifyable reference
102
        dom = qMax(dom, m_Height/2.f);
103
    } else {
104
        QPoint p = m_dominanceGrid->indexAt(m_Position); // pos of tree on height grid
62 Werner 105
 
106
        int ringcount = int(floor(m_Height / cellsize));
59 Werner 107
        int ix, iy;
108
        int ring;
109
        QPoint pos;
62 Werner 110
        float hdom;
111
        float h_out = fmod(m_Height, cellsize) / 2.;
59 Werner 112
        for (ix=-ringcount;ix<=ringcount;ix++)
113
            for (iy=-ringcount; iy<=+ringcount; iy++) {
114
            ring = qMax(abs(ix), abs(iy));
115
            QPoint pos(ix+p.x(), iy+p.y());
116
            if (m_dominanceGrid->isIndexValid(pos)) {
117
                // apply value....
62 Werner 118
                if (ring==0) {
119
                    hdom = m_Height- cellsize/4.;
120
                } else if (ring==abs(ringcount)) {
121
                    // outermost ring: use again height/2.
122
                    hdom = h_out;
123
                } else {
124
                    hdom = m_Height- ring*cellsize;
125
                }
126
                m_dominanceGrid->valueAtIndex(pos) = qMax(m_dominanceGrid->valueAtIndex(pos), hdom);
59 Werner 127
            }
45 Werner 128
 
59 Werner 129
        }
130
    }
131
 
39 Werner 132
}
40 Werner 133
 
134
double Tree::readStamp()
135
{
51 Werner 136
    if (!m_stamp)
137
        return 0.;
47 Werner 138
    const Stamp *stamp = m_stamp->reader();
40 Werner 139
    if (!stamp)
140
        return 0.;
141
    QPoint pos = m_grid->indexAt(m_Position);
142
    int offset = stamp->offset();
143
    pos-=QPoint(offset, offset);
144
    QPoint p;
145
 
146
    int x,y;
147
    double sum=0.;
148
    for (x=0;x<stamp->size();++x) {
149
        for (y=0;y<stamp->size(); ++y) {
150
           p = pos + QPoint(x,y);
151
           if (m_grid->isIndexValid(p))
152
               sum += m_grid->valueAtIndex(p) * (*stamp)(x,y);
153
        }
154
    }
53 Werner 155
    float eigenvalue = m_stamp->readSum() * lafactor;
156
    mImpact = sum - eigenvalue;// additive
157
    float dom_height = (*m_dominanceGrid)[m_Position];
158
    if (dom_height>0.)
159
       mImpact = mImpact / dom_height;
160
 
161
    //mImpact = sum + eigenvalue;// multiplicative
48 Werner 162
    // read dominance field...
53 Werner 163
 
48 Werner 164
    if (dom_height < m_Height) {
165
        // if tree is higher than Z*, the dominance height
166
        // a part of the crown is in "full light".
167
        // total value = zstar/treeheight*value + 1-zstar/height
168
        // reformulated to:
169
        mImpact =  mImpact * dom_height/m_Height ;
170
        m_statAboveZ++;
171
    }
47 Werner 172
    if (fabs(mImpact < 0.000001))
173
        mImpact = 0.f;
174
    qDebug() << "Tree #"<< id() << "value" << sum << "eigenvalue" << eigenvalue << "Impact" << mImpact;
42 Werner 175
    return mImpact;
40 Werner 176
}
177
 
58 Werner 178
double Tree::readStampMul()
179
{
180
    if (!m_stamp)
181
        return 0.;
182
    const Stamp *reader = m_stamp->reader();
183
    if (!reader)
184
        return 0.;
185
    QPoint pos_reader = m_grid->indexAt(m_Position);
186
 
187
    int offset_reader = reader->offset();
188
    int offset_writer = m_stamp->offset();
189
    int d_offset = offset_writer - offset_reader;
190
 
191
    QPoint pos_writer=pos_reader - QPoint(offset_writer, offset_writer);
192
    pos_reader-=QPoint(offset_reader, offset_reader);
193
    QPoint p;
194
 
195
    float dom_height = (*m_dominanceGrid)[m_Position];
196
 
197
    int x,y;
198
    double sum=0.;
199
    double value, own_value;
200
    for (x=0;x<reader->size();++x) {
201
        for (y=0;y<reader->size(); ++y) {
202
            p = pos_reader + QPoint(x,y);
203
            if (m_grid->isIndexValid(p)) {
204
                own_value = 1. - m_stamp->offsetValue(x,y,d_offset)*lafactor /dom_height;
59 Werner 205
                own_value = qMax(own_value, 0.02);
58 Werner 206
                value =  m_grid->valueAtIndex(p) / own_value; // remove impact of focal tree
207
                if (value>0.)
208
                    sum += value * (*reader)(x,y);
209
                //value = (1. - m_stamp->offsetValue(x,y,d_offset)/dom_height);
210
                //value = (1 - m_grid->valueAtIndex(p)) / (m_stamp->offsetValue(x,y,d_offset)/dom_height * lafactor);
211
                if (isDebugging()) {
212
                    qDebug() << "Tree" << id() << "Coord" << p << "gridvalue" << m_grid->valueAtIndex(p) << "value" << value << "reader" << (*reader)(x,y) << "writer" << m_stamp->offsetValue(x,y,d_offset);
213
                }
214
 
215
            }
216
        }
217
    }
218
    mImpact = sum;
219
    // read dominance field...
220
    if (dom_height < m_Height) {
221
        // if tree is higher than Z*, the dominance height
222
        // a part of the crown is in "full light".
223
        m_statAboveZ++;
224
        mImpact = 1. - (1. - mImpact)*dom_height/m_Height;
225
    }
226
    if (mImpact > 1)
227
        mImpact = 1.f;
61 Werner 228
    //qDebug() << "Tree #"<< id() << "value" << sum << "Impact" << mImpact;
58 Werner 229
    return mImpact;
230
}
231
 
232
 
40 Werner 233
void Tree::resetStatistics()
234
{
235
    m_statPrint=0;
48 Werner 236
    m_statAboveZ=0;
40 Werner 237
    m_nextId=1;
238
}