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

Generated by: LCOV version 1.14