Subversion Repositories public iLand

Rev

Rev 776 | Rev 780 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 776 Rev 779
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
2
/********************************************************************************************
2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
6
**
7
**    This program is free software: you can redistribute it and/or modify
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
10
**    (at your option) any later version.
11
**
11
**
12
**    This program is distributed in the hope that it will be useful,
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
15
**    GNU General Public License for more details.
16
**
16
**
17
**    You should have received a copy of the GNU General Public License
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
19
********************************************************************************************/
20
20
21
/** ModelController is a helper class used to control the flow of operations during a model run.
21
/** ModelController is a helper class used to control the flow of operations during a model run.
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
23
  iLand GUI as well as the command line version (ilandc).
23
  iLand GUI as well as the command line version (ilandc).
24

24

25
  */
25
  */
26
26
27
#include "global.h"
27
#include "global.h"
28
#include "modelcontroller.h"
28
#include "modelcontroller.h"
29
#include <QObject>
29
#include <QObject>
30
30
31
#include "model.h"
31
#include "model.h"
32
#include "helper.h"
32
#include "helper.h"
33
#include "expression.h"
33
#include "expression.h"
34
#include "expressionwrapper.h"
34
#include "expressionwrapper.h"
35
#include "../output/outputmanager.h"
35
#include "../output/outputmanager.h"
36
36
37
#include "species.h"
37
#include "species.h"
38
#include "speciesset.h"
38
#include "speciesset.h"
39
#include "mapgrid.h"
39
#include "mapgrid.h"
40
40
41
#ifdef ILAND_GUI
41
#ifdef ILAND_GUI
42
#include "mainwindow.h" // for the debug message buffering
42
#include "mainwindow.h" // for the debug message buffering
43
#endif
43
#endif
44
44
45
ModelController::ModelController()
45
ModelController::ModelController()
46
{
46
{
47
    mModel = NULL;
47
    mModel = NULL;
48
    mPaused = false;
48
    mPaused = false;
49
    mRunning = false;
49
    mRunning = false;
50
    mYearsToRun = 0;
50
    mYearsToRun = 0;
51
    mViewerWindow = 0;
51
    mViewerWindow = 0;
52
}
52
}
53
53
54
ModelController::~ModelController()
54
ModelController::~ModelController()
55
{
55
{
56
    destroy();
56
    destroy();
57
}
57
}
58
58
59
void ModelController::connectSignals()
59
void ModelController::connectSignals()
60
{
60
{
61
    if (!mViewerWindow)
61
    if (!mViewerWindow)
62
        return;
62
        return;
63
#ifdef ILAND_GUI
63
#ifdef ILAND_GUI
64
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
64
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
65
#endif
65
#endif
66
}
66
}
67
67
68
/// prepare a list of all (active) species
68
/// prepare a list of all (active) species
69
QHash<QString, QString> ModelController::availableSpecies()
69
QHash<QString, QString> ModelController::availableSpecies()
70
{
70
{
71
    QHash<QString, QString> list;
71
    QHash<QString, QString> list;
72
    if (mModel) {
72
    if (mModel) {
73
        SpeciesSet *set = mModel->speciesSet();
73
        SpeciesSet *set = mModel->speciesSet();
74
        if (!set)
74
        if (!set)
75
            throw IException("there are 0 or more than one species sets.");
75
            throw IException("there are 0 or more than one species sets.");
76
        foreach (const Species *s, set->activeSpecies()) {
76
        foreach (const Species *s, set->activeSpecies()) {
77
            list[s->id()] = s->name();
77
            list[s->id()] = s->name();
78
        }
78
        }
79
    }
79
    }
80
    return list;
80
    return list;
81
}
81
}
82
82
83
bool ModelController::canCreate()
83
bool ModelController::canCreate()
84
{
84
{
85
    if (mModel)
85
    if (mModel)
86
        return false;
86
        return false;
87
    return true;
87
    return true;
88
}
88
}
89
89
90
bool ModelController::canDestroy()
90
bool ModelController::canDestroy()
91
{
91
{
92
    return mModel != NULL;
92
    return mModel != NULL;
93
}
93
}
94
94
95
bool ModelController::canRun()
95
bool ModelController::canRun()
96
{
96
{
97
    if (mModel && mModel->isSetup())
97
    if (mModel && mModel->isSetup())
98
        return true;
98
        return true;
99
    return false;
99
    return false;
100
}
100
}
101
101
102
bool ModelController::isRunning()
102
bool ModelController::isRunning()
103
{
103
{
104
    return mRunning;
104
    return mRunning;
105
}
105
}
106
106
107
bool ModelController::isFinished()
107
bool ModelController::isFinished()
108
{
108
{
109
    if (!mModel)
109
    if (!mModel)
110
        return false;
110
        return false;
111
    return canRun() && !isRunning()  && mFinished;
111
    return canRun() && !isRunning()  && mFinished;
112
}
112
}
113
113
114
bool ModelController::isPaused()
114
bool ModelController::isPaused()
115
{
115
{
116
    return mPaused;
116
    return mPaused;
117
}
117
}
118
118
119
int ModelController::currentYear() const
119
int ModelController::currentYear() const
120
{
120
{
121
    return GlobalSettings::instance()->currentYear();
121
    return GlobalSettings::instance()->currentYear();
122
}
122
}
123
123
124
void ModelController::setFileName(QString initFileName)
124
void ModelController::setFileName(QString initFileName)
125
{
125
{
126
    mInitFile = initFileName;
126
    mInitFile = initFileName;
127
    try {
127
    try {
128
        GlobalSettings::instance()->loadProjectFile(mInitFile);
128
        GlobalSettings::instance()->loadProjectFile(mInitFile);
129
    } catch(const IException &e) {
129
    } catch(const IException &e) {
130
        QString error_msg = e.message();
130
        QString error_msg = e.message();
131
        Helper::msg(error_msg);
131
        Helper::msg(error_msg);
132
        qDebug() << error_msg;
132
        qDebug() << error_msg;
133
    }
133
    }
134
}
134
}
135
135
136
void ModelController::create()
136
void ModelController::create()
137
{
137
{
138
    if (!canCreate())
138
    if (!canCreate())
139
        return;
139
        return;
140
    emit bufferLogs(true);
140
    emit bufferLogs(true);
141
141
142
    try {
142
    try {
143
        DebugTimer::clearAllTimers();
143
        DebugTimer::clearAllTimers();
144
        mModel = new Model();
144
        mModel = new Model();
145
        mModel->loadProject();
145
        mModel->loadProject();
146
        if (!mModel->isSetup())
146
        if (!mModel->isSetup())
147
            return;
147
            return;
148
148
149
        // reset clock...
149
        // reset clock...
150
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
150
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
151
        // initialization of trees, output on startup
151
        // initialization of trees, output on startup
152
        mModel->beforeRun();
152
        mModel->beforeRun();
153
    } catch(const IException &e) {
153
    } catch(const IException &e) {
154
        QString error_msg = e.message();
154
        QString error_msg = e.message();
155
        Helper::msg(error_msg);
155
        Helper::msg(error_msg);
156
        qDebug() << error_msg;
156
        qDebug() << error_msg;
157
    }
157
    }
158
    emit bufferLogs(false);
158
    emit bufferLogs(false);
159
159
160
    qDebug() << "Model created.";
160
    qDebug() << "Model created.";
161
}
161
}
162
162
163
void ModelController::destroy()
163
void ModelController::destroy()
164
{
164
{
165
    if (canDestroy()) {
165
    if (canDestroy()) {
166
        delete mModel;
166
        delete mModel;
167
        mModel = 0;
167
        mModel = 0;
168
        GlobalSettings::instance()->setCurrentYear(0);
168
        GlobalSettings::instance()->setCurrentYear(0);
169
        qDebug() << "ModelController: Model destroyed.";
169
        qDebug() << "ModelController: Model destroyed.";
170
    }
170
    }
171
}
171
}
172
172
173
void ModelController::runloop()
173
void ModelController::runloop()
174
{
174
{
175
    static QTime sLastTime = QTime::currentTime();
175
    static QTime sLastTime = QTime::currentTime();
176
#ifdef ILAND_GUI
176
#ifdef ILAND_GUI
177
 //   QApplication::processEvents();
177
 //   QApplication::processEvents();
178
#else
178
#else
179
 //   QCoreApplication::processEvents();
179
 //   QCoreApplication::processEvents();
180
#endif
180
#endif
181
    if (mPaused)
181
    if (mPaused)
182
        return;
182
        return;
183
    bool doStop = false;
183
    bool doStop = false;
184
    bool hasError = false;
184
    bool hasError = false;
185
    if (GlobalSettings::instance()->currentYear()<=1) {
185
    if (GlobalSettings::instance()->currentYear()<=1) {
186
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
186
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
187
    }
187
    }
188
188
189
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
189
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
190
        emit bufferLogs(true);
190
        emit bufferLogs(true);
191
191
192
        hasError = runYear(); // do the work!
192
        hasError = runYear(); // do the work!
193
193
194
        mRunning = true;
194
        mRunning = true;
195
        emit year(GlobalSettings::instance()->currentYear());
195
        emit year(GlobalSettings::instance()->currentYear());
196
        if (!hasError) {
196
        if (!hasError) {
197
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
197
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
198
            int time=0;
198
            int time=0;
199
            if (currentYear()%50==0 && elapsed>10000)
199
            if (currentYear()%50==0 && elapsed>10000)
200
                time = 100; // a 100ms pause...
200
                time = 100; // a 100ms pause...
201
            if (currentYear()%100==0 && elapsed>10000) {
201
            if (currentYear()%100==0 && elapsed>10000) {
202
                time = 500; // a 500ms pause...
202
                time = 500; // a 500ms pause...
203
            }
203
            }
204
            if (time>0) {
204
            if (time>0) {
205
                sLastTime = QTime::currentTime(); // reset clock
205
                sLastTime = QTime::currentTime(); // reset clock
206
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
206
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
207
                //QTimer::singleShot(time,this, SLOT(runloop()));
207
                //QTimer::singleShot(time,this, SLOT(runloop()));
208
            }
208
            }
209
209
210
        }
210
        }
211
        else
211
        else
212
           doStop = true; // an error occured
212
           doStop = true; // an error occured
213
213
214
    } else {
214
    } else {
215
        doStop = true; // all years simulated
215
        doStop = true; // all years simulated
216
    }
216
    }
