Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
269 werner 2
#include "global.h"
3
#include "environment.h"
280 werner 4
#include "helper.h"
5
#include "csvfile.h"
567 werner 6
#include "gisgrid.h"
269 werner 7
 
8
#include "climate.h"
280 werner 9
#include "speciesset.h"
269 werner 10
 
11
/** Represents the physical simulation site with regard to climate, soil properties and such.
12
    Data is read from various sources and presented to the core model with a standardized interface.
13
*/
14
Environment::Environment()
15
{
567 werner 16
    mInfile = 0;
17
    mGrid = 0;
18
    mGridMode = false;
19
    mCurrentSpeciesSet = 0;
20
    mCurrentClimate = 0;
569 werner 21
    mCurrentID = 0;
269 werner 22
}
280 werner 23
Environment::~Environment()
24
{
314 werner 25
    if (mInfile) {
280 werner 26
        delete mInfile;
314 werner 27
    }
567 werner 28
    if (mGrid)
29
        delete mGrid;
280 werner 30
}
31
 
32
bool Environment::loadFromFile(const QString &fileName)
33
{
284 werner 34
    QString source = Helper::loadTextFile(GlobalSettings::instance()->path(fileName));
280 werner 35
    if (source.isEmpty())
36
        throw IException(QString("Environment: input file does not exist or is empty (%1)").arg(fileName));
37
    return loadFromString(source);
38
}
39
 
281 werner 40
// ******** specific keys *******
41
const QString speciesKey = "model.species.source";
42
const QString climateKey = "model.climate.tableName";
43
 
280 werner 44
bool Environment::loadFromString(const QString &source)
45
{
46
    try {
47
        if (mInfile)
48
            delete mInfile;
49
        mInfile = new CSVFile();
50
 
51
        mInfile->loadFromString(source);
52
        mKeys = mInfile->captions();
53
 
54
        XmlHelper xml(GlobalSettings::instance()->settings());
55
        mSpeciesSets.clear(); // note: the objects are not destroyed - potential memory leak.
56
        mClimate.clear();
57
        mRowCoordinates.clear();
281 werner 58
        mCreatedObjects.clear();
59
 
280 werner 60
        int index;
567 werner 61
        if (mGridMode) {
62
            int id = mInfile->columnIndex("id");
63
            if (id<0)
64
                throw IException("Environment:: (grid mode) input file has no 'id' column!");
65
            for (int row=0;row<mInfile->rowCount();row++) {
66
                mRowCoordinates[mInfile->value(row, id).toString()] = row;
67
            }
68
 
69
        } else {
70
            // ***  Matrix mode ******
71
            // each row must contain 'x' and 'y' coordinates
72
            // setup coordinates (x,y)
73
            int ix,iy;
74
            ix = mInfile->columnIndex("x");
75
            iy = mInfile->columnIndex("y");
76
            if (ix<0 || iy<0)
77
                throw IException("Environment:: (matrix mode) input file has no x/y coordinates!");
78
            for (int row=0;row<mInfile->rowCount();row++) {
79
                QString key=QString("%1_%2")
280 werner 80
                        .arg(mInfile->value(row, ix).toString())
81
                        .arg(mInfile->value(row, iy).toString());
567 werner 82
                mRowCoordinates[key] = row;
83
            }
280 werner 84
        }
85
 
86
 
281 werner 87
 
280 werner 88
        // ******** setup of Species Sets *******
89
        if ((index = mKeys.indexOf(speciesKey))>-1) {
90
            DebugTimer t("environment:load species");
91
            QStringList speciesNames = mInfile->column(index);
92
            speciesNames.removeDuplicates();
93
            qDebug() << "creating species sets:" << speciesNames;
94
            foreach (const QString &name, speciesNames) {
95
                xml.setNodeValue(speciesKey,name); // set xml value
96
                // create species sets
97
                SpeciesSet *set = new SpeciesSet();
98
                mSpeciesSets.push_back(set);
281 werner 99
                mCreatedObjects[name] = (void*)set;
318 werner 100
                set->setup();
280 werner 101
            }
102
            qDebug() << mSpeciesSets.count() << "species sets created.";
314 werner 103
        } else {
104
            // no species sets specified
105
            SpeciesSet *speciesSet = new SpeciesSet();
318 werner 106
            mSpeciesSets.push_back(speciesSet);
315 werner 107
            speciesSet->setup();
314 werner 108
            mCurrentSpeciesSet = speciesSet;
280 werner 109
        }
110
 
111
        // ******** setup of Climate *******
112
        if ((index = mKeys.indexOf(climateKey))>-1) {
113
            DebugTimer t("environment:load climate");
114
            QStringList climateNames = mInfile->column(index);
115
            climateNames.removeDuplicates();
116
            qDebug() << "creating climatae: " << climateNames;
117
            foreach (QString name, climateNames) {
118
                xml.setNodeValue(climateKey,name); // set xml value
119
                // create climate sets
120
                Climate *climate = new Climate();
121
                mClimate.push_back(climate);
316 werner 122
                mCreatedObjects[name]=(void*)climate;
318 werner 123
                climate->setup();
280 werner 124
            }
125
            qDebug() << mClimate.count() << "climates created";
314 werner 126
        } else {
127
            // no climate defined - setup default climate
128
            Climate *c = new Climate();
318 werner 129
            mClimate.push_back(c);
314 werner 130
            c->setup();
131
            mCurrentClimate = c;
280 werner 132
        }
567 werner 133
        if (!mCurrentClimate && mClimate.count()>0)
134
            mCurrentClimate = mClimate[0];
135
        if (!mCurrentSpeciesSet && mSpeciesSets.count()>0)
136
            mCurrentSpeciesSet = mSpeciesSets[0];
280 werner 137
        return true;
138
 
139
    } catch(const IException &e) {
318 werner 140
        QString addMsg;
141
        if (!mClimate.isEmpty())
142
            addMsg = QString("last Climate: %1 ").arg(mClimate.last()->name());
143
        if (!mSpeciesSets.isEmpty())
144
            addMsg += QString("last Speciesset table: %1").arg(mSpeciesSets.last()->name());
575 werner 145
        QString error_msg = QString("An error occured during the setup of the environment: \n%1\n%2").arg(e.message()).arg(addMsg);
280 werner 146
        qDebug() << error_msg;
147
        Helper::msg(error_msg);
148
        return false;
149
    }
150
}
151
 
