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