Subversion Repositories public iLand

Rev

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

Rev 1064 Rev 1068
Line 27... Line 27...
27
GrassCover::GrassCover()
27
GrassCover::GrassCover()
28
{
28
{
29
    mLayers = new GrassCoverLayers();
29
    mLayers = new GrassCoverLayers();
30
    mLayers->setGrid(mGrid, this);
30
    mLayers->setGrid(mGrid, this);
31
    mEnabled = false;
31
    mEnabled = false;
-
 
32
    mType = Invalid;
32
}
33
}
33
34
34
GrassCover::~GrassCover()
35
GrassCover::~GrassCover()
35
{
36
{
36
    delete mLayers;
37
    delete mLayers;
Line 48... Line 49...
48
        return;
49
        return;
49
    }
50
    }
50
    // create the grid
51
    // create the grid
51
    mGrid.setup(GlobalSettings::instance()->model()->grid()->metricRect(), GlobalSettings::instance()->model()->grid()->cellsize());
52
    mGrid.setup(GlobalSettings::instance()->model()->grid()->metricRect(), GlobalSettings::instance()->model()->grid()->cellsize());
52
    mGrid.wipe();
53
    mGrid.wipe();
53
    QString formula = xml.value("model.settings.grass.grassPotential");
-
 
54
    if (formula.isEmpty())
-
 
55
        throw IException("setup of 'grass': required expression 'grassPotential' is missing.");
-
 
56
    mGrassPotential.setExpression(formula);
-
 
57
    mGrassPotential.linearize(0.,1., qMin(GRASSCOVERSTEPS, 1000));
-
 
58
54
59
    formula = xml.value("model.settings.grass.grassEffect");
-
 
60
    if (formula.isEmpty())
-
 
61
        throw IException("setup of 'grass': required expression 'grassEffect' is missing.");
-
 
62
    mGrassEffect.setExpression(formula);
-
 
63
    mMaxTimeLag = xml.valueDouble("model.settings.grass.maxTimeLag");
-
 
64
    if (mMaxTimeLag==0)
-
 
65
        throw IException("setup of 'grass': value of 'maxTimeLag' is invalid or missing.");
-
 
66
    mGrowthRate = GRASSCOVERSTEPS / mMaxTimeLag;
-
 
-
 
55
    mType = Invalid;
-
 
56
    QString type = xml.value("model.settings.grass.type");
-
 
57
    if (type == QStringLiteral("pixel"))
-
 
58
        mType = Pixel;
67
59
68
    // set up the effect on regeneration in NSTEPS steps
-
 
69
    for (int i=0;i<GRASSCOVERSTEPS;++i) {
-
 
70
        double effect = mGrassEffect.calculate(i/double(GRASSCOVERSTEPS-1));
-
 
71
        mEffect[i] = limit(effect, 0., 1.);
-
 
72
    }
-
 
-
 
60
    if (type==QStringLiteral("continuous"))
-
 
61
        mType = Continuous;
73
62
74
    mMaxState = limit(mGrassPotential.calculate(1.f), 0., 1.)*(GRASSCOVERSTEPS-1); // the max value of the potential function
-
 
-
 
63
    if (mType == Invalid)
-
 
64
        throw IException("GrassCover::setup: invalid 'grass.type'. Allowed: 'continous' and 'pixel'.");
-
 
65
-
 
