TeImportBNA.cpp

Go to the documentation of this file.
00001 /************************************************************************************
00002 TerraLib - a library for developing GIS applications.
00003 Copyright � 2001-2007 INPE and Tecgraf/PUC-Rio.
00004 
00005 This code is part of the TerraLib library.
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 You should have received a copy of the GNU Lesser General Public
00012 License along with this library.
00013 
00014 The authors reassure the license terms regarding the warranties.
00015 They specifically disclaim any warranties, including, but not limited to,
00016 the implied warranties of merchantability and fitness for a particular purpose.
00017 The library provided hereunder is on an "as is" basis, and the authors have no
00018 obligation to provide maintenance, support, updates, enhancements, or modifications.
00019 In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
00020 indirect, special, incidental, or consequential damages arising out of the use
00021 of this library and its documentation.
00022 *************************************************************************************/
00023 
00024 #include <string>
00025 #include <iostream>
00026 #include <list>
00027 
00028 #ifdef WIN32
00029 #include <io.h>
00030 #else
00031 #include <unistd.h>
00032 #endif
00033 
00034 using namespace std;
00035 
00036 #include "TeDriverBNA.h"
00037 #include "../kernel/TeTable.h"
00038 #include "../kernel/TeGeometry.h"
00039 #include "../kernel/TeAsciiFile.h"
00040 #include "../kernel/TeException.h"
00041 #include "../kernel/TeProjection.h"
00042 #include "../kernel/TeAttribute.h"
00043 #include "../kernel/TeTable.h"
00044 #include "../kernel/TeAssertions.h"
00045 #include "../kernel/TeUtils.h"
00046 #include "../kernel/TeLayer.h"
00047 #include "../kernel/TeGeometryAlgorithms.h"
00048 #include "../kernel/TeDatabase.h"
00049 
00050 bool TeReadBNAObjects(TeAsciiFile& bnaFile, TeTable& attTable, TePointSet& ptSet,
00051                                           TeLineSet& lnSet, TePolygonSet& pSet, 
00052                                           int ncolumns, int nrecords, int delta, int attLinkColumnIndex);
00053 
00054 bool TeBNARegionDecode(TeAsciiFile& bnaFile, TePolygonSet& temp, string& index, const int& npoints);
00055 
00056 bool TeBNALineDecode(TeAsciiFile& bnaFile, TeLineSet& temp, string& index, const int& npoints);
00057 
00058 bool TeBNAPointDecode(TeAsciiFile& bnaFile, TePointSet& temp, string& index);
00059 
00060 
00061 
00062 TeLayer* TeImportBNA(const string& bnaFileName, TeDatabase* db, const string& layerName, const std::string& linkName)
00063 {
00064         if(!db || bnaFileName.empty()) 
00065                 return 0;
00066 
00067         // check if format is complete (BNA file exist)
00068         string filePrefix = TeGetName(bnaFileName.c_str());
00069         string ftest = filePrefix + ".bna";
00070         if(access(ftest.c_str(),04) == -1)
00071         {
00072                 ftest = filePrefix + ".BNA";
00073                 if (access(ftest.c_str(),04) == -1)
00074                         return 0;
00075         }
00076 
00077         // found a valid layer name
00078         string lName = layerName;
00079 
00080         if(layerName.empty())
00081                 lName = TeGetBaseName(bnaFileName.c_str());     
00082 
00083         string newLayerName = lName;
00084 
00085         TeLayerMap& layerMap = db->layerMap();
00086         TeLayerMap::iterator it;
00087 
00088         bool flag = true;
00089 
00090         int n = 1;
00091 
00092         while(flag)
00093         {
00094                 for(it = layerMap.begin(); it != layerMap.end(); ++it)
00095                 {
00096                         if(TeStringCompare(it->second->name(), newLayerName))
00097                                 break;
00098                 }
00099 
00100                 if(it == layerMap.end())
00101                         flag = 0;
00102                 else
00103                         newLayerName = lName + "_" + Te2String(n);
00104 
00105                 n++;    
00106         }
00107 
00108         // Use no projection
00109         TeLayer* newLayer = new TeLayer(newLayerName, db);
00110 
00111         if(newLayer->id() <= 0)
00112                 return 0;                               // couldn�t create new layer
00113 
00114         TeAttributeList attList;
00115 
00116         std::string tableName = "";
00117         std::string linkNameCopy = linkName;
00118         bool res = TeImportBNA(newLayer, bnaFileName, tableName, attList, 60, linkNameCopy);
00119 
00120         if (res)
00121                 return newLayer;
00122         else
00123         {
00124                 db->deleteLayer(newLayer->id());
00125 
00126                 delete newLayer;
00127 
00128                 return 0;
00129         }
00130 }
00131 
00132 bool TeImportBNA(TeLayer* layer, const string& bnaFileName, string attrTableName,
00133                                  TeAttributeList& attList, int unsigned chunkSize, std::string& linkName)
00134 {
00135         if(chunkSize <= 0)
00136                 chunkSize = 1;
00137 
00138         //-- Step 1: Read any adicional information (ex. projection) 
00139         char separator = ',';
00140 
00141 
00142         if(!TeReadBNAAttributeList(bnaFileName, attList))
00143                 return false;   // Attributelist read error
00144 
00145         bool autoIndex = true;
00146         int linkIndex = -1;
00147         unsigned int count = 0;
00148         int ncol = attList.size();
00149         if(linkName.empty())
00150         {
00151                 linkName = "object_id_" + Te2String(layer->id());
00152                 std::string s2 = TeConvertToUpperCase(linkName);
00153                 while(true)
00154                 {
00155                         unsigned int j = 0;
00156                         for (j=0; j<attList.size(); j++)
00157                         {
00158                                 string s0 = attList[j].rep_.name_;
00159                                 string s1 = TeConvertToUpperCase(s0);
00160                                 if ( s1 == s2)
00161                                 {
00162                                         break;
00163                                 }
00164                         }
00165                         if(j < attList.size())
00166                         {
00167                                 ++count;
00168                                 linkName = "object_id_" + Te2String(count);
00169                         }
00170                         else
00171                         {
00172                                 break;
00173                         }
00174                 }
00175 
00176                 TeAttribute at;
00177                 at.rep_.type_ = TeSTRING;
00178                 at.rep_.numChar_ = 16;
00179                 at.rep_.name_ = linkName;
00180                 at.rep_.isPrimaryKey_ = true;
00181                 attList.push_back(at);
00182                 linkIndex = attList.size()-1;
00183                 autoIndex = true;
00184         }
00185         else
00186         {
00187                 unsigned int j = 0;
00188                 // check if given index is valid
00189                 TeAttributeList::iterator it = attList.begin();
00190                 while (it != attList.end())
00191                 {
00192                         if (TeConvertToUpperCase((*it).rep_.name_) == TeConvertToUpperCase(linkName))           // index found
00193                         {
00194                                 if ((*it).rep_.type_ != TeSTRING)       // make sure it is a String type
00195                                 {
00196                                         (*it).rep_.type_ = TeSTRING;
00197                                         (*it).rep_.numChar_ = 16;
00198                                 }
00199                                 (*it).rep_.isPrimaryKey_ = true;
00200                                 linkIndex = j;
00201                                 break;
00202                         }
00203                         ++it;
00204                         ++j;
00205                 }
00206                 if (it == attList.end())                        // index not found
00207                 {
00208                         linkName = "object_id_" + Te2String(layer->id());;
00209                         while(true)
00210                         {
00211                                 for(j=0; j<attList.size(); j++)
00212                                 {
00213                                         if (TeConvertToUpperCase(attList[j].rep_.name_) == TeConvertToUpperCase(linkName))
00214                                         {
00215                                                 break;
00216                                         }
00217                                 }
00218                                 if(j < attList.size())
00219                                 {
00220                                         ++count;
00221                                         linkName = "object_id_" + Te2String(count);
00222                                 }
00223                                 else
00224                                 {
00225                                         break;
00226                                 }
00227                         }
00228                         TeAttribute at;
00229                         at.rep_.type_ = TeSTRING;
00230                         at.rep_.numChar_ = 16;
00231                         at.rep_.name_ = linkName;
00232                         at.rep_.isPrimaryKey_ = true;
00233                         attList.push_back(at);
00234                         autoIndex = true;
00235                 }
00236         }
00237 
00238         // define a TeAttributeTable
00239         if (attrTableName.empty())
00240         {
00241                 if (layer->name().empty())
00242                         return false;
00243                 else
00244                         attrTableName = layer->name();
00245         }
00246         
00247         TeTable attTable(attrTableName, attList, linkName, linkName, TeAttrStatic);
00248 
00249         attTable.setSeparator(separator);
00250 
00251         // insert the table into the database
00252         if(!layer->createAttributeTable(attTable))
00253         {
00254                 return false;
00255         }       
00256         
00257         TeAsciiFile bnaFile(bnaFileName);
00258 
00259         int delta = 0;
00260 
00261         TePointSet ptSet;
00262         TeLineSet lnSet;
00263         TePolygonSet pSet;
00264 
00265         while(TeReadBNAObjects(bnaFile, attTable, ptSet, lnSet, pSet, ncol, chunkSize, delta, linkIndex))
00266         {
00267                 // save table
00268                 if (!layer->saveAttributeTable( attTable ))
00269                 {
00270                         attTable.clear();
00271                         break;
00272                 }
00273 
00274                 // save the remaining geometries
00275                 if(ptSet.size() > 0)
00276                 {
00277                         layer->addPoints(ptSet); 
00278                         ptSet.clear();
00279                 }
00280 
00281                 if(lnSet.size() > 0)
00282                 {
00283                         layer->addLines(lnSet);
00284                         lnSet.clear();
00285                 }
00286 
00287                 if(pSet.size() > 0)
00288                 {
00289                         layer->addPolygons(pSet); 
00290                         pSet.clear();
00291                 }
00292 
00293                 delta += attTable.size();
00294                 
00295                 attTable.clear();
00296         }       
00297 
00298         // Create the spatial indexes
00299         int rep = layer->geomRep();
00300         if (rep & TePOINTS)
00301         {
00302                 layer->database()->insertMetadata(layer->tableName(TePOINTS),layer->database()->getSpatialIdxColumn(TePOINTS), 0.0005,0.0005,layer->box());
00303                 layer->database()->createSpatialIndex(layer->tableName(TePOINTS),layer->database()->getSpatialIdxColumn(TePOINTS), (TeSpatialIndexType)TeRTREE);
00304         }
00305         if (rep & TeLINES)
00306         {
00307                 layer->database()->insertMetadata(layer->tableName(TeLINES),layer->database()->getSpatialIdxColumn(TeLINES), 0.0005,0.0005,layer->box());
00308                 layer->database()->createSpatialIndex(layer->tableName(TeLINES),layer->database()->getSpatialIdxColumn(TeLINES), (TeSpatialIndexType)TeRTREE);
00309         }
00310         if (rep & TePOLYGONS)
00311         {
00312                 layer->database()->insertMetadata(layer->tableName(TePOLYGONS),layer->database()->getSpatialIdxColumn(TePOLYGONS), 0.0005,0.0005,layer->box());
00313                 layer->database()->createSpatialIndex(layer->tableName(TePOLYGONS),layer->database()->getSpatialIdxColumn(TePOLYGONS), (TeSpatialIndexType)TeRTREE);
00314         }
00315         return true;
00316 }
00317 
00318 
00319 bool TeReadBNAAttributeList(const string& bnaFileName, TeAttributeList& attList)
00320 {
00321         TeAsciiFile bnaFile(bnaFileName);
00322 
00323         if(!bnaFile.isNotAtEOF())
00324                  return false;
00325 
00326         vector<string> strList;
00327 
00328         bnaFile.readStringListCSV(strList, ',');
00329 
00330         unsigned int nFields = (strList.size() - 1u);
00331 
00332         if(nFields <= 0)
00333                 return false;
00334 
00335         if(attList.size() > 0u) // Has already defined attributes, only check the number
00336         {
00337                 if(attList.size() != nFields)
00338                         return false;
00339                 else
00340                         return true;
00341         }
00342 
00343         // In future, look for a better way to find the field name
00344         // see in the specification of file format there is something about the field names!
00345 
00346         TeAttribute at1;
00347         at1.rep_.type_ = TeSTRING;
00348         at1.rep_.numChar_ = 255;                
00349         at1.rep_.name_ = "IBGE_CODE";
00350         at1.rep_.isPrimaryKey_ = false;
00351         attList.push_back(at1);
00352 
00353         if(nFields > 1)
00354         {
00355                 TeAttribute at2;
00356                 at2.rep_.type_ = TeSTRING;
00357                 at2.rep_.numChar_ = 255;                
00358                 at2.rep_.name_ = "IBGE_NAME";
00359                 at2.rep_.isPrimaryKey_ = false;
00360                 attList.push_back(at2);
00361         }
00362 
00363         for(unsigned int i = 2; i < nFields; ++i)
00364         {
00365                 TeAttribute at;
00366                 at.rep_.type_ = TeSTRING;
00367                 at.rep_.numChar_ = 255;         
00368                 at.rep_.name_ = string("FIELD_") + Te2String(i);
00369                 at.rep_.isPrimaryKey_ = false;
00370                 attList.push_back(at);
00371         }
00372 
00373         return true;
00374 }
00375 
00376 
00377 bool TeReadBNAObjects(TeAsciiFile& bnaFile, TeTable& attTable, TePointSet& ptSet,
00378                                           TeLineSet& lnSet, TePolygonSet& pSet, 
00379                                           int ncolumns, int nrecords, int delta , int attLinkColumnIndex)
00380 {
00381         if (!bnaFile.isNotAtEOF() || nrecords <=0 || ncolumns <= 0)
00382                 return false;
00383 
00384         char separator = attTable.separator();
00385 
00386         int count;
00387 
00388         for(count=0; count < nrecords; ++count)
00389         {
00390                 if(!bnaFile.isNotAtEOF())
00391                          break;
00392 
00393                 // Ler os atributos do objeto e o tipo/tamanho da geometria
00394 
00395                 TeTableRow row;
00396                 for(int n = 0; n < ncolumns; ++n)
00397                 {
00398                         std::string value;
00399 
00400                         try 
00401                         {
00402                                 value = bnaFile.readStringCSVNoQuote(separator);
00403                         }
00404                         catch(...)
00405                         {
00406                                 if(count > 0)
00407                                         return true;
00408                                 else
00409                                         return false;
00410                         }
00411 
00412                         row.push_back (value);
00413                 }
00414 
00415                 if(attLinkColumnIndex == row.size())
00416                 {
00417                         row.push_back(Te2String(delta));
00418                 }
00419                 attTable.add(row);
00420 
00421                 string bnaGeometryTypeLen = bnaFile.readStringCSVNoQuote(separator);
00422 
00423                 int bnaGTypeLen = atoi(bnaGeometryTypeLen.c_str());
00424 
00425                 std::string index = row[attLinkColumnIndex];
00426 
00427                 // Go to the geometry line begin
00428                 bnaFile.findNewLine();
00429 
00430                 if(bnaGTypeLen > 2)
00431                 {
00432                         if(!TeBNARegionDecode(bnaFile, pSet, index, bnaGTypeLen))
00433                                 return false;
00434                 }
00435                 else if(bnaGTypeLen < -1)
00436                 {
00437                         if(!TeBNALineDecode(bnaFile, lnSet, index, -bnaGTypeLen))
00438                                 return false;
00439                 }
00440                 else if(bnaGTypeLen == 1)
00441                 {
00442                         if(!TeBNAPointDecode(bnaFile, ptSet, index))
00443                                 return false;
00444                 }
00445                 else
00446                         return false;
00447 
00448                 ++delta;
00449                 bnaFile.findNewLine();
00450         }
00451 
00452         return true;
00453 }
00454 
00455 bool TeBNARegionDecode(TeAsciiFile& bnaFile, TePolygonSet& temp, string& index, const int& npoints)
00456 {
00457         int i;
00458         unsigned int j;
00459 
00460         vector<TePolygon> pVec;
00461         TeLine2D l;
00462 
00463         TeCoord2D coordMainArea;
00464         TeCoord2D firstCoord;
00465         bool first = false;
00466 
00467         for(i = 0; i < npoints; ++i)
00468         {
00469                 if(!bnaFile.isNotAtEOF())
00470                         return false;
00471 
00472                 double x = bnaFile.readFloat();
00473                 bnaFile.readChar();
00474                 double y = bnaFile.readFloat();
00475 
00476                 //bnaFile.findNewLine();
00477 
00478                 TeCoord2D c(x, y);
00479 
00480                 if(i == 0)
00481                 {
00482                         coordMainArea.setXY(x, y);
00483                         firstCoord = coordMainArea;
00484                         first = false;
00485                         l.add(c);
00486                 }
00487                 else
00488                 {
00489                         if(c == firstCoord)
00490                         {
00491                                 l.add(c);
00492                                 l.objectId(index);
00493                                 TeLinearRing r(l);
00494                                 r.objectId(index);
00495                                 TePolygon p;
00496                                 p.add(r);
00497                                 p.objectId(index);
00498 
00499                                 if(pVec.size() == 0)
00500                                         pVec.push_back(p);
00501                                 else
00502                                 {
00503                                         for(j = 0; j < pVec.size(); ++j)
00504                                         {       
00505                                                 TePolygon paux =        pVec[j];                                
00506                                                 if(TeWithin(p, paux))
00507                                                 {
00508                                                         pVec[j].add(p[0]);
00509                                                         break;
00510                                                 }               
00511                                                 
00512                                         }
00513 
00514                                         if(j == pVec.size())
00515                                                 pVec.push_back(p);
00516                                 }
00517 
00518                                 // Make new line - Don't clear!
00519                                 l = TeLine2D();
00520 
00521                                 first = true;
00522 
00523                         }
00524                         else if(c == coordMainArea)
00525                         {
00526                                 continue;
00527                         }
00528                         else
00529                         {
00530                                 if(first)
00531                                 {
00532                                         firstCoord = c;
00533                                         first = false;
00534                                 }
00535 
00536                                 l.add(c);
00537                         }
00538                 }
00539         }
00540 
00541         for(unsigned int k = 0; k < pVec.size(); ++k)
00542                 temp.add(pVec[k]);
00543 
00544 
00545         return true;
00546 }
00547 
00548 bool TeBNALineDecode(TeAsciiFile& bnaFile, TeLineSet& temp, string& index, const int& npoints)
00549 {
00550         TeLine2D l;
00551 
00552         l.objectId(index);
00553 
00554         for(int i = 0; i < npoints; ++i)
00555         {
00556                 if(!bnaFile.isNotAtEOF())
00557                         return false;
00558 
00559                 double x = bnaFile.readFloat();
00560                 bnaFile.readChar();
00561                 double y = bnaFile.readFloat();
00562 
00563                 //bnaFile.findNewLine();
00564 
00565                 TeCoord2D c(x, y);
00566 
00567                 l.add(c);
00568         }
00569 
00570         temp.add(l);
00571 
00572         return true;
00573 }
00574 
00575 bool TeBNAPointDecode(TeAsciiFile& bnaFile, TePointSet& temp, string& index)
00576 {
00577         if(!bnaFile.isNotAtEOF())
00578                 return false;
00579 
00580         double x = bnaFile.readFloat();
00581         bnaFile.readChar();
00582         double y = bnaFile.readFloat();
00583 
00584         //bnaFile.findNewLine();
00585 
00586         TeCoord2D c(x, y);
00587 
00588         TePoint pt(c);
00589 
00590         pt.objectId(index);
00591 
00592         temp.add(pt);
00593 
00594         return true;
00595 }

Generated on Sun Jul 29 04:01:21 2012 for TerraLib - Development Source by  doxygen 1.5.3