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. |
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< |
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( |
31 | if (!hg->valueAtIndex(lif_grid->index5(i)).isValid()) |
30 |
|
32 | s->state = SaplingCell::CellInvalid; |
31 | else
|
33 | else
|
32 |
|
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 |
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 = |
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[ |
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)[ |
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 = |
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 |
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 = |
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( |
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 ( |
297 | if (scell.saplings[i].is_occupied()) { |
271 | // add carbon to the ground
|
298 | // add carbon to the ground
|
272 | rus->saplingStat().addCarbonOfDeadSapling( |
299 | rus->saplingStat().addCarbonOfDeadSapling( scell.saplings[i].height / species->saplingGrowthParameters().hdSapling * 100.f ); |
273 |
|
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
|