Subversion Repositories public iLand

Rev

Rev 1158 | Rev 1160 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1158 Rev 1159
Line 19... Line 19...
19
19
20
}
20
}
21
21
22
void Saplings::setup()
22
void Saplings::setup()
23
{
23
{
24
    mGrid.setup(GlobalSettings::instance()->model()->grid()->metricRect(), GlobalSettings::instance()->model()->grid()->cellsize());
24
    //mGrid.setup(GlobalSettings::instance()->model()->grid()->metricRect(), GlobalSettings::instance()->model()->grid()->cellsize());
25
-
 
-
 
25
    FloatGrid *lif_grid = GlobalSettings::instance()->model()->grid();
26
    // mask out out-of-project areas
26
    // mask out out-of-project areas
27
    HeightGrid *hg = GlobalSettings::instance()->model()->heightGrid();
27
    HeightGrid *hg = GlobalSettings::instance()->model()->heightGrid();
28
    for (int i=0;i<mGrid.count();++i) {
28
    for (int i=0; i<lif_grid->count(); ++i) {
-
 
29
        SaplingCell *s = cell(lif_grid->indexOf(i), false); // false: retrieve also invalid cells
-
 
30
        if (s) {
29
        if (!hg->valueAtIndex(mGrid.index5(i)).isValid())
31
            if (!hg->valueAtIndex(lif_grid->index5(i)).isValid())
30
            mGrid[i].state = SaplingCell::CellInvalid;
32
                s->state = SaplingCell::CellInvalid;
31
        else
33
            else
32
            mGrid[i].state = SaplingCell::CellFree;
34
                s->state = SaplingCell::CellFree;
33
    }
35
        }
34
36
-
 
37
    }
35
38
36
}
39
}
37
40
38
void Saplings::establishment(const ResourceUnit *ru)
41
void Saplings::establishment(const ResourceUnit *ru)
39
{
42
{
Line 74... Line 77...
74
        double abiotic_env = rus->establishment().abioticEnvironment();
77
        double abiotic_env = rus->establishment().abioticEnvironment();
75
        if (abiotic_env==0.)
78
        if (abiotic_env==0.)
76
            continue;
79
            continue;
77
80
78
        // loop over all 2m cells on this resource unit
81
        // loop over all 2m cells on this resource unit
-
 
82
        SaplingCell *sap_cells = ru->saplingCellArray();
79
        SaplingCell *s;
83
        SaplingCell *s;
80
        int isc = 0; // index on 2m cell
84
        int isc = 0; // index on 2m cell
81
        for (int iy=0; iy<cPxPerRU; ++iy) {
85
        for (int iy=0; iy<cPxPerRU; ++iy) {
82
            s = mGrid.ptr(imap.x(), imap.y()+iy); // ptr to the row
86
            //s = mGrid.ptr(imap.x(), imap.y()+iy); // ptr to the row
-
 
87
            s = &sap_cells[iy*cPxPerRU]; // pointer to a row
83
            isc = mGrid.index(imap.x(), imap.y()+iy);
88
            isc = lif_grid->index(imap.x(), imap.y()+iy);
84
89
85
            for (int ix=0;ix<cPxPerRU; ++ix, ++s, ++isc) {
90
            for (int ix=0;ix<cPxPerRU; ++ix, ++s, ++isc) {
86
                if (s->state == SaplingCell::CellFree) {
91
                if (s->state == SaplingCell::CellFree) {
87
                    // is a sapling of the current species already on the pixel?
92
                    // is a sapling of the current species already on the pixel?
88
                    // * test for sapling height already in cell state
93
                    // * test for sapling height already in cell state
Line 98... Line 103...
98
                        }
103
                        }
99
                    }
104
                    }
100
105
101
                    if (stree) {
106
                    if (stree) {
102
                        // grass cover?
107
                        // grass cover?
103
                        float seed_map_value = seedmap[mGrid.index10(isc)];
108
                        float seed_map_value = seedmap[lif_grid->index10(isc)];
104
                        if (seed_map_value==0.f)
109
                        if (seed_map_value==0.f)
105
                            continue;
110
                            continue;
106
                        const HeightGridValue &hgv = (*height_grid)[mGrid.index5(isc)];
111
                        const HeightGridValue &hgv = (*height_grid)[lif_grid->index5(isc)];
107
                        float lif_value = (*lif_grid)[isc];
112
                        float lif_value = (*lif_grid)[isc];
108
113
109
                        double &lif_corrected = lif_corr[iy*cPxPerRU+ix];
114
                        double &lif_corrected = lif_corr[iy*cPxPerRU+ix];
110
                        // calculate the LIFcorrected only once per pixel
115
                        // calculate the LIFcorrected only once per pixel
111
                        if (lif_corrected<0.)
116
                        if (lif_corrected<0.)
Line 133... Line 138...
133
void Saplings::saplingGrowth(const ResourceUnit *ru)
138
void Saplings::saplingGrowth(const ResourceUnit *ru)
134
{
139
{
135
    HeightGrid *height_grid = GlobalSettings::instance()->model()->heightGrid();
140
    HeightGrid *height_grid = GlobalSettings::instance()->model()->heightGrid();
136
    FloatGrid *lif_grid = GlobalSettings::instance()->model()->grid();
141
    FloatGrid *lif_grid = GlobalSettings::instance()->model()->grid();
137
142
138
    QPoint imap =  mGrid.indexAt(ru->boundingBox().topLeft());
143
    QPoint imap = ru->cornerPointOffset();
139
    bool need_check=false;
144
    bool need_check=false;
-
 
145
    SaplingCell *sap_cells = ru->saplingCellArray();
140
    for (int iy=0; iy<cPxPerRU; ++iy) {
146
    for (int iy=0; iy<cPxPerRU; ++iy) {
141
        SaplingCell *s = mGrid.ptr(imap.x(), imap.y()+iy); // ptr to the row
147
        //SaplingCell *s = mGrid.ptr(imap.x(), imap.y()+iy); // ptr to the row
-
 
148
        SaplingCell *s = &sap_cells[iy*cPxPerRU]; // ptr to row
142
        int isc = mGrid.index(imap.x(), imap.y()+iy);
149
        int isc = lif_grid->index(imap.x(), imap.y()+iy);
143
150
144
        for (int ix=0;ix<cPxPerRU; ++ix, ++s, ++isc) {
151
        for (int ix=0;ix<cPxPerRU; ++ix, ++s, ++isc) {
145
            if (s->state != SaplingCell::CellInvalid) {
152
            if (s->state != SaplingCell::CellInvalid) {
146
                need_check=false;
153
                need_check=false;
147
                for (int i=0;i<NSAPCELLS;++i) {
154
                for (int i=0;i<NSAPCELLS;++i) {
148
                    if (s->saplings[i].is_occupied()) {
155
                    if (s->saplings[i].is_occupied()) {
149
                        // growth of this sapling tree
156
                        // growth of this sapling tree
150
                        const HeightGridValue &hgv = (*height_grid)[height_grid->index5(isc)];
157
                        const HeightGridValue &hgv = (*height_grid)[height_grid->index5(isc)];
151
                        float lif_value = (*lif_grid)[isc];
158
                        float lif_value = (*lif_grid)[isc];
152
159
153
                        need_check |= growSapling(ru, s->saplings[i], isc, hgv.height, lif_value);
160
                        need_check |= growSapling(ru, *s, s->saplings[i], isc, hgv.height, lif_value);
154
                    }
161
                    }
155
                }
162
                }
156
                if (need_check)
163
                if (need_check)
157
                    s->checkState();
164
                    s->checkState();
158
            }
165
            }
Line 165... Line 172...
165
    // store statistics on saplings/regeneration
172
    // store statistics on saplings/regeneration
166
    for (QList<ResourceUnitSpecies*>::const_iterator i=ru->ruSpecies().constBegin(); i!=ru->ruSpecies().constEnd(); ++i) {
173
    for (QList<ResourceUnitSpecies*>::const_iterator i=ru->ruSpecies().constBegin(); i!=ru->ruSpecies().constEnd(); ++i) {
167
        (*i)->saplingStat().calculate((*i)->species(), const_cast<ResourceUnit*>(ru));
174
        (*i)->saplingStat().calculate((*i)->species(), const_cast<ResourceUnit*>(ru));
168
        (*i)->statistics().add(&((*i)->saplingStat()));
175
        (*i)->statistics().add(&((*i)->saplingStat()));
169
    }
176
    }
-
 
177
}
-
 
178
-
 
179
SaplingCell *Saplings::cell(QPoint lif_coords, bool only_valid)
-
 
180
{
-
 
181
    FloatGrid *lif_grid = GlobalSettings::instance()->model()->grid();
-
 
182
-
 
183
    // in this case, getting the actual cell is quite cumbersome: first, retrieve the resource unit, then the
-
 
184
    // cell based on the offset of the given coordiantes relative to the corner of the resource unit.
-
 
185
    ResourceUnit *ru = GlobalSettings::instance()->model()->ru(lif_grid->cellCenterPoint(lif_coords));
-
 
186
    // ResourceUnit *ru = GlobalSettings::instance()->model()->RUgrid().constValueAt(lif_grid->cellCenterPoint(lif_coords));
-
 
187
    if (ru) {
-
 
188
        QPoint local_coords = lif_coords - ru->cornerPointOffset();
-
 
189
        int idx = local_coords.y() * cPxPerRU + local_coords.x();
-
 
190
        DBGMODE( if (idx<0 || idx>=cPxPerHectare)
-
 
191
                 qDebug("invalid coords in Saplings::cell");
-
 
192
                    );
-
 
193
        SaplingCell *s=&ru->saplingCellArray()[idx];
-
 
194
        if (s && (!only_valid || s->state!=SaplingCell::CellInvalid))
-
 
195
            return s;
-
 
196
    }
-
 
197
    return 0;
170
}
198
}
171
199
172
void Saplings::updateBrowsingPressure()
200
void Saplings::updateBrowsingPressure()
173
{
201
{
174
    if (GlobalSettings::instance()->settings().valueBool("model.settings.browsing.enabled"))
202
    if (GlobalSettings::instance()->settings().valueBool("model.settings.browsing.enabled"))
175
        Saplings::mBrowsingPressure = GlobalSettings::instance()->settings().valueDouble("model.settings.browsing.browsingPressure");
203
        Saplings::mBrowsingPressure = GlobalSettings::instance()->settings().valueDouble("model.settings.browsing.browsingPressure");
176
    else
204
    else
177
        Saplings::mBrowsingPressure = 0.;
205
        Saplings::mBrowsingPressure = 0.;
178
}
206
}
179
207
180
bool Saplings::growSapling(const ResourceUnit *ru, SaplingTree &tree, int isc, float dom_height, float lif_value)
208
bool Saplings::growSapling(const ResourceUnit *ru, SaplingCell &scell, SaplingTree &tree, int isc, float dom_height, float lif_value)
181
{
209
{
182
    ResourceUnitSpecies *rus = const_cast<ResourceUnitSpecies*>(ru->ruSpecies()[tree.species_index]);
210
    ResourceUnitSpecies *rus = const_cast<ResourceUnitSpecies*>(ru->ruSpecies()[tree.species_index]);
183
    const Species *species = rus->species();
211
    const Species *species = rus->species();
184
212
185
    // (1) calculate height growth potential for the tree (uses linerization of expressions...)
213
    // (1) calculate height growth potential for the tree (uses linerization of expressions...)
Line 250... Line 278...
250
278
251
        // add a new tree
279
        // add a new tree
252
        for (int i=0;i<to_establish;i++) {
280
        for (int i=0;i<to_establish;i++) {
253
            Tree &bigtree = const_cast<ResourceUnit*>(ru)->newTree();
281
            Tree &bigtree = const_cast<ResourceUnit*>(ru)->newTree();
254
282
255
            bigtree.setPosition(mGrid.indexOf(isc));
283
            bigtree.setPosition(GlobalSettings::instance()->model()->grid()->indexOf(isc));
256
            // add variation: add +/-10% to dbh and *independently* to height.
284
            // add variation: add +/-10% to dbh and *independently* to height.
257
            bigtree.setDbh(static_cast<float>(dbh * nrandom(1. - mRecruitmentVariation, 1. + mRecruitmentVariation)));
285
            bigtree.setDbh(static_cast<float>(dbh * nrandom(1. - mRecruitmentVariation, 1. + mRecruitmentVariation)));
258
            bigtree.setHeight(static_cast<float>(tree.height * nrandom(1. - mRecruitmentVariation, 1. + mRecruitmentVariation)));
286
            bigtree.setHeight(static_cast<float>(tree.height * nrandom(1. - mRecruitmentVariation, 1. + mRecruitmentVariation)));
259
            bigtree.setSpecies( const_cast<Species*>(species) );
287
            bigtree.setSpecies( const_cast<Species*>(species) );
260
            bigtree.setAge(tree.age,tree.height);
288
            bigtree.setAge(tree.age,tree.height);
Line 263... Line 291...
263
            const Tree *t = &bigtree;
291
            const Tree *t = &bigtree;
264
            const_cast<ResourceUnitSpecies*>(rus)->statistics().add(t, 0); // count the newly created trees already in the stats
292
            const_cast<ResourceUnitSpecies*>(rus)->statistics().add(t, 0); // count the newly created trees already in the stats
265
        }
293
        }
266
        // clear all regeneration from this pixel (including this tree)
294
        // clear all regeneration from this pixel (including this tree)
267
        tree.clear(); // clear this tree (no carbon flow to the ground)
295
        tree.clear(); // clear this tree (no carbon flow to the ground)
268
        SaplingCell &s=mGrid[isc];
-
 
269
        for (int i=0;i<NSAPCELLS;++i) {
296
        for (int i=0;i<NSAPCELLS;++i) {
270
            if (s.saplings[i].is_occupied()) {
297
            if (scell.saplings[i].is_occupied()) {
271
                // add carbon to the ground
298
                // add carbon to the ground
272
                rus->saplingStat().addCarbonOfDeadSapling( s.saplings[i].height / species->saplingGrowthParameters().hdSapling * 100.f );
299
                rus->saplingStat().addCarbonOfDeadSapling( scell.saplings[i].height / species->saplingGrowthParameters().hdSapling * 100.f );
273
                s.saplings[i].clear();
300
                scell.saplings[i].clear();
274
            }
301
            }
275
        }
302
        }
276
        return true; // need cleanup
303
        return true; // need cleanup
277
    }
304
    }
278
    // book keeping (only for survivors) for the sapling of the resource unit / species
305
    // book keeping (only for survivors) for the sapling of the resource unit / species