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