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
|