217
217
218
    if (doStop || mCanceled) {
218
    if (doStop || mCanceled) {
219
                // finished
219
                // finished
220
        internalStop();
220
        internalStop();
221
    }
221
    }
222
222
223
#ifdef ILAND_GUI
223
#ifdef ILAND_GUI
224
    QApplication::processEvents();
224
    QApplication::processEvents();
225
#else
225
#else
226
    QCoreApplication::processEvents();
226
    QCoreApplication::processEvents();
227
#endif
227
#endif
228
}
228
}
229
229
230
bool ModelController::internalRun()
230
bool ModelController::internalRun()
231
{
231
{
232
    // main loop
232
    // main loop
233
233
234
    while (mRunning && !mPaused &&  !mFinished) {
234
    while (mRunning && !mPaused &&  !mFinished) {
235
        runloop(); // start the running loop
235
        runloop(); // start the running loop
236
    }
236
    }
237
    return isFinished();
237
    return isFinished();
238
}
238
}
239
239
240
void ModelController::internalStop()
240
void ModelController::internalStop()
241
{
241
{
242
    if (mRunning) {
242
    if (mRunning) {
243
        GlobalSettings::instance()->outputManager()->save();
243
        GlobalSettings::instance()->outputManager()->save();
244
        DebugTimer::printAllTimers();
244
        DebugTimer::printAllTimers();
245
        mFinished = true;
245
        mFinished = true;
246
    }
246
    }
247
    mRunning = false;
247
    mRunning = false;
248
    emit bufferLogs(false); // stop buffering
248
    emit bufferLogs(false); // stop buffering
249
    emit finished(QString());
249
    emit finished(QString());
250
    emit stateChanged();
250
    emit stateChanged();
251
251
252
}
252
}
253
253
254
void ModelController::run(int years)
254
void ModelController::run(int years)
255
{
255
{
256
    if (!canRun())
256
    if (!canRun())
257
        return;
257
        return;
258
    emit bufferLogs(true); // start buffering
258
    emit bufferLogs(true); // start buffering
259
259
260
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
260
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
261
    mPaused = false;
261
    mPaused = false;
262
    mFinished = false;
262
    mFinished = false;
263
    mCanceled = false;
263
    mCanceled = false;
264
    mYearsToRun = years;
264
    mYearsToRun = years;
265
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
265
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
266
266
267
    DebugTimer::clearAllTimers();
267
    DebugTimer::clearAllTimers();
268
268
269
    mRunning = true;
269
    mRunning = true;
270
    emit stateChanged();
270
    emit stateChanged();
271
271
272
    qDebug() << "ModelControler: runloop started.";
272
    qDebug() << "ModelControler: runloop started.";
273
    internalRun();
273
    internalRun();
274
    emit stateChanged();
274
    emit stateChanged();
275
}
275
}
276
276
277
bool ModelController::runYear()
277
bool ModelController::runYear()
278
{
278
{
279
    if (!canRun()) return false;
279
    if (!canRun()) return false;
280
    DebugTimer t("ModelController:runYear");
280
    DebugTimer t("ModelController:runYear");
281
    qDebug() << "ModelController: run year" << currentYear();
281
    qDebug() << "ModelController: run year" << currentYear();
282
282
283
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
283
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
284
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
284
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
285
    bool err=false;
285
    bool err=false;
286
    try {
286
    try {
287
        emit bufferLogs(true);
287
        emit bufferLogs(true);
288
        mModel->runYear();
288
        mModel->runYear();
289
        fetchDynamicOutput();
289
        fetchDynamicOutput();
290
    } catch(const IException &e) {
290
    } catch(const IException &e) {
291
        QString error_msg = e.message();
291
        QString error_msg = e.message();
292
#ifdef ILAND_GUI
292
#ifdef ILAND_GUI
293
        Helper::msg(error_msg);
293
        Helper::msg(error_msg);
294
#endif
294
#endif
295
        qDebug() << error_msg;
295
        qDebug() << error_msg;
296
        err=true;
296
        err=true;
297
    }
297
    }
298
    emit bufferLogs(false);
298
    emit bufferLogs(false);
299
    return err;
299
    return err;
300
}
300
}
301
301
302
bool ModelController::pause()
302
bool ModelController::pause()
303
{
303
{
304
    if(!isRunning())
304
    if(!isRunning())
305
        return mPaused;
305
        return mPaused;
306
306
307
    if (mPaused) {
307
    if (mPaused) {
308
        // currently in pause - mode -> continue
308
        // currently in pause - mode -> continue
309
        mPaused = false;
309
        mPaused = false;
310
310
311
    } else {
311
    } else {
312
        // currently running -> set to pause mode
312
        // currently running -> set to pause mode
313
        GlobalSettings::instance()->outputManager()->save();
313
        GlobalSettings::instance()->outputManager()->save();
314
        mPaused = true;
314
        mPaused = true;
315
        emit bufferLogs(false);
315
        emit bufferLogs(false);
316
    }
316
    }
317
    emit stateChanged();
317
    emit stateChanged();
318
    return mPaused;
318
    return mPaused;
319
}
319
}
320
320
321
bool ModelController::continueRun()
321
bool ModelController::continueRun()
322
{
322
{
323
    mRunning = true;
323
    mRunning = true;
324
    emit stateChanged();
324
    emit stateChanged();
325
    return internalRun();
325
    return internalRun();
326
}
326
}
327
327
328
void ModelController::cancel()
328
void ModelController::cancel()
329
{
329
{
330
    mCanceled = true;
330
    mCanceled = true;
331
    internalStop();
331
    internalStop();
332
    emit stateChanged();
332
    emit stateChanged();
333
}
333
}
334
334
335
QMutex error_mutex;
335
QMutex error_mutex;
336
void ModelController::throwError(const QString msg)
336
void ModelController::throwError(const QString msg)
337
{
337
{
338
    QMutexLocker lock(&error_mutex); // serialize access
338
    QMutexLocker lock(&error_mutex); // serialize access
339
    qDebug() << "ModelController: throwError reached:";
339
    qDebug() << "ModelController: throwError reached:";
340
    qDebug() << msg;
340
    qDebug() << msg;
341
    emit bufferLogs(false);
341
    emit bufferLogs(false);
342
    emit bufferLogs(true); // start buffering again
342
    emit bufferLogs(true); // start buffering again
343
343
344
    throw IException(msg); // raise error again
344
    throw IException(msg); // raise error again
345
345
346
}
346
}
347
//////////////////////////////////////
347
//////////////////////////////////////
348
// dynamic outut
348
// dynamic outut
349
//////////////////////////////////////
349
//////////////////////////////////////
350
//////////////////////////////////////
350
//////////////////////////////////////
351
void ModelController::setupDynamicOutput(QString fieldList)
351
void ModelController::setupDynamicOutput(QString fieldList)
352
{
352
{
353
    mDynFieldList.clear();
353
    mDynFieldList.clear();
354
    if (!fieldList.isEmpty()) {
354
    if (!fieldList.isEmpty()) {
355
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
355
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
356
        int pos=0;
356
        int pos=0;
357
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
357
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
358
            mDynFieldList.append(rx.cap(1));
358
            mDynFieldList.append(rx.cap(1));
359
            pos += rx.matchedLength();
359
            pos += rx.matchedLength();
360
        }
360
        }
361
361
362
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
362
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
363
        mDynFieldList.prepend("count");
363
        mDynFieldList.prepend("count");
364
        mDynFieldList.prepend("year"); // fixed fields.
364
        mDynFieldList.prepend("year"); // fixed fields.
365
    }
365
    }
