Pixel.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 "Pixel.h"
00021 #include "ThreadManager.h"
00022 #include "Scheduler.h"
00023 #include "Init.h"
00024 
00025 Pixel::Pixel(double ID_h, ThreadManager* MTHREAD_h): ID(ID_h)
00026 {
00027     pxOwner=NULL;
00028     pxTenant=NULL;
00029     cachedAgent=NULL;
00030     MTHREAD=MTHREAD_h;
00031     rentingTerm=0;
00032     startRentingYear=0;
00033     rentalCosts=0;
00034     shRentalPriceCoeff=0;
00035 }
00036 
00037 Pixel::~Pixel()
00038 {
00039 }
00040 
00050 vector <Pixel *>
00051 Pixel::getPixelsAtDistLevel(int distLevel_h) const{
00052 
00053     if (distLevel_h<1) {
00054         msgOut(MSG_CRITICAL_ERROR, "getPixelsAtDistLevel() is defined for distances of at least 1 !");
00055     }
00056 
00057     vector <Pixel *> toReturn;
00058     int xNPixels = MTHREAD->GIS->getXNPixels();
00059     int yNPixels = MTHREAD->GIS->getYNPixels();
00060     int thisX = this->getX();
00061     int thisY = this->getY();
00062     int minX = max(0        , (thisX - distLevel_h)+1);
00063     int maxX = min(xNPixels , thisX + distLevel_h);
00064     int minY = max(0        , (thisY - distLevel_h)+1);
00065     int maxY = min(yNPixels , thisY + distLevel_h);
00066 
00067     // getting the top pixels (corner exluded)...
00068     if (thisY-distLevel_h >=0){
00069         for(int i=minX;i<maxX;i++){
00070             toReturn.push_back(MTHREAD->GIS->getPixel(i,thisY-distLevel_h));
00071         }
00072     }
00073     // getting the right pixels (corner exluded)...
00074     if (thisX+distLevel_h < xNPixels){
00075         for(int i=minY;i<maxY;i++){
00076             toReturn.push_back(MTHREAD->GIS->getPixel(thisX+distLevel_h,i));
00077         }
00078     }
00079     // getting the bottom pixels (corner exluded)...
00080     if (thisY+distLevel_h < yNPixels){
00081         for(int i=minX;i<maxX;i++){
00082             toReturn.push_back(MTHREAD->GIS->getPixel(i,thisY+distLevel_h));
00083         }
00084     }
00085     // getting the left pixels (corner exluded)...
00086     if (thisX-distLevel_h >= 0){
00087         for(int i=minY;i<maxY;i++){
00088             toReturn.push_back(MTHREAD->GIS->getPixel(thisX-distLevel_h,i));
00089         }
00090     }
00091 
00092     // getting the corners (correctly at the end, after already retrieved the other pixels..)...
00093     // top-left..
00094     if (thisX-distLevel_h >= 0 && thisY-distLevel_h >=0){
00095         toReturn.push_back(MTHREAD->GIS->getPixel(thisX-distLevel_h,thisY-distLevel_h));
00096     }
00097     // top-right..
00098     if (thisX+distLevel_h < xNPixels && thisY-distLevel_h >=0){
00099         toReturn.push_back(MTHREAD->GIS->getPixel(thisX+distLevel_h,thisY-distLevel_h));
00100     }
00101     // bottom-right..
00102     if (thisX+distLevel_h < xNPixels && thisY+distLevel_h <yNPixels){ // bug discovered 20070719
00103         toReturn.push_back(MTHREAD->GIS->getPixel(thisX+distLevel_h,thisY+distLevel_h));
00104     }
00105     // bottom-left..
00106     if (thisX-distLevel_h >= 0 && thisY+distLevel_h <yNPixels){
00107         toReturn.push_back(MTHREAD->GIS->getPixel(thisX-distLevel_h,thisY+distLevel_h));
00108     }
00109     return toReturn;
00110 } 
00111 
00112 void
00113 Pixel::setValue(string layerName_h, double value_h){
00114     values.insert(pair<string, double>(layerName_h, value_h));
00115 }
00116 
00117 void
00118 Pixel::changeValue(string layerName_h, double value_h){
00119     map<string, double>::iterator p;
00120     p=values.find(layerName_h);
00121     if(p != values.end())
00122         p->second = value_h;
00123     else 
00124         msgOut(MSG_ERROR, "Coud not change pixel value for layer "+layerName_h+". Layer don't found.");
00125     return;
00126 }
00127 
00128 double
00129 Pixel::getDoubleValue(string layerName_h) const{
00130     map<string, double>::const_iterator p;
00131     p=values.find(layerName_h);
00132     if(p != values.end())
00133         return p->second;
00134     else 
00135         msgOut(MSG_WARNING, "No layer \""+layerName_h+"\" found on pixel ("+i2s(getX())+","+i2s(getY())+"). Sure you didn't mispelled it?");
00136         return MTHREAD->GIS->getNoValue();
00137 }
00138 
00143 void
00144 Pixel::acquireObject(ModelObject acquiredObject_h, int case_h){
00145     if(case_h==STAGE_INIT){
00146         acquiredObject_h.setRandomAge();
00147     }
00148     else {
00149         acquiredObject_h.setStartYear(MTHREAD->SCD->getYear());
00150     }
00151 
00152     if (acquiredObject_h.getLastYear() > this->getLastRentingYear()){ // adjust the renting term to cover all the life period of the spatial object
00153         setRentingTerm(acquiredObject_h.getLastYear()-MTHREAD->SCD->getYear()+1);
00154     }
00155 
00156     if(pxTenant){
00157         acquiredObject_h.setOwner(((Agent_base*)this->pxTenant)); // if it is a rented plot, spatial objects are ALWAYS assigned to the tenant
00158     }
00159     else if (pxOwner){
00160         acquiredObject_h.setOwner(((Agent_base*)this->pxOwner)); // if it is a owned plot, spatial objects are assigned to the pixel owner
00161     }
00162     else {
00163         if(case_h != STAGE_INIT){ // is not an error in the intit stage, as we have objects that are not owned by anyone!
00164             msgOut(MSG_CRITICAL_ERROR, "who-ho.. who paid for a spatial object to a plot without both owners and tenants???");
00165         }
00166     }
00167     
00168     myObjects.push_back(acquiredObject_h);
00169 }
00170 
00175 void
00176 Pixel::initObjects(){
00177     int landUse = ((int)this->getDoubleValue("landUse"));
00178     vector <ModelObject> candidates = MTHREAD->RD->getModelObjectsBySoilType(landUse);
00179     if (candidates.size()>0){
00180         int randomObject = int (( (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*candidates.size());
00181         this->acquireObject(candidates.at(randomObject),STAGE_INIT);
00182     }
00183 }
00184 
00185 vector <ModelObject*>
00186 Pixel::getIncludedObjects(){
00187     vector <ModelObject*> toReturn;
00188     for (uint i=0;i<myObjects.size();i++){
00189         toReturn.push_back(&myObjects.at(i));
00190     }
00191     return toReturn;
00192 }
00193 
00194 vector <string>
00195 Pixel::getIncludedObjectNames() const {
00196     vector <string> toReturn;
00197     for (uint i=0;i<myObjects.size();i++){
00198         toReturn.push_back(myObjects.at(i).getName());
00199     }
00200     return toReturn;
00201 }
00202 
00203 void
00204 Pixel::newYear(){
00205     
00206     if (getLastRentingYear() <= MTHREAD->SCD->getYear() ){
00207         destroyRentalContract();
00208     }
00209 
00210     vector<ModelObject>::iterator p;
00211     for ( p = myObjects.begin() ; p != myObjects.end();){
00212         if(p->getLastYear() <= MTHREAD->SCD->getYear()){
00213             myObjects.erase(p);
00214         }
00215         else {
00216             ++p;
00217         }
00218     }
00219 
00220 }
00221 
00225 void
00226 Pixel::destroyRentalContract(){
00227         //TOnotDO:pxTenant->removePixel(this); no.. this will be done by the agent, the plot doesn't know anything about the owner
00228         // This is the "distructor" of the renting contract...
00229         pxTenant = 0;
00230         rentingTerm = 0;
00231         startRentingYear=0;
00232         rentalCosts=0;
00233 }
00234 
00235 
00241 void
00242 Pixel::setRandomRenting(string contractType){
00243     if(contractType=="agrContract"){
00244         int minAgrContract = MTHREAD->RD->getIntSetting("minAgrContractLength");
00245         int maxAgrContract = MTHREAD->RD->getIntSetting("maxAgrContractLength");
00246         int maxObjectAge = 0;
00247         int remainingRentingYears =0;
00248         if(MTHREAD->INIT->getInitState() < 5) {
00249             for (uint i=0;i<myObjects.size();i++){
00250                 if (myObjects[i].getRemainingAge()>maxObjectAge){
00251                     maxObjectAge=myObjects[i].getRemainingAge();
00252                 }
00253             }
00254             if (maxObjectAge > maxAgrContract){
00255                 remainingRentingYears = minAgrContract +( (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*(maxAgrContract-minAgrContract+1); // [minAgrContract, maxAgrContract]
00256             }
00257             else if (maxObjectAge > minAgrContract){
00258                 remainingRentingYears = minAgrContract +( (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*(maxObjectAge-minAgrContract+1); // [minAgrContract, maxObjectAge]
00259             }
00260             else if (maxObjectAge > 0){ // we have objects but with shorter years than minContract
00261                 remainingRentingYears = maxObjectAge;
00262             }
00263             else { // no objects on plot
00264                 remainingRentingYears = minAgrContract +( (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*(maxAgrContract-minAgrContract+1); // [minAgrContract, maxAgrContract]
00265             // if the farm invest on permanent crop the remainingRentingYears will be updated to the duration of the object
00266             }
00267             setRemainingRentingTerm(remainingRentingYears);
00268         }
00269         else { //we are in the init stage, remaining age can be less than minimum contract as the renting conctract may have happened in the past. Furthermore no spatial objects are yet assigned to plots, as this happen later on in the init process
00270             remainingRentingYears = 1 +( (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*(maxAgrContract-minAgrContract+1); // [1, maxAgrContract]
00271             setRemainingRentingTerm(remainingRentingYears);
00272         }
00273     }
00274     else {
00275         msgOut(MSG_ERROR, "Unknow renting contract. Skipped");
00276     }
00277 }
00278 
00279 bool
00280 Pixel::isAgricultural() const{
00281     
00282     vector <int> agrLandTypes = MTHREAD->RD->getIntVectorSetting("agrLandTypes");
00283     string valuesToMatch;
00284     unsigned int z;
00285 
00286     //string of the required land values to match;
00287     for (uint j=0;j<agrLandTypes.size();j++){
00288         valuesToMatch = valuesToMatch + " " + i2s(agrLandTypes.at(j));
00289     }
00290 
00291     z = valuesToMatch.find(d2s(this->getDoubleValue("landUse"))); // search if in the string of required values is included also the value of the current plot
00292     if( z!=string::npos ){
00293         return true;
00294     }
00295     else {
00296         return false;
00297     }
00298 }
00299 
00300 void
00301 Pixel::setRemainingRentingTerm(int years_h){
00302     if(!startRentingYear) { // this is a new renting contract
00303         startRentingYear = MTHREAD->SCD->getYear(); // bug found 2007.10.16, Antonello
00304     }
00305     rentingTerm = MTHREAD->SCD->getYear()+years_h-startRentingYear;
00306 }
00307 
00308 int
00309 Pixel::getRentingAge() const{
00310     return MTHREAD->SCD->getYear()-startRentingYear;
00311 }
00312 
00313 double
00314 Pixel::getStartingRentalCosts() const {
00315     int landType = ((int)this->getDoubleValue("landUse"));
00316     vector <int> agrLandTypes = MTHREAD->RD->getIntVectorSetting("agrLandTypes");
00317     vector <double> agrLandRents = MTHREAD->RD->getDoubleVectorSetting("agrInitialRentalPrices");
00318     for (uint i=0;i<agrLandTypes.size();i++){
00319         if(agrLandTypes[i]==landType) return agrLandRents.at(i);
00320     }
00321     msgOut(MSG_CRITICAL_ERROR, "Plot of unknow land type: "+i2s(landType));
00322     return 0;
00323 }
00324