Gis.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2008 by Antonello Lobianco                         *
00003  *   http://regmas.org                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 3 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <algorithm> //alghoritm used to shuffle (randomize) the array
00021 #include <QtCore>
00022 #include <math.h>
00023 
00024 #include "Gis.h"
00025 #include "Pixel.h"
00026 
00027 //#include "InputDocument.h"
00028 #include "MainWindow.h"
00029 #include "Agent_space.h"
00030 #include "SuperAgentManager.h"
00031 #include "Scheduler.h"
00032 
00033 using namespace std;
00034 
00040 Gis::Gis(ThreadManager* MTHREAD_h)
00041 {
00042     MTHREAD=MTHREAD_h;
00043     subRegionMode = false;
00044 }
00045 
00046 Gis::~Gis()
00047 {
00048 }
00049 
00059 void
00060 Gis::setSpace(){
00061 
00062 
00063 
00064     msgOut(MSG_INFO,"Creating the space...");
00065 
00066     // init basic settings....
00067     geoTopY = MTHREAD->RD->getDoubleSetting("geoNorthEdge");
00068     geoBottomY = MTHREAD->RD->getDoubleSetting("geoSouthEdge");
00069     geoLeftX = MTHREAD->RD->getDoubleSetting("geoWestEdge");
00070     geoRightX = MTHREAD->RD->getDoubleSetting("geoEastEdge");
00071     xNPixels = MTHREAD->RD->getIntSetting("nCols");
00072     yNPixels = MTHREAD->RD->getIntSetting("nRows");
00073     noValue = MTHREAD->RD->getDoubleSetting("noValue");
00074     xyNPixels = xNPixels * yNPixels;
00075     xMetersByPixel = (geoRightX - geoLeftX)/xNPixels;
00076     yMetersByPixel = (geoTopY - geoBottomY)/yNPixels;
00077     MTHREAD->treeViewerChangeGeneralPropertyValue("total plots", d2s(getXyNPixels()));
00078     MTHREAD->treeViewerChangeGeneralPropertyValue("total land", d2s(xyNPixels*getHaByPixel()));
00079     // creating pixels...
00080     for (int i=0;i<yNPixels;i++){
00081         for (int j=0;j<xNPixels;j++){
00082             Pixel myPixel(i*xNPixels+j, MTHREAD);
00083             myPixel.setCoordinates(j,i);
00084             pxVector.push_back(myPixel);
00085         }
00086     }
00087 
00088     initLayers();
00089     loadLayersDataFromFile();
00090     MTHREAD->fitInWindow(); // tell the gui to fit the map to the widget
00091     countItems("landUse",false); // count the various records assigned to each legendItem. Do not print debug infos
00092     return;
00093 };
00094 
00103 void
00104 Gis::initLayers(){
00105     // setting layers...
00106     //string filename_complete= MTHREAD->RD->getFilenameByType("gis");
00107     string filename_complete = MTHREAD->getBaseDirectory()+MTHREAD->RD->getStringSetting("gisFilename");
00108 
00109     InputNode gisDocument;
00110     bool test=gisDocument.setWorkingFile(filename_complete);
00111     if (!test){msgOut(MSG_CRITICAL_ERROR, "Error opening the gis file "+filename_complete+".");}
00112     vector<InputNode> layerNodes = gisDocument.getNodesByName("layer");
00113     for (uint i=0; i<layerNodes.size();i++){
00114         
00115         string name = layerNodes.at(i).getNodeByName("name").getStringContent();
00116         string label = layerNodes.at(i).getNodeByName("label").getStringContent();
00117         bool isInteger = layerNodes.at(i).getNodeByName("isInteger").getBoolContent();
00118         bool dynamicContent = layerNodes.at(i).getNodeByName("dynamicContent").getBoolContent();
00119         string readAtStart = layerNodes.at(i).getNodeByName("readAtStart").getStringContent();
00120         if (readAtStart != "true") continue;
00121         string dirName = layerNodes.at(i).getNodeByName("dirName").getStringContent();
00122         string fileName = layerNodes.at(i).getNodeByName("fileName").getStringContent();
00123         //cout <<"getBaseDirectory(): " << MTHREAD->RD->getBaseDirectory() << endl;
00124         
00125         string fullFileName = MTHREAD->RD->getBaseDirectory()+dirName+fileName;
00126         //cout <<"fullFileName: " << fullFileName << endl;
00127         addLayer(name,label,isInteger,dynamicContent,fullFileName);
00128         //legend..
00129         vector<InputNode> legendItemsNodes = layerNodes.at(i).getNodesByName("legendItem");
00130         for (uint j=0; j<legendItemsNodes.size();j++){
00131             int lID = legendItemsNodes.at(j).getIntContent();
00132             string llabel = legendItemsNodes.at(j).getStringAttributeByName("label");
00133             int rColor = legendItemsNodes.at(j).getIntAttributeByName("rColor");
00134             int gColor = legendItemsNodes.at(j).getIntAttributeByName("gColor");
00135             int bColor = legendItemsNodes.at(j).getIntAttributeByName("bColor");
00136             double minValue, maxValue;
00137             if (isInteger){
00138                 minValue = ((double)lID);
00139                 maxValue = ((double)lID);
00140             }
00141             else {
00142                 minValue = legendItemsNodes.at(j).getDoubleAttributeByName("minValue");
00143                 maxValue = legendItemsNodes.at(j).getDoubleAttributeByName("maxValue");
00144             }
00145             addLegendItem(name, lID, llabel, rColor, gColor, bColor, minValue, maxValue);
00146         }
00147         //reclassification rule..
00148         vector<InputNode> reclassificationRulesNodes = layerNodes.at(i).getNodesByName("reclassRule");
00149         for (uint z=0; z<reclassificationRulesNodes.size();z++){
00150             int inCode = reclassificationRulesNodes.at(z).getIntContent();
00151             int outCode = reclassificationRulesNodes.at(z).getIntAttributeByName("outCode");
00152             double p = reclassificationRulesNodes.at(z).getDoubleAttributeByName("p");
00153             addReclassificationRule(name, inCode, outCode, p);
00154         }
00155     }
00156 
00157     //initializing spatial activities layer...
00158     addLayer("farmActivities","Spatial farm activities",true, true);
00159     vector<RegActivities*> activities = MTHREAD->RD->getRegActivities();
00160     for(uint i=0; i<activities.size(); i++){
00161         if(activities[i]->getSpatiallyExplicit()){
00162             int lID = activities[i]->getMapCode();
00163             string llabel = activities[i]->getName();
00164             int rColor = activities[i]->getMapRColor();
00165             int gColor = activities[i]->getMapGColor();
00166             int bColor = activities[i]->getMapBColor();
00167             addLegendItem("farmActivities", lID, llabel, rColor, gColor, bColor, ((double)lID), ((double)lID));
00168         }
00169     }
00170     // adding a "mixed" activitiescategory for thos plots that are growed with several products and no-one is more than 60%
00171     addLegendItem("farmActivities", 900, "Mixed farming activities", 120, 180, 30, ((double)900), ((double)900));
00172 
00173     int mByPx;
00174     if(xMetersByPixel>yMetersByPixel){
00175         mByPx = xMetersByPixel;
00176     }
00177     else {
00178         mByPx = yMetersByPixel;
00179     }
00180     addLayer("distanceToFarm","(Experimental) Distance from the closest farm",false,true);
00181     addLegendItem("distanceToFarm", 1, "0 - "+d2s(((double)1)*mByPx)+" meters", 0,0,0, 0, 1*mByPx);
00182     addLegendItem("distanceToFarm", 2, d2s(((double)1)*mByPx)+" - "+d2s(((double)2)*mByPx)+" meters", 50,50,50, 1*mByPx, 2*mByPx);
00183     addLegendItem("distanceToFarm", 3, d2s(((double)2)*mByPx)+" - "+d2s(((double)5)*mByPx)+" meters", 100,100,100, 2*mByPx, 5*mByPx);
00184     addLegendItem("distanceToFarm", 4, d2s(((double)5)*mByPx)+" - "+d2s(((double)10)*mByPx)+" meters", 200,200,200, 5*mByPx, 10*mByPx);
00185     addLegendItem("distanceToFarm", 5, "Over "+d2s(((double)10)*mByPx)+" meters", 250,250,250, 10*mByPx, 1000000*mByPx);
00186 
00187 }
00188 
00201 void
00202 Gis::addLayer(string name_h, string label_h, bool isInteger_h, bool dynamicContent_h, string fullFileName_h){
00203 
00204     for(uint i=0; i<layerVector.size(); i++){
00205         if (layerVector.at(i).getName() == name_h){
00206             msgOut(MSG_ERROR, "Layer already exist with that name");
00207             return;
00208         }
00209     }
00210     Layers LAYER (MTHREAD, name_h, label_h, isInteger_h, dynamicContent_h, fullFileName_h); 
00211     layerVector.push_back(LAYER);
00212 
00213     for (uint i=0;i<xyNPixels; i++){
00214         pxVector.at(i).setValue(name_h,noValue);
00215     }
00216     MTHREAD->addLayer(name_h,label_h);
00217     
00218 }
00219 
00220 void
00221 Gis::resetLayer(string layerName_h){
00222 
00223     for(uint i=0; i<layerVector.size(); i++){
00224         if (layerVector.at(i).getName() == layerName_h){
00225             for (uint i=0;i<xyNPixels; i++){
00226                 pxVector.at(i).changeValue(layerName_h,noValue); // bug solved 20071022, Antonello
00227             }
00228             return;
00229         }
00230     }
00231     msgOut(MSG_ERROR, "I could not reset layer "+layerName_h+" as it doesn't exist!");  
00232 }
00233 
00234 bool
00235 Gis::layerExist(string layerName_h){
00236     for(uint i=0; i<layerVector.size(); i++){
00237         if (layerVector.at(i).getName() == layerName_h){
00238             return true;
00239         }
00240     }
00241     return false;
00242 }
00243 
00251 void
00252 Gis::addLegendItem(string name_h, int ID_h, string label_h, int rColor_h, int gColor_h, int bColor_h, double minValue_h, double maxValue_h){
00253     
00254     for(uint i=0; i<layerVector.size(); i++){
00255         if (layerVector.at(i).getName() == name_h){
00256             layerVector.at(i).addLegendItem(ID_h, label_h, rColor_h, gColor_h, bColor_h, minValue_h, maxValue_h);
00257             return;
00258         }
00259     }
00260     msgOut(MSG_ERROR, "Trying to add a legend item to a layer that doesn't exist.");
00261     return;
00262 }
00263 
00271 void
00272 Gis::countItems(string layerName_h, bool debug){
00273 
00274     for(uint i=0; i<layerVector.size(); i++){
00275         if (layerVector.at(i).getName() == layerName_h){
00276             layerVector.at(i).countMyPixels(debug);
00277             return;
00278         }
00279     }
00280     msgOut(MSG_ERROR, "Trying to get statistics (count pixels) of a layer that doesn't exist.");
00281     return;
00282 }
00283 
00290 void
00291 Gis::addReclassificationRule(string name_h, int inCode_h, int outCode_h, double p_h){
00292     for(uint i=0; i<layerVector.size(); i++){
00293         if (layerVector.at(i).getName() == name_h){
00294             layerVector.at(i).addReclassificationRule(inCode_h, outCode_h, p_h);
00295             return;
00296         }
00297     }
00298     msgOut(MSG_ERROR, "Trying to add a reclassification rule to a layer that doesn't exist.");
00299     return; 
00300 }
00301 
00313 void
00314 Gis::loadLayersDataFromFile(){
00315     double localNoValue = noValue;
00316     double inputValue;
00317     double outputValue;
00318     QColor color;
00319 
00320     for(uint i=0;i<layerVector.size();i++){
00321         string layerName =layerVector.at(i).getName();
00322         string fileName=layerVector.at(i).getFilename();
00323         if(fileName == "") return;
00324         QFile file(fileName.c_str());
00325         if (!file.open(QFile::ReadOnly)) {
00326             cerr << "Cannot open file for reading: "
00327                 << qPrintable(file.errorString()) << endl;
00328             msgOut(MSG_ERROR, "Cannot open map file "+fileName+" for reading.");
00329             continue;
00330         }
00331         QTextStream in(&file);
00332         int countRow = 0;
00333         QImage image = QImage(xNPixels, yNPixels, QImage::Format_RGB32);
00334         image.fill(qRgb(255, 255, 255));
00335         while (!in.atEnd()) {
00336             QString line = in.readLine();
00337             QStringList fields = line.split(' ');
00338             if ( 
00339                 (fields.at(0)== "north:" && fields.at(1).toDouble() != geoTopY)
00340                 || ((fields.at(0)== "south:" || fields.at(0) == "yllcorner" ) && fields.at(1).toDouble() != geoBottomY)
00341                 || (fields.at(0)== "east:" && fields.at(1).toDouble() != geoRightX)
00342                 || ((fields.at(0)== "west:" || fields.at(0) == "xllcorner" ) && fields.at(1).toDouble() != geoLeftX)
00343                 || ((fields.at(0)== "rows:" || fields.at(0) == "nrows" ) && fields.at(1).toInt() != yNPixels)
00344                 || ((fields.at(0)== "cols:" || fields.at(0) == "ncols" ) && fields.at(1).toInt() != xNPixels)
00345             )
00346             {
00347                 msgOut(MSG_ERROR, "Layer "+layerName+" has different coordinates. Aborting reading.");
00348                 break;
00349             } else if (fields.at(0)== "null:" || fields.at(0) == "NODATA_value" || fields.at(0) == "nodata_value" ) {
00350                 localNoValue = fields.at(1).toDouble();
00351             } else if (fields.size() > 5) {
00352                 for (int countColumn=0;countColumn<xNPixels;countColumn++){
00353                     inputValue = fields.at(countColumn).toDouble();
00354                     if (inputValue == localNoValue){
00355                         outputValue = noValue;
00356                         pxVector.at((countRow*xNPixels+countColumn)).changeValue(layerName,outputValue);
00357                         QColor nocolor(255,255,255);
00358                         color = nocolor;
00359                     }
00360                     else {
00361                         outputValue=layerVector.at(i).filterExogenousDataset(fields.at(countColumn).toDouble());
00362                         pxVector.at((countRow*xNPixels+countColumn)).changeValue(layerName,outputValue);
00363                         color = layerVector.at(i).getColor(outputValue);
00364                     }
00365                     image.setPixel(countColumn,countRow,color.rgb());
00366                 }
00367                 countRow++;
00368             }
00369         }
00370         if (MTHREAD->RD->getBoolSetting("initialRandomShuffle") ){
00371             layerVector.at(i).randomShuffle();
00372         }
00373         MTHREAD->updateImage(layerName,image);
00374         this->filterSubRegion(layerName);
00375         //send the image to the gui...
00376         refreshGUI();
00377 
00378 
00379     }
00380 }
00381 
00387 void
00388 Gis::updateImage(string layerName_h){
00389     msgOut (1, "Update image "+layerName_h+"...");
00390 
00391     // sub{X,Y}{R,L,T,B} refer to the subregion coordinates, but when this is not active they coincide with the whole region
00392     QImage image = QImage(subXR-subXL+1, subYB-subYT+1, QImage::Format_RGB32);
00393 
00394     image.fill(qRgb(255, 255, 255));
00395     int layerIndex=-1;
00396     for (uint i=0;i<layerVector.size();i++){
00397         if (layerVector.at(i).getName() == layerName_h){
00398             layerIndex=i;
00399             break;
00400         }
00401     }
00402     if (layerIndex <0) msgOut(MSG_CRITICAL_ERROR, "Layer not found in Gis::updateImage()");
00403 
00404     for (int countRow=subYT;countRow<subYB;countRow++){
00405         for (int countColumn=subXL;countColumn<subXR;countColumn++){            
00406             double value = pxVector.at((countRow*xNPixels+countColumn)).getDoubleValue(layerName_h);
00407             QColor color = layerVector.at(layerIndex).getColor(value);
00408             image.setPixel(countColumn-subXL,countRow-subYT,color.rgb());
00409         }
00410     }
00411     MTHREAD->updateImage(layerName_h,image);
00412     refreshGUI();
00413 }
00414 
00415 Pixel*
00416 Gis::getRandomPlotByValue(string layer_h, int layerValue_h, bool onlyFreePlots){
00417     
00418     vector <Pixel* > candidates;
00419     vector <uint> counts;
00420     for(uint i=0;i<pxVector.size();i++) counts.push_back(i);
00421     random_shuffle(counts.begin(), counts.end()); // randomize the elements of the array.
00422 
00423     if (onlyFreePlots){
00424         for (uint i=0;i<counts.size();i++){
00425             if(pxVector.at(counts.at(i)).getDoubleValue(layer_h) == layerValue_h ) {
00426                 if (!pxVector.at(counts.at(i)).getOwner() && !pxVector.at(counts.at(i)).getTenant()) {
00427                     return &pxVector.at(counts.at(i));
00428                 }
00429             }
00430         }
00431     }
00432     else {
00433         for (uint i=0;i<counts.size();i++){
00434             if(pxVector.at(counts.at(i)).getDoubleValue(layer_h) == layerValue_h ) {
00435                     return &pxVector.at(counts.at(i));
00436             }
00437         }
00438     }
00439 
00440     msgOut(MSG_CRITICAL_ERROR,"We can't find any plot with "+d2s(layerValue_h)+" value on layer "+layer_h+".");
00441     Pixel* toReturn;
00442     toReturn =0;
00443     return toReturn;
00444 }
00454 vector <Pixel*>
00455 Gis::getAllPlotsByValue(string layer_h, int layerValue_h, bool onlyFreePlots, int outputLevel){
00456     // this would be easier to mantain and cleaned code, but slighly slower:
00457     //vector<int> layerValues;
00458     //layerValues.push_back(layerValue_h);
00459     //return getAllPlotsByValue(layer_h, layerValues, onlyFreePlots, outputLevel);
00460 
00461     vector <Pixel* > candidates;
00462     if (onlyFreePlots){
00463         for (uint i=0;i<pxVector.size();i++){
00464             if(pxVector.at(i).getDoubleValue(layer_h) == layerValue_h && ! pxVector.at(i).getOwner() && !pxVector.at(i).getTenant()){
00465                 candidates.push_back(&pxVector.at(i));
00466             }
00467         }
00468     }
00469     else {
00470         for (uint i=0;i<pxVector.size();i++){
00471             if(pxVector.at(i).getDoubleValue(layer_h) == layerValue_h){
00472                 candidates.push_back(&pxVector.at(i));
00473             }
00474         }
00475     }
00476     if (candidates.size()>0){
00477         random_shuffle(candidates.begin(), candidates.end()); // randomize ther elements of the array... cool !!! ;-)))
00478     }
00479     else {
00480         msgOut(outputLevel,"We can't find any free plot with "+d2s(layerValue_h)+" value on layer "+layer_h+".");
00481     }
00482     return candidates;
00483 }
00484 
00494 vector <Pixel*>
00495 Gis::getAllPlotsByValue(string layer_h, vector<int> layerValues_h, bool onlyFreePlots, int outputLevel){
00496     vector <Pixel* > candidates;
00497     string valuesToMatch;
00498     unsigned int z;
00499 
00500     //string of the required land values to match;
00501     for (uint j=0;j<layerValues_h.size();j++){
00502         valuesToMatch = valuesToMatch + " " + i2s(layerValues_h.at(j));
00503     }
00504 
00505     if (onlyFreePlots){
00506         for (uint i=0;i<pxVector.size();i++){
00507             z = valuesToMatch.find(d2s(pxVector.at(i).getDoubleValue(layer_h))); // search if in the string of required values is included also the value of the current plot
00508             if( z!=string::npos && ! pxVector.at(i).getOwner() && !pxVector.at(i).getTenant()){
00509                 candidates.push_back(&pxVector.at(i));
00510             }
00511         }
00512     }
00513     else {
00514         for (uint i=0;i<pxVector.size();i++){
00515             z = valuesToMatch.find(d2s(pxVector.at(i).getDoubleValue(layer_h))); // search if in the string of required values is included also the value of the current plot
00516             if(z!=string::npos){ //z is not at the end of the string, means found!
00517                 candidates.push_back(&pxVector.at(i));
00518             }
00519         }
00520     }
00521 
00522     if (candidates.size()>0){
00523         random_shuffle(candidates.begin(), candidates.end()); // randomize ther elements of the array... cool !!! ;-)))
00524     }
00525     else {
00526         msgOut(outputLevel,"We can't find any free plot with the specified values ("+valuesToMatch+") on layer "+layer_h+".");
00527     }
00528     return candidates;
00529 }
00530 
00537 vector <Pixel*>
00538 Gis::getAllPlots(bool onlyFreePlots, int outputLevel){
00539     vector <Pixel* > candidates;
00540     if (onlyFreePlots){
00541         for (uint i=0;i<pxVector.size();i++){
00542             if(! pxVector.at(i).getOwner() && !pxVector.at(i).getTenant()){
00543                 candidates.push_back(&pxVector.at(i));
00544             }
00545         }
00546     }
00547     else {
00548         for (uint i=0;i<pxVector.size();i++){
00549             candidates.push_back(&pxVector.at(i));
00550         }
00551     }
00552     if (candidates.size()>0){
00553         random_shuffle(candidates.begin(), candidates.end()); // randomize ther elements of the array... cool !!! ;-)))
00554     }
00555     else {
00556         msgOut(outputLevel,"We can't find any free plot.");
00557     }
00558     return candidates;
00559 }
00560 
00561 
00562 
00563 vector <string>
00564 Gis::getLayerNames(){
00565     vector <string> toReturn;
00566     for (uint i=0;i<layerVector.size();i++){
00567         toReturn.push_back(layerVector[i].getName());
00568     }
00569     return toReturn;
00570 }
00571 
00572 vector <Layers*>
00573 Gis::getLayerPointers(){
00574     vector <Layers*> toReturn;
00575     for (uint i=0;i<layerVector.size();i++){
00576         toReturn.push_back(&layerVector[i]);
00577     }
00578     return toReturn;
00579 }
00580 
00581 void
00582 Gis::printDebugValues (string layerName_h, int min_h, int max_h){
00583     int min=min_h;
00584     int max;
00585     int ID, X, Y;
00586     string out;
00587     double value;
00588     double noValue = MTHREAD->RD->getDoubleSetting("noValue");
00589     if (max_h==0){
00590         max= pxVector.size();
00591     }
00592     else {
00593         max = max_h;
00594     }
00595     msgOut(MSG_DEBUG,"Printing debug information for layer "+layerName_h+".");
00596     for (int i=min;i<max;i++){
00597         value = pxVector.at(i).getDoubleValue(layerName_h);
00598         if (value != noValue){ 
00599             ID    = i;
00600             X     = pxVector.at(i).getX();
00601             Y     = pxVector.at(i).getY();
00602             out = "Px. "+i2s(ID)+" ("+i2s(X)+","+i2s(Y)+"): "+d2s(value);
00603             msgOut(MSG_DEBUG,out);
00604         }
00605     }
00606 }
00607 
00614 void
00615 Gis::filterSubRegion(string layerName_h){
00616     if (MTHREAD->RD->getBoolSetting("subRegionMode")){
00617         subRegionMode = true;
00618         subXL  = MTHREAD->RD->getIntSetting("subRegionXLeft");
00619         subXR   = MTHREAD->RD->getIntSetting("subRegionXRight");
00620         subYT = MTHREAD->RD->getIntSetting("subRegionYTop");
00621         subYB = MTHREAD->RD->getIntSetting("subRegionYBottom");
00622         for (int y=0;y<yNPixels;y++){
00623             for (int x=0;x<xNPixels;x++){
00624                 if (x>=subXL && x<= subXR && y>=subYT && y<=subYB){
00625                 }
00626                 else {
00627                     this->getPixel(x,y)->changeValue(layerName_h, noValue);
00628                 }
00629             }
00630         }
00631         updateImage(layerName_h);
00632     }
00633     else {
00634         subXL = 0;
00635         subYT = 0;
00636         subXR = xNPixels-1;
00637         subYB = yNPixels-1; 
00638     }
00639 }
00640 
00641 double
00642 Gis::getDistance(const Pixel* px1, const Pixel* px2){
00643     return sqrt (
00644                 pow ( (((double)px1->getX()) - ((double)px2->getX()))*xMetersByPixel,2)
00645                 +
00646                 pow ( (((double)px1->getY()) - ((double)px2->getY()))*yMetersByPixel,2)
00647             );
00648 }
00649 
00650 
00651 double
00652 Gis::getAgrDistCost(const Pixel* px1, const Pixel* px2){
00653     return getDistance(px1, px2) * MTHREAD->RD->getDoubleSetting("agrDistCost");
00654 }
00662 vector <Agent_space*>
00663 Gis::getClosestAgents(Pixel* px_h, int size, const string &category){
00664 
00665     map <double, Agent_space*> mapOfAgentDistance;
00666     vector <Agent_space*> toReturn;
00667     vector <Agent_base*> agents= MTHREAD->SAM->getAgentsByType(true, category);
00668     for(uint i=0;i<agents.size();i++){
00669         Agent_space* currentAgent = dynamic_cast<Agent_space*> (agents.at(i));
00670         if (currentAgent){
00671             double distance= currentAgent->getDistance(px_h);
00672             mapOfAgentDistance.insert(pair<double, Agent_space*>(distance, currentAgent));
00673         }
00674     }
00675 
00676     map<double, Agent_space*>::iterator p;
00677     int counter = 0;
00678     for(p=mapOfAgentDistance.begin();p!=mapOfAgentDistance.end();p++){ // loop over a map
00679             toReturn.push_back(p->second);
00680             counter ++;
00681             if (counter >= size) break;
00682     }
00683     return toReturn;
00684 }
00685 
00686 vector<double>
00687 Gis::getAgrLandStats(){
00688     vector<double> toReturn;
00689     int totalAgrPlots=0, ownedAgrPlots=0, rentedAgrPlots=0;
00690 
00691     for(uint i=0; i< pxVector.size(); i++){
00692         if (pxVector.at(i).isAgricultural()){
00693             totalAgrPlots++;
00694             if (pxVector.at(i).getOwner()){
00695                 ownedAgrPlots++;
00696             }
00697             else if (pxVector.at(i).getTenant()){ // FIXME: it doesn't count plots owned by the collectorAgent and still normally rented !!!!
00698                 rentedAgrPlots++;
00699             }
00700         }
00701     }
00702     toReturn.push_back(totalAgrPlots*getHaByPixel());
00703     toReturn.push_back(ownedAgrPlots*getHaByPixel());
00704     toReturn.push_back(rentedAgrPlots*getHaByPixel());
00705 
00706     return toReturn;
00707 
00708 }
00709 
00710 void
00711 Gis::printLayers(string layerName_h){
00712     msgOut(MSG_DEBUG,"Printing the layers");
00713     int iteration = MTHREAD->SCD->getIteration(); // are we on the first year of the simulation ??
00714     if(layerName_h == ""){
00715         for (uint i=0;i<layerVector.size();i++){
00716             // not printing if we are in a not-0 iteration and the content of the map doesn't change
00717             if (!iteration || layerVector[i].getDynamicContent()) layerVector[i].print();
00718         }
00719     } else {
00720         for (uint i=0;i<layerVector.size();i++){
00721             if(layerVector[i].getName() == layerName_h){
00722                 if (!iteration || layerVector[i].getDynamicContent()) layerVector[i].print();
00723                 return;
00724             }
00725         }
00726         msgOut(MSG_ERROR, "Layer "+layerName_h+" unknow. No layer printed.");
00727     }
00728 }
00729 
00730 void
00731 Gis::printBinMaps(string layerName_h){
00732     msgOut(MSG_DEBUG,"Printing the maps as images");
00733     int iteration = MTHREAD->SCD->getIteration(); // are we on the first year of the simulation ??
00734     if(layerName_h == ""){
00735         for (uint i=0;i<layerVector.size();i++){
00736             if (!iteration || layerVector[i].getDynamicContent()) {layerVector[i].printBinMap();}
00737         }
00738     } else {
00739         for (uint i=0;i<layerVector.size();i++){
00740             if(layerVector[i].getName() == layerName_h){
00741                 if (!iteration || layerVector[i].getDynamicContent()) {layerVector[i].printBinMap();}
00742                 return;
00743             }
00744         }
00745         msgOut(MSG_ERROR, "Layer "+layerName_h+" unknow. No layer printed.");
00746     }
00747 }
00748 
00749 int
00750 Gis::sub2realID(int id_h){
00751     // IMPORTANT: this function is called at refreshGUI() times, so if there are output messages, call them with the option to NOT refresh the gui, otherwise we go to an infinite loop...
00752     if (!MTHREAD->RD->getBoolSetting("subRegionMode")) {return id_h;}
00753     int subX, subY, realX, realY;
00754     subX = id_h%((subXR-subXL)+1);
00755     subY = id_h/((subXR-subXL)+1);
00756 
00757     realX = subX+subXL;
00758     realY = subY+subYT;
00759 
00760     if ( (realX<subXL) || (realX>subXR) || (realY < subYT) || (realY>subYB)  ){
00761         msgOut(MSG_ERROR, "Calling sub2realID() function with an ID that is out of subregion range!!", false);
00762         return -1;
00763     }
00764     return realX+realY*xNPixels;
00765 
00766 }
00767 
00768 
00769 bool
00770 Gis::isAgrCode(int code_h){
00771     vector<int> agrLandTypes = MTHREAD->RD->getIntVectorSetting("agrLandTypes");
00772     for (uint i=0;i<agrLandTypes.size();i++){
00773         if(agrLandTypes[i] == code_h) return true;
00774     }
00775     return false;
00776 }
00777 
00778 void
00779 Gis::calculateDistancesToClosestFarm(){
00780     for (uint i=0;i<pxVector.size();i++) {
00781         if(!pxVector[i].isAgricultural()) continue;
00782         vector<Agent_space*> closestAgents = getClosestAgents(&pxVector[i],1,"farmer");
00783         double distance = getDistance(closestAgents.at(0)->getHomePlot(),&pxVector[i]);
00784         pxVector[i].changeValue("distanceToFarm",distance);
00785     }
00786 
00787 }