340 werner 152
/** sets the "pointer" to a "position" (metric coordinates).
153
    All specified values are set (also the climate/species-set pointers).
154
*/
280 werner 155
void Environment::setPosition(const QPointF position)
156
{
281 werner 157
    // no changes occur, when the "environment" is not loaded
158
    if (!isSetup())
159
        return;
567 werner 160
    QString key;
568 werner 161
    int ix=-1, iy=-1, id=-1;
567 werner 162
    if (mGridMode) {
163
        // grid mode
164
        id = mGrid->value(position);
569 werner 165
        mCurrentID = id;
567 werner 166
        key = QString::number(id);
167
        if (id==-1)
168
            return; // no data for the resource unit
169
    } else {
170
        // access data in the matrix by resource unit indices
171
        ix = int(position.x() / 100.); // suppose size of 1 ha for each coordinate
172
        iy = int(position.y() / 100.);
173
        key=QString("%1_%2").arg(ix).arg(iy);
174
    }
280 werner 175
 
176
    if (mRowCoordinates.contains(key)) {
177
        XmlHelper xml(GlobalSettings::instance()->settings());
178
        int row = mRowCoordinates[key];
179
        QString value;
550 werner 180
        if (logLevelInfo()) qDebug() << "settting up point" << position << "with row" << row;
280 werner 181
        for (int col=0;col<mInfile->colCount(); col++) {
567 werner 182
            if (mKeys[col]=="x" || mKeys[col]=="y" || mKeys[col]=="id") // ignore "x" and "y" keys
280 werner 183
                continue;
184
            value = mInfile->value(row,col).toString();
550 werner 185
            if (logLevelInfo()) qDebug() << "set" << mKeys[col] << "to" << value;
280 werner 186
            xml.setNodeValue(mKeys[col], value);
281 werner 187
            // special handling for constructed objects:
188
            if (mKeys[col]==speciesKey)
189
                mCurrentSpeciesSet = (SpeciesSet*)mCreatedObjects[value];
190
            if (mKeys[col]==climateKey)
191
                mCurrentClimate = (Climate*)mCreatedObjects[value];
192
 
280 werner 193
        }
194
 
567 werner 195
    } else {
196
        if (mGridMode)
197
            throw IException(QString("Environment:setposition: invalid grid id (or not present in input file): %1m/%2m (mapped to id %3).")
198
                             .arg(position.x()).arg(position.y()).arg(id));
199
        else
200
            throw IException(QString("Environment:setposition: invalid coordinates (or not present in input file): %1m/%2m (mapped to indices %3/%4).")
201
                             .arg(position.x()).arg(position.y()).arg(ix).arg(iy));
202
    }
280 werner 203
}
567 werner 204
 
205
bool Environment::setGridMode(const QString &grid_file_name)
206
{
207
    mGrid = new GisGrid();
208
    mGrid->loadFromFile(grid_file_name);
209
    mGridMode = true;
210
    return true;
211
}