66
    if (mType == Pixel) {
-
 
67
        // setup of pixel based / discrete approach
-
 
68
        QString formula = xml.value("model.settings.grass.grassDuration");
-
 
69
        if (formula.isEmpty())
-
 
70
            throw IException("GrassCover::setup(): missing equation for 'grassDuration'.");
-
 
71
        mPDF.setup(formula, 0., 100.);
-
 
72
        mGrassLIFThreshold = xml.valueDouble("model.settings.grass.LIFThreshold", 0.2);
-
 
73
-
 
74
        // clear array
-
 
75
        for (int i=0;i<GRASSCOVERSTEPS;++i) {
-
 
76
            mEffect[i] = 0.;
-
 
77
        }
-
 
78
-
 
79
    } else {
-
 
80
-
 
81
        // setup of continuous grass concept
-
 
82
-
 
83
        QString formula = xml.value("model.settings.grass.grassPotential");
-
 
84
        if (formula.isEmpty())
-
 
85
            throw IException("setup of 'grass': required expression 'grassPotential' is missing.");
-
 
86
        mGrassPotential.setExpression(formula);
-
 
87
        mGrassPotential.linearize(0.,1., qMin(GRASSCOVERSTEPS, 1000));
-
 
88
-
 
89
        formula = xml.value("model.settings.grass.grassEffect");
-
 
90
        if (formula.isEmpty())
-
 
91
            throw IException("setup of 'grass': required expression 'grassEffect' is missing.");
-
 
92
        mGrassEffect.setExpression(formula);
-
 
93
        mMaxTimeLag = xml.valueDouble("model.settings.grass.maxTimeLag");
-
 
94
        if (mMaxTimeLag==0)
-
 
95
            throw IException("setup of 'grass': value of 'maxTimeLag' is invalid or missing.");
-
 
96
        mGrowthRate = GRASSCOVERSTEPS / mMaxTimeLag;
-
 
97
-
 
98
        // set up the effect on regeneration in NSTEPS steps
-
 
99
        for (int i=0;i<GRASSCOVERSTEPS;++i) {
-
 
100
            double effect = mGrassEffect.calculate(i/double(GRASSCOVERSTEPS-1));
-
 
101
            mEffect[i] = limit(effect, 0., 1.);
-
 
102
        }
-
 
103
-
 
104
        mMaxState = limit(mGrassPotential.calculate(1.f), 0., 1.)*(GRASSCOVERSTEPS-1); // the max value of the potential function
-
 
105
    }
75
106
76
    GlobalSettings::instance()->controller()->addLayers(mLayers, QStringLiteral("grass cover"));
107
    GlobalSettings::instance()->controller()->addLayers(mLayers, QStringLiteral("grass cover"));
77
    mEnabled = true;
108
    mEnabled = true;
78
    qDebug() << "setup of grass cover complete.";
109
    qDebug() << "setup of grass cover complete.";
79
110
Line 81... Line 112...
81
112
82
void GrassCover::setInitialValues(const QVector<float *> &LIFpixels, const int percent)
113
void GrassCover::setInitialValues(const QVector<float *> &LIFpixels, const int percent)
83
{
114
{
84
    if (!enabled())
115
    if (!enabled())
85
        return;
116
        return;
86
    grid_type cval = limit(percent / 100., 0., 1.)*(GRASSCOVERSTEPS-1);
-
 
87
    if (cval > mMaxState)
-
 
88
        cval = mMaxState;
-
 
-
 
117
    if (mType == Continuous) {
-
 
118
        grass_grid_type cval = limit(percent / 100., 0., 1.)*(GRASSCOVERSTEPS-1);
-
 
119
        if (cval > mMaxState)
-
 
120
            cval = mMaxState;
89
121
90
    Grid<float> *lif_grid = GlobalSettings::instance()->model()->grid();
-
 
91
    for (QVector<float *>::const_iterator it = LIFpixels.constBegin(); it!=LIFpixels.constEnd(); ++it)
-
 
92
        mGrid.valueAtIndex(lif_grid->indexOf(*it)) = cval;
-
 
-
 
122
        Grid<float> *lif_grid = GlobalSettings::instance()->model()->grid();
-
 
123
        for (QVector<float *>::const_iterator it = LIFpixels.constBegin(); it!=LIFpixels.constEnd(); ++it)
-
 
124
            mGrid.valueAtIndex(lif_grid->indexOf(*it)) = cval;
-
 
125
    } else {
-
 
126
        // mType == Pixel
-
 
127
        Grid<float> *lif_grid = GlobalSettings::instance()->model()->grid();
-
 
128
        for (QVector<float *>::const_iterator it = LIFpixels.constBegin(); it!=LIFpixels.constEnd(); ++it) {
-
 
129
            if (percent > irandom(0,100))
-
 
130
                mGrid.valueAtIndex(lif_grid->indexOf(*it)) = mPDF.get();
-
 
131
            else
-
 
132
                mGrid.valueAtIndex(lif_grid->indexOf(*it)) = 0;
-
 
133
        }
-
 
134
-
 
135
    }
93
}
136
}
94
137
95
void GrassCover::execute()
138
void GrassCover::execute()
96
{
139
{
97
    if (!enabled())
140
    if (!enabled())
98
        return;
141
        return;
99
142
100
    // Main function of the grass submodule
143
    // Main function of the grass submodule
101
    float *lif = GlobalSettings::instance()->model()->grid()->begin();
144
    float *lif = GlobalSettings::instance()->model()->grid()->begin();
102
    float *end_lif = GlobalSettings::instance()->model()->grid()->end();
145
    float *end_lif = GlobalSettings::instance()->model()->grid()->end();
103
    grid_type *gr = mGrid.begin();
-
 
-
 
146
    grass_grid_type *gr = mGrid.begin();
104
147
105
    // loop over every LIF pixel
-
 
106
    int skipped=0;
-
 
107
    for (; lif!=end_lif;++lif, ++gr) {
-
 
108
        // calculate potential grass vegetation cover
-
 
109
        if (*lif == 1.f && *gr==mMaxState) {
-
 
110
            ++skipped;
-
 
111
            continue;
-
 
112
        }
-
 
-
 
148
    if (mType == Continuous) {
-
 
149
        // loop over every LIF pixel
-
 
150
        int skipped=0;
-
 
151
        for (; lif!=end_lif;++lif, ++gr) {
-
 
152
            // calculate potential grass vegetation cover
-
 
153
            if (*lif == 1.f && *gr==mMaxState) {
-
 
154
                ++skipped;
-
 
155
                continue;
-
 
156
            }
113
157
114
        int potential = limit(mGrassPotential.calculate(*lif), 0., 1.)*(GRASSCOVERSTEPS-1);
-
 
115
        *gr = qMin( int(*gr) + mGrowthRate, potential);
-
 
-
 
158
            int potential = limit(mGrassPotential.calculate(*lif), 0., 1.)*(GRASSCOVERSTEPS-1);
-
 
159
            *gr = qMin( int(*gr) + mGrowthRate, potential);
116
160
-
 
161
        }
-
 
162
        //qDebug() << "skipped" << skipped;
-
 
163
    } else {
-
 
164
        // type = Pixel
-
 
165
        for (; lif!=end_lif;++lif, ++gr) {
-
 
166
            if (*gr>1)
-
 
167
                (*gr)--; // count down the years (until gr=1)
-
 
168
-
 
169
            if (*gr==0 && *lif>mGrassLIFThreshold) {
-
 
170
                // enable grass cover
-
 
171
                double v = qMax(mPDF.get(), 0.);
-
 
172
                *gr = v + 1;
-
 
173
            }
-
 
174
            if (*gr==1 && *lif<mGrassLIFThreshold) {
-
 
175
                // now LIF is below the threshold - this enables the pixel get grassy again
-
 
176
                *gr = 0;
-
 
177
            }
-
 
178
        }
117
    }
179
    }
118
    qDebug() << "skipped" << skipped;
-
 
119
180
120
}
181
}
121
182
122
183
123
184
124
double GrassCoverLayers::value(const grid_type &data, const int index) const
-
 
