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