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

Generated by: LCOV version 1.14