LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/edigeo - ogredigeodatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 784 700 89.3 %
Date: 2011-12-18 Functions: 27 23 85.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z rouault $
       3                 :  *
       4                 :  * Project:  EDIGEO Translator
       5                 :  * Purpose:  Implements OGREDIGEODataSource class
       6                 :  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_edigeo.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z rouault $");
      35                 : 
      36                 : #ifndef M_PI
      37                 : # define M_PI  3.1415926535897932384626433832795
      38                 : #endif
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                        OGREDIGEODataSource()                         */
      42                 : /************************************************************************/
      43                 : 
      44              62 : OGREDIGEODataSource::OGREDIGEODataSource()
      45                 : 
      46                 : {
      47              62 :     papoLayers = NULL;
      48              62 :     nLayers = 0;
      49                 : 
      50              62 :     pszName = NULL;
      51              62 :     poSRS = NULL;
      52                 : 
      53              62 :     bExtentValid = FALSE;
      54              62 :     dfMinX = dfMinY = dfMaxX = dfMaxY = 0;
      55                 : 
      56              62 :     fpTHF = NULL;
      57              62 :     bHasReadEDIGEO = FALSE;
      58                 : 
      59                 :     bIncludeFontFamily = CSLTestBoolean(CPLGetConfigOption(
      60              62 :                                  "OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"));
      61                 : 
      62              62 :     iATR = iDI3 = iDI4 = iHEI = iFON = -1;
      63              62 :     iATR_VAL = iANGLE = iSIZE = iOBJ_LNK = iOBJ_LNK_LAYER = -1;
      64              62 :     dfSizeFactor = atof(CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"));
      65              62 :     if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
      66               0 :         dfSizeFactor = 2;
      67                 : 
      68                 :     bRecodeToUTF8 = CSLTestBoolean(CPLGetConfigOption(
      69              62 :                                         "OGR_EDIGEO_RECODE_TO_UTF8", "YES"));
      70              62 :     bHasUTF8ContentOnly = TRUE;
      71              62 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                      ~OGREDIGEODataSource()                          */
      75                 : /************************************************************************/
      76                 : 
      77              62 : OGREDIGEODataSource::~OGREDIGEODataSource()
      78                 : 
      79                 : {
      80              86 :     for( int i = 0; i < nLayers; i++ )
      81              24 :         delete papoLayers[i];
      82              62 :     CPLFree( papoLayers );
      83                 : 
      84              62 :     CPLFree( pszName );
      85                 : 
      86              62 :     if (fpTHF)
      87               0 :         VSIFCloseL(fpTHF);
      88                 : 
      89              62 :     if (poSRS)
      90               1 :         poSRS->Release();
      91              62 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                           TestCapability()                           */
      95                 : /************************************************************************/
      96                 : 
      97               0 : int OGREDIGEODataSource::TestCapability( const char * pszCap )
      98                 : 
      99                 : {
     100               0 :     return FALSE;
     101                 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*                              GetLayer()                              */
     105                 : /************************************************************************/
     106                 : 
     107             199 : OGRLayer *OGREDIGEODataSource::GetLayer( int iLayer )
     108                 : 
     109                 : {
     110             199 :     ReadEDIGEO();
     111             199 :     if( iLayer < 0 || iLayer >= nLayers )
     112               0 :         return NULL;
     113                 :     else
     114             199 :         return papoLayers[iLayer];
     115                 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                         GetLayerCount()                              */
     119                 : /************************************************************************/
     120                 : 
     121             200 : int OGREDIGEODataSource::GetLayerCount()
     122                 : {
     123             200 :     ReadEDIGEO();
     124             200 :     return nLayers;
     125                 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                              ReadTHF()                               */
     129                 : /************************************************************************/
     130                 : 
     131               1 : int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
     132                 : {
     133                 :     const char* pszLine;
     134              47 :     while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
     135                 :     {
     136              45 :         if (strlen(pszLine) < 8 || pszLine[7] != ':')
     137               5 :             continue;
     138                 : 
     139                 :         /* Cf Z 52000 tableau 56 for field list*/
     140                 : 
     141              40 :         if (strncmp(pszLine, "LONSA", 5) == 0)
     142                 :         {
     143               1 :             if (osLON.size() != 0)
     144                 :             {
     145               0 :                 CPLDebug("EDIGEO", "We only handle one lot per THF file");
     146               0 :                 break;
     147                 :             }
     148               1 :             osLON = pszLine + 8;
     149                 :         }
     150              39 :         else if (strncmp(pszLine, "GNNSA", 5) == 0)
     151               1 :             osGNN = pszLine + 8;
     152              38 :         else if (strncmp(pszLine, "GONSA", 5) == 0)
     153               1 :             osGON = pszLine + 8;
     154              37 :         else if (strncmp(pszLine, "QANSA", 5) == 0)
     155               1 :             osQAN = pszLine + 8;
     156              36 :         else if (strncmp(pszLine, "DINSA", 5) == 0)
     157               1 :             osDIN = pszLine + 8;
     158              35 :         else if (strncmp(pszLine, "SCNSA", 5) == 0)
     159               1 :             osSCN = pszLine + 8;
     160              34 :         else if (strncmp(pszLine, "GDNSA", 5) == 0)
     161               4 :             aosGDN.push_back(pszLine + 8);
     162                 :     }
     163               1 :     if (osLON.size() == 0)
     164                 :     {
     165               0 :         CPLDebug("EDIGEO", "LON field missing");
     166               0 :         return 0;
     167                 :     }
     168               1 :     if (osGON.size() == 0)
     169                 :     {
     170               0 :         CPLDebug("EDIGEO", "GON field missing");
     171               0 :         return 0;
     172                 :     }
     173               1 :     if (osDIN.size() == 0)
     174                 :     {
     175               0 :         CPLDebug("EDIGEO", "DIN field missing");
     176               0 :         return 0;
     177                 :     }
     178               1 :     if (osSCN.size() == 0)
     179                 :     {
     180               0 :         CPLDebug("EDIGEO", "SCN field missing");
     181               0 :         return FALSE;
     182                 :     }
     183                 : 
     184               1 :     CPLDebug("EDIGEO", "LON = %s", osLON.c_str());
     185               1 :     CPLDebug("EDIGEO", "GNN = %s", osGNN.c_str());
     186               1 :     CPLDebug("EDIGEO", "GON = %s", osGON.c_str());
     187               1 :     CPLDebug("EDIGEO", "QAN = %s", osQAN.c_str());
     188               1 :     CPLDebug("EDIGEO", "DIN = %s", osDIN.c_str());
     189               1 :     CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str());
     190               5 :     for(int i=0;i<(int)aosGDN.size();i++)
     191               4 :         CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str());
     192                 :     
     193               1 :     return TRUE;
     194                 : }
     195                 : 
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                             OpenFile()                               */
     199                 : /************************************************************************/
     200                 : 
     201               9 : VSILFILE* OGREDIGEODataSource::OpenFile(const char *pszType,
     202                 :                                         const CPLString& osExt)
     203                 : {
     204               9 :     CPLString osTmp = osLON + pszType;
     205                 :     CPLString osFilename = CPLFormCIFilename(CPLGetPath(pszName),
     206               9 :                                              osTmp.c_str(), osExt.c_str());
     207               9 :     VSILFILE* fp = VSIFOpenL(osFilename, "rb");
     208               9 :     if (fp == NULL)
     209                 :     {
     210               0 :         CPLString osExtLower = osExt;
     211               0 :         for(int i=0;i<(int)osExt.size();i++)
     212               0 :             osExtLower[i] = (char)tolower(osExt[i]);
     213                 :         CPLString osFilename2 = CPLFormCIFilename(CPLGetPath(pszName),
     214               0 :                                              osTmp.c_str(), osExtLower.c_str());
     215               0 :         fp = VSIFOpenL(osFilename2, "rb");
     216               0 :         if (fp == NULL)
     217                 :         {
     218               0 :             CPLDebug("EDIGEO", "Cannot open %s", osFilename.c_str());
     219               0 :         }
     220                 :     }
     221               9 :     return fp;
     222                 : }
     223                 : 
     224                 : /************************************************************************/
     225                 : /*                              ReadGEO()                               */
     226                 : /************************************************************************/
     227                 : 
     228               1 : int OGREDIGEODataSource::ReadGEO()
     229                 : {
     230               1 :     VSILFILE* fp = OpenFile(osGON, "GEO");
     231               1 :     if (fp == NULL)
     232               0 :         return FALSE;
     233                 : 
     234                 :     const char* pszLine;
     235              10 :     while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
     236                 :     {
     237               9 :         if (strlen(pszLine) < 8 || pszLine[7] != ':')
     238               2 :             continue;
     239                 : 
     240               7 :         if (strncmp(pszLine, "RELSA", 5) == 0)
     241                 :         {
     242               1 :             osREL = pszLine + 8;
     243               1 :             CPLDebug("EDIGEO", "REL = %s", osREL.c_str());
     244               1 :             break;
     245                 :         }
     246                 :     }
     247                 : 
     248               1 :     VSIFCloseL(fp);
     249                 : 
     250               1 :     if (osREL.size() == 0)
     251                 :     {
     252               0 :         CPLDebug("EDIGEO", "REL field missing");
     253               0 :         return FALSE;
     254                 :     }
     255                 : 
     256                 :     /* All the SRS names mentionned in B.8.2.3 and B.8.3.1 are in the IGN file */
     257               1 :     poSRS = new OGRSpatialReference();
     258               2 :     CPLString osProj4Str = "+init=IGNF:" + osREL;
     259               1 :     if (poSRS->SetFromUserInput(osProj4Str.c_str()) != OGRERR_NONE)
     260                 :     {
     261                 :         /* Hard code a few common cases */
     262               0 :         if (osREL == "LAMB1")
     263               0 :             poSRS->importFromProj4("+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.99987734 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
     264               0 :         else if (osREL == "LAMB2")
     265               0 :             poSRS->importFromProj4("+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
     266               0 :         else if (osREL == "LAMB3")
     267               0 :             poSRS->importFromProj4("+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.9998775 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
     268               0 :         else if (osREL == "LAMB4")
     269               0 :             poSRS->importFromProj4("+proj=lcc +lat_1=42.165 +lat_0=42.165 +lon_0=0 +k_0=0.99994471 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
     270               0 :         else if (osREL == "LAMB93")
     271               0 :             poSRS->importFromProj4("+proj=lcc +lat_1=44 +lat_2=49 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS81 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
     272                 :         else
     273                 :         {
     274               0 :             CPLDebug("EDIGEO", "Cannot resolve %s SRS. Check that the IGNF file is in the directory of PROJ.4 ressource files", osREL.c_str());
     275               0 :             delete poSRS;
     276               0 :             poSRS = NULL;
     277                 :         }
     278                 :     }
     279                 :     
     280               1 :     return TRUE;
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /*                              ReadGEN()                               */
     285                 : /************************************************************************/
     286                 : 
     287               1 : int OGREDIGEODataSource::ReadGEN()
     288                 : {
     289               1 :     VSILFILE* fp = OpenFile(osGNN, "GEN");
     290               1 :     if (fp == NULL)
     291               0 :         return FALSE;
     292                 : 
     293                 :     const char* pszLine;
     294               1 :     CPLString osCM1, osCM2;
     295              40 :     while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
     296                 :     {
     297              38 :         if (strlen(pszLine) < 8 || pszLine[7] != ':')
     298              11 :             continue;
     299                 : 
     300              27 :         if (strncmp(pszLine, "CM1CC", 5) == 0)
     301                 :         {
     302               1 :             osCM1 = pszLine + 8;
     303                 :         }
     304              26 :         else if (strncmp(pszLine, "CM2CC", 5) == 0)
     305                 :         {
     306               1 :             osCM2 = pszLine + 8;
     307                 :         }
     308                 :     }
     309                 : 
     310               1 :     VSIFCloseL(fp);
     311                 : 
     312               1 :     if (osCM1.size() == 0 || osCM2.size() == 0)
     313               0 :         return FALSE;
     314                 : 
     315               1 :     char** papszTokens1 = CSLTokenizeString2(osCM1.c_str(), ";", 0);
     316               1 :     char** papszTokens2 = CSLTokenizeString2(osCM2.c_str(), ";", 0);
     317               1 :     if (CSLCount(papszTokens1) == 2 && CSLCount(papszTokens2) == 2)
     318                 :     {
     319               1 :         bExtentValid = TRUE;
     320               1 :         dfMinX = atof(papszTokens1[0]);
     321               1 :         dfMinY = atof(papszTokens1[1]);
     322               1 :         dfMaxX = atof(papszTokens2[0]);
     323               1 :         dfMaxY = atof(papszTokens2[1]);
     324                 :     }
     325               1 :     CSLDestroy(papszTokens1);
     326               1 :     CSLDestroy(papszTokens2);
     327                 : 
     328               1 :     return bExtentValid;
     329                 : }
     330                 : 
     331                 : /************************************************************************/
     332                 : /*                              ReadDIC()                               */
     333                 : /************************************************************************/
     334                 : 
     335               1 : int OGREDIGEODataSource::ReadDIC()
     336                 : {
     337               1 :     VSILFILE* fp = OpenFile(osDIN, "DIC");
     338               1 :     if (fp == NULL)
     339               0 :         return FALSE;
     340                 : 
     341                 :     const char* pszLine;
     342               1 :     CPLString osRTY, osRID, osLAB, osTYP;
     343            1147 :     while(TRUE)
     344                 :     {
     345            1148 :         pszLine = CPLReadLine2L(fp, 81, NULL);
     346            1148 :         if (pszLine != NULL)
     347                 :         {
     348            1147 :             if (strlen(pszLine) < 8 || pszLine[7] != ':')
     349             153 :                 continue;
     350                 :         }
     351                 : 
     352             995 :         if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
     353                 :         {
     354              77 :             if (osRTY == "DID")
     355                 :             {
     356                 :                 //CPLDebug("EDIGEO", "Object %s = %s",
     357                 :                 //         osRID.c_str(), osLAB.c_str());
     358              21 :                 mapObjects[osRID] = osLAB;
     359                 :             }
     360              56 :             else if (osRTY == "DIA")
     361                 :             {
     362                 :                 //CPLDebug("EDIGEO", "Attribute %s = %s, %s",
     363                 :                 //         osRID.c_str(), osLAB.c_str(), osTYP.c_str());
     364              53 :                 OGREDIGEOAttributeDef sAttributeDef;
     365              53 :                 sAttributeDef.osLAB = osLAB;
     366              53 :                 sAttributeDef.osTYP = osTYP;
     367              53 :                 mapAttributes[osRID] = sAttributeDef;
     368                 :             }
     369              77 :             if (pszLine == NULL)
     370                 :                 break;
     371              76 :             osRTY = pszLine + 8;
     372              76 :             osRID = "";
     373              76 :             osLAB = "";
     374              76 :             osTYP = "";
     375                 :         }
     376             994 :         if (strncmp(pszLine, "RIDSA", 5) == 0)
     377              76 :             osRID = pszLine + 8;
     378             918 :         else if (strncmp(pszLine, "LABSA", 5) == 0)
     379              76 :             osLAB = pszLine + 8;
     380             842 :         else if (strncmp(pszLine, "TYPSA", 5) == 0)
     381              53 :             osTYP = pszLine + 8;
     382                 :     }
     383                 : 
     384               1 :     VSIFCloseL(fp);
     385                 : 
     386                 : 
     387               1 :     return TRUE;
     388                 : }
     389                 : 
     390                 : /************************************************************************/
     391                 : /*                              ReadSCD()                               */
     392                 : /************************************************************************/
     393                 : 
     394               1 : int OGREDIGEODataSource::ReadSCD()
     395                 : {
     396               1 :     VSILFILE* fp = OpenFile(osSCN, "SCD");
     397               1 :     if (fp == NULL)
     398               0 :         return FALSE;
     399                 : 
     400                 :     const char* pszLine;
     401               1 :     CPLString osRTY, osRID, osNameRID, osKND;
     402               1 :     strListType aosAttrRID;
     403               1 :     int nWidth = 0;
     404            1406 :     while(TRUE)
     405                 :     {
     406            1407 :         pszLine = CPLReadLine2L(fp, 81, NULL);
     407            1407 :         if (pszLine != NULL)
     408                 :         {
     409            1406 :             if (strlen(pszLine) < 8 || pszLine[7] != ':')
     410             239 :                 continue;
     411                 :         }
     412                 : 
     413            1168 :         if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
     414                 :         {
     415             120 :             if (osRTY == "OBJ")
     416                 :             {
     417              22 :                 if (mapObjects.find(osNameRID) == mapObjects.end())
     418                 :                 {
     419                 :                     CPLDebug("EDIGEO", "Cannot find object %s",
     420               0 :                              osNameRID.c_str());
     421                 :                 }
     422                 :                 else
     423                 :                 {
     424              22 :                     OGREDIGEOObjectDescriptor objDesc;
     425              22 :                     objDesc.osRID = osRID;
     426              22 :                     objDesc.osNameRID = osNameRID;
     427              22 :                     objDesc.osKND = osKND;
     428              22 :                     objDesc.aosAttrRID = aosAttrRID;
     429                 :                     /*CPLDebug("EDIGEO", "Object %s = %s, %s, %d attributes",
     430                 :                             osRID.c_str(), osNameRID.c_str(), osKND.c_str(),
     431                 :                             (int)aosAttrRID.size());*/
     432                 : 
     433              22 :                     aoObjList.push_back(objDesc);
     434                 :                 }
     435                 :             }
     436              98 :             else if (osRTY == "ATT")
     437                 :             {
     438              53 :                 if (mapAttributes.find(osNameRID) == mapAttributes.end())
     439                 :                 {
     440                 :                     CPLDebug("EDIGEO", "Cannot find attribute %s",
     441               0 :                              osNameRID.c_str());
     442                 :                 }
     443                 :                 else
     444                 :                 {
     445              53 :                     OGREDIGEOAttributeDescriptor attDesc;
     446              53 :                     attDesc.osRID = osRID;
     447              53 :                     attDesc.osNameRID = osNameRID;
     448              53 :                     attDesc.nWidth = nWidth;
     449                 :                     /*CPLDebug("EDIGEO", "Attribute %s = %s, %d",
     450                 :                             osRID.c_str(), osNameRID.c_str(), nWidth);*/
     451                 : 
     452              53 :                     mapAttributesSCD[osRID] = attDesc;
     453                 :                 }
     454                 :             }
     455             120 :             if (pszLine == NULL)
     456                 :                 break;
     457             119 :             osRTY = pszLine + 8;
     458             119 :             osRID = "";
     459             119 :             osNameRID = "";
     460             119 :             osKND = "";
     461             119 :             aosAttrRID.resize(0);
     462             119 :             nWidth = 0;
     463                 :         }
     464            1167 :         if (strncmp(pszLine, "RIDSA", 5) == 0)
     465             119 :             osRID = pszLine + 8;
     466            1048 :         else if (strncmp(pszLine, "DIPCP", 5) == 0)
     467                 :         {
     468              88 :             const char* pszDIP = pszLine + 8;
     469              88 :             char** papszTokens = CSLTokenizeString2(pszDIP, ";", 0);
     470              88 :             if (CSLCount(papszTokens) == 4)
     471                 :             {
     472              88 :                 osNameRID = papszTokens[3];
     473                 :             }
     474              88 :             CSLDestroy(papszTokens);
     475                 :         }
     476             960 :         else if (strncmp(pszLine, "KNDSA", 5) == 0)
     477              53 :             osKND = pszLine + 8;
     478             907 :         else if (strncmp(pszLine, "AAPCP", 5) == 0)
     479                 :         {
     480             107 :             const char* pszAAP = pszLine + 8;
     481             107 :             char** papszTokens = CSLTokenizeString2(pszAAP, ";", 0);
     482             107 :             if (CSLCount(papszTokens) == 4)
     483                 :             {
     484             107 :                 const char* pszAttRID = papszTokens[3];
     485             107 :                 aosAttrRID.push_back(pszAttRID);
     486                 :             }
     487             107 :             CSLDestroy(papszTokens);
     488                 :         }
     489             800 :         else if (strncmp(pszLine, "CANSN", 5) == 0)
     490              53 :             nWidth = atoi(pszLine + 8);
     491                 :     }
     492                 : 
     493               1 :     VSIFCloseL(fp);
     494                 : 
     495                 : 
     496               1 :     return TRUE;
     497                 : }
     498                 : 
     499                 : /************************************************************************/
     500                 : /*                              ReadQAL()                               */
     501                 : /************************************************************************/
     502                 : 
     503               1 : int OGREDIGEODataSource::ReadQAL()
     504                 : {
     505               1 :     VSILFILE* fp = OpenFile(osQAN, "QAL");
     506               1 :     if (fp == NULL)
     507               0 :         return FALSE;
     508                 : 
     509                 :     const char* pszLine;
     510               1 :     CPLString osRTY, osRID;
     511               1 :     int nODA = 0, nUDA = 0;
     512            6040 :     while(TRUE)
     513                 :     {
     514            6041 :         pszLine = CPLReadLine2L(fp, 81, NULL);
     515            6041 :         if (pszLine != NULL)
     516                 :         {
     517            6040 :             if (strlen(pszLine) < 8 || pszLine[7] != ':')
     518            1007 :                 continue;
     519                 :         }
     520                 : 
     521            5537 :         if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
     522                 :         {
     523             504 :             if (osRTY == "QUP")
     524                 :             {
     525             503 :                 mapQAL[osRID] = intintType(nODA, nUDA);
     526                 :             }
     527             504 :             if (pszLine == NULL)
     528                 :                 break;
     529             503 :             osRTY = pszLine + 8;
     530             503 :             osRID = "";
     531             503 :             nODA = 0;
     532             503 :             nUDA = 0;
     533                 :         }
     534            4530 :         else if (strncmp(pszLine, "RIDSA", 5) == 0)
     535             503 :             osRID = pszLine + 8;
     536            4027 :         else if (strncmp(pszLine, "ODASD", 5) == 0)
     537             503 :             nODA = atoi(pszLine + 8);
     538            3524 :         else if (strncmp(pszLine, "UDASD", 5) == 0)
     539             503 :             nUDA = atoi(pszLine + 8);
     540                 :     }
     541                 : 
     542               1 :     VSIFCloseL(fp);
     543                 : 
     544               1 :     return TRUE;
     545                 : }
     546                 : 
     547                 : /************************************************************************/
     548                 : /*                       CreateLayerFromObjectDesc()                    */
     549                 : /************************************************************************/
     550                 : 
     551              22 : int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescriptor& objDesc)
     552                 : {
     553              22 :     OGRwkbGeometryType eType = wkbUnknown;
     554              22 :     if (objDesc.osKND == "ARE")
     555              11 :         eType = wkbPolygon;
     556              11 :     else if (objDesc.osKND == "LIN")
     557               2 :         eType = wkbLineString;
     558               9 :     else if (objDesc.osKND == "PCT")
     559               9 :         eType = wkbPoint;
     560                 :     else
     561                 :     {
     562               0 :         CPLDebug("EDIGEO", "Unknown KND : %s", objDesc.osKND.c_str());
     563               0 :         return FALSE;
     564                 :     }
     565                 : 
     566              22 :     const char* pszLayerName = objDesc.osRID.c_str();
     567                 :         //mapObjects.find(objDesc.osNameRID)->second.c_str();
     568                 :     OGREDIGEOLayer* poLayer = new OGREDIGEOLayer(this, pszLayerName,
     569              22 :                                                     eType, poSRS);
     570                 : 
     571              44 :     poLayer->AddFieldDefn("OBJECT_RID", OFTString, "");
     572                 : 
     573             129 :     for(int j=0;j<(int)objDesc.aosAttrRID.size();j++)
     574                 :     {
     575                 :         std::map<CPLString,OGREDIGEOAttributeDescriptor>::iterator it =
     576             107 :             mapAttributesSCD.find(objDesc.aosAttrRID[j]);
     577             107 :         if (it != mapAttributesSCD.end())
     578                 :         {
     579             107 :             const OGREDIGEOAttributeDescriptor& attrDesc = it->second;
     580                 :             const OGREDIGEOAttributeDef& attrDef =
     581             107 :                                     mapAttributes[attrDesc.osNameRID];
     582             107 :             OGRFieldType eType = OFTString;
     583             107 :             if (attrDef.osTYP == "R" || attrDef.osTYP == "E")
     584              19 :                 eType = OFTReal;
     585              88 :             else if (attrDef.osTYP == "I" || attrDef.osTYP == "N")
     586               0 :                 eType = OFTInteger;
     587                 : 
     588             107 :             poLayer->AddFieldDefn(attrDef.osLAB, eType, objDesc.aosAttrRID[j]);
     589                 :         }
     590                 :     }
     591                 : 
     592                 : 
     593              22 :     if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") == 0)
     594                 :     {
     595               1 :         OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
     596                 : 
     597               1 :         iATR = poFDefn->GetFieldIndex("ATR");
     598               1 :         iDI3 = poFDefn->GetFieldIndex("DI3");
     599               1 :         iDI4 = poFDefn->GetFieldIndex("DI4");
     600               1 :         iHEI = poFDefn->GetFieldIndex("HEI");
     601               1 :         iFON = poFDefn->GetFieldIndex("FON");
     602                 : 
     603               1 :         poLayer->AddFieldDefn("OGR_OBJ_LNK", OFTString, "");
     604               1 :         iOBJ_LNK = poFDefn->GetFieldIndex("OGR_OBJ_LNK");
     605                 : 
     606               2 :         poLayer->AddFieldDefn("OGR_OBJ_LNK_LAYER", OFTString, "");
     607               1 :         iOBJ_LNK_LAYER = poFDefn->GetFieldIndex("OGR_OBJ_LNK_LAYER");
     608                 : 
     609               2 :         poLayer->AddFieldDefn("OGR_ATR_VAL", OFTString, "");
     610               1 :         iATR_VAL = poFDefn->GetFieldIndex("OGR_ATR_VAL");
     611                 : 
     612               2 :         poLayer->AddFieldDefn("OGR_ANGLE", OFTReal, "");
     613               1 :         iANGLE = poFDefn->GetFieldIndex("OGR_ANGLE");
     614                 : 
     615               2 :         poLayer->AddFieldDefn("OGR_FONT_SIZE", OFTReal, "");
     616               1 :         iSIZE = poFDefn->GetFieldIndex("OGR_FONT_SIZE");
     617                 :     }
     618              21 :     else if (mapQAL.size() != 0)
     619                 :     {
     620              21 :         poLayer->AddFieldDefn("CREAT_DATE", OFTInteger, "");
     621              42 :         poLayer->AddFieldDefn("UPDATE_DATE", OFTInteger, "");
     622                 :     }
     623                 : 
     624              22 :     mapLayer[objDesc.osRID] = poLayer;
     625                 : 
     626                 :     papoLayers = (OGRLayer**)
     627              22 :         CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     628              22 :     papoLayers[nLayers] = poLayer;
     629              22 :     nLayers ++;
     630                 : 
     631              22 :     return TRUE;
     632                 : }
     633                 : 
     634                 : /************************************************************************/
     635                 : /*                              ReadVEC()                               */
     636                 : /************************************************************************/
     637                 : 
     638               4 : int OGREDIGEODataSource::ReadVEC(const char* pszVECName)
     639                 : {
     640               4 :     VSILFILE* fp = OpenFile(pszVECName, "VEC");
     641               4 :     if (fp == NULL)
     642               0 :         return FALSE;
     643                 : 
     644                 :     const char* pszLine;
     645               4 :     CPLString osRTY, osRID;
     646               4 :     xyPairListType aXY;
     647               4 :     CPLString osLnkStartType, osLnkStartName, osLnkEndType, osLnkEndName;
     648               4 :     strListType osLnkEndNameList;
     649               4 :     CPLString osAttId;
     650               4 :     std::vector< strstrType > aosAttIdVal;
     651               4 :     CPLString osSCP;
     652               4 :     CPLString osQUP_RID;
     653               4 :     int bIso8859_1 = FALSE;
     654                 : 
     655           69082 :     while(TRUE)
     656                 :     {
     657           69086 :         pszLine = CPLReadLine2L(fp, 81, NULL);
     658                 : skip_read_next_line:
     659           73090 :         if (pszLine != NULL)
     660                 :         {
     661           73086 :             if (strlen(pszLine) < 8 || pszLine[7] != ':')
     662           11170 :                 continue;
     663                 :         }
     664                 : 
     665           67503 :         if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
     666                 :         {
     667            5587 :             if (osRTY == "PAR")
     668                 :             {
     669             744 :                 if (aXY.size() < 2)
     670                 :                     CPLDebug("EDIGEO", "Error: ARC %s has not enough points",
     671               0 :                                     osRID.c_str());
     672                 :                 else
     673             744 :                     mapPAR[osRID] = aXY;
     674                 :             }
     675            4843 :             else if (osRTY == "LNK")
     676                 :             {
     677            3214 :                 if (osLnkStartType == "PAR" && osLnkEndType == "PFE")
     678                 :                 {
     679                 :                     /*CPLDebug("EDIGEO", "PFE[%s] -> PAR[%s]",
     680                 :                              osLnkEndName.c_str(), osLnkStartName.c_str());*/
     681             941 :                     if (mapPFE_PAR.find(osLnkEndName) == mapPFE_PAR.end())
     682             285 :                         mapPFE_PAR[osLnkEndName].push_back(osLnkStartName);
     683                 :                     else
     684                 :                     {
     685             656 :                         int bAlreadyExists = FALSE;
     686             656 :                         strListType& osPARList = mapPFE_PAR[osLnkEndName];
     687            9822 :                         for(int j=0;j<(int)osPARList.size();j++)
     688                 :                         {
     689            9166 :                             if (osPARList[j] == osLnkStartName)
     690               0 :                                 bAlreadyExists = TRUE;
     691                 :                         }
     692             656 :                         if (!bAlreadyExists)
     693             656 :                             osPARList.push_back(osLnkStartName);
     694                 :                     }
     695                 :                 }
     696            2273 :                 else if (osLnkStartType == "FEA" && osLnkEndType == "PFE")
     697                 :                 {
     698                 :                     /*CPLDebug("EDIGEO", "FEA[%s] -> PFE[%s]",
     699                 :                              osLnkStartName.c_str(), osLnkEndName.c_str());*/
     700                 :                     listFEA_PFE.push_back(strstrType
     701             276 :                                                (osLnkStartName, osLnkEndName));
     702                 :                 }
     703            1997 :                 else if (osLnkStartType == "FEA" && osLnkEndType == "PAR")
     704                 :                 {
     705                 :                     /*CPLDebug("EDIGEO", "FEA[%s] -> PAR[%s]",
     706                 :                              osLnkStartName.c_str(), osLnkEndName.c_str());*/
     707                 :                     listFEA_PAR.push_back(std::pair<CPLString, strListType >
     708             149 :                                                 (osLnkStartName, osLnkEndNameList));
     709                 :                 }
     710            1848 :                 else if (osLnkStartType == "FEA" && osLnkEndType == "PNO")
     711                 :                 {
     712                 :                     /*CPLDebug("EDIGEO", "FEA[%s] -> PNO[%s]",
     713                 :                              osLnkStartName.c_str(), osLnkEndName.c_str());*/
     714                 :                     listFEA_PNO.push_back(strstrType
     715             326 :                                                 (osLnkStartName, osLnkEndName));
     716                 :                 }
     717            1522 :                 else if (osLnkStartType == "FEA" && osLnkEndType == "FEA")
     718                 :                 {
     719                 :                     /*CPLDebug("EDIGEO", "FEA[%s] -> FEA[%s]",
     720                 :                              osLnkStartName.c_str(), osLnkEndName.c_str());*/
     721             700 :                     if (osSCP == "IS_S_REL_IWW")
     722             248 :                         mapFEA_FEA[osLnkStartName] = osLnkEndName;
     723                 :                 }
     724             822 :                 else if (osLnkStartType == "PAR" && osLnkEndType == "PNO")
     725                 :                 {
     726                 :                 }
     727                 :                 else
     728                 :                 {
     729                 :                     CPLDebug("EDIGEO", "Unhandled LNK(%s) %s=%s --> %s=%s",
     730                 :                              osRID.c_str(),
     731                 :                              osLnkStartType.c_str(), osLnkStartName.c_str(),
     732               0 :                              osLnkEndType.c_str(), osLnkEndName.c_str());
     733                 :                 }
     734                 :             }
     735            1629 :             else if (osRTY == "FEA")
     736                 :             {
     737             751 :                 OGREDIGEOFEADesc feaDesc;
     738             751 :                 feaDesc.aosAttIdVal = aosAttIdVal;
     739             751 :                 feaDesc.osSCP = osSCP;
     740             751 :                 feaDesc.osQUP_RID = osQUP_RID;
     741             751 :                 mapFEA[osRID] = feaDesc;
     742                 :             }
     743             878 :             else if (osRTY == "PNO")
     744                 :             {
     745             589 :                 if (aXY.size() == 1)
     746                 :                 {
     747                 :                     /*CPLDebug("EDIGEO", "PNO[%s] = %f, %f",
     748                 :                              osRID.c_str(), aXY[0].first, aXY[0].second);*/
     749             589 :                     mapPNO[osRID] = aXY[0];
     750                 :                 }
     751                 :             }
     752            5587 :             if (pszLine == NULL)
     753                 :                 break;
     754            5583 :             osRTY = pszLine + 8;
     755            5583 :             osRID = "";
     756            5583 :             aXY.resize(0);
     757            5583 :             osLnkStartType = "";
     758            5583 :             osLnkStartName = "";
     759            5583 :             osLnkEndType = "";
     760            5583 :             osLnkEndName = "";
     761            5583 :             osAttId = "";
     762            5583 :             aosAttIdVal.resize(0);
     763            5583 :             osLnkEndNameList.resize(0);
     764            5583 :             osSCP = "";
     765            5583 :             osQUP_RID = "";
     766            5583 :             bIso8859_1 = FALSE;
     767                 :         }
     768           56333 :         else if (strncmp(pszLine, "RIDSA", 5) == 0)
     769            5583 :             osRID = pszLine + 8;
     770           50750 :         else if (strncmp(pszLine, "CORCC", 5) == 0)
     771                 :         {
     772            8009 :             const char* pszY = strchr(pszLine+8, ';');
     773            8009 :             if (pszY)
     774                 :             {
     775            8009 :                 double dfX = atof(pszLine + 8);
     776            8009 :                 double dfY = atof(pszY + 1);
     777            8009 :                 aXY.push_back(xyPairType (dfX, dfY));
     778                 :             }
     779                 :         }
     780           42741 :         else if (strncmp(pszLine, "FTPCP", 5) == 0)
     781                 :         {
     782            6499 :             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
     783            6499 :             if (CSLCount(papszTokens) == 4)
     784                 :             {
     785            6499 :                 if (osLnkStartType.size() == 0)
     786                 :                 {
     787            3214 :                     osLnkStartType = papszTokens[2];
     788            3214 :                     osLnkStartName = papszTokens[3];
     789                 :                 }
     790                 :                 else
     791                 :                 {
     792            3285 :                     osLnkEndType = papszTokens[2];
     793            3285 :                     osLnkEndName = papszTokens[3];
     794            3285 :                     osLnkEndNameList.push_back(osLnkEndName);
     795                 :                 }
     796                 :             }
     797            6499 :             CSLDestroy(papszTokens);
     798                 :         }
     799           36242 :         else if (strncmp(pszLine, "SCPCP", 5) == 0)
     800                 :         {
     801            5583 :             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
     802            5583 :             if (CSLCount(papszTokens) == 4)
     803                 :             {
     804            5583 :                 if (osRTY == "LNK")
     805                 :                 {
     806            3214 :                     if (strcmp(papszTokens[2], "ASS") == 0)
     807             700 :                         osSCP = papszTokens[3];
     808                 :                 }
     809            2369 :                 else if (strcmp(papszTokens[2], "OBJ") == 0)
     810             751 :                     osSCP = papszTokens[3];
     811                 :             }
     812            5583 :             CSLDestroy(papszTokens);
     813                 :         }
     814           30659 :         else if (strncmp(pszLine, "ATPCP", 5) == 0)
     815                 :         {
     816            4252 :             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
     817            4252 :             if (CSLCount(papszTokens) == 4)
     818                 :             {
     819            4252 :                 if (strcmp(papszTokens[2], "ATT") == 0)
     820            4252 :                     osAttId = papszTokens[3];
     821                 :             }
     822            4252 :             CSLDestroy(papszTokens);
     823                 :         }
     824           26407 :         else if (strcmp(pszLine, "TEXT 06:8859-1") == 0)
     825                 :         {
     826             658 :             bIso8859_1 = TRUE;
     827                 :         }
     828           25749 :         else if (strncmp(pszLine, "ATVS", 4) == 0)
     829                 :         {
     830            4004 :             CPLString osAttVal = pszLine + 8;
     831            4004 :             int bSkipReadNextLine = FALSE;
     832               0 :             while(TRUE)
     833                 :             {
     834            4004 :                 pszLine = CPLReadLine2L(fp, 81, NULL);
     835            8008 :                 if (pszLine != NULL &&
     836                 :                     strlen(pszLine) >= 8 &&
     837            4004 :                     pszLine[7] == ':' &&
     838                 :                     strncmp(pszLine, "NEXT ", 5) == 0)
     839                 :                 {
     840               0 :                     osAttVal += pszLine + 8;
     841                 :                 }
     842                 :                 else
     843                 :                 {
     844            4004 :                     bSkipReadNextLine = TRUE;
     845                 :                     break;
     846                 :                 }
     847                 :             }
     848            4662 :             if (bIso8859_1 && bRecodeToUTF8)
     849                 :             {
     850                 :                 char* pszNewVal = CPLRecode(osAttVal.c_str(),
     851             658 :                                             CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
     852             658 :                 osAttVal = pszNewVal;
     853             658 :                 CPLFree(pszNewVal);
     854                 :             }
     855            3346 :             else if (bHasUTF8ContentOnly)
     856                 :             {
     857            3346 :                 bHasUTF8ContentOnly = CPLIsUTF8(osAttVal.c_str(), -1);
     858                 :             }
     859            4004 :             if (osAttId.size() != 0)
     860            4004 :                 aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
     861            4004 :             osAttId = "";
     862            4004 :             bIso8859_1 = FALSE;
     863            4004 :             if (bSkipReadNextLine)
     864               0 :                 goto skip_read_next_line;
     865                 :         }
     866           21745 :         else if (strncmp(pszLine, "ATVCP", 5) == 0)
     867                 :         {
     868             248 :             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
     869             248 :             if (CSLCount(papszTokens) == 4)
     870                 :             {
     871             248 :                 if (strcmp(papszTokens[2], "ATT") == 0)
     872                 :                 {
     873             248 :                     CPLString osAttVal = papszTokens[3];
     874             248 :                     if (osAttId.size() != 0)
     875             248 :                         aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
     876             248 :                     osAttId = "";
     877                 :                 }
     878                 :             }
     879             248 :             CSLDestroy(papszTokens);
     880                 :         }
     881           21497 :         else if (strncmp(pszLine, "QAPCP", 5) == 0)
     882                 :         {
     883             503 :             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
     884             503 :             if (CSLCount(papszTokens) == 4)
     885                 :             {
     886             503 :                 if (strcmp(papszTokens[2], "QUP") == 0)
     887                 :                 {
     888             503 :                     osQUP_RID = papszTokens[3];
     889                 :                 }
     890                 :             }
     891             503 :             CSLDestroy(papszTokens);
     892                 :         }
     893                 :     }
     894                 : 
     895               4 :     VSIFCloseL(fp);
     896                 : 
     897               4 :     return TRUE;
     898                 : }
     899                 : 
     900                 : /************************************************************************/
     901                 : /*                        CreateFeature()                               */
     902                 : /************************************************************************/
     903                 : 
     904             751 : OGRFeature* OGREDIGEODataSource::CreateFeature(const CPLString& osFEA)
     905                 : {
     906                 :     const std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA =
     907             751 :                                                         mapFEA.find(osFEA);
     908             751 :     if (itFEA == mapFEA.end())
     909                 :     {
     910               0 :         CPLDebug("EDIGEO", "ERROR: Cannot find FEA %s", osFEA.c_str());
     911               0 :         return NULL;
     912                 :     }
     913                 : 
     914             751 :     const OGREDIGEOFEADesc& fea = itFEA->second;
     915                 :     const std::map<CPLString,OGREDIGEOLayer*>::iterator itLyr =
     916             751 :                                                     mapLayer.find(fea.osSCP);
     917             751 :     if (itLyr != mapLayer.end())
     918                 :     {
     919             751 :         OGREDIGEOLayer* poLayer = itLyr->second;
     920                 : 
     921             751 :         OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn());
     922             751 :         poFeature->SetField(0, itFEA->first.c_str());
     923            5003 :         for(int i=0;i<(int)fea.aosAttIdVal.size();i++)
     924                 :         {
     925            4252 :             const CPLString& id = fea.aosAttIdVal[i].first;
     926            4252 :             const CPLString& val = fea.aosAttIdVal[i].second;
     927            4252 :             int iIndex = poLayer->GetAttributeIndex(id);
     928            4252 :             if (iIndex != -1)
     929            4252 :                 poFeature->SetField(iIndex, val.c_str());
     930                 :             else
     931                 :                 CPLDebug("EDIGEO",
     932               0 :                          "ERROR: Cannot find attribute %s", id.c_str());
     933                 :         }
     934                 : 
     935             751 :         if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 &&
     936                 :             mapQAL.size() != 0 && fea.osQUP_RID.size() != 0)
     937                 :         {
     938                 :             const std::map<CPLString, intintType>::iterator itQAL =
     939             503 :                                                         mapQAL.find(fea.osQUP_RID);
     940             503 :             if (itQAL != mapQAL.end())
     941                 :             {
     942             502 :                 const intintType& creationUpdateDate = itQAL->second;
     943             502 :                 if (creationUpdateDate.first != 0)
     944             502 :                     poFeature->SetField("CREAT_DATE", creationUpdateDate.first);
     945             502 :                 if (creationUpdateDate.second != 0)
     946             502 :                     poFeature->SetField("UPDATE_DATE", creationUpdateDate.second);
     947                 :             }
     948                 :         }
     949                 : 
     950             751 :         poLayer->AddFeature(poFeature);
     951                 : 
     952             751 :         return poFeature;
     953                 :     }
     954                 :     else
     955                 :     {
     956               0 :         CPLDebug("EDIGEO", "ERROR: Cannot find layer %s", fea.osSCP.c_str());
     957               0 :         return NULL;
     958                 :     }
     959                 : }
     960                 : 
     961                 : /************************************************************************/
     962                 : /*                             SetStyle()                               */
     963                 : /************************************************************************/
     964                 : 
     965             326 : int OGREDIGEODataSource::SetStyle(const CPLString& osFEA,
     966                 :                                   OGRFeature* poFeature)
     967                 : {
     968                 :     /* EDIGEO PCI specific */
     969                 :     /* See EDIGeO_PCI.pdf, chapter 3 "Principes généraux de */
     970                 :     /* positionnement de la toponymie. */
     971             326 :     const char* pszATR = NULL;
     972             326 :     if (strcmp(poFeature->GetDefnRef()->GetName(), "ID_S_OBJ_Z_1_2_2") == 0 &&
     973                 :         iATR != -1 && (pszATR = poFeature->GetFieldAsString(iATR)) != NULL)
     974                 :     {
     975             248 :         const CPLString osATR = pszATR;
     976                 :         std::map< CPLString, CPLString>::iterator itFEA_FEA =
     977             248 :                                                 mapFEA_FEA.find(osFEA);
     978             248 :         if (itFEA_FEA != mapFEA_FEA.end())
     979                 :         {
     980             248 :             const CPLString& osOBJ_LNK = itFEA_FEA->second;
     981                 :             std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA_LNK =
     982             248 :                                                         mapFEA.find(osOBJ_LNK);
     983             248 :             if (itFEA_LNK != mapFEA.end())
     984                 :             {
     985             248 :                 const OGREDIGEOFEADesc& fea_lnk = itFEA_LNK->second;
     986             542 :                 for(int j=0;j<(int)fea_lnk.aosAttIdVal.size();j++)
     987                 :                 {
     988             542 :                     if (fea_lnk.aosAttIdVal[j].first == osATR)
     989                 :                     {
     990             248 :                         double dfAngle = 0;
     991             248 :                         if (iDI3 != -1 && iDI4 != -1)
     992                 :                         {
     993                 :                             double dfBaseVectorX =
     994             248 :                                 poFeature->GetFieldAsDouble(iDI3);
     995                 :                             double dfBaseVectorY =
     996             248 :                                 poFeature->GetFieldAsDouble(iDI4);
     997                 :                             dfAngle = atan2(dfBaseVectorY, dfBaseVectorX)
     998             248 :                                                                 / M_PI * 180;
     999             248 :                             if (dfAngle < 0)
    1000              42 :                                 dfAngle += 360;
    1001                 :                         }
    1002             248 :                         double dfSize = 1;
    1003             248 :                         if (iHEI != -1)
    1004             248 :                             dfSize = poFeature->GetFieldAsDouble(iHEI);
    1005             248 :                         if (dfSize <= 0 || dfSize >= 100)
    1006               0 :                             dfSize = 1;
    1007             248 :                         const char* pszFontFamily = NULL;
    1008             248 :                         if (iFON != -1)
    1009             248 :                             pszFontFamily = poFeature->GetFieldAsString(iFON);
    1010                 : 
    1011             248 :                         CPLString osStyle("LABEL(t:\"");
    1012             248 :                         osStyle += fea_lnk.aosAttIdVal[j].second;
    1013             248 :                         osStyle += "\"";
    1014             248 :                         if (dfAngle != 0)
    1015                 :                         {
    1016             114 :                             osStyle += ",a:";
    1017             114 :                             osStyle += CPLString().Printf("%.1f", dfAngle);
    1018                 :                         }
    1019             248 :                         if (pszFontFamily != NULL && bIncludeFontFamily)
    1020                 :                         {
    1021             248 :                             osStyle += ",f:\"";
    1022             248 :                             osStyle += pszFontFamily;
    1023             248 :                             osStyle += "\"";
    1024                 :                         }
    1025             248 :                         osStyle += ",s:";
    1026             248 :                         osStyle += CPLString().Printf("%.1f", dfSize);
    1027             248 :                         osStyle += ",c:#000000)";
    1028             248 :                         poFeature->SetStyleString(osStyle);
    1029                 : 
    1030                 :                         poFeature->SetField(iATR_VAL,
    1031             248 :                                             fea_lnk.aosAttIdVal[j].second);
    1032             248 :                         poFeature->SetField(iANGLE, dfAngle);
    1033             248 :                         poFeature->SetField(iSIZE, dfSize * dfSizeFactor);
    1034             248 :                         poFeature->SetField(iOBJ_LNK, osOBJ_LNK);
    1035             248 :                         poFeature->SetField(iOBJ_LNK_LAYER, fea_lnk.osSCP);
    1036                 : 
    1037             248 :                         setLayersWithLabels.insert(fea_lnk.osSCP);
    1038                 : 
    1039             248 :                         break;
    1040                 :                     }
    1041                 :                 }
    1042                 :             }
    1043             248 :         }
    1044                 :     }
    1045                 : 
    1046             326 :     return TRUE;
    1047                 : }
    1048                 : 
    1049                 : /************************************************************************/
    1050                 : /*                           BuildPoints()                              */
    1051                 : /************************************************************************/
    1052                 : 
    1053               4 : int OGREDIGEODataSource::BuildPoints()
    1054                 : {
    1055             330 :     for(int i=0;i<(int)listFEA_PNO.size();i++)
    1056                 :     {
    1057             326 :         const CPLString& osFEA = listFEA_PNO[i].first;
    1058             326 :         const CPLString& osPNO = listFEA_PNO[i].second;
    1059                 :         const std::map< CPLString, xyPairType >::iterator itPNO =
    1060             326 :                                                         mapPNO.find(osPNO);
    1061             326 :         if (itPNO == mapPNO.end())
    1062                 :         {
    1063               0 :             CPLDebug("EDIGEO", "Cannot find PNO %s", osPNO.c_str());
    1064                 :         }
    1065                 :         else
    1066                 :         {
    1067             326 :             OGRFeature* poFeature = CreateFeature(osFEA);
    1068             326 :             if (poFeature)
    1069                 :             {
    1070             326 :                 const xyPairType& pno = itPNO->second;
    1071             326 :                 OGRPoint* poPoint = new OGRPoint(pno.first, pno.second);
    1072             326 :                 if (poSRS)
    1073             326 :                     poPoint->assignSpatialReference(poSRS);
    1074             326 :                 poFeature->SetGeometryDirectly(poPoint);
    1075                 : 
    1076             326 :                 SetStyle(osFEA, poFeature);
    1077                 :             }
    1078                 :         }
    1079                 :     }
    1080                 : 
    1081               4 :     return TRUE;
    1082                 : }
    1083                 : 
    1084                 : /************************************************************************/
    1085                 : /*                        BuildLineStrings()                            */
    1086                 : /************************************************************************/
    1087                 : 
    1088               4 : int OGREDIGEODataSource::BuildLineStrings()
    1089                 : {
    1090                 :     int i, iter;
    1091                 : 
    1092             153 :     for(iter=0;iter<(int)listFEA_PAR.size();iter++)
    1093                 :     {
    1094             149 :         const CPLString& osFEA = listFEA_PAR[iter].first;
    1095             149 :         const strListType & aosPAR = listFEA_PAR[iter].second;
    1096             149 :         OGRFeature* poFeature = CreateFeature(osFEA);
    1097             149 :         if (poFeature)
    1098                 :         {
    1099             149 :             OGRMultiLineString* poMulti = NULL;
    1100             363 :             for(int k=0;k<(int)aosPAR.size();k++)
    1101                 :             {
    1102                 :                 const std::map< CPLString, xyPairListType >::iterator itPAR =
    1103             214 :                                                     mapPAR.find(aosPAR[k]);
    1104             214 :                 if (itPAR != mapPAR.end())
    1105                 :                 {
    1106             214 :                     const xyPairListType& arc = itPAR->second;
    1107                 : 
    1108             214 :                     OGRLineString* poLS = new OGRLineString();
    1109             214 :                     poLS->setNumPoints((int)arc.size());
    1110            1635 :                     for(i=0;i<(int)arc.size();i++)
    1111                 :                     {
    1112            1421 :                         poLS->setPoint(i, arc[i].first, arc[i].second);
    1113                 :                     }
    1114                 : 
    1115             214 :                     if (poFeature->GetGeometryRef() != NULL)
    1116                 :                     {
    1117              65 :                         if (poMulti == NULL)
    1118                 :                         {
    1119                 :                             OGRLineString* poPrevLS =
    1120              36 :                                 (OGRLineString*) poFeature->StealGeometry();
    1121              36 :                             poMulti = new OGRMultiLineString();
    1122              36 :                             poMulti->addGeometryDirectly(poPrevLS);
    1123              36 :                             poFeature->SetGeometryDirectly(poMulti);
    1124                 :                         }
    1125              65 :                         poMulti->addGeometryDirectly(poLS);
    1126                 :                     }
    1127                 :                     else
    1128             149 :                         poFeature->SetGeometryDirectly(poLS);
    1129                 :                 }
    1130                 :                 else
    1131                 :                     CPLDebug("EDIGEO",
    1132               0 :                              "ERROR: Cannot find ARC %s", aosPAR[k].c_str());
    1133                 :             }
    1134             149 :             if (poFeature->GetGeometryRef())
    1135             149 :                 poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
    1136                 :         }
    1137                 :     }
    1138                 : 
    1139               4 :     return TRUE;
    1140                 : }
    1141                 : 
    1142                 : /************************************************************************/
    1143                 : /*                           BuildPolygon()                             */
    1144                 : /************************************************************************/
    1145                 : 
    1146             276 : int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
    1147                 :                                       const CPLString& osPFE)
    1148                 : {
    1149                 :     int i;
    1150                 : 
    1151                 :     const std::map< CPLString, strListType >::iterator itPFE_PAR =
    1152             276 :                                                     mapPFE_PAR.find(osPFE);
    1153             276 :     if (itPFE_PAR == mapPFE_PAR.end())
    1154                 :     {
    1155               0 :         CPLDebug("EDIGEO", "ERROR: Cannot find PFE %s", osPFE.c_str());
    1156               0 :         return FALSE;
    1157                 :     }
    1158                 : 
    1159             276 :     const strListType & aosPARList = itPFE_PAR->second;
    1160                 : 
    1161                 : /* -------------------------------------------------------------------- */
    1162                 : /*      Resolve arc ids to arc coordinate lists.                        */
    1163                 : /* -------------------------------------------------------------------- */
    1164             276 :     std::vector< const xyPairListType *> aoPARPtrList;
    1165            1078 :     for(i=0;i<(int)aosPARList.size();i++)
    1166                 :     {
    1167                 :         const std::map< CPLString, xyPairListType >::iterator itPAR =
    1168             802 :                                             mapPAR.find(aosPARList[i]);
    1169             802 :         if (itPAR != mapPAR.end())
    1170             802 :             aoPARPtrList.push_back(&(itPAR->second));
    1171                 :         else
    1172                 :             CPLDebug("EDIGEO",
    1173               0 :                      "ERROR: Cannot find ARC %s", aosPARList[i].c_str());
    1174                 :     }
    1175                 : 
    1176             276 :     if (aoPARPtrList.size() == 0)
    1177               0 :         return FALSE;
    1178                 : 
    1179                 : /* -------------------------------------------------------------------- */
    1180                 : /*      Now try to chain all arcs together.                             */
    1181                 : /* -------------------------------------------------------------------- */
    1182             276 :     std::vector<xyPairListType> aoXYList;
    1183                 : 
    1184                 :     int j;
    1185             552 :     for(j=0;j<(int)aoPARPtrList.size();j++)
    1186                 :     {
    1187             802 :         if (aoPARPtrList[j] == NULL)
    1188             526 :             continue;
    1189             276 :         const xyPairListType& sFirstRing = *(aoPARPtrList[j]);
    1190             276 :         const xyPairType* psNext = &(sFirstRing[sFirstRing.size()-1]);
    1191                 : 
    1192             276 :         xyPairListType aoXY;
    1193            4855 :         for(i=0;i<(int)sFirstRing.size();i++)
    1194            4579 :             aoXY.push_back(sFirstRing[i]);
    1195             276 :         aoPARPtrList[j] = NULL;
    1196                 : 
    1197             276 :         int nIter = 1;
    1198            1078 :         while(aoXY[aoXY.size()-1] != aoXY[0] && nIter < (int)aoPARPtrList.size())
    1199                 :         {
    1200             526 :             int bFound = FALSE;
    1201             526 :             int bReverseSecond = FALSE;
    1202            1921 :             for(i=0;i<(int)aoPARPtrList.size();i++)
    1203                 :             {
    1204            1921 :                 if (aoPARPtrList[i] != NULL)
    1205                 :                 {
    1206            1017 :                     const xyPairListType& sSecondRing = *(aoPARPtrList[i]);
    1207            1017 :                     if (*psNext == sSecondRing[0])
    1208                 :                     {
    1209             259 :                         bFound = TRUE;
    1210             259 :                         bReverseSecond = FALSE;
    1211             259 :                         break;
    1212                 :                     }
    1213             758 :                     else if (*psNext == sSecondRing[sSecondRing.size()-1])
    1214                 :                     {
    1215             267 :                         bFound = TRUE;
    1216             267 :                         bReverseSecond = TRUE;
    1217             267 :                         break;
    1218                 :                     }
    1219                 :                 }
    1220                 :             }
    1221                 : 
    1222             526 :             if (!bFound)
    1223                 :             {
    1224                 :                 CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s",
    1225               0 :                         osFEA.c_str(), osPFE.c_str());
    1226               0 :                 break;
    1227                 :             }
    1228                 :             else
    1229                 :             {
    1230             526 :                 const xyPairListType& secondRing = *(aoPARPtrList[i]);
    1231             526 :                 aoPARPtrList[i] = NULL;
    1232             526 :                 if (!bReverseSecond)
    1233                 :                 {
    1234             918 :                     for(i=1;i<(int)secondRing.size();i++)
    1235             659 :                         aoXY.push_back(secondRing[i]);
    1236             259 :                     psNext = &secondRing[secondRing.size()-1];
    1237                 :                 }
    1238                 :                 else
    1239                 :                 {
    1240            1057 :                     for(i=1;i<(int)secondRing.size();i++)
    1241             790 :                         aoXY.push_back(secondRing[secondRing.size()-1-i]);
    1242             267 :                     psNext = &secondRing[0];
    1243                 :                 }
    1244                 :             }
    1245                 : 
    1246             526 :             nIter ++;
    1247                 :         }
    1248                 : 
    1249             276 :         aoXYList.push_back(aoXY);
    1250                 :     }
    1251                 : 
    1252                 : /* -------------------------------------------------------------------- */
    1253                 : /*      Create feature.                                                 */
    1254                 : /* -------------------------------------------------------------------- */
    1255             276 :     OGRFeature* poFeature = CreateFeature(osFEA);
    1256             276 :     if (poFeature)
    1257                 :     {
    1258             276 :         std::vector<OGRGeometry*> aosPolygons;
    1259             552 :         for(j=0;j<(int)aoXYList.size();j++)
    1260                 :         {
    1261             276 :             const xyPairListType& aoXY = aoXYList[j];
    1262             276 :             OGRLinearRing* poLS = new OGRLinearRing();
    1263             552 :             poLS->setNumPoints((int)aoXY.size());
    1264            6304 :             for(i=0;i<(int)aoXY.size();i++)
    1265            6028 :                 poLS->setPoint(i, aoXY[i].first, aoXY[i].second);
    1266             276 :             poLS->closeRings();
    1267             276 :             OGRPolygon* poPolygon = new OGRPolygon();
    1268             276 :             poPolygon->addRingDirectly(poLS);
    1269             276 :             aosPolygons.push_back(poPolygon);
    1270                 :         }
    1271                 : 
    1272                 :         int bIsValidGeometry;
    1273                 :         OGRGeometry* poGeom = OGRGeometryFactory::organizePolygons(
    1274                 :             &aosPolygons[0], (int)aosPolygons.size(),
    1275             276 :             &bIsValidGeometry, NULL);
    1276             276 :         if (poGeom)
    1277                 :         {
    1278             276 :             if (poSRS)
    1279             276 :                 poGeom->assignSpatialReference(poSRS);
    1280             276 :             poFeature->SetGeometryDirectly(poGeom);
    1281             276 :         }
    1282                 :     }
    1283                 : 
    1284             276 :     return TRUE;
    1285                 : }
    1286                 : 
    1287                 : /************************************************************************/
    1288                 : /*                          BuildPolygons()                             */
    1289                 : /************************************************************************/
    1290                 : 
    1291               4 : int OGREDIGEODataSource::BuildPolygons()
    1292                 : {
    1293                 :     int iter;
    1294             280 :     for(iter=0;iter<(int)listFEA_PFE.size();iter++)
    1295                 :     {
    1296             276 :         const CPLString& osFEA = listFEA_PFE[iter].first;
    1297             276 :         const CPLString& osPFE = listFEA_PFE[iter].second;
    1298             276 :         BuildPolygon(osFEA, osPFE);
    1299                 :     }
    1300                 : 
    1301               4 :     return TRUE;
    1302                 : }
    1303                 : 
    1304                 : /************************************************************************/
    1305                 : /*                  OGREDIGEOSortForQGIS()                              */
    1306                 : /************************************************************************/
    1307                 : 
    1308              47 : static int OGREDIGEOSortForQGIS(const void* a, const void* b)
    1309                 : {
    1310              47 :     OGREDIGEOLayer* poLayerA = *((OGREDIGEOLayer**) a);
    1311              47 :     OGREDIGEOLayer* poLayerB = *((OGREDIGEOLayer**) b);
    1312                 :     int nTypeA, nTypeB;
    1313              47 :     switch (poLayerA->GetLayerDefn()->GetGeomType())
    1314                 :     {
    1315              14 :         case wkbPoint: nTypeA = 1; break;
    1316               6 :         case wkbLineString: nTypeA = 2; break;
    1317              27 :         case wkbPolygon: nTypeA = 3; break;
    1318               0 :         default: nTypeA = 4; break;
    1319                 :     }
    1320              47 :     switch (poLayerB->GetLayerDefn()->GetGeomType())
    1321                 :     {
    1322              11 :         case wkbPoint: nTypeB = 1; break;
    1323               7 :         case wkbLineString: nTypeB = 2; break;
    1324              29 :         case wkbPolygon: nTypeB = 3; break;
    1325               0 :         default: nTypeB = 4; break;
    1326                 :     }
    1327              47 :     if (nTypeA == nTypeB)
    1328                 :     {
    1329              29 :         int nCmp = strcmp(poLayerA->GetName(), poLayerB->GetName());
    1330              29 :         if (nCmp == 0)
    1331               0 :             return 0;
    1332                 : 
    1333                 :         static const char* apszPolyOrder[] =
    1334                 :             { "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id",
    1335                 :               "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id" };
    1336             144 :         for(int i=0;i<(int)(sizeof(apszPolyOrder)/sizeof(char*));i++)
    1337                 :         {
    1338             134 :             if (strcmp(poLayerA->GetName(), apszPolyOrder[i]) == 0)
    1339              11 :                 return -1;
    1340             123 :             if (strcmp(poLayerB->GetName(), apszPolyOrder[i]) == 0)
    1341               8 :                 return 1;
    1342                 :         }
    1343              10 :         return nCmp;
    1344                 :     }
    1345                 :     else
    1346              18 :         return nTypeB - nTypeA;
    1347                 : }
    1348                 : 
    1349                 : /************************************************************************/
    1350                 : /*                                Open()                                */
    1351                 : /************************************************************************/
    1352                 : 
    1353              62 : int OGREDIGEODataSource::Open( const char * pszFilename, int bUpdateIn)
    1354                 : 
    1355                 : {
    1356              62 :     if (bUpdateIn)
    1357                 :     {
    1358              11 :         return FALSE;
    1359                 :     }
    1360                 : 
    1361              51 :     pszName = CPLStrdup( pszFilename );
    1362                 : 
    1363                 : /* -------------------------------------------------------------------- */
    1364                 : /*      Does this appear to be a .THF file?                             */
    1365                 : /* -------------------------------------------------------------------- */
    1366              51 :     if( !EQUAL(CPLGetExtension(pszFilename), "thf") )
    1367              50 :         return FALSE;
    1368                 : 
    1369               1 :     fpTHF = VSIFOpenL(pszFilename, "rb");
    1370               1 :     if (fpTHF == NULL)
    1371               0 :         return FALSE;
    1372                 : 
    1373                 :     const char* pszLine;
    1374               1 :     int i = 0;
    1375               1 :     int bIsEDIGEO = FALSE;
    1376               5 :     while(i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, NULL)) != NULL)
    1377                 :     {
    1378               4 :         if (strcmp(pszLine, "RTYSA03:GTS") == 0)
    1379                 :         {
    1380               1 :             bIsEDIGEO = TRUE;
    1381               1 :             break;
    1382                 :         }
    1383               3 :         i++;
    1384                 :     }
    1385                 : 
    1386               1 :     if (!bIsEDIGEO)
    1387                 :     {
    1388               0 :         VSIFCloseL(fpTHF);
    1389               0 :         fpTHF = NULL;
    1390               0 :         return FALSE;
    1391                 :     }
    1392                 : 
    1393               1 :     return TRUE;
    1394                 : }
    1395                 : 
    1396                 : /************************************************************************/
    1397                 : /*                           ReadEDIGEO()                               */
    1398                 : /************************************************************************/
    1399                 : 
    1400             399 : void OGREDIGEODataSource::ReadEDIGEO()
    1401                 : {
    1402             399 :     if (bHasReadEDIGEO)
    1403             398 :         return;
    1404                 : 
    1405               1 :     bHasReadEDIGEO = TRUE;
    1406                 : 
    1407                 : /* -------------------------------------------------------------------- */
    1408                 : /*      Read .THF file                                                  */
    1409                 : /* -------------------------------------------------------------------- */
    1410               1 :     VSIFSeekL(fpTHF, 0, SEEK_SET);
    1411               1 :     if (!ReadTHF(fpTHF))
    1412                 :     {
    1413               0 :         VSIFCloseL(fpTHF);
    1414               0 :         fpTHF = NULL;
    1415               0 :         return;
    1416                 :     }
    1417               1 :     VSIFCloseL(fpTHF);
    1418               1 :     fpTHF = NULL;
    1419                 : 
    1420                 : /* -------------------------------------------------------------------- */
    1421                 : /*      Read .GEO file                                                  */
    1422                 : /* -------------------------------------------------------------------- */
    1423               1 :     if (!ReadGEO())
    1424               0 :         return;
    1425                 : 
    1426                 : /* -------------------------------------------------------------------- */
    1427                 : /*      Read .GEN file                                                  */
    1428                 : /* -------------------------------------------------------------------- */
    1429               1 :     if (osGNN.size() != 0)
    1430               1 :         ReadGEN();
    1431                 : 
    1432                 : /* -------------------------------------------------------------------- */
    1433                 : /*      Read .DIC file                                                  */
    1434                 : /* -------------------------------------------------------------------- */
    1435               1 :     if (!ReadDIC())
    1436               0 :         return;
    1437                 : 
    1438                 : /* -------------------------------------------------------------------- */
    1439                 : /*      Read .SCD file                                                  */
    1440                 : /* -------------------------------------------------------------------- */
    1441               1 :     if (!ReadSCD())
    1442               0 :         return;
    1443                 : 
    1444                 : /* -------------------------------------------------------------------- */
    1445                 : /*      Read .QAL file                                                  */
    1446                 : /* -------------------------------------------------------------------- */
    1447               1 :     if (osQAN.size() != 0)
    1448               1 :         ReadQAL();
    1449                 : 
    1450                 : /* -------------------------------------------------------------------- */
    1451                 : /*      Create layers from SCD definitions                              */
    1452                 : /* -------------------------------------------------------------------- */
    1453                 :     int i;
    1454              23 :     for(i=0;i<(int)aoObjList.size();i++)
    1455                 :     {
    1456              22 :         CreateLayerFromObjectDesc(aoObjList[i]);
    1457                 :     }
    1458                 : 
    1459                 : /* -------------------------------------------------------------------- */
    1460                 : /*      Read .VEC files and create features                             */
    1461                 : /* -------------------------------------------------------------------- */
    1462               5 :     for(i=0;i<(int)aosGDN.size();i++)
    1463                 :     {
    1464               4 :         ReadVEC(aosGDN[i]);
    1465                 : 
    1466               4 :         BuildPoints();
    1467               4 :         BuildLineStrings();
    1468               4 :         BuildPolygons();
    1469                 : 
    1470               4 :         mapPNO.clear();
    1471               4 :         mapPAR.clear();
    1472               4 :         mapFEA.clear();
    1473               4 :         mapPFE_PAR.clear();
    1474               4 :         listFEA_PFE.clear();
    1475               4 :         listFEA_PAR.clear();
    1476               4 :         listFEA_PNO.clear();
    1477               4 :         mapFEA_FEA.clear();
    1478                 :     }
    1479                 : 
    1480               1 :     mapObjects.clear();
    1481               1 :     mapAttributes.clear();
    1482               1 :     mapAttributesSCD.clear();
    1483               1 :     mapQAL.clear();
    1484                 : 
    1485                 : /* -------------------------------------------------------------------- */
    1486                 : /*      Delete empty layers                                             */
    1487                 : /* -------------------------------------------------------------------- */
    1488              24 :     for(i=0;i<nLayers;/*nothing*/)
    1489                 :     {
    1490              22 :         if (papoLayers[i]->GetFeatureCount(TRUE) == 0)
    1491                 :         {
    1492               5 :             delete papoLayers[i];
    1493               5 :             if (i < nLayers - 1)
    1494                 :                 memmove(papoLayers + i, papoLayers + i + 1,
    1495               5 :                         (nLayers - i - 1) * sizeof(OGREDIGEOLayer*));
    1496               5 :             nLayers --;
    1497                 :         }
    1498                 :         else
    1499              17 :             i++;
    1500                 :     }
    1501                 : 
    1502                 : /* -------------------------------------------------------------------- */
    1503                 : /*      When added from QGIS, the layers must be ordered from           */
    1504                 : /*      bottom (Polygon) to top (Point) to get nice visual effect       */
    1505                 : /* -------------------------------------------------------------------- */
    1506               1 :     if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES")))
    1507               1 :         qsort(papoLayers, nLayers, sizeof(OGREDIGEOLayer*), OGREDIGEOSortForQGIS);
    1508                 : 
    1509                 : /* -------------------------------------------------------------------- */
    1510                 : /*      Create a label layer for each feature layer                     */
    1511                 : /* -------------------------------------------------------------------- */
    1512               1 :     if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES")))
    1513               1 :         CreateLabelLayers();
    1514                 : 
    1515               1 :     return;
    1516                 : }
    1517                 : 
    1518                 : /************************************************************************/
    1519                 : /*                         CreateLabelLayers()                          */
    1520                 : /************************************************************************/
    1521                 : 
    1522               1 : void OGREDIGEODataSource::CreateLabelLayers()
    1523                 : {
    1524               1 :     OGRLayer* poLayer = GetLayerByName("ID_S_OBJ_Z_1_2_2");
    1525               1 :     if (poLayer == NULL)
    1526               0 :         return;
    1527                 : 
    1528               1 :     std::map<CPLString, OGREDIGEOLayer*> mapLayerNameToLayer;
    1529                 : 
    1530                 :     OGRFeature* poFeature;
    1531               1 :     OGRFeatureDefn* poFeatureDefn = poLayer->GetLayerDefn();
    1532             250 :     while((poFeature = poLayer->GetNextFeature()) != NULL)
    1533                 :     {
    1534                 :         const char* pszBelongingLayerName =
    1535             248 :             poFeature->GetFieldAsString(iOBJ_LNK_LAYER);
    1536             248 :         if (pszBelongingLayerName)
    1537                 :         {
    1538             248 :             CPLString osBelongingLayerName = pszBelongingLayerName;
    1539                 :             std::map<CPLString, OGREDIGEOLayer*>::iterator it =
    1540             248 :                         mapLayerNameToLayer.find(osBelongingLayerName);
    1541                 :             OGREDIGEOLayer* poLabelLayer;
    1542                 : 
    1543             248 :             if (it == mapLayerNameToLayer.end())
    1544                 :             {
    1545                 :                 /* Create label layer if it does not already exist */
    1546               7 :                 CPLString osLayerLabelName = osBelongingLayerName + "_LABEL";
    1547                 :                 poLabelLayer = new OGREDIGEOLayer(this, osLayerLabelName.c_str(),
    1548               7 :                                              wkbPoint, poSRS);
    1549                 :                 int i;
    1550              14 :                 OGRFeatureDefn* poLabelFeatureDefn = poLabelLayer->GetLayerDefn();
    1551             140 :                 for(i=0;i<poFeatureDefn->GetFieldCount();i++)
    1552             133 :                     poLabelFeatureDefn->AddFieldDefn(poFeatureDefn->GetFieldDefn(i));
    1553               7 :                 mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer;
    1554                 : 
    1555                 :                 papoLayers = (OGRLayer**)
    1556               7 :                     CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
    1557               7 :                 papoLayers[nLayers] = poLabelLayer;
    1558               7 :                 nLayers ++;
    1559                 :             }
    1560                 :             else
    1561             241 :                 poLabelLayer = mapLayerNameToLayer[osBelongingLayerName];
    1562                 : 
    1563             248 :             OGRFeature* poNewFeature = new OGRFeature(poLabelLayer->GetLayerDefn());
    1564             248 :             poNewFeature->SetFrom(poFeature);
    1565             248 :             poLabelLayer->AddFeature(poNewFeature);
    1566                 :         }
    1567             248 :         delete poFeature;
    1568                 :     }
    1569                 : 
    1570               1 :     poLayer->ResetReading();
    1571                 : }
    1572                 : 

Generated by: LCOV version 1.7