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
|