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: 300 382 78.5 %
Date: 2025-09-10 17:48:50 Functions: 7 7 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 "../../../frmts/miramon_common/mm_gdal_functions.h"
      22             : #include "../../../frmts/miramon_common/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         121 :     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         121 :     memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer));
      40         121 :     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         121 :     hMiraMonLayer->ReadOrWrite = MM_READING_MODE;
      47         121 :     strcpy(hMiraMonLayer->pszFlags, "rb");
      48             : 
      49         121 :     hMiraMonLayer->pszSrcLayerName = CPLStrdup(pszFilename);
      50             : 
      51         121 :     hMiraMonLayer->LayerVersion =
      52         121 :         (char)MMGetVectorVersion(&hMiraMonLayer->TopHeader);
      53         121 :     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         121 :     if (hMiraMonLayer->LayerVersion == MM_LAST_VERSION)
      60           0 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
      61         121 :     else if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
      62         115 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS;
      63             :     else
      64           6 :         hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
      65             : 
      66         121 :     if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
      67          90 :         hMiraMonLayer->TopHeader.aFileType[1] == 'N' &&
      68          42 :         hMiraMonLayer->TopHeader.aFileType[2] == 'T')
      69             :     {
      70          42 :         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          30 :             hMiraMonLayer->eLT = MM_LayerType_Point;
      77             : 
      78          42 :         hMiraMonLayer->bIsPoint = TRUE;
      79             :     }
      80          79 :     else if (hMiraMonLayer->TopHeader.aFileType[0] == 'A' &&
      81          31 :              hMiraMonLayer->TopHeader.aFileType[1] == 'R' &&
      82          31 :              hMiraMonLayer->TopHeader.aFileType[2] == 'C')
      83             :     {
      84          31 :         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          24 :             hMiraMonLayer->eLT = MM_LayerType_Arc;
      91             : 
      92          31 :         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         121 :     if (MMInitLayerByType(hMiraMonLayer))
     116           8 :         return 1;
     117         113 :     hMiraMonLayer->bIsBeenInit = 1;
     118             : 
     119             :     // Get the basic metadata
     120         113 :     pszSRS = MMReturnValueFromSectionINIFile(
     121         113 :         hMiraMonLayer->pszMainREL_LayerName,
     122             :         "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL", "HorizontalSystemIdentifier");
     123         113 :     if (pszSRS)
     124          69 :         hMiraMonLayer->pSRS = pszSRS;
     125             :     else
     126          44 :         hMiraMonLayer->pSRS = nullptr;
     127             : 
     128         113 :     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         113 :     if (!ReturnEPSGCodeSRSFromMMIDSRS(hMiraMonLayer->pSRS, szResult))
     139             :     {
     140          61 :         if (MMIsEmptyString(szResult))
     141           0 :             hMiraMonLayer->nSRS_EPSG = 0;
     142             :         else
     143          61 :             hMiraMonLayer->nSRS_EPSG = atoi(szResult);
     144             :     }
     145             :     else
     146          52 :         hMiraMonLayer->nSRS_EPSG = 0;
     147             : 
     148         113 :     if (hMiraMonLayer->nSRS_EPSG == 0)
     149             :     {
     150          52 :         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         113 :     hMiraMonLayer->nNumStringToOperate = 0;
     160         113 :     if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 5000))
     161           0 :         return 1;
     162             : 
     163         113 :     return 0;
     164             : }
     165             : 
     166        1580 : static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag)
     167             : {
     168        1580 :     if (*proposta == MM_NODATA_COORD_Z)
     169           0 :         return;
     170             : 
     171        1580 :     if (flag & MM_STRING_HIGHEST_ALTITUDE)
     172             :     {
     173           0 :         if (*desti == MM_NODATA_COORD_Z || *desti < *proposta)
     174           0 :             *desti = *proposta;
     175             :     }
     176        1580 :     else if (flag & MM_STRING_LOWEST_ALTITUDE)
     177             :     {
     178           0 :         if (*desti == MM_NODATA_COORD_Z || *desti > *proposta)
     179           0 :             *desti = *proposta;
     180             :     }
     181             :     else
     182             :     {
     183             :         // First coordinate of this vertice
     184        1580 :         if (*desti == MM_NODATA_COORD_Z)
     185        1580 :             *desti = *proposta;
     186             :     }
     187             : }
     188             : 
     189         689 : static int MM_GetArcHeights(double *coord_z, VSILFILE *pF,
     190             :                             MM_N_VERTICES_TYPE n_vrt,
     191             :                             struct MM_ZD *pZDescription, uint32_t flag)
     192             : {
     193             :     MM_N_HEIGHT_TYPE i;
     194             :     MM_N_VERTICES_TYPE i_vrt;
     195             :     double *pcoord_z;
     196             :     MM_N_HEIGHT_TYPE n_alcada, n_h_total;
     197             :     int tipus;
     198         689 :     double *alcada = nullptr, *palcada, *palcada_i;
     199             : #define MM_N_ALCADA_LOCAL 50  // Nr of local heights
     200             :     double local_CinquantaAlcades[MM_N_ALCADA_LOCAL];
     201             : 
     202         689 :     if (!pZDescription)
     203           0 :         return 0;
     204             : 
     205        2271 :     for (i_vrt = 0; i_vrt < n_vrt; i_vrt++)
     206        1582 :         coord_z[i_vrt] = MM_NODATA_COORD_Z;
     207             : 
     208         689 :     if (pZDescription->nZCount == INT_MIN)
     209           0 :         return 0;
     210         689 :     tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount);
     211         689 :     n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount);
     212         689 :     if (n_vrt == 0 || n_alcada == 0)
     213           0 :         return 0;
     214             : 
     215         689 :     if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
     216             :     {
     217         688 :         if (n_vrt > (unsigned)(INT_MAX / n_alcada))
     218             :         {
     219           0 :             CPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow");
     220           0 :             return 1;
     221             :         }
     222         688 :         n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada;
     223             :     }
     224             :     else
     225           1 :         n_h_total = n_alcada;
     226             : 
     227         689 :     if (n_h_total <= MM_N_ALCADA_LOCAL)
     228         689 :         palcada = local_CinquantaAlcades;
     229             :     else
     230             :     {
     231           0 :         if (MMCheckSize_t(n_h_total, sizeof(double)))
     232           0 :             return 1;
     233           0 :         if (nullptr ==
     234           0 :             (palcada = alcada = VSICalloc((size_t)n_h_total, sizeof(double))))
     235           0 :             return 1;
     236             :     }
     237             : 
     238         689 :     if (VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET))
     239             :     {
     240           0 :         if (alcada)
     241           0 :             VSIFree(alcada);
     242           0 :         return 1;
     243             :     }
     244         689 :     if (n_h_total !=
     245         689 :         (MM_N_HEIGHT_TYPE)VSIFReadL(palcada, sizeof(double), n_h_total, pF))
     246             :     {
     247           0 :         if (alcada)
     248           0 :             VSIFree(alcada);
     249           0 :         return 1;
     250             :     }
     251             : 
     252         689 :     if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
     253             :     {
     254         688 :         palcada_i = palcada;
     255        1376 :         for (i = 0; i < n_alcada; i++)
     256             :         {
     257        2267 :             for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt;
     258        1579 :                  i_vrt++, pcoord_z++, palcada_i++)
     259        1579 :                 MM_AdoptHeight(pcoord_z, palcada_i, flag);
     260             :         }
     261             :     }
     262             :     else
     263             :     {
     264           1 :         palcada_i = palcada;
     265           1 :         pcoord_z = coord_z;
     266           2 :         for (i = 0; i < n_alcada; i++, palcada_i++)
     267           1 :             MM_AdoptHeight(pcoord_z, palcada_i, flag);
     268             : 
     269           1 :         if (*pcoord_z != MM_NODATA_COORD_Z)
     270             :         {
     271             :             /*Copio el mateix valor a totes les alcades.*/
     272           3 :             for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt;
     273           2 :                  i_vrt++, pcoord_z++)
     274           2 :                 *pcoord_z = *coord_z;
     275             :         }
     276             :     }
     277         689 :     if (alcada)
     278           0 :         VSIFree(alcada);
     279         689 :     return 0;
     280             : }  // End of MM_GetArcHeights()
     281             : 
     282             : // Reads stringline coordinates and puts them in a buffer
     283             : static int
     284        1169 : MMAddStringLineCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
     285             :                            MM_INTERNAL_FID i_elem, uint32_t flag_z,
     286             :                            MM_N_VERTICES_TYPE nStartVertice,
     287             :                            MM_BOOLEAN bAvoidFirst, unsigned char VFG)
     288             : {
     289             :     VSILFILE *pF;
     290             :     struct MM_AH *pArcHeader;
     291             :     struct MiraMonArcLayer *pMMArc;
     292        1169 :     struct MM_ZD *pZDescription = nullptr;
     293             : 
     294        1169 :     if (hMiraMonLayer->bIsPolygon)
     295         803 :         pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
     296             :     else
     297         366 :         pMMArc = &hMiraMonLayer->MMArc;
     298             : 
     299        1169 :     pF = pMMArc->pF;
     300        1169 :     pArcHeader = pMMArc->pArcHeader;
     301        1169 :     if (hMiraMonLayer->TopHeader.bIs3d)
     302         695 :         pZDescription = pMMArc->pZSection.pZDescription;
     303             : 
     304        1169 :     VSIFSeekL(pF, pArcHeader[i_elem].nOffset, SEEK_SET);
     305             : 
     306        1169 :     if (hMiraMonLayer->bIsPolygon && (VFG & MM_POL_REVERSE_ARC))  // &&
     307             :         //nStartVertice > 0)
     308         249 :     {
     309             :         MM_N_VERTICES_TYPE nIVertice;
     310             : 
     311             :         // Reading arcs vertices in an inverse order
     312         249 :         if (MMResizeMM_POINT2DPointer(
     313             :                 &hMiraMonLayer->ReadFeature.pCoord,
     314             :                 &hMiraMonLayer->ReadFeature.nMaxpCoord,
     315         249 :                 nStartVertice + pArcHeader[i_elem].nElemCount *
     316             :                                     2,  // ask for twice memory to reverse
     317             :                 0, 0))
     318           0 :             return 1;
     319             : 
     320             :         // Get the vertices far away from their place to be inverted later
     321         249 :         if (pArcHeader[i_elem].nElemCount !=
     322         249 :             VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
     323         249 :                           pArcHeader[i_elem].nElemCount,
     324             :                       sizeof(*hMiraMonLayer->ReadFeature.pCoord),
     325         249 :                       (size_t)pArcHeader[i_elem].nElemCount, pF))
     326             :         {
     327           0 :             return 1;
     328             :         }
     329             : 
     330         249 :         if (hMiraMonLayer->TopHeader.bIs3d)
     331             :         {
     332         171 :             if (MMResizeDoublePointer(
     333             :                     &hMiraMonLayer->ReadFeature.pZCoord,
     334             :                     &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     335         171 :                     nStartVertice + pArcHeader[i_elem].nElemCount * 2, 0, 0))
     336           0 :                 return 1;
     337             : 
     338             :             // +nStartVertice
     339         171 :             MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
     340         171 :                                  nStartVertice + pArcHeader[i_elem].nElemCount,
     341         171 :                              pF, pArcHeader[i_elem].nElemCount,
     342         171 :                              pZDescription + i_elem, flag_z);
     343             : 
     344             :             // If there is a value for Z-nodata in GDAL this lines can be uncommented
     345             :             // and MM_GDAL_NODATA_COORD_Z can be defined
     346             :             /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
     347             :             {
     348             :                 MM_N_VERTICES_TYPE nIVertice;
     349             :                 for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
     350             :                     hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
     351             :             }
     352             :             */
     353             :         }
     354             : 
     355             :         // Reverse the vertices while putting on their place
     356        1392 :         for (nIVertice = 0; nIVertice < pArcHeader[i_elem].nElemCount;
     357        1143 :              nIVertice++)
     358             :         {
     359        1143 :             memcpy(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
     360         758 :                        ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) + nIVertice,
     361        1143 :                    hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
     362        1143 :                        2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
     363             :                    sizeof(*hMiraMonLayer->ReadFeature.pCoord));
     364             : 
     365        1143 :             if (hMiraMonLayer->TopHeader.bIs3d)
     366             :             {
     367         342 :                 memcpy(hMiraMonLayer->ReadFeature.pZCoord + nStartVertice -
     368         560 :                            ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) +
     369             :                            nIVertice,
     370         342 :                        hMiraMonLayer->ReadFeature.pZCoord + nStartVertice +
     371         342 :                            2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
     372             :                        sizeof(*hMiraMonLayer->ReadFeature.pZCoord));
     373             :             }
     374             :         }
     375             :     }
     376             :     else
     377             :     {
     378             :         // Reading arcs vertices
     379         920 :         if (MMResizeMM_POINT2DPointer(
     380             :                 &hMiraMonLayer->ReadFeature.pCoord,
     381             :                 &hMiraMonLayer->ReadFeature.nMaxpCoord,
     382         920 :                 nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
     383           0 :             return 1;
     384             : 
     385         920 :         if (pArcHeader[i_elem].nElemCount !=
     386         920 :             VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
     387             :                           (bAvoidFirst ? 1 : 0),
     388             :                       sizeof(*hMiraMonLayer->ReadFeature.pCoord),
     389         920 :                       (size_t)pArcHeader[i_elem].nElemCount, pF))
     390             :         {
     391           8 :             return 1;
     392             :         }
     393             : 
     394         912 :         if (hMiraMonLayer->TopHeader.bIs3d)
     395             :         {
     396         518 :             if (MMResizeDoublePointer(
     397             :                     &hMiraMonLayer->ReadFeature.pZCoord,
     398             :                     &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     399         518 :                     nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
     400           0 :                 return 1;
     401             : 
     402             :             // +nStartVertice
     403        1036 :             MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
     404         518 :                                  nStartVertice - (bAvoidFirst ? 1 : 0),
     405         518 :                              pF, pArcHeader[i_elem].nElemCount,
     406         518 :                              pZDescription + i_elem, flag_z);
     407             : 
     408             :             // If there is a value for Z-nodata in GDAL this lines can be uncommented
     409             :             // and MM_GDAL_NODATA_COORD_Z can be defined
     410             :             /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
     411             :             {
     412             :                 MM_N_VERTICES_TYPE nIVertice;
     413             :                 for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
     414             :                     hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
     415             :             }
     416             :             */
     417             :         }
     418             :     }
     419        1161 :     hMiraMonLayer->ReadFeature.nNumpCoord =
     420        1161 :         pArcHeader[i_elem].nElemCount == 0
     421             :             ? 0
     422        1161 :             : pArcHeader[i_elem].nElemCount - (bAvoidFirst ? 1 : 0);
     423             : 
     424        1161 :     return 0;
     425             : }
     426             : 
     427             : // Reads Polygon coordinates and puts them in a buffer
     428             : static int
     429         352 : MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
     430             :                              MM_INTERNAL_FID i_pol, uint32_t flag_z)
     431             : {
     432             :     struct MM_PH *pPolHeader;
     433             :     struct MM_AH *pArcHeader;
     434             :     char *pBuffer;
     435             :     MM_POLYGON_ARCS_COUNT nIndex;
     436             :     MM_BOOLEAN bAvoidFirst;
     437         352 :     MM_N_VERTICES_TYPE nNAcumulVertices = 0;
     438             : 
     439             :     // Checking if the index of the polygon is in the correct range.
     440         352 :     if (i_pol >= hMiraMonLayer->TopHeader.nElemCount)
     441           0 :         return 1;
     442             : 
     443         352 :     MMResetFeatureGeometry(&hMiraMonLayer->ReadFeature);
     444         352 :     MMResetFeatureRecord(&hMiraMonLayer->ReadFeature);
     445         352 :     pPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + i_pol;
     446             : 
     447             :     // It's accepted not having arcs in the universal polygon
     448         352 :     if (!pPolHeader->nArcsCount)
     449             :     {
     450           0 :         if (i_pol == 0)
     451           0 :             return 0;
     452             :         else
     453           0 :             return 1;
     454             :     }
     455             : 
     456         352 :     if (MMResizeMiraMonPolygonArcs(&hMiraMonLayer->pArcs,
     457             :                                    &hMiraMonLayer->nMaxArcs,
     458             :                                    pPolHeader->nArcsCount, 0, 0))
     459           0 :         return 1;
     460             : 
     461         352 :     if (MMInitFlush(&hMiraMonLayer->FlushPAL, hMiraMonLayer->MMPolygon.pF,
     462         352 :                     hMiraMonLayer->MMPolygon.nPALElementSize *
     463         352 :                         pPolHeader->nArcsCount,
     464             :                     &pBuffer, pPolHeader->nOffset, 0))
     465             :     {
     466           0 :         if (pBuffer)
     467           0 :             VSIFree(pBuffer);
     468           0 :         return 1;
     469             :     }
     470             : 
     471         352 :     hMiraMonLayer->FlushPAL.pBlockWhereToSaveOrRead = (void *)pBuffer;
     472         352 :     if (MMReadFlush(&hMiraMonLayer->FlushPAL))
     473             :     {
     474           6 :         if (pBuffer)
     475           6 :             VSIFree(pBuffer);
     476           6 :         return 1;
     477             :     }
     478             : 
     479         346 :     hMiraMonLayer->ReadFeature.nNRings = 0;
     480         346 :     hMiraMonLayer->ReadFeature.nNumpCoord = 0;
     481         346 :     if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     482             :             &hMiraMonLayer->ReadFeature.pNCoordRing,
     483             :             &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
     484         346 :             (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10))
     485             :     {
     486           0 :         VSIFree(pBuffer);
     487           0 :         return 1;
     488             :     }
     489             : 
     490         346 :     if (MMResizeVFGPointer(&hMiraMonLayer->ReadFeature.flag_VFG,
     491             :                            &hMiraMonLayer->ReadFeature.nMaxVFG,
     492         346 :                            (MM_INTERNAL_FID)pPolHeader->nArcsCount, 0,
     493             :                            0))  // Perhaps more memory than needed
     494             :     {
     495           0 :         VSIFree(pBuffer);
     496           0 :         return 1;
     497             :     }
     498             : 
     499             :     // Preparing memory for all coordinates
     500         346 :     hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
     501             :         0;
     502        1149 :     for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
     503             :     {
     504         803 :         hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
     505             :             sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
     506         803 :         hMiraMonLayer->FlushPAL.pBlockToBeSaved =
     507         803 :             (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
     508         803 :         if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
     509             :         {
     510           0 :             if (pBuffer)
     511           0 :                 VSIFree(pBuffer);
     512           0 :             return 1;
     513             :         }
     514             : 
     515             :         // Arc index
     516         803 :         if (MMReadGUInt64DependingOnVersion(
     517             :                 hMiraMonLayer, &hMiraMonLayer->FlushPAL,
     518         803 :                 &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
     519             :         {
     520           0 :             if (pBuffer)
     521           0 :                 VSIFree(pBuffer);
     522           0 :             return 1;
     523             :         }
     524             : 
     525         803 :         if (hMiraMonLayer->MMPolygon.MMArc.pArcHeader == nullptr)
     526             :         {
     527           0 :             if (pBuffer)
     528           0 :                 VSIFree(pBuffer);
     529           0 :             return 1;
     530             :         }
     531             : 
     532             :         // Checking if the index of the arc is in the correct range.
     533         803 :         if ((hMiraMonLayer->pArcs + nIndex)->nIArc >=
     534         803 :             hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount)
     535             :         {
     536           0 :             VSIFree(pBuffer);
     537           0 :             return 1;
     538             :         }
     539             : 
     540         803 :         pArcHeader = hMiraMonLayer->MMPolygon.MMArc.pArcHeader +
     541         803 :                      (hMiraMonLayer->pArcs + nIndex)->nIArc;
     542             : 
     543         803 :         if (hMiraMonLayer->ReadFeature
     544         803 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     545         803 :             UINT64_MAX - pArcHeader->nElemCount)
     546             :         {
     547           0 :             VSIFree(pBuffer);
     548           0 :             return 1;
     549             :         }
     550             : 
     551         803 :         if (hMiraMonLayer->ReadFeature
     552         803 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     553         803 :             UINT64_MAX - pArcHeader->nElemCount)
     554             :         {
     555           0 :             VSIFree(pBuffer);
     556           0 :             return 1;
     557             :         }
     558             : 
     559             :         hMiraMonLayer->ReadFeature
     560         803 :             .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
     561         803 :             pArcHeader->nElemCount;
     562             :     }
     563         346 :     if (MMResizeMM_POINT2DPointer(
     564             :             &hMiraMonLayer->ReadFeature.pCoord,
     565             :             &hMiraMonLayer->ReadFeature.nMaxpCoord,
     566             :             hMiraMonLayer->ReadFeature
     567         346 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings],
     568             :             0, 0))
     569             :     {
     570           0 :         VSIFree(pBuffer);
     571           0 :         return 1;
     572             :     }
     573             : 
     574         346 :     hMiraMonLayer->FlushPAL.CurrentOffset = 0;
     575             : 
     576             :     // Real work
     577         346 :     hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
     578             :         0;
     579        1148 :     for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
     580             :     {
     581         803 :         hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
     582             :             sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
     583         803 :         hMiraMonLayer->FlushPAL.pBlockToBeSaved =
     584         803 :             (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
     585         803 :         if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
     586             :         {
     587           0 :             if (pBuffer)
     588           0 :                 VSIFree(pBuffer);
     589           0 :             return 1;
     590             :         }
     591             : 
     592             :         // Arc index
     593         803 :         if (MMReadGUInt64DependingOnVersion(
     594             :                 hMiraMonLayer, &hMiraMonLayer->FlushPAL,
     595         803 :                 &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
     596             :         {
     597           0 :             if (pBuffer)
     598           0 :                 VSIFree(pBuffer);
     599           0 :             return 1;
     600             :         }
     601             : 
     602         803 :         bAvoidFirst = FALSE;
     603         803 :         if (hMiraMonLayer->ReadFeature
     604         803 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] != 0)
     605         310 :             bAvoidFirst = TRUE;
     606             : 
     607             :         // Add coordinates to hMiraMonLayer->ReadFeature.pCoord
     608         803 :         if (MMAddStringLineCoordinates(hMiraMonLayer,
     609         803 :                                        (hMiraMonLayer->pArcs + nIndex)->nIArc,
     610             :                                        flag_z, nNAcumulVertices, bAvoidFirst,
     611         803 :                                        (hMiraMonLayer->pArcs + nIndex)->VFG))
     612             :         {
     613           1 :             VSIFree(pBuffer);
     614           1 :             return 1;
     615             :         }
     616             : 
     617         802 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     618             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     619             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
     620         802 :                 (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10,
     621             :                 10))
     622             :         {
     623           0 :             VSIFree(pBuffer);
     624           0 :             return 1;
     625             :         }
     626             : 
     627         802 :         if (hMiraMonLayer->ReadFeature
     628         802 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
     629         802 :             UINT64_MAX - hMiraMonLayer->ReadFeature.nNumpCoord)
     630             :         {
     631           0 :             VSIFree(pBuffer);
     632           0 :             return 1;
     633             :         }
     634             : 
     635             :         hMiraMonLayer->ReadFeature
     636         802 :             .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
     637         802 :             hMiraMonLayer->ReadFeature.nNumpCoord;
     638         802 :         nNAcumulVertices += hMiraMonLayer->ReadFeature.nNumpCoord;
     639             : 
     640         802 :         if ((hMiraMonLayer->pArcs + nIndex)->VFG & MM_POL_END_RING)
     641             :         {
     642             :             hMiraMonLayer->ReadFeature
     643         492 :                 .flag_VFG[hMiraMonLayer->ReadFeature.nNRings] =
     644         492 :                 (hMiraMonLayer->pArcs + nIndex)->VFG;
     645         492 :             hMiraMonLayer->ReadFeature.nNRings++;
     646             :             hMiraMonLayer->ReadFeature
     647         492 :                 .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] = 0;
     648             :         }
     649             :     }
     650         345 :     hMiraMonLayer->nNumArcs = pPolHeader->nArcsCount;
     651         345 :     if (pBuffer)
     652         345 :         VSIFree(pBuffer);
     653             : 
     654         345 :     return 0;
     655             : }
     656             : 
     657             : // Reads the geographical part of a MiraMon layer feature
     658        1772 : int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer,
     659             :                               MM_INTERNAL_FID i_elem)
     660             : {
     661             :     VSILFILE *pF;
     662             :     struct MM_ZD *pZDescription;
     663             :     uint32_t flag_z;
     664             :     int num;
     665             :     double cz;
     666             : 
     667        1772 :     if (hMiraMonLayer->nSelectCoordz == MM_SELECT_HIGHEST_COORDZ)
     668           1 :         flag_z = MM_STRING_HIGHEST_ALTITUDE;
     669        1771 :     else if (hMiraMonLayer->nSelectCoordz == MM_SELECT_LOWEST_COORDZ)
     670           1 :         flag_z = MM_STRING_LOWEST_ALTITUDE;
     671             :     else
     672        1770 :         flag_z = 0L;
     673             : 
     674        1772 :     if (hMiraMonLayer->bIsPoint)
     675             :     {
     676        1054 :         pF = hMiraMonLayer->MMPoint.pF;
     677             : 
     678             :         // Getting to the i-th element offset
     679        1054 :         VSIFSeekL(pF,
     680        1054 :                   hMiraMonLayer->nHeaderDiskSize +
     681        1054 :                       sizeof(MM_COORD_TYPE) * 2 * i_elem,
     682             :                   SEEK_SET);
     683             : 
     684             :         // Reading the point
     685        1054 :         if (MMResizeMM_POINT2DPointer(&hMiraMonLayer->ReadFeature.pCoord,
     686             :                                       &hMiraMonLayer->ReadFeature.nMaxpCoord,
     687             :                                       hMiraMonLayer->ReadFeature.nNumpCoord, 1,
     688             :                                       1))
     689           0 :             return 1;
     690             : 
     691        1054 :         if (1 != VSIFReadL(hMiraMonLayer->ReadFeature.pCoord,
     692             :                            sizeof(MM_COORD_TYPE) * 2, 1, pF))
     693             :         {
     694           5 :             return 1;
     695             :         }
     696             : 
     697        1049 :         hMiraMonLayer->ReadFeature.nNRings = 1;
     698             : 
     699        1049 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     700             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     701             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
     702           0 :             return 1;
     703             : 
     704        1049 :         hMiraMonLayer->ReadFeature.pNCoordRing[0] = 1;
     705             : 
     706        1049 :         if (hMiraMonLayer->TopHeader.bIs3d)
     707             :         {
     708         907 :             pZDescription =
     709         907 :                 hMiraMonLayer->MMPoint.pZSection.pZDescription + i_elem;
     710         907 :             if (pZDescription->nZCount == INT_MIN)
     711           0 :                 return 1;
     712         907 :             num = MM_ARC_TOTAL_N_HEIGHTS_DISK(pZDescription->nZCount, 1);
     713             : 
     714         907 :             if (MMResizeDoublePointer(&hMiraMonLayer->ReadFeature.pZCoord,
     715             :                                       &hMiraMonLayer->ReadFeature.nMaxpZCoord,
     716             :                                       1, 1, 1))
     717           0 :                 return 1;
     718             : 
     719         907 :             if (num == 0)
     720           0 :                 hMiraMonLayer->ReadFeature.pZCoord[0] = MM_NODATA_COORD_Z;
     721             :             else
     722             :             {
     723         907 :                 if (flag_z == MM_STRING_HIGHEST_ALTITUDE)  // Max z
     724           1 :                     cz = pZDescription->dfBBmaxz;
     725         906 :                 else if (flag_z == MM_STRING_LOWEST_ALTITUDE)  // Min z
     726           1 :                     cz = pZDescription->dfBBminz;
     727             :                 else
     728             :                 {
     729             :                     // Reading the first z coordinate
     730         905 :                     VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET);
     731         905 :                     if ((size_t)1 !=
     732         905 :                         VSIFReadL(&cz,
     733             :                                   sizeof(*hMiraMonLayer->ReadFeature.pZCoord),
     734             :                                   1, pF))
     735             :                     {
     736           0 :                         return 1;
     737             :                     }
     738             :                 }
     739             :                 // If there is a value for Z-nodata in GDAL this lines can be uncommented
     740             :                 // and MM_GDAL_NODATA_COORD_Z can be defined
     741             :                 /*if(!DOUBLES_DIFERENTS_DJ(cz, MM_NODATA_COORD_Z))
     742             :                     hMiraMonLayer->ReadFeature.pZCoord[0]=MM_GDAL_NODATA_COORD_Z;
     743             :                 else */
     744         907 :                 hMiraMonLayer->ReadFeature.pZCoord[0] = cz;
     745             :             }
     746             :         }
     747             : 
     748        1049 :         return 0;
     749             :     }
     750             : 
     751             :     // Stringlines
     752         718 :     if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
     753             :     {
     754         366 :         if (MMAddStringLineCoordinates(hMiraMonLayer, i_elem, flag_z, 0, FALSE,
     755             :                                        0))
     756           7 :             return 1;
     757             : 
     758         359 :         if (MMResize_MM_N_VERTICES_TYPE_Pointer(
     759             :                 &hMiraMonLayer->ReadFeature.pNCoordRing,
     760             :                 &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
     761           0 :             return 1;
     762             : 
     763         359 :         hMiraMonLayer->ReadFeature.pNCoordRing[0] =
     764         359 :             hMiraMonLayer->ReadFeature.nNumpCoord;
     765             : 
     766         359 :         return 0;
     767             :     }
     768             : 
     769             :     // Polygons or multipolygons
     770         352 :     if (MMGetMultiPolygonCoordinates(hMiraMonLayer, i_elem, flag_z))
     771           7 :         return 1;
     772             : 
     773         345 :     return 0;
     774             : }
     775             : 
     776             : // Reads the header of a MiraMon DBF
     777             : // Please read the format at this link:
     778             : // https://www.miramon.cat/new_note/usa/notes/DBF_estesa.pdf
     779         162 : int MM_ReadExtendedDBFHeader(struct MiraMonVectLayerInfo *hMiraMonLayer)
     780             : {
     781         162 :     const char *pszRelFile = nullptr;
     782             :     struct MM_DATA_BASE_XP *pMMBDXP;
     783         162 :     const char *szDBFFileName = nullptr;
     784             : 
     785             :     // If read don't read again. It happens when Polygon reads
     786             :     // the database and then in initArc() it's read again.
     787         162 :     if (hMiraMonLayer->pMMBDXP)
     788          44 :         return 0;
     789             : 
     790         118 :     pMMBDXP = hMiraMonLayer->pMMBDXP = VSICalloc(1, sizeof(*pMMBDXP));
     791         118 :     if (!pMMBDXP)
     792           0 :         return 1;
     793             : 
     794         118 :     if (hMiraMonLayer->bIsPoint)
     795             :     {
     796          41 :         hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP = pMMBDXP;
     797          41 :         szDBFFileName = hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName;
     798          41 :         pszRelFile = hMiraMonLayer->MMPoint.pszREL_LayerName;
     799             :     }
     800          77 :     else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
     801             :     {
     802          30 :         hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP = pMMBDXP;
     803          30 :         szDBFFileName = hMiraMonLayer->MMArc.MMAdmDB.pszExtDBFLayerName;
     804          30 :         pszRelFile = hMiraMonLayer->MMArc.pszREL_LayerName;
     805             :     }
     806          47 :     else if (hMiraMonLayer->bIsPolygon)
     807             :     {
     808          47 :         hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP = pMMBDXP;
     809          47 :         szDBFFileName = hMiraMonLayer->MMPolygon.MMAdmDB.pszExtDBFLayerName;
     810          47 :         pszRelFile = hMiraMonLayer->MMPolygon.pszREL_LayerName;
     811             :     }
     812             : 
     813         118 :     if (MM_ReadExtendedDBFHeaderFromFile(szDBFFileName, pMMBDXP, pszRelFile))
     814             :     {
     815           1 :         CPLError(CE_Failure, CPLE_NotSupported,
     816             :                  "Error reading the format in the DBF file %s.", szDBFFileName);
     817           1 :         return 1;
     818             :     }
     819             : 
     820         117 :     fclose_and_nullify(&pMMBDXP->pfDataBase);
     821         117 :     return 0;
     822             : }
     823             : 
     824             : CPL_C_END  // Necessary for compiling in GDAL project

Generated by: LCOV version 1.14