LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/miramon - mm_rdlayr.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 255 315 81.0 %
Date: 2024-05-18 15:15:27 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  C API to read a MiraMon layer
       5             :  * Author:   Abel Pau, a.pau@creaf.uab.cat, based on the MiraMon codes,
       6             :  *           mainly written by Xavier Pons, Joan Maso (correctly written
       7             :  *           "Mas0xF3"), Abel Pau, Nuria Julia (N0xFAria Juli0xE0),
       8             :  *           Xavier Calaf, Lluis (Llu0xEDs) Pesquer and Alaitz Zabala, from
       9             :  *           CREAF and Universitat Autonoma (Aut0xF2noma) de Barcelona.
      10             :  *           For a complete list of contributors:
      11             :  *           https://www.miramon.cat/eng/QuiSom.htm
      12             :  ******************************************************************************
      13             :  * Copyright (c) 2024, Xavier Pons
      14             :  *
      15             :  * Permission is hereby granted, free of charge, to any person obtaining a
      16             :  * copy of this software and associated documentation files (the "Software"),
      17             :  * to deal in the Software without restriction, including without limitation
      18             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      19             :  * and/or sell copies of the Software, and to permit persons to whom the
      20             :  * Software is furnished to do so, subject to the following conditions:
      21             :  *
      22             :  * The above copyright notice and this permission notice shall be included
      23             :  * in all copies or substantial portions of the Software.
      24             :  *
      25             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      26             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      27             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      28             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      29             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      30             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      31             :  * DEALINGS IN THE SOFTWARE.
      32             :  ****************************************************************************/
      33             : 
      34             : #ifdef GDAL_COMPILATION
      35             : #include "ogr_api.h"  // For CPL_C_START
      36             : #include "mm_wrlayr.h"
      37             : #include "mm_wrlayr.h"  // For MMReadHeader()
      38             : #include "mm_gdal_functions.h"
      39             : #include "mm_gdal_constants.h"
      40             : #else
      41             : #include "CmptCmp.h"                    // Compatibility between compilers
      42             : #include "mm_gdal\mm_wrlayr.h"          // For MMReadHeader()
      43             : #include "mm_gdal\mm_gdal_functions.h"  // For int MM_GetArcHeights()
      44             : #include "mm_constants.h"
      45             : #endif
      46             : 
      47             : #include "mm_rdlayr.h"
      48             : 
      49             : #ifdef GDAL_COMPILATION
      50             : CPL_C_START  // Necessary for compiling in GDAL project
      51             : #endif
      52             : 
      53             :     /* -------------------------------------------------------------------- */
      54             :     /*      Reading MiraMon format file functions                           */
      55             :     /* -------------------------------------------------------------------- */
      56             : 
      57             :     // Initializes a MiraMon vector layer for reading
      58             :     int
      59         118 :     MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer,
      60             :                       FILE_TYPE *m_fp, const char *pszFilename)
      61             : {
      62             :     char szResult[MM_MAX_ID_SNY + 10];
      63             :     char *pszSRS;
      64             : 
      65         118 :     memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer));
      66         118 :     if (MMReadHeader(m_fp, &hMiraMonLayer->TopHeader))
      67             :     {
      68           0 :         MMCPLError(CE_Failure, CPLE_NoWriteAccess,
      69             :                    "Error reading header of file %s", pszFilename);
      70           0 :         return 1;
      71             :     }
      72         118 :     hMiraMonLayer->ReadOrWrite = MM_READING_MODE;
      73         118 :     strcpy(hMiraMonLayer->pszFlags, "rb");
      74             : 
      75         118 :     hMiraMonLayer->pszSrcLayerName = strdup_function(pszFilename);
      76             : 
      77         118 :     hMiraMonLayer->LayerVersion =
      78         118 :         (char)MMGetVectorVersion(&hMiraMonLayer->TopHeader);
      79         118 :     if (hMiraMonLayer->LayerVersion == MM_UNKNOWN_VERSION)
      80             :     {
      81           0 :         MMCPLError(CE_Failure, CPLE_NotSupported,
      82             :                    "MiraMon version file unknown.");
      83           0 :         return 1;
      84             :     }
      85         118 :     if (hMiraMonLayer->LayerVersion == MM_LAST_VERSION)
      86           0 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
      87         118 :     else if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
      88         112 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS;
      89             :     else
      90           6 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
      91             : 
      92         118 :     if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
      93          88 :         hMiraMonLayer->TopHeader.aFileType[1] == 'N' &&
      94          41 :         hMiraMonLayer->TopHeader.aFileType[2] == 'T')
      95             :     {
      96          41 :         if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
      97             :         {
      98          12 :             hMiraMonLayer->TopHeader.bIs3d = 1;
      99          12 :             hMiraMonLayer->eLT = MM_LayerType_Point3d;
     100             :         }
     101             :         else
     102          29 :             hMiraMonLayer->eLT = MM_LayerType_Point;
     103             : 
     104          41 :         hMiraMonLayer->bIsPoint = TRUE;
     105             :     }
     106          77 :     else if (hMiraMonLayer->TopHeader.aFileType[0] == 'A' &&
     107          30 :              hMiraMonLayer->TopHeader.aFileType[1] == 'R' &&
     108          30 :              hMiraMonLayer->TopHeader.aFileType[2] == 'C')
     109             :     {
     110          30 :         if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
     111             :         {
     112           7 :             hMiraMonLayer->TopHeader.bIs3d = 1;
     113           7 :             hMiraMonLayer->eLT = MM_LayerType_Arc3d;
     114             :         }
     115             :         else
     116          23 :             hMiraMonLayer->eLT = MM_LayerType_Arc;
     117             : 
     118          30 :         hMiraMonLayer->bIsArc = TRUE;
     119             :     }
     120          47 :     else if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
     121          47 :              hMiraMonLayer->TopHeader.aFileType[1] == 'O' &&
     122          47 :              hMiraMonLayer->TopHeader.aFileType[2] == 'L')
     123             :     {
     124             :         // 3D
     125          47 :         if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
     126             :         {
     127           2 :             hMiraMonLayer->TopHeader.bIs3d = 1;
     128           2 :             hMiraMonLayer->eLT = MM_LayerType_Pol3d;
     129             :         }
     130             :         else
     131          45 :             hMiraMonLayer->eLT = MM_LayerType_Pol;
     132             : 
     133          47 :         hMiraMonLayer->bIsPolygon = TRUE;
     134             : 
     135          47 :         if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_MULTIPOLYGON)
     136          21 :             hMiraMonLayer->TopHeader.bIsMultipolygon = 1;
     137             :     }
     138             : 
     139             :     //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION;
     140             : 
     141         118 :     if (MMInitLayerByType(hMiraMonLayer))
     142           8 :         return 1;
     143         110 :     hMiraMonLayer->bIsBeenInit = 1;
     144             : 
     145             :     // Get the basic metadata
     146         110 :     pszSRS = MMReturnValueFromSectionINIFile(
     147         110 :         hMiraMonLayer->pszMainREL_LayerName,
     148             :         "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL", "HorizontalSystemIdentifier");
     149         110 :     if (pszSRS)
     150          67 :         hMiraMonLayer->pSRS = pszSRS;
     151             :     else
     152          43 :         hMiraMonLayer->pSRS = nullptr;
     153             : 
     154         110 :     if (!hMiraMonLayer->pSRS && hMiraMonLayer->bIsPolygon)
     155             :     {
     156          43 :         pszSRS = MMReturnValueFromSectionINIFile(
     157          43 :             hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName,
     158             :             "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL",
     159             :             "HorizontalSystemIdentifier");
     160             : 
     161          43 :         hMiraMonLayer->pSRS = pszSRS;
     162             :     }
     163             : 
     164         110 :     if (!ReturnEPSGCodeSRSFromMMIDSRS(hMiraMonLayer->pSRS, szResult))
     165             :     {
     166          59 :         if (MMIsEmptyString(szResult))
     167           0 :             hMiraMonLayer->nSRS_EPSG = 0;
     168             :         else
     169          59 :             hMiraMonLayer->nSRS_EPSG = atoi(szResult);
     170             :     }
     171             :     else
     172          51 :         hMiraMonLayer->nSRS_EPSG = 0;
     173             : 
     174         110 :     if (hMiraMonLayer->nSRS_EPSG == 0)
     175             :     {
     176          51 :         if (hMiraMonLayer->pSRS && strcmp(hMiraMonLayer->pSRS, "plane"))
     177             :         {
     178           0 :             MMCPLWarning(CE_Warning, CPLE_NotSupported,
     179             :                          "The MiraMon layer SRS has no equivalent "
     180             :                          "in EPSG code");
     181             :         }
     182             :     }
     183             : 
     184             :     // If more nNumStringToOperate is needed, it'll be increased.
     185         110 :     hMiraMonLayer->nNumStringToOperate = 0;
     186         110 :     if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 5000))
     187           0 :         return 1;
     188             : 
     189         110 :     return 0;
     190             : }
     191             : 
     192             : // Reads stringline coordinates and puts them in a buffer
     193             : static int
     194        1127 : MMAddStringLineCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
     195             :                            MM_INTERNAL_FID i_elem, uint32_t flag_z,
     196             :                            MM_N_VERTICES_TYPE nStartVertice,
     197             :                            MM_BOOLEAN bAvoidFirst, unsigned char VFG)
     198             : {
     199             :     FILE_TYPE *pF;
     200             :     struct MM_AH *pArcHeader;
     201             :     struct MiraMonArcLayer *pMMArc;
     202        1127 :     struct MM_ZD *pZDescription = nullptr;
     203             : 
     204        1127 :     if (hMiraMonLayer->bIsPolygon)
     205         773 :         pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
     206             :     else
     207         354 :         pMMArc = &hMiraMonLayer->MMArc;
     208             : 
     209        1127 :     pF = pMMArc->pF;
     210        1127 :     pArcHeader = pMMArc->pArcHeader;
     211        1127 :     if (hMiraMonLayer->TopHeader.bIs3d)
     212         671 :         pZDescription = pMMArc->pZSection.pZDescription;
     213             : 
     214        1127 :     fseek_function(pF, pArcHeader[i_elem].nOffset, SEEK_SET);
     215             : 
     216        1127 :     if (hMiraMonLayer->bIsPolygon && (VFG & MM_POL_REVERSE_ARC))  // &&
     217             :         //nStartVertice > 0)
     218         239 :     {
     219             :         MM_N_VERTICES_TYPE nIVertice;
     220             : 
     221             :         // Reading arcs vertices in an inverse order
     222         239 :         if (MMResizeMM_POINT2DPointer(
     223             :                 &hMiraMonLayer->ReadFeature.pCoord,
     224             :                 &hMiraMonLayer->ReadFeature.nMaxpCoord,
     225         239 :                 nStartVertice + pArcHeader[i_elem].nElemCount *
     226             :                                     2,  // ask for twice memory to reverse
     227             :                 0, 0))
     228           0 :             return 1;
     229             : 
     230             :         // Get the vertices far away from their place to be inverted later
     231         239 :         if (pArcHeader[i_elem].nElemCount !=
     232         239 :             fread_function(hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
     233             :                                pArcHeader[i_elem].nElemCount,
     234             :                            sizeof(*hMiraMonLayer->ReadFeature.pCoord),
     235             :                            (size_t)pArcHeader[i_elem].nElemCount, pF))
     236             :         {
     237           0 :             return 1;
     238             :         }
     239             : 
     240         239 :         if (hMiraMonLayer->TopHeader.bIs3d)
     241             :         {
     242         165 :             if (MMResizeDoublePointer(
     243             :                     &hMiraMonLayer->ReadFeature.pZCoord,
     244             :                     &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     245         165 :                     nStartVertice + pArcHeader[i_elem].nElemCount * 2, 0, 0))
     246           0 :                 return 1;
     247             : 
     248             :             // +nStartVertice
     249         165 :             MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
     250         165 :                                  nStartVertice + pArcHeader[i_elem].nElemCount,
     251         165 :                              pF, pArcHeader[i_elem].nElemCount,
     252         165 :                              pZDescription + i_elem, flag_z);
     253             : 
     254             :             // If there is a value for Z-nodata in GDAL this lines can be uncommented
     255             :             // and MM_GDAL_NODATA_COORD_Z can be defined
     256             :             /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
     257             :             {
     258             :                 MM_N_VERTICES_TYPE nIVertice;
     259             :                 for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
     260             :                     hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
     261             :             }
     262             :             */
     263             :         }
     264             : 
     265             :         // Reverse the vertices while putting on their place
     266        1333 :         for (nIVertice = 0; nIVertice < pArcHeader[i_elem].nElemCount;
     267        1094 :              nIVertice++)
     268             :         {
     269        1094 :             memcpy(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
     270         726 :                        ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) + nIVertice,
     271        1094 :                    hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
     272        1094 :                        2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
     273             :                    sizeof(*hMiraMonLayer->ReadFeature.pCoord));
     274             : 
     275        1094 :             if (hMiraMonLayer->TopHeader.bIs3d)
     276             :             {
     277         330 :                 memcpy(hMiraMonLayer->ReadFeature.pZCoord + nStartVertice -
     278         540 :                            ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) +
     279             :                            nIVertice,
     280         330 :                        hMiraMonLayer->ReadFeature.pZCoord + nStartVertice +
     281         330 :                            2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
     282             :                        sizeof(*hMiraMonLayer->ReadFeature.pZCoord));
     283             :             }
     284             :         }
     285             :     }
     286             :     else
     287             :     {
     288             :         // Reading arcs vertices
     289         888 :         if (MMResizeMM_POINT2DPointer(
     290             :                 &hMiraMonLayer->ReadFeature.pCoord,
     291             :                 &hMiraMonLayer->ReadFeature.nMaxpCoord,
     292         888 :                 nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
     293           0 :             return 1;
     294             : 
     295         888 :         if (pArcHeader[i_elem].nElemCount !=
     296         888 :             fread_function(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
     297             :                                (bAvoidFirst ? 1 : 0),
     298             :                            sizeof(*hMiraMonLayer->ReadFeature.pCoord),
     299             :                            (size_t)pArcHeader[i_elem].nElemCount, pF))
     300             :         {
     301           8 :             return 1;
     302             :         }
     303             : 
     304         880 :         if (hMiraMonLayer->TopHeader.bIs3d)
     305             :         {
     306         500 :             if (MMResizeDoublePointer(
     307             :                     &hMiraMonLayer->ReadFeature.pZCoord,
     308             :                     &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     309         500 :                     nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
     310           0 :                 return 1;
     311             : 
     312             :             // +nStartVertice
     313        1000 :             MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
     314         500 :                                  nStartVertice - (bAvoidFirst ? 1 : 0),
     315         500 :                              pF, pArcHeader[i_elem].nElemCount,
     316         500 :                              pZDescription + i_elem, flag_z);
     317             : 
     318             :             // If there is a value for Z-nodata in GDAL this lines can be uncommented
     319             :             // and MM_GDAL_NODATA_COORD_Z can be defined
     320             :             /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
     321             :             {
     322             :                 MM_N_VERTICES_TYPE nIVertice;
     323             :                 for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
     324             :                     hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
     325             :             }
     326             :             */
     327             :         }
     328             :     }
     329        1119 :     hMiraMonLayer->ReadFeature.nNumpCoord =
     330        1119 :         pArcHeader[i_elem].nElemCount == 0
     331             :             ? 0
     332        1119 :             : pArcHeader[i_elem].nElemCount - (bAvoidFirst ? 1 : 0);
     333             : 
     334        1119 :     return 0;
     335             : }
     336             : 
     337             : // Reads Polygon coordinates and puts them in a buffer
     338             : static int
     339         339 : MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
     340             :                              MM_INTERNAL_FID i_pol, uint32_t flag_z)
     341             : {
     342             :     struct MM_PH *pPolHeader;
     343             :     struct MM_AH *pArcHeader;
     344             :     char *pBuffer;
     345             :     MM_POLYGON_ARCS_COUNT nIndex;
     346             :     MM_BOOLEAN bAvoidFirst;
     347         339 :     MM_N_VERTICES_TYPE nNAcumulVertices = 0;
     348             : 
     349             :     // Checking if the index of the polygon is in the correct range.
     350         339 :     if (i_pol >= hMiraMonLayer->TopHeader.nElemCount)
     351           0 :         return 1;
     352             : 
     353         339 :     MMResetFeatureGeometry(&hMiraMonLayer->ReadFeature);
     354         339 :     MMResetFeatureRecord(&hMiraMonLayer->ReadFeature);
     355         339 :     pPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + i_pol;
     356             : 
     357             :     // It's accepted not having arcs in the universal polygon
     358         339 :     if (!pPolHeader->nArcsCount)
     359             :     {
     360           0 :         if (i_pol == 0)
     361           0 :             return 0;
     362             :         else
     363           0 :             return 1;
     364             :     }
     365             : 
     366         339 :     if (MMResizeMiraMonPolygonArcs(&hMiraMonLayer->pArcs,
     367             :                                    &hMiraMonLayer->nMaxArcs,
     368             :                                    pPolHeader->nArcsCount, 0, 0))
     369           0 :         return 1;
     370             : 
     371         339 :     if (MMInitFlush(&hMiraMonLayer->FlushPAL, hMiraMonLayer->MMPolygon.pF,
     372         339 :                     hMiraMonLayer->MMPolygon.nPALElementSize *
     373         339 :                         pPolHeader->nArcsCount,
     374             :                     &pBuffer, pPolHeader->nOffset, 0))
     375             :     {
     376           0 :         if (pBuffer)
     377           0 :             free_function(pBuffer);
     378           0 :         return 1;
     379             :     }
     380             : 
     381         339 :     hMiraMonLayer->FlushPAL.pBlockWhereToSaveOrRead = (void *)pBuffer;
     382         339 :     if (MMReadFlush(&hMiraMonLayer->FlushPAL))
     383             :     {
     384           6 :         if (pBuffer)
     385           6 :             free_function(pBuffer);
     386           6 :         return 1;
     387             :     }
     388             : 
     389         333 :     hMiraMonLayer->ReadFeature.nNRings = 0;
     390         333 :     hMiraMonLayer->ReadFeature.nNumpCoord = 0;
     391         333 :     if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     392             :             &hMiraMonLayer->ReadFeature.pNCoordRing,
     393             :             &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
     394         333 :             (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10))
     395             :     {
     396           0 :         free_function(pBuffer);
     397           0 :         return 1;
     398             :     }
     399             : 
     400         333 :     if (MMResizeVFGPointer(&hMiraMonLayer->ReadFeature.flag_VFG,
     401             :                            &hMiraMonLayer->ReadFeature.nMaxVFG,
     402         333 :                            (MM_INTERNAL_FID)pPolHeader->nArcsCount, 0,
     403             :                            0))  // Perhaps more memory than needed
     404             :     {
     405           0 :         free_function(pBuffer);
     406           0 :         return 1;
     407             :     }
     408             : 
     409             :     // Preparing memory for all coordinates
     410         333 :     hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
     411             :         0;
     412        1106 :     for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
     413             :     {
     414         773 :         hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
     415             :             sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
     416         773 :         hMiraMonLayer->FlushPAL.pBlockToBeSaved =
     417         773 :             (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
     418         773 :         if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
     419             :         {
     420           0 :             if (pBuffer)
     421           0 :                 free_function(pBuffer);
     422           0 :             return 1;
     423             :         }
     424             : 
     425             :         // Arc index
     426         773 :         if (MMReadGUInt64DependingOnVersion(
     427             :                 hMiraMonLayer, &hMiraMonLayer->FlushPAL,
     428         773 :                 &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
     429             :         {
     430           0 :             if (pBuffer)
     431           0 :                 free_function(pBuffer);
     432           0 :             return 1;
     433             :         }
     434             : 
     435         773 :         if (hMiraMonLayer->MMPolygon.MMArc.pArcHeader == nullptr)
     436             :         {
     437           0 :             if (pBuffer)
     438           0 :                 free_function(pBuffer);
     439           0 :             return 1;
     440             :         }
     441             : 
     442             :         // Checking if the index of the arc is in the correct range.
     443         773 :         if ((hMiraMonLayer->pArcs + nIndex)->nIArc >=
     444         773 :             hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount)
     445             :         {
     446           0 :             free_function(pBuffer);
     447           0 :             return 1;
     448             :         }
     449             : 
     450         773 :         pArcHeader = hMiraMonLayer->MMPolygon.MMArc.pArcHeader +
     451         773 :                      (hMiraMonLayer->pArcs + nIndex)->nIArc;
     452             : 
     453         773 :         if (hMiraMonLayer->ReadFeature
     454         773 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     455         773 :             UINT64_MAX - pArcHeader->nElemCount)
     456             :         {
     457           0 :             free_function(pBuffer);
     458           0 :             return 1;
     459             :         }
     460             : 
     461         773 :         if (hMiraMonLayer->ReadFeature
     462         773 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     463         773 :             UINT64_MAX - pArcHeader->nElemCount)
     464             :         {
     465           0 :             free_function(pBuffer);
     466           0 :             return 1;
     467             :         }
     468             : 
     469             :         hMiraMonLayer->ReadFeature
     470         773 :             .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
     471         773 :             pArcHeader->nElemCount;
     472             :     }
     473         333 :     if (MMResizeMM_POINT2DPointer(
     474             :             &hMiraMonLayer->ReadFeature.pCoord,
     475             :             &hMiraMonLayer->ReadFeature.nMaxpCoord,
     476             :             hMiraMonLayer->ReadFeature
     477         333 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings],
     478             :             0, 0))
     479             :     {
     480           0 :         free_function(pBuffer);
     481           0 :         return 1;
     482             :     }
     483             : 
     484         333 :     hMiraMonLayer->FlushPAL.CurrentOffset = 0;
     485             : 
     486             :     // Real work
     487         333 :     hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
     488             :         0;
     489        1105 :     for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
     490             :     {
     491         773 :         hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
     492             :             sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
     493         773 :         hMiraMonLayer->FlushPAL.pBlockToBeSaved =
     494         773 :             (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
     495         773 :         if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
     496             :         {
     497           0 :             if (pBuffer)
     498           0 :                 free_function(pBuffer);
     499           0 :             return 1;
     500             :         }
     501             : 
     502             :         // Arc index
     503         773 :         if (MMReadGUInt64DependingOnVersion(
     504             :                 hMiraMonLayer, &hMiraMonLayer->FlushPAL,
     505         773 :                 &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
     506             :         {
     507           0 :             if (pBuffer)
     508           0 :                 free_function(pBuffer);
     509           0 :             return 1;
     510             :         }
     511             : 
     512         773 :         bAvoidFirst = FALSE;
     513         773 :         if (hMiraMonLayer->ReadFeature
     514         773 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] != 0)
     515         299 :             bAvoidFirst = TRUE;
     516             : 
     517             :         // Add coordinates to hMiraMonLayer->ReadFeature.pCoord
     518         773 :         if (MMAddStringLineCoordinates(hMiraMonLayer,
     519         773 :                                        (hMiraMonLayer->pArcs + nIndex)->nIArc,
     520             :                                        flag_z, nNAcumulVertices, bAvoidFirst,
     521         773 :                                        (hMiraMonLayer->pArcs + nIndex)->VFG))
     522             :         {
     523           1 :             free_function(pBuffer);
     524           1 :             return 1;
     525             :         }
     526             : 
     527         772 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     528             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     529             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
     530         772 :                 (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10,
     531             :                 10))
     532             :         {
     533           0 :             free_function(pBuffer);
     534           0 :             return 1;
     535             :         }
     536             : 
     537         772 :         if (hMiraMonLayer->ReadFeature
     538         772 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     539         772 :             UINT64_MAX - hMiraMonLayer->ReadFeature.nNumpCoord)
     540             :         {
     541           0 :             free_function(pBuffer);
     542           0 :             return 1;
     543             :         }
     544             : 
     545             :         hMiraMonLayer->ReadFeature
     546         772 :             .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
     547         772 :             hMiraMonLayer->ReadFeature.nNumpCoord;
     548         772 :         nNAcumulVertices += hMiraMonLayer->ReadFeature.nNumpCoord;
     549             : 
     550         772 :         if ((hMiraMonLayer->pArcs + nIndex)->VFG & MM_POL_END_RING)
     551             :         {
     552             :             hMiraMonLayer->ReadFeature
     553         473 :                 .flag_VFG[hMiraMonLayer->ReadFeature.nNRings] =
     554         473 :                 (hMiraMonLayer->pArcs + nIndex)->VFG;
     555         473 :             hMiraMonLayer->ReadFeature.nNRings++;
     556             :             hMiraMonLayer->ReadFeature
     557         473 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] = 0;
     558             :         }
     559             :     }
     560         332 :     hMiraMonLayer->nNumArcs = pPolHeader->nArcsCount;
     561         332 :     if (pBuffer)
     562         332 :         free_function(pBuffer);
     563             : 
     564         332 :     return 0;
     565             : }
     566             : 
     567             : // Reads the geographical part of a MiraMon layer feature
     568        1708 : int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer,
     569             :                               MM_INTERNAL_FID i_elem)
     570             : {
     571             :     FILE_TYPE *pF;
     572             :     struct MM_ZD *pZDescription;
     573             :     uint32_t flag_z;
     574             :     int num;
     575             :     double cz;
     576             : 
     577        1708 :     if (hMiraMonLayer->nSelectCoordz == MM_SELECT_HIGHEST_COORDZ)
     578           1 :         flag_z = MM_STRING_HIGHEST_ALTITUDE;
     579        1707 :     else if (hMiraMonLayer->nSelectCoordz == MM_SELECT_LOWEST_COORDZ)
     580           1 :         flag_z = MM_STRING_LOWEST_ALTITUDE;
     581             :     else
     582        1706 :         flag_z = 0L;
     583             : 
     584        1708 :     if (hMiraMonLayer->bIsPoint)
     585             :     {
     586        1015 :         pF = hMiraMonLayer->MMPoint.pF;
     587             : 
     588             :         // Getting to the i-th element offset
     589        1015 :         fseek_function(pF,
     590             :                        hMiraMonLayer->nHeaderDiskSize +
     591             :                            sizeof(MM_COORD_TYPE) * 2 * i_elem,
     592             :                        SEEK_SET);
     593             : 
     594             :         // Reading the point
     595        1015 :         if (MMResizeMM_POINT2DPointer(&hMiraMonLayer->ReadFeature.pCoord,
     596             :                                       &hMiraMonLayer->ReadFeature.nMaxpCoord,
     597             :                                       hMiraMonLayer->ReadFeature.nNumpCoord, 1,
     598             :                                       1))
     599           0 :             return 1;
     600             : 
     601        1015 :         if (1 != fread_function(hMiraMonLayer->ReadFeature.pCoord,
     602             :                                 sizeof(MM_COORD_TYPE) * 2, 1, pF))
     603             :         {
     604           5 :             return 1;
     605             :         }
     606             : 
     607        1010 :         hMiraMonLayer->ReadFeature.nNRings = 1;
     608             : 
     609        1010 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     610             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     611             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
     612           0 :             return 1;
     613             : 
     614        1010 :         hMiraMonLayer->ReadFeature.pNCoordRing[0] = 1;
     615             : 
     616        1010 :         if (hMiraMonLayer->TopHeader.bIs3d)
     617             :         {
     618         874 :             pZDescription =
     619         874 :                 hMiraMonLayer->MMPoint.pZSection.pZDescription + i_elem;
     620         874 :             if (pZDescription->nZCount == INT_MIN)
     621           0 :                 return 1;
     622         874 :             num = MM_ARC_TOTAL_N_HEIGHTS_DISK(pZDescription->nZCount, 1);
     623             : 
     624         874 :             if (MMResizeDoublePointer(&hMiraMonLayer->ReadFeature.pZCoord,
     625             :                                       &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     626             :                                       1, 1, 1))
     627           0 :                 return 1;
     628             : 
     629         874 :             if (num == 0)
     630           0 :                 hMiraMonLayer->ReadFeature.pZCoord[0] = MM_NODATA_COORD_Z;
     631             :             else
     632             :             {
     633         874 :                 if (flag_z == MM_STRING_HIGHEST_ALTITUDE)  // Max z
     634           1 :                     cz = pZDescription->dfBBmaxz;
     635         873 :                 else if (flag_z == MM_STRING_LOWEST_ALTITUDE)  // Min z
     636           1 :                     cz = pZDescription->dfBBminz;
     637             :                 else
     638             :                 {
     639             :                     // Reading the first z coordinate
     640         872 :                     fseek_function(pF, pZDescription->nOffsetZ, SEEK_SET);
     641         872 :                     if ((size_t)1 !=
     642         872 :                         fread_function(
     643             :                             &cz, sizeof(*hMiraMonLayer->ReadFeature.pZCoord), 1,
     644             :                             pF))
     645             :                     {
     646           0 :                         return 1;
     647             :                     }
     648             :                 }
     649             :                 // If there is a value for Z-nodata in GDAL this lines can be uncommented
     650             :                 // and MM_GDAL_NODATA_COORD_Z can be defined
     651             :                 /*if(!DOUBLES_DIFERENTS_DJ(cz, MM_NODATA_COORD_Z))
     652             :                     hMiraMonLayer->ReadFeature.pZCoord[0]=MM_GDAL_NODATA_COORD_Z;
     653             :                 else */
     654         874 :                 hMiraMonLayer->ReadFeature.pZCoord[0] = cz;
     655             :             }
     656             :         }
     657             : 
     658        1010 :         return 0;
     659             :     }
     660             : 
     661             :     // Stringlines
     662         693 :     if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
     663             :     {
     664         354 :         if (MMAddStringLineCoordinates(hMiraMonLayer, i_elem, flag_z, 0, FALSE,
     665             :                                        0))
     666           7 :             return 1;
     667             : 
     668         347 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     669             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     670             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
     671           0 :             return 1;
     672             : 
     673         347 :         hMiraMonLayer->ReadFeature.pNCoordRing[0] =
     674         347 :             hMiraMonLayer->ReadFeature.nNumpCoord;
     675             : 
     676         347 :         return 0;
     677             :     }
     678             : 
     679             :     // Polygons or multipolygons
     680         339 :     if (MMGetMultiPolygonCoordinates(hMiraMonLayer, i_elem, flag_z))
     681           7 :         return 1;
     682             : 
     683         332 :     return 0;
     684             : }
     685             : 
     686             : // Reads the header of a MiraMon DBF
     687             : // Please read the format at this link:
     688             : // https://www.miramon.cat/new_note/usa/notes/DBF_estesa.pdf
     689         158 : int MM_ReadExtendedDBFHeader(struct MiraMonVectLayerInfo *hMiraMonLayer)
     690             : {
     691         158 :     const char *pszRelFile = nullptr;
     692             :     struct MM_DATA_BASE_XP *pMMBDXP;
     693         158 :     const char *szDBFFileName = nullptr;
     694             : 
     695             :     // If read don't read again. It happens when Polygon reads
     696             :     // the database and then in initArc() it's read again.
     697         158 :     if (hMiraMonLayer->pMMBDXP)
     698          43 :         return 0;
     699             : 
     700         115 :     pMMBDXP = hMiraMonLayer->pMMBDXP = calloc_function(sizeof(*pMMBDXP));
     701         115 :     if (!pMMBDXP)
     702           0 :         return 1;
     703             : 
     704         115 :     if (hMiraMonLayer->bIsPoint)
     705             :     {
     706          40 :         hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP = pMMBDXP;
     707          40 :         szDBFFileName = hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName;
     708          40 :         pszRelFile = hMiraMonLayer->MMPoint.pszREL_LayerName;
     709             :     }
     710          75 :     else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
     711             :     {
     712          29 :         hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP = pMMBDXP;
     713          29 :         szDBFFileName = hMiraMonLayer->MMArc.MMAdmDB.pszExtDBFLayerName;
     714          29 :         pszRelFile = hMiraMonLayer->MMArc.pszREL_LayerName;
     715             :     }
     716          46 :     else if (hMiraMonLayer->bIsPolygon)
     717             :     {
     718          46 :         hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP = pMMBDXP;
     719          46 :         szDBFFileName = hMiraMonLayer->MMPolygon.MMAdmDB.pszExtDBFLayerName;
     720          46 :         pszRelFile = hMiraMonLayer->MMPolygon.pszREL_LayerName;
     721             :     }
     722             : 
     723         115 :     if (MM_ReadExtendedDBFHeaderFromFile(szDBFFileName, pMMBDXP, pszRelFile))
     724             :     {
     725           1 :         MMCPLError(CE_Failure, CPLE_NotSupported,
     726             :                    "Error reading the format in the DBF file %s.",
     727             :                    szDBFFileName);
     728           1 :         return 1;
     729             :     }
     730             : 
     731         114 :     fclose_and_nullify(&pMMBDXP->pfDataBase);
     732         114 :     return 0;
     733             : }
     734             : 
     735             : #ifdef GDAL_COMPILATION
     736             : CPL_C_END  // Necessary for compiling in GDAL project
     737             : #endif

Generated by: LCOV version 1.14