LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/edigeo - ogredigeodatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 820 0.0 %
Date: 2025-01-18 12:42:00 Functions: 0 24 0.0 %

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

Generated by: LCOV version 1.14