-
 
185
double GrassCoverLayers::value(const grass_grid_type &data, const int index) const
125
{
186
{
126
    if (!mGrassCover->enabled()) return 0.;
187
    if (!mGrassCover->enabled()) return 0.;
127
    switch(index){
188
    switch(index){
128
    case 0: return mGrassCover->effect(data); //effect
189
    case 0: return mGrassCover->effect(data); //effect
129
    case 1: return data/double(GRASSCOVERSTEPS-1); // state
-
 
-
 
190
    case 1: return mGrassCover->cover(data); // cover
130
    default: throw IException(QString("invalid variable index for a GrassCoverLayers: %1").arg(index));
191
    default: throw IException(QString("invalid variable index for a GrassCoverLayers: %1").arg(index));
131
    }
192
    }
132
}
193
}
133
194
134
const QVector<LayeredGridBase::LayerElement> &GrassCoverLayers::names()
195
const QVector<LayeredGridBase::LayerElement> &GrassCoverLayers::names()
135
{
196
{
136
    if (mNames.isEmpty())
197
    if (mNames.isEmpty())
137
        mNames = QVector<LayeredGridBase::LayerElement>()
198
        mNames = QVector<LayeredGridBase::LayerElement>()
138
                << LayeredGridBase::LayerElement(QLatin1Literal("effect"), QLatin1Literal("prohibiting effect on regeneration [0..1]"), GridViewGreens)
199
                << LayeredGridBase::LayerElement(QLatin1Literal("effect"), QLatin1Literal("prohibiting effect on regeneration [0..1]"), GridViewGreens)
139
                << LayeredGridBase::LayerElement(QLatin1Literal("cover"), QLatin1Literal("current grass cover on pixels [0..1]"), GridViewGreens);
-
 
-
 
200
                << LayeredGridBase::LayerElement(QLatin1Literal("cover"), QLatin1Literal("current grass cover on pixels [0..1 for continuous, or #years for pixel mode]"), GridViewGreens);
140
    return mNames;
201
    return mNames;
141
202
142
}
203
}