Layers.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2008 by Antonello Lobianco                         *
00003  *   antonello@regmas.org                                                  *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Library General Public License as       *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (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 Library General Public     *
00016  *   License 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 <QtCore>
00021 
00022 #include <math.h>
00023 #include <algorithm>
00024 
00025 #include "Layers.h"
00026 #include "Gis.h"
00027 #include "ThreadManager.h"
00028 #include "Scheduler.h"
00029 
00030 Layers::Layers(ThreadManager* MTHREAD_h, string name_h, string label_h, bool isInteger_h, bool dynamicContent_h, string fullFilename_h)
00031 {
00032     MTHREAD=MTHREAD_h;
00033     name = name_h;
00034     label = label_h;
00035     isInteger = isInteger_h;
00036     dynamicContent = dynamicContent_h;
00037     fullFileName = fullFilename_h;
00038 }
00039 
00040 Layers::~Layers()
00041 {
00042 }
00043 
00044 void
00045 Layers::addLegendItem(int ID_h, string label_h, int rColor_h, int gColor_h, int bColor_h, double minValue_h, double maxValue_h){
00046 
00047     for (uint i=0;i<legendItems.size();i++){
00048         if (legendItems.at(i).ID == ID_h){
00049             msgOut(MSG_ERROR, "Trying to add a legend item that already exist on this layer (layer: "+label+" - legend label: "+label_h+")");
00050             //cout << "ID: "<<ID_h<<" Label: "<<label_h<<" minValue: "<<minValue_h << " maxValue: "<<maxValue_h<<endl;
00051             return;
00052         }
00053     }
00054 
00055     LegendItems ITEM;
00056     ITEM.ID = ID_h;
00057     ITEM.label = label_h;
00058     ITEM.rColor = rColor_h;
00059     ITEM.gColor = gColor_h;
00060     ITEM.bColor = bColor_h;
00061     ITEM.minValue = minValue_h;
00062     ITEM.maxValue = maxValue_h;
00063     ITEM.cashedCount=0;
00064     legendItems.push_back(ITEM);    
00065 
00066 }
00067 
00068 void
00069 Layers::addReclassificationRule(int inCode_h, int outCode_h, double p_h){
00070 
00071     ReclassRules RULE;
00072     RULE.inCode=inCode_h;
00073     RULE.outCode = outCode_h;
00074     RULE.p = p_h;
00075     reclassRulesVector.push_back(RULE);
00076 }
00077 
00082 double
00083 Layers::filterExogenousDataset(double code_h){
00084     bool check =false;
00085     std::vector <double> cumPVector;
00086     std::vector <double> outCodesVector;
00087     double cumP = 0;
00088     double returnCode=0;
00089     
00090     for(uint i=0; i<reclassRulesVector.size(); i++){
00091         if (reclassRulesVector.at(i).inCode == code_h){
00092             check = true;
00093             cumP += reclassRulesVector.at(i).p;
00094             cumPVector.push_back(cumP);
00095             outCodesVector.push_back(reclassRulesVector.at(i).outCode);
00096         }
00097     }
00098     if (!check) {return code_h;}
00099     if (cumP <= 0.99999999 || cumP >= 1.00000001){msgOut(MSG_CRITICAL_ERROR,"the sum of land use reclassification rules is not 1 for at least one input code (input code:  "+d2s(code_h)+"; cumP: "+d2s(cumP)+")");}
00100     double random;
00101     //srand(time(NULL)); // this would re-initialise the random seed
00102     random = ((double)rand() / ((double)(RAND_MAX)+(double)(1)) );
00103     for(uint i=0; i<cumPVector.size(); i++){
00104         if (random <= cumPVector.at(i)){
00105             returnCode = outCodesVector.at(i);
00106             break;  
00107         }
00108     }   
00109     return returnCode;
00110 };
00111 
00117 QColor
00118 Layers::getColor(double ID_h){
00119     QColor nocolor(255,255,255);
00120     if (ID_h == MTHREAD->RD->getDoubleSetting("noValue")){
00121         return nocolor;
00122     }
00123     if (isInteger){
00124         for(uint i=0; i<legendItems.size(); i++){
00125             if (legendItems.at(i).ID == ((int)ID_h)){
00126                 QColor color(legendItems.at(i).rColor, legendItems.at(i).gColor, legendItems.at(i).bColor);
00127                 return color;
00128             }
00129         }
00130         return nocolor;
00131     }
00132     else {
00133         for(uint i=0; i<legendItems.size(); i++){
00134             if (ID_h < legendItems.at(i).maxValue &&  ID_h >= legendItems.at(i).minValue){
00135                 QColor color(legendItems.at(i).rColor, legendItems.at(i).gColor, legendItems.at(i).bColor);
00136                 return color;
00137             }
00138         }
00139         return nocolor; 
00140     }
00141 }
00147 string
00148 Layers::getCategory(double ID_h){
00149     if (ID_h == MTHREAD->RD->getDoubleSetting("noValue")){
00150         return "";
00151     }
00152     if (isInteger){
00153         for(uint i=0; i<legendItems.size(); i++){
00154             if (legendItems.at(i).ID == ((int)ID_h)){
00155                 return legendItems.at(i).label;
00156             }
00157         }
00158         return "";
00159     }
00160     else {
00161         for(uint i=0; i<legendItems.size(); i++){
00162             if (ID_h < legendItems.at(i).maxValue &&  ID_h >= legendItems.at(i).minValue){
00163                 return legendItems.at(i).label;
00164             }
00165         }
00166         return "";  
00167     }
00168 }
00169 
00170 
00171 
00172 
00173 void
00174 Layers::countMyPixels(bool debug){
00175 
00176     for (uint i=0; i<legendItems.size(); i++){
00177         legendItems.at(i).cashedCount=0; //initialized with 0 values...
00178     }
00179     double totPixels = MTHREAD->GIS->getXyNPixels();
00180     double pixelValue;
00181     for (uint j=0;j<totPixels;j++){
00182         pixelValue = MTHREAD->GIS->getPixel(j)->getDoubleValue(name);
00183         if (isInteger){
00184             for(uint i=0; i<legendItems.size(); i++){
00185                 if (legendItems.at(i).ID == ((int)pixelValue)){
00186                     legendItems.at(i).cashedCount++;
00187                     break;
00188                 }
00189             }
00190         }
00191         else {
00192             for(uint i=0; i<legendItems.size(); i++){
00193                 if (pixelValue < legendItems.at(i).maxValue &&  pixelValue >= legendItems.at(i).minValue){
00194                     legendItems.at(i).cashedCount++;
00195                     break;
00196                 }
00197             }
00198         }
00199     }
00200     if (debug){
00201         msgOut(MSG_INFO, "Layer statistics - Count by Legend items");
00202         msgOut(MSG_INFO, "Layer name: "+label);
00203         msgOut(MSG_INFO, "Total plots: "+ d2s(totPixels));
00204         for(uint i=0;i<legendItems.size();i++){
00205             msgOut(MSG_INFO, legendItems.at(i).label+": "+i2s(legendItems.at(i).cashedCount));
00206         }
00207     }
00208 }
00209 void
00210 Layers::randomShuffle(){
00211 
00212 
00213     vector <double> origValues;
00214     int maskValue = -MTHREAD->GIS->getNoValue();
00215     double totPixels = MTHREAD->GIS->getXyNPixels();
00216     for (uint i=0;i<totPixels;i++){
00217         double pxValue= MTHREAD->GIS->getPixel(i)->getDoubleValue(name);
00218         if(pxValue != MTHREAD->GIS->getNoValue()){
00219             origValues.push_back(pxValue);
00220             MTHREAD->GIS->getPixel(i)->changeValue(name,maskValue);
00221         }
00222     }
00223     random_shuffle(origValues.begin(), origValues.end()); // randomize the elements of the array.
00224 
00225     for (uint i=0;i<totPixels;i++){
00226         double pxValue= MTHREAD->GIS->getPixel(i)->getDoubleValue(name);
00227         if(pxValue != MTHREAD->GIS->getNoValue()){
00228             double toChangeValue = origValues.at(origValues.size()-1);
00229             //cout << toChangeValue << endl;
00230             origValues.pop_back();
00231             MTHREAD->GIS->getPixel(i)->changeValue(name,toChangeValue);
00232         }
00233     }
00234 
00235 
00236 /*  if (!isInteger){
00237         msgOut(MSG_WARNING,"I'm not gonna randomShuffle layer "+name+" as this is NOT an integer layer and this function substitute the float values with their legend ones (that are the same in integer layers)");
00238     }
00239     countMyPixels();
00240     //vector <double> origValues;
00241     int maskValue = -MTHREAD->GIS->getNoValue();
00242     double totPixels = MTHREAD->GIS->getXyNPixels();
00243     for (uint i=0;i<totPixels;i++){
00244         double pxValue= MTHREAD->GIS->getPixel(i)->getDoubleValue(name);
00245         //origValues.push_back(pxValue);
00246         if(pxValue != MTHREAD->GIS->getNoValue()){
00247             //cout <<"TEEEST1: " << maskValue<<endl;
00248             MTHREAD->GIS->getPixel(i)->changeValue(name,maskValue);
00249             //cout <<"TEEEST2: " <<MTHREAD->GIS->getPixel(i)->getDoubleValue(name) << endl;
00250         }
00251     }
00252 
00253     vector<Pixel*> shufledPixels = MTHREAD->GIS->getAllPlotsByValue(name,maskValue);
00254     int pxCounter = 0;
00255     for (uint i=0; i<legendItems.size();i++){
00256         for (int j=0;j<legendItems[i].cashedCount;j++){
00257             shufledPixels.at(pxCounter)->changeValue(name,legendItems[i].ID);
00258             pxCounter++;
00259         }   
00260     }
00261 */
00262 
00263 }
00264 void
00265 Layers::print(){
00266 
00267     if(MTHREAD->RD->getIntSetting("outputLevel")<OUTVL_MAPS) return;
00268     string mapBaseDirectory = MTHREAD->RD->getBaseDirectory()+MTHREAD->RD->getOutputDirectory()+"maps/";
00269     string mapGridOutputDirectory = mapBaseDirectory+"asciiGrids/";
00270     string catsOutputDirectory = mapBaseDirectory+"cats/";
00271     string coloursOutputDirectory = mapBaseDirectory+"colr/";
00272 
00273     string mapFilename      = mapGridOutputDirectory +name+ "_" +i2s(MTHREAD->SCD->getYear()) +"_" +MTHREAD->getScenarioName();
00274     string catsFilename     = catsOutputDirectory    +name+ "_" +i2s(MTHREAD->SCD->getYear()) +"_" +MTHREAD->getScenarioName();
00275     string coloursFilename  = coloursOutputDirectory +name+ "_" +i2s(MTHREAD->SCD->getYear()) +"_" +MTHREAD->getScenarioName();
00276     string filenameListIntLayers = mapBaseDirectory+"integerListLayers";
00277     string filenameListFloatLayers = mapBaseDirectory+"floatListLayers";
00278 
00279     // printing the map...
00280     string header;
00281     if(MTHREAD->RD->getIntSetting("mapOutputFormat") == 1){ // GRASS ASCII Grid
00282         header =      "north: " + d2s(MTHREAD->GIS->getGeoTopY()) + "\n"
00283                     + "south: " + d2s(MTHREAD->GIS->getGeoBottomY()) + "\n"
00284                     + "east: " + d2s(MTHREAD->GIS->getGeoRightX()) + "\n"
00285                     + "west: " + d2s(MTHREAD->GIS->getGeoLeftX()) + "\n"
00286                     + "rows: " + i2s(MTHREAD->GIS->getYNPixels()) + "\n"
00287                     + "cols: " + i2s(MTHREAD->GIS->getXNPixels()) + "\n"
00288                     + "null: " + d2s(MTHREAD->GIS->getNoValue()) + "\n";
00289 
00290     } else if(MTHREAD->RD->getIntSetting("mapOutputFormat") == 2){
00291         header =      "ncols: " + i2s(MTHREAD->GIS->getXNPixels()) + "\n"
00292                     + "lrows: " + i2s(MTHREAD->GIS->getYNPixels()) + "\n"
00293                     + "xllcornel: " + d2s(MTHREAD->GIS->getGeoLeftX()) + "\n"
00294                     + "yllcorner: " + d2s(MTHREAD->GIS->getGeoBottomY()) + "\n"
00295                     + "cellsize: "  + d2s(MTHREAD->GIS->getXMetersByPixel()) + "\n"
00296                     + "nodata_value: " + d2s(MTHREAD->GIS->getNoValue()) + "\n";
00297         if(MTHREAD->GIS->getXMetersByPixel() != MTHREAD->GIS->getYMetersByPixel()){
00298             msgOut(MSG_ERROR, "The X resolution is different to the Y resolution. I am exporting the map in ArcInfo ASCII Grid format using the X resolution, but be aware that it is incorrect, as this format doesn't support different X-Y resolutions.");
00299         }
00300     
00301     } else {
00302         msgOut(MSG_ERROR,"Map not print for unknow output type.");
00303     }
00304 
00305     ofstream outm; //out map
00306     outm.open(mapFilename.c_str(), ios::out); //ios::app to append..
00307     if (!outm){ msgOut(MSG_ERROR,"Error in opening the file "+mapFilename+".");}
00308     outm << header << "\n";
00309 
00310     for (int i=0;i<MTHREAD->GIS->getYNPixels();i++){
00311         for (int j=0;j<MTHREAD->GIS->getXNPixels();j++){
00312             outm << MTHREAD->GIS->getPixel(j, i)->getDoubleValue(name) << " ";
00313         }
00314         outm << "\n";
00315     }
00316     outm.close();
00317 
00318     //printing the cat file
00319     ofstream outc; //out category file
00320     outc.open(catsFilename.c_str(), ios::out); //ios::app to append..
00321     if (!outc){ msgOut(MSG_ERROR,"Error in opening the file "+catsFilename+".");}
00322     outc << "# " << name  << "_-_" << i2s(MTHREAD->SCD->getYear()) << "\n\n\n";
00323     outc << "0.00 0.00 0.00 0.00"<<"\n";
00324 
00325     if (isInteger){
00326         for(uint i=0;i<legendItems.size();i++){
00327             outc << legendItems[i].ID << ":"<< legendItems[i].label << "\n";
00328         }
00329     }
00330     else {
00331         for(uint i=0;i<legendItems.size();i++){
00332             outc << legendItems[i].minValue << ":"<< legendItems[i].maxValue << ":"<< legendItems[i].label << "\n";
00333         }
00334     }
00335 
00336     //printing the colour legend file
00337     ofstream outcl; //out colour file
00338     outcl.open(coloursFilename.c_str(), ios::out); //ios::app to append..
00339     if (!outcl){ msgOut(MSG_ERROR,"Error in opening the file "+coloursFilename+".");}
00340     outcl << "% " << name  << "_-_" << i2s(MTHREAD->SCD->getYear()) << "\n\n\n";
00341     
00342     if (isInteger){
00343         for(uint i=0;i<legendItems.size();i++){
00344             outcl << legendItems[i].ID << ":"<< legendItems[i].rColor << ":" << legendItems[i].gColor << ":" << legendItems[i].bColor << "\n";
00345         }
00346     }
00347     else {
00348         for(uint i=0;i<legendItems.size();i++){
00349             outcl << legendItems[i].minValue << ":"<< legendItems[i].rColor << ":" << legendItems[i].gColor << ":" << legendItems[i].bColor << " "<< legendItems[i].maxValue << ":"<< legendItems[i].rColor << ":" << legendItems[i].gColor << ":" << legendItems[i].bColor << "\n";
00350         }
00351     }
00352 
00353     // adding the layer to the list of saved layers..
00354     ofstream outList;
00355     if (isInteger){
00356         outList.open(filenameListIntLayers.c_str(), ios::app); // append !!!
00357         outList << name << "_" << MTHREAD->SCD->getYear() << "_" << MTHREAD->getScenarioName() << "\n";
00358     }
00359     else {
00360         outList.open(filenameListFloatLayers.c_str(), ios::app); // append !!!
00361         outList << name << "_" << MTHREAD->SCD->getYear() << "_" << MTHREAD->getScenarioName() << "\n";
00362     }
00363     outList.close();
00364 }
00365 
00366 void
00367 Layers::printBinMap(){
00368 
00369     int xNPixels            = MTHREAD->GIS->getXNPixels();
00370     int subXR               = MTHREAD->GIS->getSubXR();
00371     int subXL               = MTHREAD->GIS->getSubXL();
00372     int subYT               = MTHREAD->GIS->getSubYT();
00373     int subYB               = MTHREAD->GIS->getSubYB();
00374 
00375     string mapBaseDirectory = MTHREAD->RD->getBaseDirectory()+MTHREAD->RD->getOutputDirectory()+"maps/bitmaps/";
00376     string mapFilename      = mapBaseDirectory +name+ "_" +i2s(MTHREAD->SCD->getYear()) +"_" +MTHREAD->getScenarioName()+".png";
00377 
00378     QImage image = QImage(subXR-subXL+1, subYB-subYT+1, QImage::Format_RGB32);
00379     image.fill(qRgb(255, 255, 255));
00380     for (int countRow=subYT;countRow<subYB;countRow++){
00381         for (int countColumn=subXL;countColumn<subXR;countColumn++){
00382             double value = MTHREAD->GIS->getPixel(countRow*xNPixels+countColumn)->getDoubleValue(name);
00383             QColor color = this->getColor(value);
00384             image.setPixel(countColumn-subXL,countRow-subYT,color.rgb());
00385         }
00386     }
00387     image.save(mapFilename.c_str());
00388 }