366
    mDynData.clear();
366
    mDynData.clear();
367
    mDynData.append(mDynFieldList.join(";"));
367
    mDynData.append(mDynFieldList.join(";"));
368
}
368
}
369
369
370
QString ModelController::dynamicOutput()
370
QString ModelController::dynamicOutput()
371
{
371
{
372
    return mDynData.join("\n");
372
    return mDynData.join("\n");
373
}
373
}
374
374
375
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
375
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
376
void ModelController::fetchDynamicOutput()
376
void ModelController::fetchDynamicOutput()
377
{
377
{
378
    if (mDynFieldList.isEmpty())
378
    if (mDynFieldList.isEmpty())
379
        return;
379
        return;
380
    DebugTimer t("dynamic output");
380
    DebugTimer t("dynamic output");
381
    QStringList var;
381
    QStringList var;
382
    QString lastVar = "";
382
    QString lastVar = "";
383
    QVector<double> data;
383
    QVector<double> data;
384
    AllTreeIterator at(mModel);
384
    AllTreeIterator at(mModel);
385
    TreeWrapper tw;
385
    TreeWrapper tw;
386
    int var_index;
386
    int var_index;
387
    StatData stat;
387
    StatData stat;
388
    double value;
388
    double value;
389
    QStringList line;
389
    QStringList line;
390
    Expression custom_expr;
390
    Expression custom_expr;
391
    bool simple_expression;
391
    bool simple_expression;
392
    foreach (QString field, mDynFieldList) {
392
    foreach (QString field, mDynFieldList) {
393
        if (field=="count" || field=="year")
393
        if (field=="count" || field=="year")
394
            continue;
394
            continue;
395
        if (field.count()>0 && field.at(0)=='[') {
395
        if (field.count()>0 && field.at(0)=='[') {
396
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
396
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
397
            rex.indexIn(field);
397
            rex.indexIn(field);
398
            var = rex.capturedTexts();
398
            var = rex.capturedTexts();
399
            var.pop_front(); // drop first element (contains the full string)
399
            var.pop_front(); // drop first element (contains the full string)
400
            simple_expression = false;
400
            simple_expression = false;
401
        } else {
401
        } else {
402
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
402
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
403
            simple_expression = true;
403
            simple_expression = true;
404
        }
404
        }
405
        if (var.count()!=2)
405
        if (var.count()!=2)
406
                throw IException(QString("Invalid variable name for dynamic output:") + field);
406
                throw IException(QString("Invalid variable name for dynamic output:") + field);
407
        if (var.first()!=lastVar) {
407
        if (var.first()!=lastVar) {
408
            // load new field
408
            // load new field
409
            data.clear();
409
            data.clear();
410
            at.reset(); var_index = 0;
410
            at.reset(); var_index = 0;
411
            if (simple_expression) {
411
            if (simple_expression) {
412
                var_index = tw.variableIndex(var.first());
412
                var_index = tw.variableIndex(var.first());
413
                if (var_index<0)
413
                if (var_index<0)
414
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
414
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
415
415
416
            } else {
416
            } else {
417
                custom_expr.setExpression(var.first());
417
                custom_expr.setExpression(var.first());
418
                custom_expr.setModelObject(&tw);
418
                custom_expr.setModelObject(&tw);
419
            }
419
            }
420
            while (Tree *t = at.next()) {
420
            while (Tree *t = at.next()) {
421
                tw.setTree(t);
421
                tw.setTree(t);
422
                if (simple_expression)
422
                if (simple_expression)
423
                    value = tw.value(var_index);
423
                    value = tw.value(var_index);
424
                else
424
                else
425
                    value = custom_expr.execute();
425
                    value = custom_expr.execute();
426
                data.push_back(value);
426
                data.push_back(value);
427
            }
427
            }
428
            stat.setData(data);
428
            stat.setData(data);
429
        }
429
        }
430
        // fetch data
430
        // fetch data
431
        var_index = aggList.indexOf(var[1]);
431
        var_index = aggList.indexOf(var[1]);
432
        switch (var_index) {
432
        switch (var_index) {
433
            case 0: value = stat.mean(); break;
433
            case 0: value = stat.mean(); break;
434
            case 1: value = stat.sum(); break;
434
            case 1: value = stat.sum(); break;
435
            case 2: value = stat.min(); break;
435
            case 2: value = stat.min(); break;
436
            case 3: value = stat.max(); break;
436
            case 3: value = stat.max(); break;
437
            case 4: value = stat.percentile25(); break;
437
            case 4: value = stat.percentile25(); break;
438
            case 5: value = stat.median(); break;
438
            case 5: value = stat.median(); break;
439
            case 6: value = stat.percentile75(); break;
439
            case 6: value = stat.percentile75(); break;
440
            case 7: value = stat.percentile(5); break;
440
            case 7: value = stat.percentile(5); break;
441
            case 8: value = stat.percentile(10); break;
441
            case 8: value = stat.percentile(10); break;
442
            case 9: value = stat.percentile(90); break;
442
            case 9: value = stat.percentile(90); break;
443
            case 10: value = stat.percentile(95); break;
443
            case 10: value = stat.percentile(95); break;
444
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
444
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
445
                                  .arg(var[1]).arg(aggList.join(" ")));
445
                                  .arg(var[1]).arg(aggList.join(" ")));
446
        }
446
        }
447
        line+=QString::number(value);
447
        line+=QString::number(value);
448
    }
448
    }
