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