449
    line.prepend( QString::number(data.size()) );
449
    line.prepend( QString::number(data.size()) );
450
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
450
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
451
    mDynData.append(line.join(";"));
451
    mDynData.append(line.join(";"));
452
}
452
}
453
453
454
void ModelController::saveScreenshot(QString file_name)
454
void ModelController::saveScreenshot(QString file_name)
455
{
455
{
456
#ifdef ILAND_GUI
456
#ifdef ILAND_GUI
457
    if (!mViewerWindow)
457
    if (!mViewerWindow)
458
        return;
458
        return;
459
    QImage img = mViewerWindow->screenshot();
459
    QImage img = mViewerWindow->screenshot();
460
    img.save(file_name);
460
    img.save(file_name);
461
#endif
461
#endif
462
}
462
}
463
463
464
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
464
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
465
{
465
{
466
#ifdef ILAND_GUI
466
#ifdef ILAND_GUI
467
    if (mViewerWindow) {
467
    if (mViewerWindow) {
468
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
468
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
469
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
469
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
470
    }
470
    }
471
#endif
471
#endif
472
}
472
}
473
473
474
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
474
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
475
{
475
{
476
#ifdef ILAND_GUI
476
#ifdef ILAND_GUI
477
477
478
    if (mViewerWindow) {
478
    if (mViewerWindow) {
479
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
479
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
480
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
480
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
481
    }
481
    }
482
#endif
482
#endif
483
}
483
}
484
484
485
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
485
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
486
{
486
{
487
#ifdef ILAND_GUI
487
#ifdef ILAND_GUI
488
    if (mViewerWindow)
488
    if (mViewerWindow)
489
        mViewerWindow->addLayers(layers, name);
489
        mViewerWindow->addLayers(layers, name);
490
    //qDebug() << layers->names();
490
    //qDebug() << layers->names();
491
#endif
491
#endif
492
}
492
}
493
493
494
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
494
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
495
{
495
{
496
#ifdef ILAND_GUI
496
#ifdef ILAND_GUI
497
    if (mViewerWindow)
497
    if (mViewerWindow)
498
        mViewerWindow->setViewport(center_point, scale_px_per_m);
498
        mViewerWindow->setViewport(center_point, scale_px_per_m);
499
#endif
499
#endif
500
}
500
}
501
501
502
void ModelController::repaint()
502
void ModelController::repaint()
503
{
503
{
504
#ifdef ILAND_GUI
504
#ifdef ILAND_GUI
505
    if (mViewerWindow)
505
    if (mViewerWindow)
506
        mViewerWindow->repaint();
506
        mViewerWindow->repaint();
507
#endif
507
#endif
508
}
508
}
509
509
510
510
511
511
512
 
512