/src/gdal/ogr/ogrsf_frmts/miramon/ogrmiramonlayer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: OpenGIS Simple Features Reference Implementation |
4 | | * Purpose: Implements OGRMiraMonLayer class. |
5 | | * Author: Abel Pau |
6 | | ****************************************************************************** |
7 | | * Copyright (c) 2024, Xavier Pons |
8 | | * |
9 | | * SPDX-License-Identifier: MIT |
10 | | ****************************************************************************/ |
11 | | #include "ogrmiramon.h" |
12 | | |
13 | | #include "mm_gdal_functions.h" // For MMCreateExtendedDBFIndex() |
14 | | #include "mm_rdlayr.h" // For MMInitLayerToRead() |
15 | | #include <algorithm> // For std::clamp() |
16 | | #include <string> // For std::string |
17 | | #include <algorithm> // For std::max |
18 | | |
19 | | /****************************************************************************/ |
20 | | /* OGRMiraMonLayer() */ |
21 | | /****************************************************************************/ |
22 | | OGRMiraMonLayer::OGRMiraMonLayer(GDALDataset *poDS, const char *pszFilename, |
23 | | VSILFILE *fp, const OGRSpatialReference *poSRS, |
24 | | int bUpdateIn, CSLConstList papszOpenOptions, |
25 | | struct MiraMonVectMapInfo *MMMap) |
26 | 7.20k | : m_poDS(poDS), m_poSRS(nullptr), m_poFeatureDefn(nullptr), m_iNextFID(0), |
27 | 7.20k | phMiraMonLayer(nullptr), hMiraMonLayerPNT(), hMiraMonLayerARC(), |
28 | 7.20k | hMiraMonLayerPOL(), hMiraMonLayerReadOrNonGeom(), hMMFeature(), |
29 | 7.20k | m_bUpdate(CPL_TO_BOOL(bUpdateIn)), |
30 | 7.20k | m_fp(fp ? fp : VSIFOpenL(pszFilename, (bUpdateIn ? "r+" : "r"))), |
31 | 7.20k | padfValues(nullptr), pnInt64Values(nullptr), bValidFile(false) |
32 | 7.20k | { |
33 | | |
34 | 7.20k | CPLDebugOnly("MiraMon", "Creating/Opening MiraMon layer..."); |
35 | | /* -------------------------------------------------------------------- */ |
36 | | /* Create the feature definition */ |
37 | | /* -------------------------------------------------------------------- */ |
38 | 7.20k | m_poFeatureDefn = |
39 | 7.20k | new OGRFeatureDefn(CPLGetBasenameSafe(pszFilename).c_str()); |
40 | 7.20k | SetDescription(m_poFeatureDefn->GetName()); |
41 | 7.20k | m_poFeatureDefn->Reference(); |
42 | | |
43 | 7.20k | if (m_bUpdate) |
44 | 891 | { |
45 | | /* ---------------------------------------------------------------- */ |
46 | | /* Establish the version to use */ |
47 | | /* ---------------------------------------------------------------- */ |
48 | 891 | const char *pszVersion = CSLFetchNameValue(papszOpenOptions, "Version"); |
49 | 891 | int nMMVersion; |
50 | | |
51 | 891 | if (pszVersion) |
52 | 0 | { |
53 | 0 | if (EQUAL(pszVersion, "V1.1")) |
54 | 0 | nMMVersion = MM_32BITS_VERSION; |
55 | 0 | else if (EQUAL(pszVersion, "V2.0") || |
56 | 0 | EQUAL(pszVersion, "last_version")) |
57 | 0 | nMMVersion = MM_64BITS_VERSION; |
58 | 0 | else |
59 | 0 | nMMVersion = MM_32BITS_VERSION; // Default |
60 | 0 | } |
61 | 891 | else |
62 | 891 | nMMVersion = MM_32BITS_VERSION; // Default |
63 | | |
64 | | /* ---------------------------------------------------------------- */ |
65 | | /* Establish the charset of the .dbf files */ |
66 | | /* ---------------------------------------------------------------- */ |
67 | 891 | const char *pszdbfEncoding = |
68 | 891 | CSLFetchNameValue(papszOpenOptions, "DBFEncoding"); |
69 | 891 | char nMMRecode; |
70 | | |
71 | 891 | if (pszdbfEncoding) |
72 | 0 | { |
73 | 0 | if (EQUAL(pszdbfEncoding, "UTF8")) |
74 | 0 | nMMRecode = MM_RECODE_UTF8; |
75 | 0 | else //if (EQUAL(pszdbfEncoding, "ANSI")) |
76 | 0 | nMMRecode = MM_RECODE_ANSI; |
77 | 0 | } |
78 | 891 | else |
79 | 891 | nMMRecode = MM_RECODE_ANSI; // Default |
80 | | |
81 | | /* ----------------------------------------------------------------- */ |
82 | | /* Establish the descriptors language when */ |
83 | | /* creating .rel files */ |
84 | | /* ----------------------------------------------------------------- */ |
85 | 891 | const char *pszLanguage = |
86 | 891 | CSLFetchNameValue(papszOpenOptions, "CreationLanguage"); |
87 | 891 | char nMMLanguage; |
88 | | |
89 | 891 | if (pszLanguage) |
90 | 0 | { |
91 | 0 | if (EQUAL(pszLanguage, "CAT")) |
92 | 0 | nMMLanguage = MM_CAT_LANGUAGE; |
93 | 0 | else if (EQUAL(pszLanguage, "SPA")) |
94 | 0 | nMMLanguage = MM_SPA_LANGUAGE; |
95 | 0 | else |
96 | 0 | nMMLanguage = MM_ENG_LANGUAGE; |
97 | 0 | } |
98 | 891 | else |
99 | 891 | nMMLanguage = MM_DEF_LANGUAGE; // Default |
100 | | |
101 | | /* ---------------------------------------------------------------- */ |
102 | | /* Preparing to write the layer */ |
103 | | /* ---------------------------------------------------------------- */ |
104 | | // Init the feature (memory, num,...) |
105 | 891 | if (MMInitFeature(&hMMFeature)) |
106 | 0 | { |
107 | 0 | bValidFile = false; |
108 | 0 | return; |
109 | 0 | } |
110 | | |
111 | | // Init the Layers (not in disk, only in memory until |
112 | | // the first element is read) |
113 | 891 | CPLDebugOnly("MiraMon", "Initializing MiraMon points layer..."); |
114 | 891 | if (MMInitLayer(&hMiraMonLayerPNT, pszFilename, nMMVersion, nMMRecode, |
115 | 891 | nMMLanguage, nullptr, MM_WRITING_MODE, MMMap)) |
116 | 0 | { |
117 | 0 | bValidFile = false; |
118 | 0 | return; |
119 | 0 | } |
120 | 891 | hMiraMonLayerPNT.bIsBeenInit = 0; |
121 | | |
122 | 891 | CPLDebugOnly("MiraMon", "Initializing MiraMon arcs layer..."); |
123 | 891 | if (MMInitLayer(&hMiraMonLayerARC, pszFilename, nMMVersion, nMMRecode, |
124 | 891 | nMMLanguage, nullptr, MM_WRITING_MODE, MMMap)) |
125 | 0 | { |
126 | 0 | bValidFile = false; |
127 | 0 | return; |
128 | 0 | } |
129 | 891 | hMiraMonLayerARC.bIsBeenInit = 0; |
130 | | |
131 | 891 | CPLDebugOnly("MiraMon", "Initializing MiraMon polygons layer..."); |
132 | 891 | if (MMInitLayer(&hMiraMonLayerPOL, pszFilename, nMMVersion, nMMRecode, |
133 | 891 | nMMLanguage, nullptr, MM_WRITING_MODE, MMMap)) |
134 | 0 | { |
135 | 0 | bValidFile = false; |
136 | 0 | return; |
137 | 0 | } |
138 | 891 | hMiraMonLayerPOL.bIsBeenInit = 0; |
139 | | |
140 | | // Just in case that there is no geometry but some other |
141 | | // information to get. A DBF will be generated |
142 | 891 | CPLDebugOnly("MiraMon", "Initializing MiraMon only-ext-DBF layer..."); |
143 | 891 | if (MMInitLayer(&hMiraMonLayerReadOrNonGeom, pszFilename, nMMVersion, |
144 | 891 | nMMRecode, nMMLanguage, nullptr, MM_WRITING_MODE, |
145 | 891 | nullptr)) |
146 | 0 | { |
147 | 0 | bValidFile = false; |
148 | 0 | return; |
149 | 0 | } |
150 | 891 | hMiraMonLayerPOL.bIsBeenInit = 0; |
151 | | |
152 | | // This helps the map to be created |
153 | | //GetLayerDefn()->SetName(hMiraMonLayerPNT.pszSrcLayerName); |
154 | 891 | m_poFeatureDefn->SetName(hMiraMonLayerPNT.pszSrcLayerName); |
155 | | |
156 | | // Saving the HRS in the layer structure |
157 | 891 | if (poSRS) |
158 | 64 | { |
159 | 64 | const char *pszTargetKey = nullptr; |
160 | 64 | const char *pszAuthorityName = nullptr; |
161 | 64 | const char *pszAuthorityCode = nullptr; |
162 | | |
163 | | // Reading Z units (in case of 3D vector file) |
164 | 64 | if (poSRS->GetAuthorityCode("VERT_CS") != nullptr) |
165 | 2 | { |
166 | 2 | const char *pszUnits = nullptr; |
167 | 2 | const double dfUnits = |
168 | 2 | poSRS->GetTargetLinearUnits("VERT_CS", &pszUnits); |
169 | 2 | const auto IsAlmostEqual = [](double x, double y) |
170 | 2 | { return std::fabs(x - y) <= 1e-10; }; |
171 | 2 | if (pszUnits) |
172 | 2 | { |
173 | 2 | if (!strcmp(pszUnits, "metre") && IsAlmostEqual(dfUnits, 1)) |
174 | 2 | { |
175 | 2 | hMiraMonLayerPNT.pZUnit = strdup("m"); |
176 | 2 | hMiraMonLayerARC.pZUnit = strdup("m"); |
177 | 2 | hMiraMonLayerPOL.pZUnit = strdup("m"); |
178 | 2 | } |
179 | 0 | else |
180 | 0 | { |
181 | 0 | hMiraMonLayerPNT.pZUnit = strdup(pszUnits); |
182 | 0 | hMiraMonLayerARC.pZUnit = strdup(pszUnits); |
183 | 0 | hMiraMonLayerPOL.pZUnit = strdup(pszUnits); |
184 | 0 | } |
185 | 2 | } |
186 | 2 | } |
187 | | |
188 | | // Reading horizontal reference system and horizontal units |
189 | 64 | if (poSRS->IsProjected()) |
190 | 44 | pszTargetKey = "PROJCS"; |
191 | 20 | else if (poSRS->IsGeographic() || poSRS->IsDerivedGeographic()) |
192 | 1 | pszTargetKey = "GEOGCS"; |
193 | 19 | else if (poSRS->IsGeocentric()) |
194 | 0 | pszTargetKey = "GEOCCS"; |
195 | 19 | else if (poSRS->IsLocal()) |
196 | 0 | pszTargetKey = "LOCAL_CS"; |
197 | | |
198 | 64 | if (!poSRS->IsLocal()) |
199 | 64 | { |
200 | 64 | pszAuthorityName = poSRS->GetAuthorityName(pszTargetKey); |
201 | 64 | pszAuthorityCode = poSRS->GetAuthorityCode(pszTargetKey); |
202 | 64 | } |
203 | | |
204 | 64 | if (pszAuthorityName && pszAuthorityCode && |
205 | 64 | EQUAL(pszAuthorityName, "EPSG")) |
206 | 41 | { |
207 | 41 | CPLDebugOnly("MiraMon", "Setting EPSG code %s", |
208 | 41 | pszAuthorityCode); |
209 | 41 | hMiraMonLayerPNT.pSRS = CPLStrdup(pszAuthorityCode); |
210 | 41 | hMiraMonLayerARC.pSRS = CPLStrdup(pszAuthorityCode); |
211 | 41 | hMiraMonLayerPOL.pSRS = CPLStrdup(pszAuthorityCode); |
212 | 41 | } |
213 | | // In the DBF, there are some reserved fields that need to |
214 | | // know if the layer is geographic or not to write the |
215 | | // precision (they are real) |
216 | 64 | if (poSRS->IsGeographic()) |
217 | 1 | { |
218 | 1 | hMiraMonLayerPNT.nSRSType = hMiraMonLayerARC.nSRSType = |
219 | 1 | hMiraMonLayerPOL.nSRSType = MM_SRS_LAYER_IS_GEOGRAPHIC_TYPE; |
220 | 1 | } |
221 | 63 | else |
222 | 63 | { |
223 | 63 | hMiraMonLayerPNT.nSRSType = hMiraMonLayerARC.nSRSType = |
224 | 63 | hMiraMonLayerPOL.nSRSType = MM_SRS_LAYER_IS_PROJECTED_TYPE; |
225 | 63 | } |
226 | 64 | } |
227 | 827 | else |
228 | 827 | { |
229 | 827 | hMiraMonLayerPNT.nSRSType = hMiraMonLayerARC.nSRSType = |
230 | 827 | hMiraMonLayerPOL.nSRSType = MM_SRS_LAYER_IS_UNKNOWN_TYPE; |
231 | 827 | } |
232 | 891 | } |
233 | 6.31k | else |
234 | 6.31k | { |
235 | 6.31k | if (m_fp == nullptr) |
236 | 0 | { |
237 | 0 | bValidFile = false; |
238 | 0 | return; |
239 | 0 | } |
240 | | |
241 | | /* ------------------------------------------------------------------*/ |
242 | | /* Read the header. */ |
243 | | /* ------------------------------------------------------------------*/ |
244 | 6.31k | int nMMLayerVersion; |
245 | | |
246 | 6.31k | if (MMInitLayerToRead(&hMiraMonLayerReadOrNonGeom, m_fp, pszFilename)) |
247 | 5.26k | { |
248 | 5.26k | phMiraMonLayer = &hMiraMonLayerReadOrNonGeom; |
249 | 5.26k | bValidFile = false; |
250 | 5.26k | return; |
251 | 5.26k | } |
252 | 1.05k | phMiraMonLayer = &hMiraMonLayerReadOrNonGeom; |
253 | | |
254 | 1.05k | nMMLayerVersion = MMGetVectorVersion(&phMiraMonLayer->TopHeader); |
255 | 1.05k | if (nMMLayerVersion == MM_UNKNOWN_VERSION) |
256 | 0 | { |
257 | 0 | CPLError(CE_Failure, CPLE_NotSupported, |
258 | 0 | "MiraMon version file unknown."); |
259 | 0 | bValidFile = false; |
260 | 0 | return; |
261 | 0 | } |
262 | 1.05k | if (phMiraMonLayer->bIsPoint) |
263 | 474 | { |
264 | 474 | if (phMiraMonLayer->TopHeader.bIs3d) |
265 | 119 | m_poFeatureDefn->SetGeomType(wkbPoint25D); |
266 | 355 | else |
267 | 355 | m_poFeatureDefn->SetGeomType(wkbPoint); |
268 | 474 | } |
269 | 579 | else if (phMiraMonLayer->bIsArc && !phMiraMonLayer->bIsPolygon) |
270 | 276 | { |
271 | 276 | if (phMiraMonLayer->TopHeader.bIs3d) |
272 | 211 | m_poFeatureDefn->SetGeomType(wkbLineString25D); |
273 | 65 | else |
274 | 65 | m_poFeatureDefn->SetGeomType(wkbLineString); |
275 | 276 | } |
276 | 303 | else if (phMiraMonLayer->bIsPolygon) |
277 | 303 | { |
278 | | // 3D |
279 | 303 | if (phMiraMonLayer->TopHeader.bIs3d) |
280 | 179 | { |
281 | 179 | if (phMiraMonLayer->TopHeader.bIsMultipolygon) |
282 | 79 | m_poFeatureDefn->SetGeomType(wkbMultiPolygon25D); |
283 | 100 | else |
284 | 100 | m_poFeatureDefn->SetGeomType(wkbPolygon25D); |
285 | 179 | } |
286 | 124 | else |
287 | 124 | { |
288 | 124 | if (phMiraMonLayer->TopHeader.bIsMultipolygon) |
289 | 45 | m_poFeatureDefn->SetGeomType(wkbMultiPolygon); |
290 | 79 | else |
291 | 79 | m_poFeatureDefn->SetGeomType(wkbPolygon); |
292 | 124 | } |
293 | 303 | } |
294 | 0 | else |
295 | 0 | { |
296 | 0 | CPLError(CE_Failure, CPLE_NotSupported, |
297 | 0 | "MiraMon file type not supported."); |
298 | 0 | bValidFile = false; |
299 | 0 | return; |
300 | 0 | } |
301 | | |
302 | 1.05k | if (phMiraMonLayer->TopHeader.bIs3d) |
303 | 509 | { |
304 | 509 | const char *szHeight = |
305 | 509 | CSLFetchNameValue(papszOpenOptions, "Height"); |
306 | 509 | if (szHeight) |
307 | 0 | { |
308 | 0 | if (EQUAL(szHeight, "Highest")) |
309 | 0 | phMiraMonLayer->nSelectCoordz = MM_SELECT_HIGHEST_COORDZ; |
310 | 0 | else if (EQUAL(szHeight, "Lowest")) |
311 | 0 | phMiraMonLayer->nSelectCoordz = MM_SELECT_LOWEST_COORDZ; |
312 | 0 | else |
313 | 0 | phMiraMonLayer->nSelectCoordz = MM_SELECT_FIRST_COORDZ; |
314 | 0 | } |
315 | 509 | else |
316 | 509 | phMiraMonLayer->nSelectCoordz = MM_SELECT_FIRST_COORDZ; |
317 | 509 | } |
318 | | |
319 | | /* ------------------------------------------------------------ */ |
320 | | /* Establish the descriptors language when */ |
321 | | /* opening .rel files */ |
322 | | /* ------------------------------------------------------------ */ |
323 | 1.05k | const char *pszLanguage = |
324 | 1.05k | CSLFetchNameValue(papszOpenOptions, "OpenLanguage"); |
325 | | |
326 | 1.05k | if (pszLanguage) |
327 | 0 | { |
328 | 0 | if (EQUAL(pszLanguage, "CAT")) |
329 | 0 | phMiraMonLayer->nMMLanguage = MM_CAT_LANGUAGE; |
330 | 0 | else if (EQUAL(pszLanguage, "SPA")) |
331 | 0 | phMiraMonLayer->nMMLanguage = MM_SPA_LANGUAGE; |
332 | 0 | else |
333 | 0 | phMiraMonLayer->nMMLanguage = MM_ENG_LANGUAGE; |
334 | 0 | } |
335 | 1.05k | else |
336 | 1.05k | phMiraMonLayer->nMMLanguage = MM_DEF_LANGUAGE; // Default |
337 | | |
338 | 1.05k | if (phMiraMonLayer->nSRS_EPSG != 0) |
339 | 0 | { |
340 | 0 | m_poSRS = new OGRSpatialReference(); |
341 | 0 | m_poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
342 | 0 | if (m_poSRS->importFromEPSG(phMiraMonLayer->nSRS_EPSG) != |
343 | 0 | OGRERR_NONE) |
344 | 0 | { |
345 | 0 | delete m_poSRS; |
346 | 0 | m_poSRS = nullptr; |
347 | 0 | } |
348 | 0 | else |
349 | 0 | m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSRS); |
350 | 0 | } |
351 | | |
352 | | // If there is associated information |
353 | 1.05k | if (phMiraMonLayer->pMMBDXP) |
354 | 1.05k | { |
355 | 1.05k | if (!phMiraMonLayer->pMMBDXP->pfDataBase) |
356 | 1.05k | { |
357 | 1.05k | if ((phMiraMonLayer->pMMBDXP->pfDataBase = VSIFOpenL( |
358 | 1.05k | phMiraMonLayer->pMMBDXP->szFileName, "r")) == nullptr) |
359 | 0 | { |
360 | 0 | CPLDebugOnly("MiraMon", "File '%s' cannot be opened.", |
361 | 0 | phMiraMonLayer->pMMBDXP->szFileName); |
362 | 0 | bValidFile = false; |
363 | 0 | return; |
364 | 0 | } |
365 | | |
366 | 1.05k | if (phMiraMonLayer->pMMBDXP->nFields == 0) |
367 | 3 | { |
368 | | // TODO: is this correct? At least this prevents a |
369 | | // nullptr dereference of phMiraMonLayer->pMMBDXP->pField |
370 | | // below |
371 | 3 | CPLDebug("MiraMon", |
372 | 3 | "phMiraMonLayer->pMMBDXP->nFields == 0"); |
373 | 3 | bValidFile = false; |
374 | 3 | return; |
375 | 3 | } |
376 | | |
377 | | // First time we open the extended DBF we create an index |
378 | | // to fastly find all non geometrical features. |
379 | 1.05k | phMiraMonLayer->pMultRecordIndex = MMCreateExtendedDBFIndex( |
380 | 1.05k | phMiraMonLayer->pMMBDXP->pfDataBase, |
381 | 1.05k | phMiraMonLayer->pMMBDXP->nRecords, |
382 | 1.05k | phMiraMonLayer->pMMBDXP->FirstRecordOffset, |
383 | 1.05k | phMiraMonLayer->pMMBDXP->BytesPerRecord, |
384 | 1.05k | phMiraMonLayer->pMMBDXP |
385 | 1.05k | ->pField[phMiraMonLayer->pMMBDXP->IdGraficField] |
386 | 1.05k | .AccumulatedBytes, |
387 | 1.05k | phMiraMonLayer->pMMBDXP |
388 | 1.05k | ->pField[phMiraMonLayer->pMMBDXP->IdGraficField] |
389 | 1.05k | .BytesPerField, |
390 | 1.05k | &phMiraMonLayer->isListField, &phMiraMonLayer->nMaxN); |
391 | | |
392 | | // Creation of maximum number needed for processing |
393 | | // multiple records |
394 | 1.05k | if (phMiraMonLayer->pMultRecordIndex) |
395 | 615 | { |
396 | 615 | padfValues = static_cast<double *>(CPLCalloc( |
397 | 615 | (size_t)phMiraMonLayer->nMaxN, sizeof(*padfValues))); |
398 | | |
399 | 615 | pnInt64Values = static_cast<GInt64 *>(CPLCalloc( |
400 | 615 | (size_t)phMiraMonLayer->nMaxN, sizeof(*pnInt64Values))); |
401 | 615 | } |
402 | | |
403 | 1.05k | phMiraMonLayer->iMultiRecord = |
404 | 1.05k | MM_MULTIRECORD_NO_MULTIRECORD; // No option iMultiRecord |
405 | 1.05k | const char *szMultiRecord = |
406 | 1.05k | CSLFetchNameValue(papszOpenOptions, "MultiRecordIndex"); |
407 | 1.05k | if (phMiraMonLayer->isListField && szMultiRecord) |
408 | 0 | { |
409 | 0 | if (EQUAL(szMultiRecord, "Last")) |
410 | 0 | phMiraMonLayer->iMultiRecord = MM_MULTIRECORD_LAST; |
411 | 0 | else if (EQUAL(szMultiRecord, "JSON")) |
412 | 0 | phMiraMonLayer->iMultiRecord = MM_MULTIRECORD_JSON; |
413 | 0 | else |
414 | 0 | phMiraMonLayer->iMultiRecord = atoi(szMultiRecord); |
415 | 0 | } |
416 | 1.05k | } |
417 | | |
418 | 1.05k | for (MM_EXT_DBF_N_FIELDS nIField = 0; |
419 | 63.6k | nIField < phMiraMonLayer->pMMBDXP->nFields; nIField++) |
420 | 62.5k | { |
421 | 62.5k | OGRFieldDefn oField("", OFTString); |
422 | 62.5k | oField.SetName( |
423 | 62.5k | phMiraMonLayer->pMMBDXP->pField[nIField].FieldName); |
424 | | |
425 | 62.5k | oField.SetAlternativeName( |
426 | 62.5k | phMiraMonLayer->pMMBDXP->pField[nIField] |
427 | 62.5k | .FieldDescription[phMiraMonLayer->nMMLanguage < |
428 | 62.5k | MM_NUM_IDIOMES_MD_MULTIDIOMA |
429 | 62.5k | ? phMiraMonLayer->nMMLanguage |
430 | 62.5k | : 0]); |
431 | | |
432 | 62.5k | if (phMiraMonLayer->pMMBDXP->pField[nIField].FieldType == 'C' || |
433 | 62.5k | phMiraMonLayer->pMMBDXP->pField[nIField].FieldType == 'L') |
434 | 6.71k | { |
435 | | // It's a list? |
436 | 6.71k | if (phMiraMonLayer->iMultiRecord == |
437 | 6.71k | MM_MULTIRECORD_NO_MULTIRECORD) |
438 | 6.71k | { |
439 | 6.71k | if (phMiraMonLayer->pMMBDXP->pField[nIField] |
440 | 6.71k | .FieldType == 'L') |
441 | 1.65k | { |
442 | 1.65k | if (phMiraMonLayer->isListField) |
443 | 314 | oField.SetType(OFTIntegerList); |
444 | 1.33k | else |
445 | 1.33k | oField.SetType(OFTInteger); |
446 | | |
447 | 1.65k | oField.SetSubType(OFSTBoolean); |
448 | 1.65k | } |
449 | 5.06k | else |
450 | 5.06k | { |
451 | 5.06k | if (phMiraMonLayer->isListField) |
452 | 450 | oField.SetType(OFTStringList); |
453 | 4.61k | else |
454 | 4.61k | oField.SetType(OFTString); |
455 | 5.06k | } |
456 | 6.71k | } |
457 | | // It's a serialized JSON array |
458 | 0 | else if (phMiraMonLayer->iMultiRecord == |
459 | 0 | MM_MULTIRECORD_JSON) |
460 | 0 | { |
461 | 0 | oField.SetType(OFTString); |
462 | 0 | oField.SetSubType(OFSTJSON); |
463 | 0 | } |
464 | 0 | else // iMultiRecord decides which Record translate |
465 | 0 | oField.SetType(OFTString); |
466 | 6.71k | } |
467 | 55.8k | else if (phMiraMonLayer->pMMBDXP->pField[nIField].FieldType == |
468 | 55.8k | 'N') |
469 | 5.07k | { |
470 | | // It's a list? |
471 | 5.07k | if (phMiraMonLayer->iMultiRecord == |
472 | 5.07k | MM_MULTIRECORD_NO_MULTIRECORD) |
473 | 5.07k | { |
474 | 5.07k | if (phMiraMonLayer->pMMBDXP->pField[nIField] |
475 | 5.07k | .DecimalsIfFloat) |
476 | 3.29k | oField.SetType(phMiraMonLayer->isListField |
477 | 3.29k | ? OFTRealList |
478 | 3.29k | : OFTReal); |
479 | 1.77k | else |
480 | 1.77k | { |
481 | 1.77k | if (phMiraMonLayer->pMMBDXP->pField[nIField] |
482 | 1.77k | .BytesPerField < 10) |
483 | 868 | { |
484 | 868 | oField.SetType(phMiraMonLayer->isListField |
485 | 868 | ? OFTIntegerList |
486 | 868 | : OFTInteger); |
487 | 868 | } |
488 | 906 | else |
489 | 906 | { |
490 | 906 | oField.SetType(phMiraMonLayer->isListField |
491 | 906 | ? OFTInteger64List |
492 | 906 | : OFTInteger64); |
493 | 906 | } |
494 | 1.77k | } |
495 | 5.07k | } |
496 | | // It's a serialized JSON array |
497 | 0 | else if (phMiraMonLayer->iMultiRecord == |
498 | 0 | MM_MULTIRECORD_JSON) |
499 | 0 | { |
500 | 0 | oField.SetType(OFTString); |
501 | 0 | oField.SetSubType(OFSTJSON); |
502 | 0 | } |
503 | 0 | else |
504 | 0 | { |
505 | 0 | if (phMiraMonLayer->pMMBDXP->pField[nIField] |
506 | 0 | .DecimalsIfFloat) |
507 | 0 | oField.SetType(OFTReal); |
508 | 0 | else |
509 | 0 | oField.SetType(OFTInteger); |
510 | 0 | } |
511 | 5.07k | } |
512 | 50.7k | else if (phMiraMonLayer->pMMBDXP->pField[nIField].FieldType == |
513 | 50.7k | 'D') |
514 | 1.66k | { |
515 | | // It's a serialized JSON array |
516 | 1.66k | oField.SetType(OFTDate); |
517 | 1.66k | if (phMiraMonLayer->iMultiRecord == MM_MULTIRECORD_JSON) |
518 | 0 | { |
519 | 0 | oField.SetType(OFTString); |
520 | 0 | oField.SetSubType(OFSTJSON); |
521 | 0 | } |
522 | 1.66k | } |
523 | | |
524 | 62.5k | oField.SetWidth( |
525 | 62.5k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
526 | 62.5k | oField.SetPrecision( |
527 | 62.5k | phMiraMonLayer->pMMBDXP->pField[nIField].DecimalsIfFloat); |
528 | | |
529 | 62.5k | m_poFeatureDefn->AddFieldDefn(&oField); |
530 | 62.5k | } |
531 | 1.05k | } |
532 | 1.05k | } |
533 | | |
534 | 1.94k | bValidFile = true; |
535 | 1.94k | } |
536 | | |
537 | | /****************************************************************************/ |
538 | | /* ~OGRMiraMonLayer() */ |
539 | | /****************************************************************************/ |
540 | | |
541 | | OGRMiraMonLayer::~OGRMiraMonLayer() |
542 | | |
543 | 7.20k | { |
544 | 7.20k | if (m_nFeaturesRead > 0 && m_poFeatureDefn != nullptr) |
545 | 834 | { |
546 | 834 | CPLDebugOnly("MiraMon", "%d features read on layer '%s'.", |
547 | 834 | static_cast<int>(m_nFeaturesRead), |
548 | 834 | m_poFeatureDefn->GetName()); |
549 | 834 | } |
550 | | |
551 | 7.20k | if (hMiraMonLayerPOL.bIsPolygon) |
552 | 22 | { |
553 | 22 | CPLDebugOnly("MiraMon", "Closing MiraMon polygons layer..."); |
554 | 22 | if (MMCloseLayer(&hMiraMonLayerPOL)) |
555 | 12 | { |
556 | 12 | CPLDebugOnly("MiraMon", "Error closing polygons layer"); |
557 | | |
558 | | // In case of closing we need to destroy memory |
559 | 12 | MMDestroyLayer(&hMiraMonLayerPOL); |
560 | 12 | } |
561 | 22 | if (hMiraMonLayerPOL.TopHeader.nElemCount) |
562 | 22 | { |
563 | 22 | CPLDebugOnly("MiraMon", |
564 | 22 | sprintf_UINT64 " polygon(s) written in file %s.pol", |
565 | 22 | hMiraMonLayerPOL.TopHeader.nElemCount, |
566 | 22 | hMiraMonLayerPOL.pszSrcLayerName); |
567 | 22 | } |
568 | 22 | CPLDebugOnly("MiraMon", "MiraMon polygons layer closed"); |
569 | 22 | } |
570 | 7.18k | else if (hMiraMonLayerPOL.ReadOrWrite == MM_WRITING_MODE) |
571 | 869 | { |
572 | 869 | CPLDebugOnly("MiraMon", "No MiraMon polygons layer created."); |
573 | 869 | } |
574 | | |
575 | 7.20k | if (hMiraMonLayerARC.bIsArc) |
576 | 11 | { |
577 | 11 | CPLDebugOnly("MiraMon", "Closing MiraMon arcs layer..."); |
578 | 11 | if (MMCloseLayer(&hMiraMonLayerARC)) |
579 | 1 | { |
580 | 1 | CPLDebugOnly("MiraMon", "Error closing arcs layer"); |
581 | | |
582 | | // In case of closing we need to destroy memory |
583 | 1 | MMDestroyLayer(&hMiraMonLayerARC); |
584 | 1 | } |
585 | 11 | if (hMiraMonLayerARC.TopHeader.nElemCount) |
586 | 10 | { |
587 | 10 | CPLDebugOnly("MiraMon", |
588 | 10 | sprintf_UINT64 " arc(s) written in file %s.arc", |
589 | 10 | hMiraMonLayerARC.TopHeader.nElemCount, |
590 | 10 | hMiraMonLayerARC.pszSrcLayerName); |
591 | 10 | } |
592 | | |
593 | 11 | CPLDebugOnly("MiraMon", "MiraMon arcs layer closed"); |
594 | 11 | } |
595 | 7.19k | else if (hMiraMonLayerARC.ReadOrWrite == MM_WRITING_MODE) |
596 | 880 | { |
597 | 880 | CPLDebugOnly("MiraMon", "No MiraMon arcs layer created."); |
598 | 880 | } |
599 | | |
600 | 7.20k | if (hMiraMonLayerPNT.bIsPoint) |
601 | 23 | { |
602 | 23 | CPLDebugOnly("MiraMon", "Closing MiraMon points layer..."); |
603 | 23 | if (MMCloseLayer(&hMiraMonLayerPNT)) |
604 | 5 | { |
605 | 5 | CPLDebugOnly("MiraMon", "Error closing points layer"); |
606 | | |
607 | | // In case of closing we need to destroy memory |
608 | 5 | MMDestroyLayer(&hMiraMonLayerPNT); |
609 | 5 | } |
610 | 23 | if (hMiraMonLayerPNT.TopHeader.nElemCount) |
611 | 18 | { |
612 | 18 | CPLDebugOnly("MiraMon", |
613 | 18 | sprintf_UINT64 " point(s) written in file %s.pnt", |
614 | 18 | hMiraMonLayerPNT.TopHeader.nElemCount, |
615 | 18 | hMiraMonLayerPNT.pszSrcLayerName); |
616 | 18 | } |
617 | 23 | CPLDebugOnly("MiraMon", "MiraMon points layer closed"); |
618 | 23 | } |
619 | 7.18k | else if (hMiraMonLayerPNT.ReadOrWrite == MM_WRITING_MODE) |
620 | 868 | { |
621 | 868 | CPLDebugOnly("MiraMon", "No MiraMon points layer created."); |
622 | 868 | } |
623 | | |
624 | 7.20k | if (hMiraMonLayerARC.ReadOrWrite == MM_WRITING_MODE) |
625 | 891 | { |
626 | 891 | if (hMiraMonLayerReadOrNonGeom.bIsDBF) |
627 | 750 | { |
628 | 750 | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
629 | 750 | { |
630 | 750 | CPLDebugOnly("MiraMon", "Closing MiraMon DBF table ..."); |
631 | 750 | } |
632 | 750 | if (MMCloseLayer(&hMiraMonLayerReadOrNonGeom)) |
633 | 0 | { |
634 | | // In case of closing we need to destroy memory |
635 | 0 | MMDestroyLayer(&hMiraMonLayerReadOrNonGeom); |
636 | 0 | } |
637 | 750 | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
638 | 750 | { |
639 | 750 | CPLDebugOnly("MiraMon", "MiraMon DBF table closed"); |
640 | 750 | } |
641 | 750 | } |
642 | 141 | else if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
643 | 141 | { |
644 | 141 | CPLDebugOnly("MiraMon", "No MiraMon DBF table created."); |
645 | 141 | } |
646 | 891 | } |
647 | 6.31k | else |
648 | 6.31k | { |
649 | 6.31k | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
650 | 0 | { |
651 | 0 | CPLDebugOnly("MiraMon", "Closing MiraMon layer ..."); |
652 | 0 | } |
653 | 6.31k | if (MMCloseLayer(&hMiraMonLayerReadOrNonGeom)) |
654 | 0 | { |
655 | | // In case of closing we need to destroy memory |
656 | 0 | MMDestroyLayer(&hMiraMonLayerReadOrNonGeom); |
657 | 0 | } |
658 | 6.31k | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
659 | 0 | { |
660 | 0 | CPLDebugOnly("MiraMon", "MiraMon layer closed"); |
661 | 0 | } |
662 | 6.31k | } |
663 | | |
664 | 7.20k | if (hMiraMonLayerPOL.ReadOrWrite == MM_WRITING_MODE) |
665 | 891 | { |
666 | 891 | CPLDebugOnly("MiraMon", "Destroying MiraMon polygons layer memory"); |
667 | 891 | } |
668 | 7.20k | MMDestroyLayer(&hMiraMonLayerPOL); |
669 | 7.20k | if (hMiraMonLayerPOL.ReadOrWrite == MM_WRITING_MODE) |
670 | 891 | { |
671 | 891 | CPLDebugOnly("MiraMon", "MiraMon polygons layer memory destroyed"); |
672 | 891 | } |
673 | | |
674 | 7.20k | if (hMiraMonLayerARC.ReadOrWrite == MM_WRITING_MODE) |
675 | 891 | { |
676 | 891 | CPLDebugOnly("MiraMon", "Destroying MiraMon arcs layer memory"); |
677 | 891 | } |
678 | 7.20k | MMDestroyLayer(&hMiraMonLayerARC); |
679 | 7.20k | if (hMiraMonLayerARC.ReadOrWrite == MM_WRITING_MODE) |
680 | 891 | { |
681 | 891 | CPLDebugOnly("MiraMon", "MiraMon arcs layer memory destroyed"); |
682 | 891 | } |
683 | | |
684 | 7.20k | if (hMiraMonLayerPNT.ReadOrWrite == MM_WRITING_MODE) |
685 | 891 | { |
686 | 891 | CPLDebugOnly("MiraMon", "Destroying MiraMon points layer memory"); |
687 | 891 | } |
688 | 7.20k | MMDestroyLayer(&hMiraMonLayerPNT); |
689 | 7.20k | if (hMiraMonLayerPNT.ReadOrWrite == MM_WRITING_MODE) |
690 | 891 | { |
691 | 891 | CPLDebugOnly("MiraMon", "MiraMon points layer memory destroyed"); |
692 | 891 | } |
693 | | |
694 | 7.20k | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
695 | 891 | { |
696 | 891 | CPLDebugOnly("MiraMon", "Destroying MiraMon DBF table layer memory"); |
697 | 891 | } |
698 | 6.31k | else |
699 | 6.31k | { |
700 | 6.31k | CPLDebugOnly("MiraMon", "Destroying MiraMon layer memory"); |
701 | 6.31k | } |
702 | | |
703 | 7.20k | MMDestroyLayer(&hMiraMonLayerReadOrNonGeom); |
704 | 7.20k | if (hMiraMonLayerReadOrNonGeom.ReadOrWrite == MM_WRITING_MODE) |
705 | 891 | { |
706 | 891 | CPLDebugOnly("MiraMon", "MiraMon DBF table layer memory destroyed"); |
707 | 891 | } |
708 | 6.31k | else |
709 | 6.31k | { |
710 | 6.31k | CPLDebugOnly("MiraMon", "MiraMon layer memory destroyed"); |
711 | 6.31k | } |
712 | | |
713 | 7.20k | memset(&hMiraMonLayerReadOrNonGeom, 0, sizeof(hMiraMonLayerReadOrNonGeom)); |
714 | 7.20k | memset(&hMiraMonLayerPNT, 0, sizeof(hMiraMonLayerPNT)); |
715 | 7.20k | memset(&hMiraMonLayerARC, 0, sizeof(hMiraMonLayerARC)); |
716 | 7.20k | memset(&hMiraMonLayerPOL, 0, sizeof(hMiraMonLayerPOL)); |
717 | | |
718 | 7.20k | CPLDebugOnly("MiraMon", "Destroying MiraMon temporary feature memory"); |
719 | 7.20k | MMDestroyFeature(&hMMFeature); |
720 | 7.20k | CPLDebugOnly("MiraMon", "MiraMon temporary feature memory"); |
721 | 7.20k | memset(&hMMFeature, 0, sizeof(hMMFeature)); |
722 | | |
723 | | /* -------------------------------------------------------------------- */ |
724 | | /* Clean up. */ |
725 | | /* -------------------------------------------------------------------- */ |
726 | | |
727 | 7.20k | if (m_poFeatureDefn) |
728 | 7.20k | m_poFeatureDefn->Release(); |
729 | | |
730 | 7.20k | if (m_poSRS) |
731 | 0 | m_poSRS->Release(); |
732 | | |
733 | 7.20k | if (m_fp != nullptr) |
734 | 6.31k | VSIFCloseL(m_fp); |
735 | | |
736 | 7.20k | if (padfValues != nullptr) |
737 | 434 | CPLFree(padfValues); |
738 | | |
739 | 7.20k | if (pnInt64Values != nullptr) |
740 | 434 | CPLFree(pnInt64Values); |
741 | 7.20k | } |
742 | | |
743 | | /****************************************************************************/ |
744 | | /* ResetReading() */ |
745 | | /****************************************************************************/ |
746 | | |
747 | | void OGRMiraMonLayer::ResetReading() |
748 | | |
749 | 0 | { |
750 | 0 | if (m_iNextFID == 0) |
751 | 0 | return; |
752 | | |
753 | 0 | m_iNextFID = 0; |
754 | | |
755 | | //VSIFSeekL(m_fp, 0, SEEK_SET); |
756 | 0 | if (!phMiraMonLayer) |
757 | 0 | return; |
758 | | |
759 | 0 | if (phMiraMonLayer->bIsPoint && phMiraMonLayer->MMPoint.pF) |
760 | 0 | { |
761 | 0 | VSIFSeekL(phMiraMonLayer->MMPoint.pF, 0, SEEK_SET); |
762 | 0 | return; |
763 | 0 | } |
764 | 0 | if (phMiraMonLayer->bIsArc && !phMiraMonLayer->bIsPolygon && |
765 | 0 | phMiraMonLayer->MMArc.pF) |
766 | 0 | { |
767 | 0 | VSIFSeekL(phMiraMonLayer->MMArc.pF, 0, SEEK_SET); |
768 | 0 | return; |
769 | 0 | } |
770 | 0 | if (phMiraMonLayer->bIsPolygon && phMiraMonLayer->MMPolygon.pF) |
771 | 0 | { |
772 | 0 | VSIFSeekL(phMiraMonLayer->MMPolygon.pF, 0, SEEK_SET); |
773 | 0 | return; |
774 | 0 | } |
775 | 0 | } |
776 | | |
777 | | /****************************************************************************/ |
778 | | /* GetNextRawFeature() */ |
779 | | /****************************************************************************/ |
780 | | |
781 | | void OGRMiraMonLayer::GoToFieldOfMultipleRecord(MM_INTERNAL_FID iFID, |
782 | | MM_EXT_DBF_N_RECORDS nIRecord, |
783 | | MM_EXT_DBF_N_FIELDS nIField) |
784 | | |
785 | 574k | { |
786 | | // Not an error. Simply there are no features, but there are fields |
787 | 574k | if (!phMiraMonLayer->pMultRecordIndex) |
788 | 0 | return; |
789 | | |
790 | 574k | VSIFSeekL(phMiraMonLayer->pMMBDXP->pfDataBase, |
791 | 574k | phMiraMonLayer->pMultRecordIndex[iFID].offset + |
792 | 574k | (MM_FILE_OFFSET)nIRecord * |
793 | 574k | phMiraMonLayer->pMMBDXP->BytesPerRecord + |
794 | 574k | phMiraMonLayer->pMMBDXP->pField[nIField].AccumulatedBytes, |
795 | 574k | SEEK_SET); |
796 | 574k | } |
797 | | |
798 | | /****************************************************************************/ |
799 | | /* GetNextRawFeature() */ |
800 | | /****************************************************************************/ |
801 | | |
802 | | OGRFeature *OGRMiraMonLayer::GetNextRawFeature() |
803 | 19.4k | { |
804 | 19.4k | if (!phMiraMonLayer) |
805 | 0 | return nullptr; |
806 | | |
807 | 19.4k | if (m_iNextFID >= (GUInt64)phMiraMonLayer->TopHeader.nElemCount) |
808 | 203 | return nullptr; |
809 | | |
810 | 19.2k | OGRFeature *poFeature = GetFeature(m_iNextFID); |
811 | | |
812 | 19.2k | if (!poFeature) |
813 | 845 | return nullptr; |
814 | | |
815 | 18.4k | m_iNextFID++; |
816 | 18.4k | return poFeature; |
817 | 19.2k | } |
818 | | |
819 | | /****************************************************************************/ |
820 | | /* GetFeature() */ |
821 | | /****************************************************************************/ |
822 | | |
823 | | OGRFeature *OGRMiraMonLayer::GetFeature(GIntBig nFeatureId) |
824 | | |
825 | 19.2k | { |
826 | 19.2k | OGRGeometry *poGeom = nullptr; |
827 | 19.2k | OGRPoint *poPoint = nullptr; |
828 | 19.2k | OGRLineString *poLS = nullptr; |
829 | 19.2k | MM_INTERNAL_FID nIElem; |
830 | 19.2k | MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord = 0; |
831 | | |
832 | 19.2k | if (!phMiraMonLayer) |
833 | 0 | return nullptr; |
834 | | |
835 | 19.2k | if (nFeatureId < 0) |
836 | 0 | return nullptr; |
837 | | |
838 | 19.2k | if (phMiraMonLayer->bIsPolygon) |
839 | 538 | { |
840 | 538 | if (nFeatureId == GINTBIG_MAX) |
841 | 0 | return nullptr; |
842 | | |
843 | 538 | nIElem = (MM_INTERNAL_FID)(nFeatureId + 1); |
844 | 538 | } |
845 | 18.7k | else |
846 | 18.7k | nIElem = (MM_INTERNAL_FID)nFeatureId; |
847 | | |
848 | 19.2k | if (nIElem >= phMiraMonLayer->TopHeader.nElemCount) |
849 | 15 | return nullptr; |
850 | | |
851 | | /* -------------------------------------------------------------------- */ |
852 | | /* Read nFeatureId feature directly from the file. */ |
853 | | /* -------------------------------------------------------------------- */ |
854 | 19.2k | switch (phMiraMonLayer->eLT) |
855 | 19.2k | { |
856 | 13.6k | case MM_LayerType_Point: |
857 | 17.1k | case MM_LayerType_Point3d: |
858 | | // Read point |
859 | 17.1k | poGeom = new OGRPoint(); |
860 | 17.1k | poPoint = poGeom->toPoint(); |
861 | | |
862 | | // Get X,Y (z). MiraMon has no multipoints |
863 | 17.1k | if (MMGetGeoFeatureFromVector(phMiraMonLayer, nIElem)) |
864 | 432 | { |
865 | 432 | CPLError(CE_Failure, CPLE_AppDefined, "Wrong file format."); |
866 | 432 | delete poGeom; |
867 | 432 | return nullptr; |
868 | 432 | } |
869 | | |
870 | 16.6k | poPoint->setX(phMiraMonLayer->ReadFeature.pCoord[0].dfX); |
871 | 16.6k | poPoint->setY(phMiraMonLayer->ReadFeature.pCoord[0].dfY); |
872 | 16.6k | if (phMiraMonLayer->TopHeader.bIs3d) |
873 | 3.34k | poPoint->setZ(phMiraMonLayer->ReadFeature.pZCoord[0]); |
874 | 16.6k | break; |
875 | | |
876 | 571 | case MM_LayerType_Arc: |
877 | 1.60k | case MM_LayerType_Arc3d: |
878 | 1.60k | poGeom = new OGRLineString(); |
879 | 1.60k | poLS = poGeom->toLineString(); |
880 | | |
881 | | // Get X,Y (Z) n times MiraMon has no multilines |
882 | 1.60k | if (MMGetGeoFeatureFromVector(phMiraMonLayer, nIElem)) |
883 | 110 | { |
884 | 110 | CPLError(CE_Failure, CPLE_AppDefined, "Wrong file format."); |
885 | 110 | delete poGeom; |
886 | 110 | return nullptr; |
887 | 110 | } |
888 | | |
889 | 1.49k | for (MM_N_VERTICES_TYPE nIVrt = 0; |
890 | 13.0k | nIVrt < phMiraMonLayer->ReadFeature.pNCoordRing[0]; nIVrt++) |
891 | 11.5k | { |
892 | 11.5k | if (phMiraMonLayer->TopHeader.bIs3d) |
893 | 9.89k | poLS->addPoint( |
894 | 9.89k | phMiraMonLayer->ReadFeature.pCoord[nIVrt].dfX, |
895 | 9.89k | phMiraMonLayer->ReadFeature.pCoord[nIVrt].dfY, |
896 | 9.89k | phMiraMonLayer->ReadFeature.pZCoord[nIVrt]); |
897 | 1.66k | else |
898 | 1.66k | poLS->addPoint( |
899 | 1.66k | phMiraMonLayer->ReadFeature.pCoord[nIVrt].dfX, |
900 | 1.66k | phMiraMonLayer->ReadFeature.pCoord[nIVrt].dfY); |
901 | 11.5k | } |
902 | 1.49k | break; |
903 | | |
904 | 279 | case MM_LayerType_Pol: |
905 | 523 | case MM_LayerType_Pol3d: |
906 | | // Read polygon |
907 | 523 | auto poPoly = std::make_unique<OGRPolygon>(); |
908 | 523 | MM_POLYGON_RINGS_COUNT nIRing; |
909 | 523 | MM_N_VERTICES_TYPE nIVrtAcum; |
910 | | |
911 | 523 | if (phMiraMonLayer->TopHeader.bIsMultipolygon) |
912 | 229 | { |
913 | 229 | OGRMultiPolygon *poMP = nullptr; |
914 | | |
915 | 229 | poGeom = new OGRMultiPolygon(); |
916 | 229 | poMP = poGeom->toMultiPolygon(); |
917 | | |
918 | | // Get X,Y (Z) n times MiraMon has no multilines |
919 | 229 | if (MMGetGeoFeatureFromVector(phMiraMonLayer, nIElem)) |
920 | 114 | { |
921 | 114 | CPLError(CE_Failure, CPLE_AppDefined, "Wrong file format."); |
922 | 114 | delete poGeom; |
923 | 114 | return nullptr; |
924 | 114 | } |
925 | | |
926 | 115 | nIVrtAcum = 0; |
927 | 115 | if (!(phMiraMonLayer->ReadFeature.flag_VFG[0] & |
928 | 115 | MM_EXTERIOR_ARC_SIDE)) |
929 | 5 | { |
930 | 5 | CPLError(CE_Failure, CPLE_NoWriteAccess, |
931 | 5 | "Wrong polygon format."); |
932 | 5 | delete poGeom; |
933 | 5 | return nullptr; |
934 | 5 | } |
935 | | |
936 | 5.09k | for (nIRing = 0; nIRing < phMiraMonLayer->ReadFeature.nNRings; |
937 | 4.98k | nIRing++) |
938 | 4.98k | { |
939 | 4.98k | auto poRing = std::make_unique<OGRLinearRing>(); |
940 | | |
941 | 4.98k | for (MM_N_VERTICES_TYPE nIVrt = 0; |
942 | 44.6M | nIVrt < |
943 | 44.6M | phMiraMonLayer->ReadFeature.pNCoordRing[nIRing]; |
944 | 44.6M | nIVrt++) |
945 | 44.6M | { |
946 | 44.6M | if (phMiraMonLayer->TopHeader.bIs3d) |
947 | 3.84M | { |
948 | 3.84M | poRing->addPoint( |
949 | 3.84M | phMiraMonLayer->ReadFeature.pCoord[nIVrtAcum] |
950 | 3.84M | .dfX, |
951 | 3.84M | phMiraMonLayer->ReadFeature.pCoord[nIVrtAcum] |
952 | 3.84M | .dfY, |
953 | 3.84M | phMiraMonLayer->ReadFeature.pZCoord[nIVrtAcum]); |
954 | 3.84M | } |
955 | 40.7M | else |
956 | 40.7M | { |
957 | 40.7M | poRing->addPoint( |
958 | 40.7M | phMiraMonLayer->ReadFeature.pCoord[nIVrtAcum] |
959 | 40.7M | .dfX, |
960 | 40.7M | phMiraMonLayer->ReadFeature.pCoord[nIVrtAcum] |
961 | 40.7M | .dfY); |
962 | 40.7M | } |
963 | | |
964 | 44.6M | nIVrtAcum++; |
965 | 44.6M | } |
966 | | |
967 | | // If I'm going to start a new polygon... |
968 | 4.98k | if ((nIRing + 1 < phMiraMonLayer->ReadFeature.nNRings && |
969 | 4.98k | ((phMiraMonLayer->ReadFeature.flag_VFG[nIRing + 1]) & |
970 | 4.87k | MM_EXTERIOR_ARC_SIDE)) || |
971 | 4.98k | nIRing + 1 >= phMiraMonLayer->ReadFeature.nNRings) |
972 | 3.92k | { |
973 | 3.92k | poPoly->addRingDirectly(poRing.release()); |
974 | 3.92k | poMP->addGeometryDirectly(poPoly.release()); |
975 | 3.92k | poPoly = std::make_unique<OGRPolygon>(); |
976 | 3.92k | } |
977 | 1.05k | else |
978 | 1.05k | poPoly->addRingDirectly(poRing.release()); |
979 | 4.98k | } |
980 | 110 | } |
981 | 294 | else |
982 | 294 | { |
983 | 294 | OGRPolygon *poP = nullptr; |
984 | | |
985 | 294 | poGeom = new OGRPolygon(); |
986 | 294 | poP = poGeom->toPolygon(); |
987 | | |
988 | | // Get X,Y (Z) n times because MiraMon has no multilinetrings |
989 | 294 | if (MMGetGeoFeatureFromVector(phMiraMonLayer, nIElem)) |
990 | 167 | { |
991 | 167 | CPLError(CE_Failure, CPLE_AppDefined, "Wrong file format."); |
992 | 167 | delete poGeom; |
993 | 167 | return nullptr; |
994 | 167 | } |
995 | | |
996 | 127 | if (phMiraMonLayer->ReadFeature.nNRings && |
997 | 127 | phMiraMonLayer->ReadFeature.nNumpCoord) |
998 | 84 | { |
999 | 84 | nIVrtAcum = 0; |
1000 | 84 | if (!(phMiraMonLayer->ReadFeature.flag_VFG[0] & |
1001 | 84 | MM_EXTERIOR_ARC_SIDE)) |
1002 | 1 | { |
1003 | 1 | CPLError(CE_Failure, CPLE_AssertionFailed, |
1004 | 1 | "Wrong polygon format."); |
1005 | 1 | delete poGeom; |
1006 | 1 | return nullptr; |
1007 | 1 | } |
1008 | | |
1009 | 83 | for (nIRing = 0; |
1010 | 1.16k | nIRing < phMiraMonLayer->ReadFeature.nNRings; nIRing++) |
1011 | 1.07k | { |
1012 | 1.07k | auto poRing = std::make_unique<OGRLinearRing>(); |
1013 | | |
1014 | 1.07k | for (MM_N_VERTICES_TYPE nIVrt = 0; |
1015 | 861k | nIVrt < |
1016 | 861k | phMiraMonLayer->ReadFeature.pNCoordRing[nIRing]; |
1017 | 859k | nIVrt++) |
1018 | 859k | { |
1019 | 859k | if (phMiraMonLayer->TopHeader.bIs3d) |
1020 | 818k | { |
1021 | 818k | poRing->addPoint(phMiraMonLayer->ReadFeature |
1022 | 818k | .pCoord[nIVrtAcum] |
1023 | 818k | .dfX, |
1024 | 818k | phMiraMonLayer->ReadFeature |
1025 | 818k | .pCoord[nIVrtAcum] |
1026 | 818k | .dfY, |
1027 | 818k | phMiraMonLayer->ReadFeature |
1028 | 818k | .pZCoord[nIVrtAcum]); |
1029 | 818k | } |
1030 | 41.3k | else |
1031 | 41.3k | { |
1032 | 41.3k | poRing->addPoint(phMiraMonLayer->ReadFeature |
1033 | 41.3k | .pCoord[nIVrtAcum] |
1034 | 41.3k | .dfX, |
1035 | 41.3k | phMiraMonLayer->ReadFeature |
1036 | 41.3k | .pCoord[nIVrtAcum] |
1037 | 41.3k | .dfY); |
1038 | 41.3k | } |
1039 | | |
1040 | 859k | nIVrtAcum++; |
1041 | 859k | } |
1042 | 1.07k | poP->addRingDirectly(poRing.release()); |
1043 | 1.07k | } |
1044 | 83 | } |
1045 | 127 | } |
1046 | | |
1047 | 236 | break; |
1048 | 19.2k | } |
1049 | | |
1050 | 18.4k | if (poGeom == nullptr) |
1051 | 0 | return nullptr; |
1052 | | |
1053 | | /* -------------------------------------------------------------------- */ |
1054 | | /* Create feature. */ |
1055 | | /* -------------------------------------------------------------------- */ |
1056 | 18.4k | auto poFeature = std::make_unique<OGRFeature>(m_poFeatureDefn); |
1057 | 18.4k | poGeom->assignSpatialReference(m_poSRS); |
1058 | 18.4k | poFeature->SetGeometryDirectly(poGeom); |
1059 | | |
1060 | | /* -------------------------------------------------------------------- */ |
1061 | | /* Process field values if its possible. */ |
1062 | | /* -------------------------------------------------------------------- */ |
1063 | 18.4k | if (phMiraMonLayer->pMMBDXP && |
1064 | 18.4k | (MM_EXT_DBF_N_RECORDS)nIElem < phMiraMonLayer->pMMBDXP->nRecords) |
1065 | 12.8k | { |
1066 | 12.8k | MM_EXT_DBF_N_FIELDS nIField; |
1067 | | |
1068 | 319k | for (nIField = 0; nIField < phMiraMonLayer->pMMBDXP->nFields; nIField++) |
1069 | 306k | { |
1070 | 306k | if (MMResizeStringToOperateIfNeeded( |
1071 | 306k | phMiraMonLayer, |
1072 | 306k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField + 1)) |
1073 | 1 | { |
1074 | 1 | return nullptr; |
1075 | 1 | } |
1076 | | |
1077 | 306k | if (poFeature->GetDefnRef()->GetFieldDefn(nIField)->GetType() == |
1078 | 306k | OFTStringList || |
1079 | 306k | (poFeature->GetDefnRef()->GetFieldDefn(nIField)->GetType() == |
1080 | 302k | OFTString && |
1081 | 302k | poFeature->GetDefnRef()->GetFieldDefn(nIField)->GetSubType() == |
1082 | 248k | OFSTJSON)) |
1083 | 4.22k | { |
1084 | 4.22k | if (!phMiraMonLayer->pMultRecordIndex || |
1085 | 4.22k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1086 | 3.60k | { |
1087 | 3.60k | memset( |
1088 | 3.60k | phMiraMonLayer->szStringToOperate, 0, |
1089 | 3.60k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1090 | 3.60k | continue; |
1091 | 3.60k | } |
1092 | 624 | if (poFeature->GetDefnRef() |
1093 | 624 | ->GetFieldDefn(nIField) |
1094 | 624 | ->GetSubType() == OFSTJSON) |
1095 | 0 | { |
1096 | 0 | if (MMResizeStringToOperateIfNeeded( |
1097 | 0 | phMiraMonLayer, |
1098 | 0 | phMiraMonLayer->pMMBDXP->BytesPerRecord + |
1099 | 0 | 2 * phMiraMonLayer->pMultRecordIndex[nIElem] |
1100 | 0 | .nMR + |
1101 | 0 | 8)) |
1102 | 0 | { |
1103 | 0 | return nullptr; |
1104 | 0 | } |
1105 | 0 | std::string szStringToOperate = "["; |
1106 | 0 | for (nIRecord = 0; |
1107 | 0 | nIRecord < |
1108 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR; |
1109 | 0 | nIRecord++) |
1110 | 0 | { |
1111 | 0 | GoToFieldOfMultipleRecord(nIElem, nIRecord, nIField); |
1112 | |
|
1113 | 0 | VSIFReadL(phMiraMonLayer->szStringToOperate, |
1114 | 0 | phMiraMonLayer->pMMBDXP->pField[nIField] |
1115 | 0 | .BytesPerField, |
1116 | 0 | 1, phMiraMonLayer->pMMBDXP->pfDataBase); |
1117 | 0 | phMiraMonLayer |
1118 | 0 | ->szStringToOperate[phMiraMonLayer->pMMBDXP |
1119 | 0 | ->pField[nIField] |
1120 | 0 | .BytesPerField] = '\0'; |
1121 | 0 | MM_RemoveLeadingWhitespaceOfString( |
1122 | 0 | phMiraMonLayer->szStringToOperate); |
1123 | 0 | MM_RemoveWhitespacesFromEndOfString( |
1124 | 0 | phMiraMonLayer->szStringToOperate); |
1125 | |
|
1126 | 0 | if (phMiraMonLayer->pMMBDXP->CharSet == |
1127 | 0 | MM_JOC_CARAC_OEM850_DBASE) |
1128 | 0 | MM_oemansi_n( |
1129 | 0 | phMiraMonLayer->szStringToOperate, |
1130 | 0 | phMiraMonLayer->pMMBDXP->pField[nIField] |
1131 | 0 | .BytesPerField); |
1132 | |
|
1133 | 0 | if (phMiraMonLayer->pMMBDXP->CharSet != |
1134 | 0 | MM_JOC_CARAC_UTF8_DBF) |
1135 | 0 | { |
1136 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8 |
1137 | 0 | char *pszString = |
1138 | 0 | CPLRecode(phMiraMonLayer->szStringToOperate, |
1139 | 0 | CPL_ENC_ISO8859_1, CPL_ENC_UTF8); |
1140 | |
|
1141 | 0 | CPLStrlcpy( |
1142 | 0 | phMiraMonLayer->szStringToOperate, pszString, |
1143 | 0 | (size_t)phMiraMonLayer->pMMBDXP->pField[nIField] |
1144 | 0 | .BytesPerField + |
1145 | 0 | 1); |
1146 | |
|
1147 | 0 | CPLFree(pszString); |
1148 | 0 | } |
1149 | 0 | szStringToOperate.append( |
1150 | 0 | phMiraMonLayer->szStringToOperate); |
1151 | |
|
1152 | 0 | if (nIRecord < |
1153 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR - 1) |
1154 | 0 | { |
1155 | 0 | szStringToOperate.append(","); |
1156 | 0 | } |
1157 | 0 | else |
1158 | 0 | { |
1159 | 0 | szStringToOperate.append("]"); |
1160 | 0 | } |
1161 | 0 | } |
1162 | 0 | poFeature->SetField(nIField, szStringToOperate.c_str()); |
1163 | 0 | } |
1164 | 624 | else |
1165 | 624 | { |
1166 | 624 | CPLStringList aosValues; |
1167 | 624 | for (nIRecord = 0; |
1168 | 355k | nIRecord < |
1169 | 355k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR; |
1170 | 354k | nIRecord++) |
1171 | 354k | { |
1172 | 354k | GoToFieldOfMultipleRecord(nIElem, nIRecord, nIField); |
1173 | 354k | memset(phMiraMonLayer->szStringToOperate, 0, |
1174 | 354k | phMiraMonLayer->pMMBDXP->pField[nIField] |
1175 | 354k | .BytesPerField); |
1176 | 354k | VSIFReadL(phMiraMonLayer->szStringToOperate, |
1177 | 354k | phMiraMonLayer->pMMBDXP->pField[nIField] |
1178 | 354k | .BytesPerField, |
1179 | 354k | 1, phMiraMonLayer->pMMBDXP->pfDataBase); |
1180 | 354k | phMiraMonLayer |
1181 | 354k | ->szStringToOperate[phMiraMonLayer->pMMBDXP |
1182 | 354k | ->pField[nIField] |
1183 | 354k | .BytesPerField] = '\0'; |
1184 | 354k | MM_RemoveWhitespacesFromEndOfString( |
1185 | 354k | phMiraMonLayer->szStringToOperate); |
1186 | | |
1187 | 354k | if (phMiraMonLayer->pMMBDXP->CharSet == |
1188 | 354k | MM_JOC_CARAC_OEM850_DBASE) |
1189 | 104k | MM_oemansi_n( |
1190 | 104k | phMiraMonLayer->szStringToOperate, |
1191 | 104k | phMiraMonLayer->pMMBDXP->pField[nIField] |
1192 | 104k | .BytesPerField); |
1193 | | |
1194 | 354k | if (phMiraMonLayer->pMMBDXP->CharSet != |
1195 | 354k | MM_JOC_CARAC_UTF8_DBF) |
1196 | 352k | { |
1197 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8 |
1198 | 352k | char *pszString = |
1199 | 352k | CPLRecode(phMiraMonLayer->szStringToOperate, |
1200 | 352k | CPL_ENC_ISO8859_1, CPL_ENC_UTF8); |
1201 | | |
1202 | 352k | CPLStrlcpy( |
1203 | 352k | phMiraMonLayer->szStringToOperate, pszString, |
1204 | 352k | (size_t)phMiraMonLayer->pMMBDXP->pField[nIField] |
1205 | 352k | .BytesPerField + |
1206 | 352k | 1); |
1207 | | |
1208 | 352k | CPLFree(pszString); |
1209 | 352k | } |
1210 | 354k | aosValues.AddString(phMiraMonLayer->szStringToOperate); |
1211 | 354k | } |
1212 | 624 | poFeature->SetField(nIField, aosValues.List()); |
1213 | 624 | } |
1214 | 624 | } |
1215 | 302k | else if (poFeature->GetDefnRef() |
1216 | 302k | ->GetFieldDefn(nIField) |
1217 | 302k | ->GetType() == OFTString) |
1218 | 248k | { |
1219 | 248k | if (!phMiraMonLayer->pMultRecordIndex || |
1220 | 248k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1221 | 246k | { |
1222 | 246k | memset( |
1223 | 246k | phMiraMonLayer->szStringToOperate, 0, |
1224 | 246k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1225 | 246k | continue; |
1226 | 246k | } |
1227 | 2.24k | if (phMiraMonLayer->iMultiRecord != |
1228 | 2.24k | MM_MULTIRECORD_NO_MULTIRECORD) |
1229 | 0 | { |
1230 | 0 | if (phMiraMonLayer->iMultiRecord == MM_MULTIRECORD_LAST) |
1231 | 0 | GoToFieldOfMultipleRecord( |
1232 | 0 | nIElem, |
1233 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR - 1, |
1234 | 0 | nIField); |
1235 | 0 | else if ((MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1236 | 0 | phMiraMonLayer->iMultiRecord < |
1237 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR) |
1238 | 0 | GoToFieldOfMultipleRecord( |
1239 | 0 | nIElem, |
1240 | 0 | (MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1241 | 0 | phMiraMonLayer->iMultiRecord, |
1242 | 0 | nIField); |
1243 | 0 | else |
1244 | 0 | { |
1245 | 0 | memset(phMiraMonLayer->szStringToOperate, 0, |
1246 | 0 | phMiraMonLayer->pMMBDXP->pField[nIField] |
1247 | 0 | .BytesPerField); |
1248 | 0 | continue; |
1249 | 0 | } |
1250 | 0 | } |
1251 | 2.24k | else |
1252 | 2.24k | GoToFieldOfMultipleRecord(nIElem, 0, nIField); |
1253 | | |
1254 | 2.24k | memset(phMiraMonLayer->szStringToOperate, 0, |
1255 | 2.24k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1256 | 2.24k | VSIFReadL( |
1257 | 2.24k | phMiraMonLayer->szStringToOperate, |
1258 | 2.24k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField, 1, |
1259 | 2.24k | phMiraMonLayer->pMMBDXP->pfDataBase); |
1260 | 2.24k | phMiraMonLayer |
1261 | 2.24k | ->szStringToOperate[phMiraMonLayer->pMMBDXP->pField[nIField] |
1262 | 2.24k | .BytesPerField] = '\0'; |
1263 | 2.24k | MM_RemoveWhitespacesFromEndOfString( |
1264 | 2.24k | phMiraMonLayer->szStringToOperate); |
1265 | | |
1266 | 2.24k | if (phMiraMonLayer->pMMBDXP->CharSet == |
1267 | 2.24k | MM_JOC_CARAC_OEM850_DBASE) |
1268 | 616 | MM_oemansi(phMiraMonLayer->szStringToOperate); |
1269 | | |
1270 | 2.24k | if (phMiraMonLayer->pMMBDXP->CharSet != MM_JOC_CARAC_UTF8_DBF) |
1271 | 1.31k | { |
1272 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8 |
1273 | 1.31k | char *pszString = |
1274 | 1.31k | CPLRecode(phMiraMonLayer->szStringToOperate, |
1275 | 1.31k | CPL_ENC_ISO8859_1, CPL_ENC_UTF8); |
1276 | 1.31k | CPLStrlcpy(phMiraMonLayer->szStringToOperate, pszString, |
1277 | 1.31k | (size_t)phMiraMonLayer->pMMBDXP->pField[nIField] |
1278 | 1.31k | .BytesPerField + |
1279 | 1.31k | 1); |
1280 | 1.31k | CPLFree(pszString); |
1281 | 1.31k | } |
1282 | 2.24k | poFeature->SetField(nIField, phMiraMonLayer->szStringToOperate); |
1283 | 2.24k | } |
1284 | 53.8k | else if (poFeature->GetDefnRef() |
1285 | 53.8k | ->GetFieldDefn(nIField) |
1286 | 53.8k | ->GetType() == OFTIntegerList || |
1287 | 53.8k | poFeature->GetDefnRef() |
1288 | 44.6k | ->GetFieldDefn(nIField) |
1289 | 44.6k | ->GetType() == OFTRealList) |
1290 | 11.6k | { |
1291 | 11.6k | if (!phMiraMonLayer->pMultRecordIndex || |
1292 | 11.6k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1293 | 9.20k | { |
1294 | 9.20k | memset( |
1295 | 9.20k | phMiraMonLayer->szStringToOperate, 0, |
1296 | 9.20k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1297 | 9.20k | continue; |
1298 | 9.20k | } |
1299 | 2.39k | MM_EXT_DBF_N_MULTIPLE_RECORDS nRealMR = 0; |
1300 | 2.39k | for (nIRecord = 0; |
1301 | 159k | nIRecord < phMiraMonLayer->pMultRecordIndex[nIElem].nMR; |
1302 | 157k | nIRecord++) |
1303 | 157k | { |
1304 | 157k | GoToFieldOfMultipleRecord(nIElem, nIRecord, nIField); |
1305 | 157k | memset( |
1306 | 157k | phMiraMonLayer->szStringToOperate, 0, |
1307 | 157k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1308 | 157k | VSIFReadL( |
1309 | 157k | phMiraMonLayer->szStringToOperate, |
1310 | 157k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField, |
1311 | 157k | 1, phMiraMonLayer->pMMBDXP->pfDataBase); |
1312 | 157k | phMiraMonLayer->szStringToOperate[phMiraMonLayer->pMMBDXP |
1313 | 157k | ->pField[nIField] |
1314 | 157k | .BytesPerField] = |
1315 | 157k | '\0'; |
1316 | | |
1317 | 157k | if (!MMIsEmptyString(phMiraMonLayer->szStringToOperate)) |
1318 | 155k | { |
1319 | 155k | if (poFeature->GetDefnRef() |
1320 | 155k | ->GetFieldDefn(nIField) |
1321 | 155k | ->GetType() == OFTIntegerList && |
1322 | 155k | poFeature->GetDefnRef() |
1323 | 135k | ->GetFieldDefn(nIField) |
1324 | 135k | ->GetSubType() == OFSTBoolean) |
1325 | 65.4k | { |
1326 | 65.4k | if (*phMiraMonLayer->szStringToOperate == 'T' || |
1327 | 65.4k | *phMiraMonLayer->szStringToOperate == 'S' || |
1328 | 65.4k | *phMiraMonLayer->szStringToOperate == 'Y') |
1329 | 191 | padfValues[nRealMR] = 1; |
1330 | 65.2k | else |
1331 | 65.2k | padfValues[nRealMR] = 0; |
1332 | 65.4k | } |
1333 | 89.7k | else |
1334 | 89.7k | { |
1335 | 89.7k | padfValues[nRealMR] = |
1336 | 89.7k | atof(phMiraMonLayer->szStringToOperate); |
1337 | 89.7k | } |
1338 | 155k | nRealMR++; |
1339 | 155k | } |
1340 | 157k | } |
1341 | | |
1342 | 2.39k | poFeature->SetField(nIField, nRealMR, padfValues); |
1343 | 2.39k | } |
1344 | 42.2k | else if (poFeature->GetDefnRef() |
1345 | 42.2k | ->GetFieldDefn(nIField) |
1346 | 42.2k | ->GetType() == OFTInteger64List) |
1347 | 1.27k | { |
1348 | 1.27k | if (!phMiraMonLayer->pMultRecordIndex || |
1349 | 1.27k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1350 | 1.00k | { |
1351 | 1.00k | memset( |
1352 | 1.00k | phMiraMonLayer->szStringToOperate, 0, |
1353 | 1.00k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1354 | 1.00k | continue; |
1355 | 1.00k | } |
1356 | 275 | MM_EXT_DBF_N_MULTIPLE_RECORDS nRealMR = 0; |
1357 | 275 | for (nIRecord = 0; |
1358 | 55.7k | nIRecord < phMiraMonLayer->pMultRecordIndex[nIElem].nMR; |
1359 | 55.5k | nIRecord++) |
1360 | 55.5k | { |
1361 | 55.5k | GoToFieldOfMultipleRecord(nIElem, nIRecord, nIField); |
1362 | 55.5k | memset( |
1363 | 55.5k | phMiraMonLayer->szStringToOperate, 0, |
1364 | 55.5k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1365 | 55.5k | VSIFReadL( |
1366 | 55.5k | phMiraMonLayer->szStringToOperate, |
1367 | 55.5k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField, |
1368 | 55.5k | 1, phMiraMonLayer->pMMBDXP->pfDataBase); |
1369 | 55.5k | phMiraMonLayer->szStringToOperate[phMiraMonLayer->pMMBDXP |
1370 | 55.5k | ->pField[nIField] |
1371 | 55.5k | .BytesPerField] = |
1372 | 55.5k | '\0'; |
1373 | | |
1374 | 55.5k | if (!MMIsEmptyString(phMiraMonLayer->szStringToOperate)) |
1375 | 55.1k | { |
1376 | 55.1k | pnInt64Values[nRealMR] = |
1377 | 55.1k | CPLAtoGIntBig(phMiraMonLayer->szStringToOperate); |
1378 | 55.1k | nRealMR++; |
1379 | 55.1k | } |
1380 | 55.5k | } |
1381 | | |
1382 | 275 | poFeature->SetField(nIField, nRealMR, pnInt64Values); |
1383 | 275 | } |
1384 | 40.9k | else if (poFeature->GetDefnRef() |
1385 | 40.9k | ->GetFieldDefn(nIField) |
1386 | 40.9k | ->GetType() == OFTInteger || |
1387 | 40.9k | poFeature->GetDefnRef() |
1388 | 24.3k | ->GetFieldDefn(nIField) |
1389 | 24.3k | ->GetType() == OFTInteger64 || |
1390 | 40.9k | poFeature->GetDefnRef() |
1391 | 18.8k | ->GetFieldDefn(nIField) |
1392 | 18.8k | ->GetType() == OFTReal) |
1393 | 37.6k | { |
1394 | 37.6k | if (!phMiraMonLayer->pMultRecordIndex || |
1395 | 37.6k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1396 | 33.3k | { |
1397 | 33.3k | memset( |
1398 | 33.3k | phMiraMonLayer->szStringToOperate, 0, |
1399 | 33.3k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1400 | 33.3k | continue; |
1401 | 33.3k | } |
1402 | 4.32k | if (phMiraMonLayer->iMultiRecord != |
1403 | 4.32k | MM_MULTIRECORD_NO_MULTIRECORD) |
1404 | 0 | { |
1405 | 0 | if (phMiraMonLayer->iMultiRecord == MM_MULTIRECORD_LAST) |
1406 | 0 | { |
1407 | 0 | GoToFieldOfMultipleRecord( |
1408 | 0 | nIElem, |
1409 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR - 1, |
1410 | 0 | nIField); |
1411 | 0 | } |
1412 | 0 | else if ((MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1413 | 0 | phMiraMonLayer->iMultiRecord < |
1414 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR) |
1415 | 0 | { |
1416 | 0 | GoToFieldOfMultipleRecord( |
1417 | 0 | nIElem, |
1418 | 0 | (MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1419 | 0 | phMiraMonLayer->iMultiRecord, |
1420 | 0 | nIField); |
1421 | 0 | } |
1422 | 0 | else |
1423 | 0 | { |
1424 | 0 | memset(phMiraMonLayer->szStringToOperate, 0, |
1425 | 0 | phMiraMonLayer->pMMBDXP->pField[nIField] |
1426 | 0 | .BytesPerField); |
1427 | 0 | continue; |
1428 | 0 | } |
1429 | 0 | } |
1430 | 4.32k | else |
1431 | 4.32k | GoToFieldOfMultipleRecord(nIElem, 0, nIField); |
1432 | | |
1433 | 4.32k | memset(phMiraMonLayer->szStringToOperate, 0, |
1434 | 4.32k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1435 | 4.32k | VSIFReadL( |
1436 | 4.32k | phMiraMonLayer->szStringToOperate, |
1437 | 4.32k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField, 1, |
1438 | 4.32k | phMiraMonLayer->pMMBDXP->pfDataBase); |
1439 | 4.32k | phMiraMonLayer |
1440 | 4.32k | ->szStringToOperate[phMiraMonLayer->pMMBDXP->pField[nIField] |
1441 | 4.32k | .BytesPerField] = '\0'; |
1442 | 4.32k | MM_RemoveWhitespacesFromEndOfString( |
1443 | 4.32k | phMiraMonLayer->szStringToOperate); |
1444 | | |
1445 | 4.32k | if (poFeature->GetDefnRef()->GetFieldDefn(nIField)->GetType() == |
1446 | 4.32k | OFTInteger64) |
1447 | 374 | { |
1448 | 374 | poFeature->SetField( |
1449 | 374 | nIField, |
1450 | 374 | CPLAtoGIntBig(phMiraMonLayer->szStringToOperate)); |
1451 | 374 | } |
1452 | 3.95k | else |
1453 | 3.95k | { |
1454 | 3.95k | if (poFeature->GetDefnRef() |
1455 | 3.95k | ->GetFieldDefn(nIField) |
1456 | 3.95k | ->GetType() == OFTInteger && |
1457 | 3.95k | poFeature->GetDefnRef() |
1458 | 3.29k | ->GetFieldDefn(nIField) |
1459 | 3.29k | ->GetSubType() == OFSTBoolean) |
1460 | 904 | { |
1461 | 904 | if (*phMiraMonLayer->szStringToOperate == 'T' || |
1462 | 904 | *phMiraMonLayer->szStringToOperate == 'S' || |
1463 | 904 | *phMiraMonLayer->szStringToOperate == 'Y') |
1464 | 244 | poFeature->SetField(nIField, 1); |
1465 | 660 | else |
1466 | 660 | poFeature->SetField(nIField, 0); |
1467 | 904 | } |
1468 | 3.04k | else |
1469 | 3.04k | { |
1470 | 3.04k | poFeature->SetField( |
1471 | 3.04k | nIField, atof(phMiraMonLayer->szStringToOperate)); |
1472 | 3.04k | } |
1473 | 3.95k | } |
1474 | 4.32k | } |
1475 | 3.28k | else if (poFeature->GetDefnRef() |
1476 | 3.28k | ->GetFieldDefn(nIField) |
1477 | 3.28k | ->GetType() == OFTDate) |
1478 | 3.28k | { |
1479 | 3.28k | if (!phMiraMonLayer->pMultRecordIndex || |
1480 | 3.28k | phMiraMonLayer->pMultRecordIndex[nIElem].nMR == 0) |
1481 | 2.82k | { |
1482 | 2.82k | memset( |
1483 | 2.82k | phMiraMonLayer->szStringToOperate, 0, |
1484 | 2.82k | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1485 | 2.82k | continue; |
1486 | 2.82k | } |
1487 | 462 | if (phMiraMonLayer->iMultiRecord != |
1488 | 462 | MM_MULTIRECORD_NO_MULTIRECORD) |
1489 | 0 | { |
1490 | 0 | if (phMiraMonLayer->iMultiRecord == MM_MULTIRECORD_LAST) |
1491 | 0 | GoToFieldOfMultipleRecord( |
1492 | 0 | nIElem, |
1493 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR - 1, |
1494 | 0 | nIField); |
1495 | 0 | else if ((MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1496 | 0 | phMiraMonLayer->iMultiRecord < |
1497 | 0 | phMiraMonLayer->pMultRecordIndex[nIElem].nMR) |
1498 | 0 | GoToFieldOfMultipleRecord( |
1499 | 0 | nIElem, |
1500 | 0 | (MM_EXT_DBF_N_MULTIPLE_RECORDS) |
1501 | 0 | phMiraMonLayer->iMultiRecord, |
1502 | 0 | nIField); |
1503 | 0 | else |
1504 | 0 | { |
1505 | 0 | memset(phMiraMonLayer->szStringToOperate, 0, |
1506 | 0 | phMiraMonLayer->pMMBDXP->pField[nIField] |
1507 | 0 | .BytesPerField); |
1508 | 0 | continue; |
1509 | 0 | } |
1510 | 0 | } |
1511 | 462 | else |
1512 | 462 | GoToFieldOfMultipleRecord(nIElem, 0, nIField); |
1513 | | |
1514 | 462 | memset(phMiraMonLayer->szStringToOperate, 0, |
1515 | 462 | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField); |
1516 | 462 | VSIFReadL( |
1517 | 462 | phMiraMonLayer->szStringToOperate, |
1518 | 462 | phMiraMonLayer->pMMBDXP->pField[nIField].BytesPerField, 1, |
1519 | 462 | phMiraMonLayer->pMMBDXP->pfDataBase); |
1520 | 462 | phMiraMonLayer |
1521 | 462 | ->szStringToOperate[phMiraMonLayer->pMMBDXP->pField[nIField] |
1522 | 462 | .BytesPerField] = '\0'; |
1523 | | |
1524 | 462 | MM_RemoveWhitespacesFromEndOfString( |
1525 | 462 | phMiraMonLayer->szStringToOperate); |
1526 | 462 | if (!MMIsEmptyString(phMiraMonLayer->szStringToOperate)) |
1527 | 293 | { |
1528 | 293 | char pszDate_5[5]; |
1529 | 293 | char pszDate_3[3]; |
1530 | 293 | int Year, Month, Day; |
1531 | | |
1532 | 293 | CPLStrlcpy(pszDate_5, phMiraMonLayer->szStringToOperate, 5); |
1533 | 293 | pszDate_5[4] = '\0'; |
1534 | 293 | Year = atoi(pszDate_5); |
1535 | | |
1536 | 293 | CPLStrlcpy(pszDate_3, phMiraMonLayer->szStringToOperate + 4, |
1537 | 293 | 3); |
1538 | 293 | (pszDate_3)[2] = '\0'; |
1539 | 293 | Month = atoi(pszDate_3); |
1540 | | |
1541 | 293 | CPLStrlcpy(pszDate_3, phMiraMonLayer->szStringToOperate + 6, |
1542 | 293 | 3); |
1543 | 293 | (pszDate_3)[2] = '\0'; |
1544 | 293 | Day = atoi(pszDate_3); |
1545 | | |
1546 | 293 | poFeature->SetField(nIField, Year, Month, Day); |
1547 | 293 | } |
1548 | 169 | else |
1549 | 169 | poFeature->SetField(nIField, |
1550 | 169 | phMiraMonLayer->szStringToOperate); |
1551 | 462 | } |
1552 | 306k | } |
1553 | 12.8k | } |
1554 | | |
1555 | | // Even in case of polygons, where the first feature is jumped |
1556 | | // the ID of the first feature has to be 0, the second, 1,... |
1557 | 18.4k | poFeature->SetFID(nFeatureId); |
1558 | | |
1559 | 18.4k | m_nFeaturesRead++; |
1560 | 18.4k | return poFeature.release(); |
1561 | 18.4k | } |
1562 | | |
1563 | | /****************************************************************************/ |
1564 | | /* GetFeatureCount() */ |
1565 | | /****************************************************************************/ |
1566 | | GIntBig OGRMiraMonLayer::GetFeatureCount(int bForce) |
1567 | 0 | { |
1568 | 0 | if (!phMiraMonLayer || m_poFilterGeom != nullptr || |
1569 | 0 | m_poAttrQuery != nullptr) |
1570 | 0 | return OGRLayer::GetFeatureCount(bForce); |
1571 | | |
1572 | 0 | if (phMiraMonLayer->bIsPolygon) |
1573 | 0 | { |
1574 | 0 | return std::max((GIntBig)0, |
1575 | 0 | (GIntBig)(phMiraMonLayer->TopHeader.nElemCount - 1)); |
1576 | 0 | } |
1577 | 0 | return (GIntBig)phMiraMonLayer->TopHeader.nElemCount; |
1578 | 0 | } |
1579 | | |
1580 | | /****************************************************************************/ |
1581 | | /* MMProcessMultiGeometry() */ |
1582 | | /****************************************************************************/ |
1583 | | OGRErr OGRMiraMonLayer::MMProcessMultiGeometry(OGRGeometryH hGeom, |
1584 | | OGRFeature *poFeature) |
1585 | | |
1586 | 1.14k | { |
1587 | 1.14k | OGRErr eErr = OGRERR_NONE; |
1588 | 1.14k | OGRGeometry *poGeom = OGRGeometry::FromHandle(hGeom); |
1589 | | |
1590 | 1.14k | if (poGeom == nullptr) |
1591 | 0 | { |
1592 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
1593 | 0 | "Features without geometry not supported by MiraMon writer."); |
1594 | 0 | return OGRERR_FAILURE; |
1595 | 0 | } |
1596 | | |
1597 | | // Multigeometry field processing (just in case of a MG inside a MG) |
1598 | 1.14k | if (wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection) |
1599 | 0 | { |
1600 | 0 | int nGeom = OGR_G_GetGeometryCount(OGRGeometry::ToHandle(poGeom)); |
1601 | 0 | for (int iGeom = 0; iGeom < nGeom; iGeom++) |
1602 | 0 | { |
1603 | 0 | OGRGeometryH poSubGeometry = |
1604 | 0 | OGR_G_GetGeometryRef(OGRGeometry::ToHandle(poGeom), iGeom); |
1605 | 0 | eErr = MMProcessMultiGeometry(poSubGeometry, poFeature); |
1606 | 0 | if (eErr != OGRERR_NONE) |
1607 | 0 | return eErr; |
1608 | 0 | } |
1609 | 0 | return eErr; |
1610 | 0 | } |
1611 | | // Converting multilines and multi points to simple ones |
1612 | 1.14k | if (wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString || |
1613 | 1.14k | wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint) |
1614 | 262 | { |
1615 | 262 | int nGeom = OGR_G_GetGeometryCount(OGRGeometry::ToHandle(poGeom)); |
1616 | 286 | for (int iGeom = 0; iGeom < nGeom; iGeom++) |
1617 | 24 | { |
1618 | 24 | OGRGeometryH poSubGeometry = |
1619 | 24 | OGR_G_GetGeometryRef(OGRGeometry::ToHandle(poGeom), iGeom); |
1620 | 24 | eErr = MMProcessGeometry(poSubGeometry, poFeature, (iGeom == 0)); |
1621 | 24 | if (eErr != OGRERR_NONE) |
1622 | 0 | return eErr; |
1623 | 24 | } |
1624 | 262 | return eErr; |
1625 | 262 | } |
1626 | | |
1627 | | // Processing a simple geometry |
1628 | 884 | return MMProcessGeometry(OGRGeometry::ToHandle(poGeom), poFeature, TRUE); |
1629 | 1.14k | } |
1630 | | |
1631 | | /****************************************************************************/ |
1632 | | /* MMProcessGeometry() */ |
1633 | | /****************************************************************************/ |
1634 | | OGRErr OGRMiraMonLayer::MMProcessGeometry(OGRGeometryH hGeom, |
1635 | | OGRFeature *poFeature, |
1636 | | MM_BOOLEAN bcalculateRecord) |
1637 | | |
1638 | 345k | { |
1639 | 345k | OGRErr eErr = OGRERR_NONE; |
1640 | 345k | OGRGeometry *poGeom = nullptr; |
1641 | 345k | if (hGeom) |
1642 | 908 | { |
1643 | 908 | poGeom = OGRGeometry::FromHandle(hGeom); |
1644 | | |
1645 | | // Translating types from GDAL to MiraMon |
1646 | 908 | int eLT = poGeom->getGeometryType(); |
1647 | 908 | switch (wkbFlatten(eLT)) |
1648 | 908 | { |
1649 | 296 | case wkbPoint: |
1650 | 296 | phMiraMonLayer = &hMiraMonLayerPNT; |
1651 | 296 | if (OGR_G_Is3D(hGeom)) |
1652 | 29 | phMiraMonLayer->eLT = MM_LayerType_Point3d; |
1653 | 267 | else |
1654 | 267 | phMiraMonLayer->eLT = MM_LayerType_Point; |
1655 | 296 | break; |
1656 | 273 | case wkbLineString: |
1657 | 273 | phMiraMonLayer = &hMiraMonLayerARC; |
1658 | 273 | if (OGR_G_Is3D(hGeom)) |
1659 | 41 | phMiraMonLayer->eLT = MM_LayerType_Arc3d; |
1660 | 232 | else |
1661 | 232 | phMiraMonLayer->eLT = MM_LayerType_Arc; |
1662 | 273 | break; |
1663 | 242 | case wkbPolygon: |
1664 | 291 | case wkbMultiPolygon: |
1665 | 298 | case wkbPolyhedralSurface: |
1666 | 305 | case wkbTIN: |
1667 | 309 | case wkbTriangle: |
1668 | 309 | phMiraMonLayer = &hMiraMonLayerPOL; |
1669 | 309 | if (OGR_G_Is3D(hGeom)) |
1670 | 38 | phMiraMonLayer->eLT = MM_LayerType_Pol3d; |
1671 | 271 | else |
1672 | 271 | phMiraMonLayer->eLT = MM_LayerType_Pol; |
1673 | 309 | break; |
1674 | 0 | case wkbUnknown: |
1675 | 30 | default: |
1676 | 30 | { |
1677 | 30 | CPLError(CE_Warning, CPLE_NotSupported, |
1678 | 30 | "MiraMon " |
1679 | 30 | "does not support geometry type '%d'", |
1680 | 30 | eLT); |
1681 | 30 | return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; |
1682 | 0 | } |
1683 | 908 | } |
1684 | 908 | } |
1685 | 344k | else |
1686 | 344k | { |
1687 | | // Processing only the table. A DBF will be generated |
1688 | 344k | phMiraMonLayer = &hMiraMonLayerReadOrNonGeom; |
1689 | 344k | phMiraMonLayer->eLT = MM_LayerType_Unknown; |
1690 | 344k | } |
1691 | | |
1692 | | /* -------------------------------------------------------------------- */ |
1693 | | /* Field translation from GDAL to MiraMon */ |
1694 | | /* -------------------------------------------------------------------- */ |
1695 | | // Reset the object where read coordinates are going to be stored |
1696 | 345k | MMResetFeatureGeometry(&hMMFeature); |
1697 | 345k | if (bcalculateRecord) |
1698 | 345k | { |
1699 | 345k | MMResetFeatureRecord(&hMMFeature); |
1700 | 345k | if (!phMiraMonLayer->pLayerDB) |
1701 | 822 | { |
1702 | 822 | eErr = TranslateFieldsToMM(); |
1703 | 822 | if (eErr != OGRERR_NONE) |
1704 | 0 | return eErr; |
1705 | 822 | } |
1706 | | // Content field translation from GDAL to MiraMon |
1707 | 345k | eErr = TranslateFieldsValuesToMM(poFeature); |
1708 | 345k | if (eErr != OGRERR_NONE) |
1709 | 0 | { |
1710 | 0 | CPLDebugOnly("MiraMon", "Error in MMProcessGeometry()"); |
1711 | 0 | return eErr; |
1712 | 0 | } |
1713 | 345k | } |
1714 | | |
1715 | | /* -------------------------------------------------------------------- */ |
1716 | | /* Write Geometry */ |
1717 | | /* -------------------------------------------------------------------- */ |
1718 | | |
1719 | | // Reads objects with coordinates and transform them to MiraMon |
1720 | 345k | if (poGeom) |
1721 | 878 | { |
1722 | 878 | eErr = MMLoadGeometry(OGRGeometry::ToHandle(poGeom)); |
1723 | 878 | } |
1724 | 344k | else |
1725 | 344k | { |
1726 | 344k | if (!phMiraMonLayer->bIsBeenInit) |
1727 | 750 | { |
1728 | 750 | phMiraMonLayer->bIsDBF = TRUE; |
1729 | 750 | if (MMInitLayerByType(phMiraMonLayer)) |
1730 | 0 | eErr = OGRERR_FAILURE; |
1731 | | |
1732 | 750 | phMiraMonLayer->bIsBeenInit = 1; |
1733 | 750 | } |
1734 | 344k | } |
1735 | | |
1736 | | // Writes coordinates to the disk |
1737 | 345k | if (eErr == OGRERR_NONE) |
1738 | 345k | return MMWriteGeometry(); |
1739 | 0 | CPLDebugOnly("MiraMon", "Error in MMProcessGeometry()"); |
1740 | 0 | return eErr; |
1741 | 345k | } |
1742 | | |
1743 | | /****************************************************************************/ |
1744 | | /* ICreateFeature() */ |
1745 | | /****************************************************************************/ |
1746 | | |
1747 | | OGRErr OGRMiraMonLayer::ICreateFeature(OGRFeature *poFeature) |
1748 | | |
1749 | 345k | { |
1750 | 345k | OGRErr eErr = OGRERR_NONE; |
1751 | | |
1752 | 345k | if (!m_bUpdate) |
1753 | 0 | { |
1754 | 0 | CPLError(CE_Failure, CPLE_NoWriteAccess, |
1755 | 0 | "Cannot create features on a read-only dataset."); |
1756 | 0 | return OGRERR_FAILURE; |
1757 | 0 | } |
1758 | | |
1759 | | /* -------------------------------------------------------------------- */ |
1760 | | /* Write out the feature */ |
1761 | | /* -------------------------------------------------------------------- */ |
1762 | 345k | OGRGeometry *poGeom = poFeature->GetGeometryRef(); |
1763 | | |
1764 | | // Processing a feature without geometry. |
1765 | 345k | if (poGeom == nullptr) |
1766 | 344k | { |
1767 | 344k | eErr = MMProcessGeometry(nullptr, poFeature, TRUE); |
1768 | 344k | if (phMiraMonLayer->bIsDBF && phMiraMonLayer->TopHeader.nElemCount > 0) |
1769 | 142k | poFeature->SetFID((GIntBig)phMiraMonLayer->TopHeader.nElemCount - |
1770 | 142k | 1); |
1771 | 344k | return eErr; |
1772 | 344k | } |
1773 | | |
1774 | | // Converting to simple geometries |
1775 | 1.12k | if (wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection) |
1776 | 97 | { |
1777 | 97 | int nGeom = OGR_G_GetGeometryCount(OGRGeometry::ToHandle(poGeom)); |
1778 | 174 | for (int iGeom = 0; iGeom < nGeom; iGeom++) |
1779 | 119 | { |
1780 | 119 | OGRGeometryH poSubGeometry = |
1781 | 119 | OGR_G_GetGeometryRef(OGRGeometry::ToHandle(poGeom), iGeom); |
1782 | 119 | eErr = MMProcessMultiGeometry(poSubGeometry, poFeature); |
1783 | 119 | if (eErr != OGRERR_NONE) |
1784 | 42 | return eErr; |
1785 | 119 | } |
1786 | | |
1787 | 55 | return eErr; |
1788 | 97 | } |
1789 | | |
1790 | | // Processing the geometry |
1791 | 1.02k | eErr = MMProcessMultiGeometry(OGRGeometry::ToHandle(poGeom), poFeature); |
1792 | | |
1793 | | // Set the FID from 0 index |
1794 | 1.02k | if (phMiraMonLayer) |
1795 | 1.02k | { |
1796 | 1.02k | if (phMiraMonLayer->bIsPolygon && |
1797 | 1.02k | phMiraMonLayer->TopHeader.nElemCount > 1) |
1798 | 278 | poFeature->SetFID((GIntBig)phMiraMonLayer->TopHeader.nElemCount - |
1799 | 278 | 2); |
1800 | 749 | else if (phMiraMonLayer->TopHeader.nElemCount > 0) |
1801 | 632 | poFeature->SetFID((GIntBig)phMiraMonLayer->TopHeader.nElemCount - |
1802 | 632 | 1); |
1803 | 1.02k | } |
1804 | 1.02k | return eErr; |
1805 | 1.12k | } |
1806 | | |
1807 | | /****************************************************************************/ |
1808 | | /* MMDumpVertices() */ |
1809 | | /****************************************************************************/ |
1810 | | |
1811 | | OGRErr OGRMiraMonLayer::MMDumpVertices(OGRGeometryH hGeom, |
1812 | | MM_BOOLEAN bExternalRing, |
1813 | | MM_BOOLEAN bUseVFG) |
1814 | 929 | { |
1815 | | // If the MiraMonLayer structure has not been init, |
1816 | | // here is the moment to do that. |
1817 | 929 | if (!phMiraMonLayer) |
1818 | 0 | return OGRERR_FAILURE; |
1819 | | |
1820 | 929 | if (!phMiraMonLayer->bIsBeenInit) |
1821 | 42 | { |
1822 | 42 | if (MMInitLayerByType(phMiraMonLayer)) |
1823 | 0 | return OGRERR_FAILURE; |
1824 | 42 | phMiraMonLayer->bIsBeenInit = 1; |
1825 | 42 | } |
1826 | 929 | if (MMResize_MM_N_VERTICES_TYPE_Pointer( |
1827 | 929 | &hMMFeature.pNCoordRing, &hMMFeature.nMaxpNCoordRing, |
1828 | 929 | (MM_N_VERTICES_TYPE)hMMFeature.nNRings + 1, MM_MEAN_NUMBER_OF_RINGS, |
1829 | 929 | 0)) |
1830 | 0 | return OGRERR_FAILURE; |
1831 | | |
1832 | 929 | if (bUseVFG) |
1833 | 360 | { |
1834 | 360 | if (MMResizeVFGPointer(&hMMFeature.flag_VFG, &hMMFeature.nMaxVFG, |
1835 | 360 | (MM_INTERNAL_FID)hMMFeature.nNRings + 1, |
1836 | 360 | MM_MEAN_NUMBER_OF_RINGS, 0)) |
1837 | 0 | return OGRERR_FAILURE; |
1838 | | |
1839 | 360 | hMMFeature.flag_VFG[hMMFeature.nIRing] = MM_END_ARC_IN_RING; |
1840 | 360 | if (bExternalRing) |
1841 | 220 | hMMFeature.flag_VFG[hMMFeature.nIRing] |= MM_EXTERIOR_ARC_SIDE; |
1842 | | // In MiraMon the external ring is clockwise and the internals are |
1843 | | // coounterclockwise. |
1844 | 360 | OGRGeometry *poGeom = OGRGeometry::FromHandle(hGeom); |
1845 | 360 | if ((bExternalRing && !poGeom->toLinearRing()->isClockwise()) || |
1846 | 360 | (!bExternalRing && poGeom->toLinearRing()->isClockwise())) |
1847 | 113 | hMMFeature.flag_VFG[hMMFeature.nIRing] |= MM_ROTATE_ARC; |
1848 | 360 | } |
1849 | | |
1850 | 929 | hMMFeature.pNCoordRing[hMMFeature.nIRing] = OGR_G_GetPointCount(hGeom); |
1851 | | |
1852 | 929 | if (MMResizeMM_POINT2DPointer(&hMMFeature.pCoord, &hMMFeature.nMaxpCoord, |
1853 | 929 | hMMFeature.nICoord + |
1854 | 929 | hMMFeature.pNCoordRing[hMMFeature.nIRing], |
1855 | 929 | MM_MEAN_NUMBER_OF_NCOORDS, 0)) |
1856 | 0 | return OGRERR_FAILURE; |
1857 | 929 | if (MMResizeDoublePointer(&hMMFeature.pZCoord, &hMMFeature.nMaxpZCoord, |
1858 | 929 | hMMFeature.nICoord + |
1859 | 929 | hMMFeature.pNCoordRing[hMMFeature.nIRing], |
1860 | 929 | MM_MEAN_NUMBER_OF_NCOORDS, 0)) |
1861 | 0 | return OGRERR_FAILURE; |
1862 | | |
1863 | 929 | hMMFeature.bAllZHaveSameValue = TRUE; |
1864 | 929 | for (int iPoint = 0; |
1865 | 1.54k | (MM_N_VERTICES_TYPE)iPoint < hMMFeature.pNCoordRing[hMMFeature.nIRing]; |
1866 | 929 | iPoint++) |
1867 | 619 | { |
1868 | 619 | hMMFeature.pCoord[hMMFeature.nICoord].dfX = OGR_G_GetX(hGeom, iPoint); |
1869 | 619 | hMMFeature.pCoord[hMMFeature.nICoord].dfY = OGR_G_GetY(hGeom, iPoint); |
1870 | 619 | if (OGR_G_GetCoordinateDimension(hGeom) == 2) |
1871 | 542 | hMMFeature.pZCoord[hMMFeature.nICoord] = |
1872 | 542 | MM_NODATA_COORD_Z; // Possible rare case |
1873 | 77 | else |
1874 | 77 | { |
1875 | 77 | hMMFeature.pZCoord[hMMFeature.nICoord] = OGR_G_GetZ(hGeom, iPoint); |
1876 | 77 | phMiraMonLayer->bIsReal3d = 1; |
1877 | 77 | } |
1878 | | |
1879 | | // Asking if last Z-coordinate is the same than this one. |
1880 | | // If all Z-coordinates are the same, following MiraMon specification |
1881 | | // only the hMMFeature.pZCoord[0] value will be used and the number of |
1882 | | // vertices will be saved as a negative number on disk |
1883 | 619 | if (iPoint > 0 && |
1884 | 619 | !CPLIsEqual(hMMFeature.pZCoord[hMMFeature.nICoord], |
1885 | 619 | hMMFeature.pZCoord[hMMFeature.nICoord - 1])) |
1886 | 4 | hMMFeature.bAllZHaveSameValue = FALSE; |
1887 | | |
1888 | 619 | hMMFeature.nICoord++; |
1889 | 619 | } |
1890 | 929 | hMMFeature.nIRing++; |
1891 | 929 | hMMFeature.nNRings++; |
1892 | 929 | return OGRERR_NONE; |
1893 | 929 | } |
1894 | | |
1895 | | /****************************************************************************/ |
1896 | | /* MMLoadGeometry() */ |
1897 | | /* */ |
1898 | | /* Loads on a MiraMon object Feature all coordinates from feature */ |
1899 | | /* */ |
1900 | | /****************************************************************************/ |
1901 | | OGRErr OGRMiraMonLayer::MMLoadGeometry(OGRGeometryH hGeom) |
1902 | | |
1903 | 909 | { |
1904 | 909 | OGRErr eErr = OGRERR_NONE; |
1905 | 909 | MM_BOOLEAN bExternalRing; |
1906 | | |
1907 | | /* -------------------------------------------------------------------- */ |
1908 | | /* This is a geometry with sub-geometries. */ |
1909 | | /* -------------------------------------------------------------------- */ |
1910 | 909 | int nGeom = OGR_G_GetGeometryCount(hGeom); |
1911 | | |
1912 | 909 | int eLT = wkbFlatten(OGR_G_GetGeometryType(hGeom)); |
1913 | | |
1914 | 909 | if (eLT == wkbMultiPolygon || eLT == wkbPolyhedralSurface || eLT == wkbTIN) |
1915 | 63 | { |
1916 | 94 | for (int iGeom = 0; iGeom < nGeom && eErr == OGRERR_NONE; iGeom++) |
1917 | 31 | { |
1918 | 31 | OGRGeometryH poSubGeometry = OGR_G_GetGeometryRef(hGeom, iGeom); |
1919 | | |
1920 | | // Reads all coordinates |
1921 | 31 | eErr = MMLoadGeometry(poSubGeometry); |
1922 | 31 | if (eErr != OGRERR_NONE) |
1923 | 0 | return eErr; |
1924 | 31 | } |
1925 | 63 | } |
1926 | 909 | if (eLT == wkbTriangle) |
1927 | 4 | { |
1928 | 4 | for (int iGeom = 0; iGeom < nGeom && eErr == OGRERR_NONE; iGeom++) |
1929 | 0 | { |
1930 | 0 | OGRGeometryH poSubGeometry = OGR_G_GetGeometryRef(hGeom, iGeom); |
1931 | | |
1932 | | // Reads all coordinates |
1933 | 0 | eErr = MMDumpVertices(poSubGeometry, TRUE, TRUE); |
1934 | 0 | if (eErr != OGRERR_NONE) |
1935 | 0 | return eErr; |
1936 | 0 | } |
1937 | 4 | } |
1938 | 905 | else if (eLT == wkbPolygon) |
1939 | 273 | { |
1940 | 633 | for (int iGeom = 0; iGeom < nGeom && eErr == OGRERR_NONE; iGeom++) |
1941 | 360 | { |
1942 | 360 | OGRGeometryH poSubGeometry = OGR_G_GetGeometryRef(hGeom, iGeom); |
1943 | | |
1944 | 360 | if (iGeom == 0) |
1945 | 220 | bExternalRing = true; |
1946 | 140 | else |
1947 | 140 | bExternalRing = false; |
1948 | | |
1949 | 360 | eErr = MMDumpVertices(poSubGeometry, bExternalRing, TRUE); |
1950 | 360 | if (eErr != OGRERR_NONE) |
1951 | 0 | return eErr; |
1952 | 360 | } |
1953 | 273 | } |
1954 | 632 | else if (eLT == wkbPoint || eLT == wkbLineString) |
1955 | 569 | { |
1956 | | // Reads all coordinates |
1957 | 569 | eErr = MMDumpVertices(hGeom, true, FALSE); |
1958 | | |
1959 | 569 | if (eErr != OGRERR_NONE) |
1960 | 0 | return eErr; |
1961 | 569 | } |
1962 | 63 | else if (eLT == wkbGeometryCollection) |
1963 | 0 | { |
1964 | 0 | CPLError( |
1965 | 0 | CE_Failure, CPLE_NotSupported, |
1966 | 0 | "MiraMon: wkbGeometryCollection inside a wkbGeometryCollection?"); |
1967 | 0 | return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; |
1968 | 0 | } |
1969 | | |
1970 | 909 | return OGRERR_NONE; |
1971 | 909 | } |
1972 | | |
1973 | | /****************************************************************************/ |
1974 | | /* WriteGeometry() */ |
1975 | | /* */ |
1976 | | /* Writes a geometry to the file. */ |
1977 | | /****************************************************************************/ |
1978 | | |
1979 | | OGRErr OGRMiraMonLayer::MMWriteGeometry() |
1980 | | |
1981 | 345k | { |
1982 | 345k | OGRErr eErr = MMAddFeature(phMiraMonLayer, &hMMFeature); |
1983 | | |
1984 | 345k | if (eErr == MM_FATAL_ERROR_WRITING_FEATURES) |
1985 | 202k | { |
1986 | 202k | CPLDebugOnly("MiraMon", "Error in MMAddFeature() " |
1987 | 202k | "MM_FATAL_ERROR_WRITING_FEATURES"); |
1988 | 202k | CPLError(CE_Failure, CPLE_FileIO, "MiraMon write failure: %s", |
1989 | 202k | VSIStrerror(errno)); |
1990 | 202k | return OGRERR_FAILURE; |
1991 | 202k | } |
1992 | 142k | if (eErr == MM_STOP_WRITING_FEATURES) |
1993 | 0 | { |
1994 | 0 | CPLDebugOnly("MiraMon", "Error in MMAddFeature() " |
1995 | 0 | "MM_STOP_WRITING_FEATURES"); |
1996 | 0 | CPLError(CE_Failure, CPLE_FileIO, |
1997 | 0 | "MiraMon format limitations. Try V2.0 option (-lco " |
1998 | 0 | "Version=V2.0). " sprintf_UINT64 |
1999 | 0 | " elements have been written correctly.", |
2000 | 0 | phMiraMonLayer->TopHeader.nElemCount); |
2001 | 0 | return OGRERR_FAILURE; |
2002 | 0 | } |
2003 | | |
2004 | 142k | return OGRERR_NONE; |
2005 | 142k | } |
2006 | | |
2007 | | /****************************************************************************/ |
2008 | | /* TranslateFieldsToMM() */ |
2009 | | /* */ |
2010 | | /* Translase ogr Fields to a structure that MiraMon can understand */ |
2011 | | /****************************************************************************/ |
2012 | | |
2013 | | OGRErr OGRMiraMonLayer::TranslateFieldsToMM() |
2014 | | |
2015 | 822 | { |
2016 | 822 | if (m_poFeatureDefn->GetFieldCount() == 0) |
2017 | 22 | return OGRERR_NONE; |
2018 | | |
2019 | 800 | CPLDebugOnly("MiraMon", "Translating fields to MiraMon..."); |
2020 | | // If the structure is filled we do anything |
2021 | 800 | if (phMiraMonLayer->pLayerDB) |
2022 | 0 | return OGRERR_NONE; |
2023 | | |
2024 | 800 | phMiraMonLayer->pLayerDB = static_cast<struct MiraMonDataBase *>( |
2025 | 800 | VSICalloc(sizeof(*phMiraMonLayer->pLayerDB), 1)); |
2026 | 800 | if (!phMiraMonLayer->pLayerDB) |
2027 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2028 | | |
2029 | 800 | phMiraMonLayer->pLayerDB->pFields = |
2030 | 800 | static_cast<struct MiraMonDataBaseField *>( |
2031 | 800 | VSICalloc(m_poFeatureDefn->GetFieldCount(), |
2032 | 800 | sizeof(*(phMiraMonLayer->pLayerDB->pFields)))); |
2033 | 800 | if (!phMiraMonLayer->pLayerDB->pFields) |
2034 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2035 | | |
2036 | 800 | phMiraMonLayer->pLayerDB->nNFields = 0; |
2037 | 800 | if (phMiraMonLayer->pLayerDB->pFields) |
2038 | 800 | { |
2039 | 800 | memset(phMiraMonLayer->pLayerDB->pFields, 0, |
2040 | 800 | m_poFeatureDefn->GetFieldCount() * |
2041 | 800 | sizeof(*phMiraMonLayer->pLayerDB->pFields)); |
2042 | 800 | for (MM_EXT_DBF_N_FIELDS iField = 0; |
2043 | 9.55k | iField < (MM_EXT_DBF_N_FIELDS)m_poFeatureDefn->GetFieldCount(); |
2044 | 8.75k | iField++) |
2045 | 8.75k | { |
2046 | 8.75k | switch (m_poFeatureDefn->GetFieldDefn(iField)->GetType()) |
2047 | 8.75k | { |
2048 | 52 | case OFTInteger: |
2049 | 52 | case OFTIntegerList: |
2050 | 52 | if (m_poFeatureDefn->GetFieldDefn(iField)->GetSubType() == |
2051 | 52 | OFSTBoolean) |
2052 | 0 | { |
2053 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2054 | 0 | MM_Logic; |
2055 | 0 | } |
2056 | 52 | else |
2057 | 52 | { |
2058 | 52 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2059 | 52 | MM_Numeric; |
2060 | 52 | } |
2061 | | |
2062 | 52 | phMiraMonLayer->pLayerDB->pFields[iField] |
2063 | 52 | .nNumberOfDecimals = 0; |
2064 | 52 | break; |
2065 | | |
2066 | 2 | case OFTInteger64: |
2067 | 2 | case OFTInteger64List: |
2068 | 2 | phMiraMonLayer->pLayerDB->pFields[iField].bIs64BitInteger = |
2069 | 2 | TRUE; |
2070 | 2 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2071 | 2 | MM_Numeric; |
2072 | 2 | phMiraMonLayer->pLayerDB->pFields[iField] |
2073 | 2 | .nNumberOfDecimals = 0; |
2074 | 2 | break; |
2075 | | |
2076 | 19 | case OFTReal: |
2077 | 19 | case OFTRealList: |
2078 | 19 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2079 | 19 | MM_Numeric; |
2080 | 19 | phMiraMonLayer->pLayerDB->pFields[iField] |
2081 | 19 | .nNumberOfDecimals = |
2082 | 19 | m_poFeatureDefn->GetFieldDefn(iField)->GetPrecision(); |
2083 | 19 | break; |
2084 | | |
2085 | 0 | case OFTBinary: |
2086 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2087 | 0 | MM_Character; |
2088 | 0 | break; |
2089 | | |
2090 | 0 | case OFTDate: |
2091 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2092 | 0 | MM_Data; |
2093 | 0 | break; |
2094 | | |
2095 | 0 | case OFTTime: |
2096 | 0 | case OFTDateTime: |
2097 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2098 | 0 | MM_Character; |
2099 | 0 | break; |
2100 | | |
2101 | 8.67k | case OFTString: |
2102 | 8.67k | case OFTStringList: |
2103 | 8.67k | default: |
2104 | 8.67k | phMiraMonLayer->pLayerDB->pFields[iField].eFieldType = |
2105 | 8.67k | MM_Character; |
2106 | 8.67k | break; |
2107 | 8.75k | } |
2108 | 8.75k | if (m_poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTDate) |
2109 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = 8; |
2110 | 8.75k | else if ((m_poFeatureDefn->GetFieldDefn(iField)->GetType() == |
2111 | 8.75k | OFTInteger || |
2112 | 8.75k | m_poFeatureDefn->GetFieldDefn(iField)->GetType() == |
2113 | 8.69k | OFTIntegerList) && |
2114 | 8.75k | m_poFeatureDefn->GetFieldDefn(iField)->GetSubType() == |
2115 | 52 | OFSTBoolean) |
2116 | 0 | { |
2117 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = 1; |
2118 | 0 | } |
2119 | 8.75k | else |
2120 | 8.75k | { |
2121 | | // NOTE_3812_20250527: |
2122 | | // As https://gdal.org/api/ogrfeature_cpp.html indicates that |
2123 | | // precision (number of digits after decimal point) is optional, |
2124 | | // and a 0 is probably the default value, in that case we prefer |
2125 | | // to save all the guaranteed significant figures in a double |
2126 | | // (needed if a field contains, for instance, coordinates in |
2127 | | // geodetic degrees and a 1:1000 map precision applies). |
2128 | 8.75k | if (m_poFeatureDefn->GetFieldDefn(iField)->GetPrecision() == 0) |
2129 | 8.75k | { |
2130 | 8.75k | if (m_poFeatureDefn->GetFieldDefn(iField)->GetType() == |
2131 | 8.75k | OFTReal || |
2132 | 8.75k | m_poFeatureDefn->GetFieldDefn(iField)->GetType() == |
2133 | 8.73k | OFTRealList) |
2134 | 19 | { |
2135 | 19 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2136 | 19 | 20; |
2137 | 19 | phMiraMonLayer->pLayerDB->pFields[iField] |
2138 | 19 | .nNumberOfDecimals = MAX_RELIABLE_SF_DOUBLE; |
2139 | 19 | } |
2140 | 8.73k | else |
2141 | 8.73k | { |
2142 | 8.73k | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2143 | 8.73k | m_poFeatureDefn->GetFieldDefn(iField)->GetWidth(); |
2144 | 8.73k | if (phMiraMonLayer->pLayerDB->pFields[iField] |
2145 | 8.73k | .nFieldSize == 0) |
2146 | 8.72k | phMiraMonLayer->pLayerDB->pFields[iField] |
2147 | 8.72k | .nFieldSize = 3; |
2148 | 8.73k | } |
2149 | | |
2150 | | // Some exceptions for some fields: |
2151 | 8.75k | if (EQUAL( |
2152 | 8.75k | m_poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), |
2153 | 8.75k | "fontsize")) |
2154 | 0 | { |
2155 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2156 | 0 | 11; |
2157 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2158 | 0 | .nNumberOfDecimals = 3; |
2159 | 0 | } |
2160 | 8.75k | else if (EQUAL(m_poFeatureDefn->GetFieldDefn(iField) |
2161 | 8.75k | ->GetNameRef(), |
2162 | 8.75k | "leading") || |
2163 | 8.75k | EQUAL(m_poFeatureDefn->GetFieldDefn(iField) |
2164 | 8.75k | ->GetNameRef(), |
2165 | 8.75k | "chrwidth") || |
2166 | 8.75k | EQUAL(m_poFeatureDefn->GetFieldDefn(iField) |
2167 | 8.75k | ->GetNameRef(), |
2168 | 8.75k | "chrspacing")) |
2169 | 0 | { |
2170 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2171 | 0 | 8; |
2172 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2173 | 0 | .nNumberOfDecimals = 3; |
2174 | 0 | } |
2175 | 8.75k | else if (EQUAL(m_poFeatureDefn->GetFieldDefn(iField) |
2176 | 8.75k | ->GetNameRef(), |
2177 | 8.75k | "orientacio")) |
2178 | 0 | { |
2179 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2180 | 0 | 7; |
2181 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2182 | 0 | .nNumberOfDecimals = 2; |
2183 | 0 | } |
2184 | 8.75k | } |
2185 | 0 | else |
2186 | 0 | { |
2187 | | // One more space for the "." |
2188 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].nFieldSize = |
2189 | 0 | (unsigned int)(m_poFeatureDefn->GetFieldDefn(iField) |
2190 | 0 | ->GetWidth() + |
2191 | 0 | 1); |
2192 | 0 | } |
2193 | 8.75k | } |
2194 | | |
2195 | | // Recode from UTF-8 if necessary |
2196 | 8.75k | if (phMiraMonLayer->nCharSet != MM_JOC_CARAC_UTF8_DBF) |
2197 | 8.75k | { |
2198 | 8.75k | char *pszString = CPLRecode( |
2199 | 8.75k | m_poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), |
2200 | 8.75k | CPL_ENC_UTF8, CPL_ENC_ISO8859_1); |
2201 | 8.75k | CPLStrlcpy( |
2202 | 8.75k | phMiraMonLayer->pLayerDB->pFields[iField].pszFieldName, |
2203 | 8.75k | pszString, MM_MAX_LON_FIELD_NAME_DBF); |
2204 | 8.75k | CPLFree(pszString); |
2205 | 8.75k | } |
2206 | 0 | else |
2207 | 0 | { |
2208 | 0 | CPLStrlcpy( |
2209 | 0 | phMiraMonLayer->pLayerDB->pFields[iField].pszFieldName, |
2210 | 0 | m_poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), |
2211 | 0 | MM_MAX_LON_FIELD_NAME_DBF); |
2212 | 0 | } |
2213 | | |
2214 | 8.75k | if (m_poFeatureDefn->GetFieldDefn(iField)->GetAlternativeNameRef()) |
2215 | 8.75k | { |
2216 | 8.75k | if (phMiraMonLayer->nCharSet != MM_JOC_CARAC_UTF8_DBF) |
2217 | 8.75k | { |
2218 | 8.75k | char *pszString = |
2219 | 8.75k | CPLRecode(m_poFeatureDefn->GetFieldDefn(iField) |
2220 | 8.75k | ->GetAlternativeNameRef(), |
2221 | 8.75k | CPL_ENC_UTF8, CPL_ENC_ISO8859_1); |
2222 | 8.75k | CPLStrlcpy(phMiraMonLayer->pLayerDB->pFields[iField] |
2223 | 8.75k | .pszFieldDescription, |
2224 | 8.75k | pszString, MM_MAX_BYTES_FIELD_DESC); |
2225 | 8.75k | CPLFree(pszString); |
2226 | 8.75k | } |
2227 | 0 | else |
2228 | 0 | { |
2229 | 0 | CPLStrlcpy(phMiraMonLayer->pLayerDB->pFields[iField] |
2230 | 0 | .pszFieldDescription, |
2231 | 0 | m_poFeatureDefn->GetFieldDefn(iField) |
2232 | 0 | ->GetAlternativeNameRef(), |
2233 | 0 | MM_MAX_BYTES_FIELD_DESC); |
2234 | 0 | } |
2235 | 8.75k | } |
2236 | 8.75k | phMiraMonLayer->pLayerDB->nNFields++; |
2237 | 8.75k | } |
2238 | 800 | } |
2239 | | |
2240 | 800 | CPLDebugOnly("MiraMon", "Fields to MiraMon translated."); |
2241 | 800 | return OGRERR_NONE; |
2242 | 800 | } |
2243 | | |
2244 | | /****************************************************************************/ |
2245 | | /* TranslateFieldsValuesToMM() */ |
2246 | | /* */ |
2247 | | /* Translate ogr Fields to a structure that MiraMon can understand */ |
2248 | | /****************************************************************************/ |
2249 | | |
2250 | | OGRErr OGRMiraMonLayer::TranslateFieldsValuesToMM(OGRFeature *poFeature) |
2251 | | |
2252 | 345k | { |
2253 | 345k | if (m_poFeatureDefn->GetFieldCount() == 0) |
2254 | 22 | { |
2255 | | // MiraMon have private DataBase records |
2256 | 22 | hMMFeature.nNumMRecords = 1; |
2257 | 22 | return OGRERR_NONE; |
2258 | 22 | } |
2259 | | |
2260 | 345k | MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord; |
2261 | 345k | MM_EXT_DBF_N_FIELDS nNumFields = m_poFeatureDefn->GetFieldCount(); |
2262 | 345k | MM_EXT_DBF_N_MULTIPLE_RECORDS nNumRecords, nRealNumRecords; |
2263 | 345k | hMMFeature.nNumMRecords = 0; |
2264 | 345k | #define MAX_SIZE_OF_FIELD_NUMBER_WITH_MINUS 22 |
2265 | | |
2266 | 1.39M | for (MM_EXT_DBF_N_FIELDS iField = 0; iField < nNumFields; iField++) |
2267 | 1.04M | { |
2268 | 1.04M | OGRFieldType eFType = m_poFeatureDefn->GetFieldDefn(iField)->GetType(); |
2269 | 1.04M | OGRFieldSubType eFSType = |
2270 | 1.04M | m_poFeatureDefn->GetFieldDefn(iField)->GetSubType(); |
2271 | 1.04M | const char *pszRawValue = poFeature->GetFieldAsString(iField); |
2272 | | |
2273 | 1.04M | if (eFType == OFTStringList) |
2274 | 0 | { |
2275 | 0 | char **papszValues = poFeature->GetFieldAsStringList(iField); |
2276 | 0 | nRealNumRecords = nNumRecords = CSLCount(papszValues); |
2277 | 0 | if (nNumRecords == 0) |
2278 | 0 | nNumRecords++; |
2279 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, nNumRecords); |
2280 | 0 | if (MMResizeMiraMonRecord( |
2281 | 0 | &hMMFeature.pRecords, &hMMFeature.nMaxMRecords, |
2282 | 0 | hMMFeature.nNumMRecords, MM_INC_NUMBER_OF_RECORDS, |
2283 | 0 | hMMFeature.nNumMRecords)) |
2284 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2285 | | |
2286 | 0 | for (nIRecord = 0; nIRecord < nRealNumRecords; nIRecord++) |
2287 | 0 | { |
2288 | 0 | hMMFeature.pRecords[nIRecord].nNumField = |
2289 | 0 | m_poFeatureDefn->GetFieldCount(); |
2290 | |
|
2291 | 0 | if (MMResizeMiraMonFieldValue( |
2292 | 0 | &(hMMFeature.pRecords[nIRecord].pField), |
2293 | 0 | &hMMFeature.pRecords[nIRecord].nMaxField, |
2294 | 0 | hMMFeature.pRecords[nIRecord].nNumField, |
2295 | 0 | (nIRecord == 0) |
2296 | 0 | ? MM_INC_NUMBER_OF_FIELDS |
2297 | 0 | : hMMFeature.pRecords[nIRecord - 1].nMaxField, |
2298 | 0 | hMMFeature.pRecords[nIRecord].nNumField)) |
2299 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2300 | | |
2301 | 0 | if (nIRecord > 0) |
2302 | 0 | { |
2303 | | // The number of fields of this new record is the same as the |
2304 | | // last one |
2305 | 0 | hMMFeature.pRecords[nIRecord].nNumField = |
2306 | 0 | hMMFeature.pRecords[nIRecord - 1].nNumField; |
2307 | 0 | } |
2308 | |
|
2309 | 0 | if (phMiraMonLayer->nCharSet != MM_JOC_CARAC_UTF8_DBF) |
2310 | 0 | { |
2311 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode from UTF-8 |
2312 | 0 | char *pszString = CPLRecode( |
2313 | 0 | papszValues[nIRecord], CPL_ENC_UTF8, CPL_ENC_ISO8859_1); |
2314 | 0 | if (MM_SecureCopyStringFieldValue( |
2315 | 0 | &hMMFeature.pRecords[nIRecord] |
2316 | 0 | .pField[iField] |
2317 | 0 | .pDinValue, |
2318 | 0 | pszString, |
2319 | 0 | &hMMFeature.pRecords[nIRecord] |
2320 | 0 | .pField[iField] |
2321 | 0 | .nNumDinValue)) |
2322 | 0 | { |
2323 | 0 | CPLFree(pszString); |
2324 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2325 | 0 | } |
2326 | 0 | CPLFree(pszString); |
2327 | 0 | } |
2328 | 0 | else |
2329 | 0 | { |
2330 | 0 | if (MM_SecureCopyStringFieldValue( |
2331 | 0 | &hMMFeature.pRecords[nIRecord] |
2332 | 0 | .pField[iField] |
2333 | 0 | .pDinValue, |
2334 | 0 | papszValues[nIRecord], |
2335 | 0 | &hMMFeature.pRecords[nIRecord] |
2336 | 0 | .pField[iField] |
2337 | 0 | .nNumDinValue)) |
2338 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2339 | 0 | } |
2340 | 0 | hMMFeature.pRecords[nIRecord].pField[iField].bIsValid = 1; |
2341 | 0 | } |
2342 | 0 | } |
2343 | 1.04M | else if (eFType == OFTIntegerList) |
2344 | 0 | { |
2345 | 0 | int nCount = 0; |
2346 | 0 | const int *panValues = |
2347 | 0 | poFeature->GetFieldAsIntegerList(iField, &nCount); |
2348 | |
|
2349 | 0 | nRealNumRecords = nNumRecords = nCount; |
2350 | 0 | if (nNumRecords == 0) |
2351 | 0 | nNumRecords++; |
2352 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, nNumRecords); |
2353 | 0 | if (MMResizeMiraMonRecord( |
2354 | 0 | &hMMFeature.pRecords, &hMMFeature.nMaxMRecords, |
2355 | 0 | hMMFeature.nNumMRecords, MM_INC_NUMBER_OF_RECORDS, |
2356 | 0 | hMMFeature.nNumMRecords)) |
2357 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2358 | | |
2359 | | // It will contains the i-th element of the list. |
2360 | 0 | for (nIRecord = 0; nIRecord < nRealNumRecords; nIRecord++) |
2361 | 0 | { |
2362 | 0 | if (MMResizeMiraMonFieldValue( |
2363 | 0 | &(hMMFeature.pRecords[nIRecord].pField), |
2364 | 0 | &hMMFeature.pRecords[nIRecord].nMaxField, |
2365 | 0 | hMMFeature.pRecords[nIRecord].nNumField, |
2366 | 0 | (nIRecord == 0) |
2367 | 0 | ? MM_INC_NUMBER_OF_FIELDS |
2368 | 0 | : hMMFeature.pRecords[nIRecord - 1].nMaxField, |
2369 | 0 | hMMFeature.pRecords[nIRecord].nNumField)) |
2370 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2371 | | |
2372 | 0 | if (nIRecord > 0) |
2373 | 0 | { |
2374 | | // The number of fields of this new record is the same as the |
2375 | | // last one |
2376 | 0 | hMMFeature.pRecords[nIRecord].nNumField = |
2377 | 0 | hMMFeature.pRecords[nIRecord - 1].nNumField; |
2378 | 0 | } |
2379 | |
|
2380 | 0 | if (eFSType == OFSTBoolean) |
2381 | 0 | { |
2382 | 0 | if (panValues[nIRecord] == 1) |
2383 | 0 | { |
2384 | 0 | if (MM_SecureCopyStringFieldValue( |
2385 | 0 | &hMMFeature.pRecords[nIRecord] |
2386 | 0 | .pField[iField] |
2387 | 0 | .pDinValue, |
2388 | 0 | "T", |
2389 | 0 | &hMMFeature.pRecords[nIRecord] |
2390 | 0 | .pField[iField] |
2391 | 0 | .nNumDinValue)) |
2392 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2393 | 0 | } |
2394 | 0 | else |
2395 | 0 | { |
2396 | 0 | if (MM_SecureCopyStringFieldValue( |
2397 | 0 | &hMMFeature.pRecords[nIRecord] |
2398 | 0 | .pField[iField] |
2399 | 0 | .pDinValue, |
2400 | 0 | "F", |
2401 | 0 | &hMMFeature.pRecords[nIRecord] |
2402 | 0 | .pField[iField] |
2403 | 0 | .nNumDinValue)) |
2404 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2405 | 0 | } |
2406 | 0 | } |
2407 | 0 | else |
2408 | 0 | { |
2409 | 0 | if (MM_SecureCopyStringFieldValue( |
2410 | 0 | &hMMFeature.pRecords[nIRecord] |
2411 | 0 | .pField[iField] |
2412 | 0 | .pDinValue, |
2413 | 0 | CPLSPrintf("%d", panValues[nIRecord]), |
2414 | 0 | &hMMFeature.pRecords[nIRecord] |
2415 | 0 | .pField[iField] |
2416 | 0 | .nNumDinValue)) |
2417 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2418 | 0 | } |
2419 | | |
2420 | 0 | hMMFeature.pRecords[nIRecord].pField[iField].bIsValid = 1; |
2421 | 0 | } |
2422 | 0 | } |
2423 | 1.04M | else if (eFType == OFTInteger64List) |
2424 | 0 | { |
2425 | 0 | int nCount = 0; |
2426 | 0 | const GIntBig *panValues = |
2427 | 0 | poFeature->GetFieldAsInteger64List(iField, &nCount); |
2428 | |
|
2429 | 0 | nRealNumRecords = nNumRecords = nCount; |
2430 | 0 | if (nNumRecords == 0) |
2431 | 0 | nNumRecords++; |
2432 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, nNumRecords); |
2433 | 0 | if (MMResizeMiraMonRecord( |
2434 | 0 | &hMMFeature.pRecords, &hMMFeature.nMaxMRecords, |
2435 | 0 | hMMFeature.nNumMRecords, MM_INC_NUMBER_OF_RECORDS, |
2436 | 0 | hMMFeature.nNumMRecords)) |
2437 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2438 | | |
2439 | | // It will contains the i-th element of the list. |
2440 | 0 | for (nIRecord = 0; nIRecord < nRealNumRecords; nIRecord++) |
2441 | 0 | { |
2442 | 0 | if (MMResizeMiraMonFieldValue( |
2443 | 0 | &(hMMFeature.pRecords[nIRecord].pField), |
2444 | 0 | &hMMFeature.pRecords[nIRecord].nMaxField, |
2445 | 0 | hMMFeature.pRecords[nIRecord].nNumField, |
2446 | 0 | (nIRecord == 0) |
2447 | 0 | ? MM_INC_NUMBER_OF_FIELDS |
2448 | 0 | : hMMFeature.pRecords[nIRecord - 1].nMaxField, |
2449 | 0 | hMMFeature.pRecords[nIRecord].nNumField)) |
2450 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2451 | | |
2452 | 0 | if (nIRecord > 0) |
2453 | 0 | { |
2454 | | // The number of fields of this new record is the same as the |
2455 | | // last one |
2456 | 0 | hMMFeature.pRecords[nIRecord].nNumField = |
2457 | 0 | hMMFeature.pRecords[nIRecord - 1].nNumField; |
2458 | 0 | } |
2459 | |
|
2460 | 0 | hMMFeature.pRecords[nIRecord].pField[iField].iValue = |
2461 | 0 | panValues[nIRecord]; |
2462 | |
|
2463 | 0 | if (MM_SecureCopyStringFieldValue( |
2464 | 0 | &hMMFeature.pRecords[nIRecord].pField[iField].pDinValue, |
2465 | 0 | CPLSPrintf("%" CPL_FRMT_GB_WITHOUT_PREFIX "d", |
2466 | 0 | panValues[nIRecord]), |
2467 | 0 | &hMMFeature.pRecords[nIRecord] |
2468 | 0 | .pField[iField] |
2469 | 0 | .nNumDinValue)) |
2470 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2471 | 0 | hMMFeature.pRecords[nIRecord].pField[iField].bIsValid = 1; |
2472 | 0 | } |
2473 | 0 | } |
2474 | 1.04M | else if (eFType == OFTRealList) |
2475 | 0 | { |
2476 | 0 | int nCount = 0; |
2477 | 0 | const double *padfRLValues = |
2478 | 0 | poFeature->GetFieldAsDoubleList(iField, &nCount); |
2479 | | //char format[23]; |
2480 | |
|
2481 | 0 | nRealNumRecords = nNumRecords = nCount; |
2482 | 0 | if (nNumRecords == 0) |
2483 | 0 | nNumRecords++; |
2484 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, nNumRecords); |
2485 | 0 | if (MMResizeMiraMonRecord( |
2486 | 0 | &hMMFeature.pRecords, &hMMFeature.nMaxMRecords, |
2487 | 0 | hMMFeature.nNumMRecords, MM_INC_NUMBER_OF_RECORDS, |
2488 | 0 | hMMFeature.nNumMRecords)) |
2489 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2490 | | |
2491 | | // It will contains the i-th element of the list. |
2492 | 0 | for (nIRecord = 0; nIRecord < nRealNumRecords; nIRecord++) |
2493 | 0 | { |
2494 | 0 | if (MMResizeMiraMonFieldValue( |
2495 | 0 | &(hMMFeature.pRecords[nIRecord].pField), |
2496 | 0 | &hMMFeature.pRecords[nIRecord].nMaxField, |
2497 | 0 | hMMFeature.pRecords[nIRecord].nNumField, |
2498 | 0 | (nIRecord == 0) |
2499 | 0 | ? MM_INC_NUMBER_OF_FIELDS |
2500 | 0 | : hMMFeature.pRecords[nIRecord - 1].nMaxField, |
2501 | 0 | hMMFeature.pRecords[nIRecord].nNumField)) |
2502 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2503 | | |
2504 | 0 | if (nIRecord > 0) |
2505 | 0 | { |
2506 | | // The number of fields of this new record is the same as the |
2507 | | // last one |
2508 | 0 | hMMFeature.pRecords[nIRecord].nNumField = |
2509 | 0 | hMMFeature.pRecords[nIRecord - 1].nNumField; |
2510 | 0 | } |
2511 | |
|
2512 | 0 | char szChain[MAX_SIZE_OF_FIELD_NUMBER_WITH_MINUS]; |
2513 | 0 | if (phMiraMonLayer->pLayerDB->pFields[iField] |
2514 | 0 | .nNumberOfDecimals > 0 && |
2515 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2516 | 0 | .nNumberOfDecimals < MAX_RELIABLE_SF_DOUBLE) |
2517 | 0 | { |
2518 | 0 | CPLsnprintf(szChain, sizeof(szChain), "%.*f", |
2519 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2520 | 0 | .nNumberOfDecimals, |
2521 | 0 | padfRLValues[nIRecord]); |
2522 | 0 | } |
2523 | 0 | else |
2524 | 0 | { |
2525 | 0 | MM_SprintfDoubleSignifFigures( |
2526 | 0 | szChain, sizeof(szChain), |
2527 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2528 | 0 | .nNumberOfDecimals, |
2529 | 0 | padfRLValues[nIRecord]); |
2530 | 0 | } |
2531 | |
|
2532 | 0 | if (MM_SecureCopyStringFieldValue( |
2533 | 0 | &hMMFeature.pRecords[nIRecord].pField[iField].pDinValue, |
2534 | 0 | szChain, |
2535 | 0 | &hMMFeature.pRecords[nIRecord] |
2536 | 0 | .pField[iField] |
2537 | 0 | .nNumDinValue)) |
2538 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2539 | 0 | hMMFeature.pRecords[nIRecord].pField[iField].bIsValid = 1; |
2540 | 0 | } |
2541 | 0 | } |
2542 | 1.04M | else if (eFType == OFTString) |
2543 | 979k | { |
2544 | 979k | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2545 | 979k | hMMFeature.pRecords[0].nNumField = nNumFields; |
2546 | 979k | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2547 | 979k | &hMMFeature.pRecords[0].nMaxField, |
2548 | 979k | hMMFeature.pRecords[0].nNumField, |
2549 | 979k | MM_INC_NUMBER_OF_FIELDS, |
2550 | 979k | hMMFeature.pRecords[0].nNumField)) |
2551 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2552 | | |
2553 | 979k | if (MMIsEmptyString(pszRawValue)) |
2554 | 653k | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2555 | 979k | { |
2556 | 979k | if (phMiraMonLayer->nCharSet != MM_JOC_CARAC_UTF8_DBF) |
2557 | 979k | { |
2558 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode from UTF-8 |
2559 | 979k | char *pszString = |
2560 | 979k | CPLRecode(pszRawValue, CPL_ENC_UTF8, CPL_ENC_ISO8859_1); |
2561 | 979k | if (MM_SecureCopyStringFieldValue( |
2562 | 979k | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2563 | 979k | pszString, |
2564 | 979k | &hMMFeature.pRecords[0] |
2565 | 979k | .pField[iField] |
2566 | 979k | .nNumDinValue)) |
2567 | 0 | { |
2568 | 0 | CPLFree(pszString); |
2569 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2570 | 0 | } |
2571 | 979k | CPLFree(pszString); |
2572 | 979k | } |
2573 | 0 | else |
2574 | 0 | { |
2575 | 0 | if (MM_SecureCopyStringFieldValue( |
2576 | 0 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2577 | 0 | pszRawValue, |
2578 | 0 | &hMMFeature.pRecords[0] |
2579 | 0 | .pField[iField] |
2580 | 0 | .nNumDinValue)) |
2581 | 0 | { |
2582 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2583 | 0 | } |
2584 | 0 | } |
2585 | 979k | } |
2586 | 979k | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2587 | 979k | } |
2588 | 66.1k | else if (eFType == OFTDate) |
2589 | 0 | { |
2590 | 0 | char szDate[15]; |
2591 | |
|
2592 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2593 | 0 | hMMFeature.pRecords[0].nNumField = nNumFields; |
2594 | 0 | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2595 | 0 | &hMMFeature.pRecords[0].nMaxField, |
2596 | 0 | hMMFeature.pRecords[0].nNumField, |
2597 | 0 | MM_INC_NUMBER_OF_FIELDS, |
2598 | 0 | hMMFeature.pRecords[0].nNumField)) |
2599 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2600 | | |
2601 | 0 | if (MMIsEmptyString(pszRawValue)) |
2602 | 0 | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2603 | 0 | else |
2604 | 0 | { |
2605 | 0 | const OGRField *poField = poFeature->GetRawFieldRef(iField); |
2606 | 0 | if (poField->Date.Year >= 0) |
2607 | 0 | snprintf(szDate, sizeof(szDate), "%04d%02d%02d", |
2608 | 0 | poField->Date.Year, poField->Date.Month, |
2609 | 0 | poField->Date.Day); |
2610 | 0 | else |
2611 | 0 | snprintf(szDate, sizeof(szDate), "%04d%02d%02d", 0, 0, 0); |
2612 | |
|
2613 | 0 | if (MM_SecureCopyStringFieldValue( |
2614 | 0 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2615 | 0 | szDate, |
2616 | 0 | &hMMFeature.pRecords[0].pField[iField].nNumDinValue)) |
2617 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2618 | 0 | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2619 | 0 | } |
2620 | 0 | } |
2621 | 66.1k | else if (eFType == OFTTime || eFType == OFTDateTime) |
2622 | 0 | { |
2623 | 0 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2624 | 0 | hMMFeature.pRecords[0].nNumField = nNumFields; |
2625 | 0 | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2626 | 0 | &hMMFeature.pRecords[0].nMaxField, |
2627 | 0 | hMMFeature.pRecords[0].nNumField, |
2628 | 0 | MM_INC_NUMBER_OF_FIELDS, |
2629 | 0 | hMMFeature.pRecords[0].nNumField)) |
2630 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2631 | | |
2632 | 0 | if (MMIsEmptyString(pszRawValue)) |
2633 | 0 | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2634 | 0 | else |
2635 | 0 | { |
2636 | | // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode from UTF-8 |
2637 | 0 | if (MM_SecureCopyStringFieldValue( |
2638 | 0 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2639 | 0 | pszRawValue, |
2640 | 0 | &hMMFeature.pRecords[0].pField[iField].nNumDinValue)) |
2641 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2642 | | |
2643 | 0 | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2644 | 0 | } |
2645 | 0 | } |
2646 | 66.1k | else if (eFType == OFTInteger) |
2647 | 46.4k | { |
2648 | 46.4k | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2649 | 46.4k | hMMFeature.pRecords[0].nNumField = nNumFields; |
2650 | 46.4k | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2651 | 46.4k | &hMMFeature.pRecords[0].nMaxField, |
2652 | 46.4k | hMMFeature.pRecords[0].nNumField, |
2653 | 46.4k | MM_INC_NUMBER_OF_FIELDS, |
2654 | 46.4k | hMMFeature.pRecords[0].nNumField)) |
2655 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2656 | | |
2657 | 46.4k | if (MMIsEmptyString(pszRawValue)) |
2658 | 45.6k | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2659 | 852 | else |
2660 | 852 | { |
2661 | 852 | if (eFSType == OFSTBoolean) |
2662 | 0 | { |
2663 | 0 | if (!strcmp(pszRawValue, "1")) |
2664 | 0 | { |
2665 | 0 | if (MM_SecureCopyStringFieldValue( |
2666 | 0 | &hMMFeature.pRecords[0] |
2667 | 0 | .pField[iField] |
2668 | 0 | .pDinValue, |
2669 | 0 | "T", |
2670 | 0 | &hMMFeature.pRecords[0] |
2671 | 0 | .pField[iField] |
2672 | 0 | .nNumDinValue)) |
2673 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2674 | 0 | } |
2675 | 0 | else |
2676 | 0 | { |
2677 | 0 | if (MM_SecureCopyStringFieldValue( |
2678 | 0 | &hMMFeature.pRecords[0] |
2679 | 0 | .pField[iField] |
2680 | 0 | .pDinValue, |
2681 | 0 | "F", |
2682 | 0 | &hMMFeature.pRecords[0] |
2683 | 0 | .pField[iField] |
2684 | 0 | .nNumDinValue)) |
2685 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2686 | 0 | } |
2687 | 0 | } |
2688 | 852 | else |
2689 | 852 | { |
2690 | 852 | if (MM_SecureCopyStringFieldValue( |
2691 | 852 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2692 | 852 | pszRawValue, |
2693 | 852 | &hMMFeature.pRecords[0] |
2694 | 852 | .pField[iField] |
2695 | 852 | .nNumDinValue)) |
2696 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2697 | 852 | } |
2698 | 852 | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2699 | 852 | } |
2700 | 46.4k | } |
2701 | 19.6k | else if (eFType == OFTInteger64) |
2702 | 4 | { |
2703 | 4 | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2704 | 4 | hMMFeature.pRecords[0].nNumField = nNumFields; |
2705 | 4 | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2706 | 4 | &hMMFeature.pRecords[0].nMaxField, |
2707 | 4 | hMMFeature.pRecords[0].nNumField, |
2708 | 4 | MM_INC_NUMBER_OF_FIELDS, |
2709 | 4 | hMMFeature.pRecords[0].nNumField)) |
2710 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2711 | | |
2712 | 4 | if (MMIsEmptyString(pszRawValue)) |
2713 | 3 | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2714 | 1 | else |
2715 | 1 | { |
2716 | 1 | hMMFeature.pRecords[0].pField[iField].iValue = |
2717 | 1 | poFeature->GetFieldAsInteger64(iField); |
2718 | | |
2719 | 1 | if (MM_SecureCopyStringFieldValue( |
2720 | 1 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2721 | 1 | pszRawValue, |
2722 | 1 | &hMMFeature.pRecords[0].pField[iField].nNumDinValue)) |
2723 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2724 | 1 | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2725 | 1 | } |
2726 | 4 | } |
2727 | 19.6k | else if (eFType == OFTReal) |
2728 | 19.6k | { |
2729 | 19.6k | hMMFeature.nNumMRecords = MAX(hMMFeature.nNumMRecords, 1); |
2730 | 19.6k | hMMFeature.pRecords[0].nNumField = nNumFields; |
2731 | 19.6k | if (MMResizeMiraMonFieldValue(&(hMMFeature.pRecords[0].pField), |
2732 | 19.6k | &hMMFeature.pRecords[0].nMaxField, |
2733 | 19.6k | hMMFeature.pRecords[0].nNumField, |
2734 | 19.6k | MM_INC_NUMBER_OF_FIELDS, |
2735 | 19.6k | hMMFeature.pRecords[0].nNumField)) |
2736 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2737 | | |
2738 | 19.6k | if (MMIsEmptyString(pszRawValue)) |
2739 | 19.5k | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2740 | 55 | else |
2741 | 55 | { |
2742 | 55 | char szChain[MAX_SIZE_OF_FIELD_NUMBER_WITH_MINUS]; |
2743 | | // According to NOTE_3812_20250527 |
2744 | 55 | if (phMiraMonLayer->pLayerDB->pFields[iField] |
2745 | 55 | .nNumberOfDecimals > 0 && |
2746 | 55 | phMiraMonLayer->pLayerDB->pFields[iField] |
2747 | 55 | .nNumberOfDecimals < MAX_RELIABLE_SF_DOUBLE) |
2748 | 0 | { |
2749 | 0 | CPLsnprintf(szChain, sizeof(szChain), "%.*f", |
2750 | 0 | phMiraMonLayer->pLayerDB->pFields[iField] |
2751 | 0 | .nNumberOfDecimals, |
2752 | 0 | poFeature->GetFieldAsDouble(iField)); |
2753 | 0 | } |
2754 | 55 | else |
2755 | 55 | { |
2756 | 55 | MM_SprintfDoubleSignifFigures( |
2757 | 55 | szChain, sizeof(szChain), |
2758 | 55 | phMiraMonLayer->pLayerDB->pFields[iField] |
2759 | 55 | .nNumberOfDecimals, |
2760 | 55 | poFeature->GetFieldAsDouble(iField)); |
2761 | 55 | } |
2762 | | |
2763 | 55 | if (MM_SecureCopyStringFieldValue( |
2764 | 55 | &hMMFeature.pRecords[0].pField[iField].pDinValue, |
2765 | 55 | szChain, |
2766 | 55 | &hMMFeature.pRecords[0].pField[iField].nNumDinValue)) |
2767 | 0 | return OGRERR_NOT_ENOUGH_MEMORY; |
2768 | 55 | hMMFeature.pRecords[0].pField[iField].bIsValid = 1; |
2769 | 55 | } |
2770 | 19.6k | } |
2771 | 0 | else |
2772 | 0 | { |
2773 | 0 | CPLError(CE_Warning, CPLE_NotSupported, |
2774 | 0 | "MiraMon: Field type %d not processed by MiraMon\n", |
2775 | 0 | eFType); |
2776 | 0 | hMMFeature.pRecords[0].pField[iField].bIsValid = 0; |
2777 | 0 | } |
2778 | 1.04M | } |
2779 | | |
2780 | 345k | return OGRERR_NONE; |
2781 | 345k | } |
2782 | | |
2783 | | /****************************************************************************/ |
2784 | | /* GetLayerDefn() */ |
2785 | | /* */ |
2786 | | /****************************************************************************/ |
2787 | | OGRFeatureDefn *OGRMiraMonLayer::GetLayerDefn() |
2788 | 392k | { |
2789 | 392k | return m_poFeatureDefn; |
2790 | 392k | } |
2791 | | |
2792 | | /****************************************************************************/ |
2793 | | /* IGetExtent() */ |
2794 | | /* */ |
2795 | | /* Fetch extent of the data currently stored in the dataset. */ |
2796 | | /* The bForce flag has no effect on SHO files since that value */ |
2797 | | /* is always in the header. */ |
2798 | | /****************************************************************************/ |
2799 | | |
2800 | | OGRErr OGRMiraMonLayer::IGetExtent(int /* iGeomField*/, OGREnvelope *psExtent, |
2801 | | bool bForce) |
2802 | | |
2803 | 0 | { |
2804 | 0 | if (phMiraMonLayer) |
2805 | 0 | { |
2806 | 0 | if (phMiraMonLayer->bIsDBF) |
2807 | 0 | return OGRERR_FAILURE; |
2808 | | |
2809 | | // For polygons we need another polygon apart from the universal one |
2810 | | // to have a valid extension |
2811 | 0 | if (phMiraMonLayer->bIsPolygon && |
2812 | 0 | phMiraMonLayer->TopHeader.nElemCount < 1) |
2813 | 0 | return OGRERR_FAILURE; |
2814 | | |
2815 | 0 | if (phMiraMonLayer->TopHeader.nElemCount < 1) |
2816 | 0 | return OGRERR_FAILURE; |
2817 | | |
2818 | 0 | psExtent->MinX = phMiraMonLayer->TopHeader.hBB.dfMinX; |
2819 | 0 | psExtent->MaxX = phMiraMonLayer->TopHeader.hBB.dfMaxX; |
2820 | 0 | psExtent->MinY = phMiraMonLayer->TopHeader.hBB.dfMinY; |
2821 | 0 | psExtent->MaxY = phMiraMonLayer->TopHeader.hBB.dfMaxY; |
2822 | 0 | } |
2823 | 0 | else |
2824 | 0 | { |
2825 | 0 | if (!bForce) |
2826 | 0 | return OGRERR_FAILURE; |
2827 | 0 | } |
2828 | | |
2829 | 0 | return OGRERR_NONE; |
2830 | 0 | } |
2831 | | |
2832 | | /****************************************************************************/ |
2833 | | /* TestCapability() */ |
2834 | | /****************************************************************************/ |
2835 | | |
2836 | | int OGRMiraMonLayer::TestCapability(const char *pszCap) |
2837 | | |
2838 | 2.39k | { |
2839 | 2.39k | if (EQUAL(pszCap, OLCRandomRead)) |
2840 | 0 | return TRUE; |
2841 | | |
2842 | 2.39k | if (EQUAL(pszCap, OLCSequentialWrite)) |
2843 | 0 | return m_bUpdate; |
2844 | | |
2845 | 2.39k | if (EQUAL(pszCap, OLCFastFeatureCount)) |
2846 | 0 | return !m_poFilterGeom && !m_poAttrQuery; |
2847 | | |
2848 | 2.39k | if (EQUAL(pszCap, OLCFastGetExtent)) |
2849 | 0 | return TRUE; |
2850 | | |
2851 | 2.39k | if (EQUAL(pszCap, OLCCreateField)) |
2852 | 0 | return m_bUpdate; |
2853 | | |
2854 | 2.39k | if (EQUAL(pszCap, OLCZGeometries)) |
2855 | 0 | return TRUE; |
2856 | | |
2857 | 2.39k | if (EQUAL(pszCap, OLCStringsAsUTF8)) |
2858 | 0 | return TRUE; |
2859 | | |
2860 | 2.39k | return FALSE; |
2861 | 2.39k | } |
2862 | | |
2863 | | /****************************************************************************/ |
2864 | | /* CreateField() */ |
2865 | | /****************************************************************************/ |
2866 | | |
2867 | | OGRErr OGRMiraMonLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK) |
2868 | | |
2869 | 9.99k | { |
2870 | 9.99k | if (!m_bUpdate) |
2871 | 0 | { |
2872 | 0 | CPLError(CE_Failure, CPLE_NoWriteAccess, |
2873 | 0 | "Cannot create fields on a read-only dataset."); |
2874 | 0 | return OGRERR_FAILURE; |
2875 | 0 | } |
2876 | | |
2877 | 9.99k | if (phMiraMonLayer && phMiraMonLayer->TopHeader.nElemCount > 0) |
2878 | 0 | { |
2879 | 0 | CPLError(CE_Failure, CPLE_NoWriteAccess, |
2880 | 0 | "Cannot create fields to a layer with " |
2881 | 0 | "already existing features in it."); |
2882 | 0 | return OGRERR_FAILURE; |
2883 | 0 | } |
2884 | | |
2885 | 9.99k | switch (poField->GetType()) |
2886 | 9.99k | { |
2887 | 51 | case OFTInteger: |
2888 | 51 | case OFTIntegerList: |
2889 | 53 | case OFTInteger64: |
2890 | 53 | case OFTInteger64List: |
2891 | 71 | case OFTReal: |
2892 | 71 | case OFTRealList: |
2893 | 9.99k | case OFTString: |
2894 | 9.99k | case OFTStringList: |
2895 | 9.99k | case OFTDate: |
2896 | 9.99k | m_poFeatureDefn->AddFieldDefn(poField); |
2897 | 9.99k | return OGRERR_NONE; |
2898 | 0 | default: |
2899 | 0 | if (!bApproxOK) |
2900 | 0 | { |
2901 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
2902 | 0 | "Field %s is of an unsupported type: %s.", |
2903 | 0 | poField->GetNameRef(), |
2904 | 0 | poField->GetFieldTypeName(poField->GetType())); |
2905 | 0 | return OGRERR_FAILURE; |
2906 | 0 | } |
2907 | 0 | else |
2908 | 0 | { |
2909 | 0 | OGRFieldDefn oModDef(poField); |
2910 | 0 | oModDef.SetType(OFTString); |
2911 | 0 | m_poFeatureDefn->AddFieldDefn(poField); |
2912 | 0 | return OGRERR_NONE; |
2913 | 0 | } |
2914 | 9.99k | } |
2915 | 9.99k | } |
2916 | | |
2917 | | /************************************************************************/ |
2918 | | /* AddToFileList() */ |
2919 | | /************************************************************************/ |
2920 | | |
2921 | | void OGRMiraMonLayer::AddToFileList(CPLStringList &oFileList) |
2922 | 0 | { |
2923 | 0 | if (!phMiraMonLayer) |
2924 | 0 | return; |
2925 | | |
2926 | 0 | char szAuxFile[MM_CPL_PATH_BUF_SIZE]; |
2927 | |
|
2928 | 0 | oFileList.AddStringDirectly( |
2929 | 0 | VSIGetCanonicalFilename(phMiraMonLayer->pszSrcLayerName)); |
2930 | 0 | char *pszMMExt = |
2931 | 0 | CPLStrdup(CPLGetExtensionSafe(phMiraMonLayer->pszSrcLayerName).c_str()); |
2932 | |
|
2933 | 0 | if (phMiraMonLayer->bIsPoint) |
2934 | 0 | { |
2935 | | // As it's explicit on documentation a point has also two more files: |
2936 | | |
2937 | | // FILE_NAME_WITHOUT_EXTENSION.pnt --> FILE_NAME_WITHOUT_EXTENSION + T.rel |
2938 | 0 | CPLStrlcpy(szAuxFile, |
2939 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2940 | 0 | MM_CPL_PATH_BUF_SIZE); |
2941 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "T.rel" : "T.REL", |
2942 | 0 | MM_CPL_PATH_BUF_SIZE); |
2943 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
2944 | 0 | CPLFormFilenameSafe( |
2945 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2946 | 0 | szAuxFile, nullptr) |
2947 | 0 | .c_str())); |
2948 | | |
2949 | | // FILE_NAME_WITHOUT_EXTENSION.pnt --> FILE_NAME_WITHOUT_EXTENSION + T.dbf |
2950 | 0 | CPLStrlcpy(szAuxFile, |
2951 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2952 | 0 | MM_CPL_PATH_BUF_SIZE); |
2953 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "T.dbf" : "T.DBF", |
2954 | 0 | MM_CPL_PATH_BUF_SIZE); |
2955 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
2956 | 0 | CPLFormFilenameSafe( |
2957 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2958 | 0 | szAuxFile, nullptr) |
2959 | 0 | .c_str())); |
2960 | 0 | } |
2961 | 0 | else if (phMiraMonLayer->bIsArc && !phMiraMonLayer->bIsPolygon) |
2962 | 0 | { |
2963 | | // As it's explicit on documentation a point has also five more files: |
2964 | | |
2965 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + A.rel |
2966 | 0 | CPLStrlcpy(szAuxFile, |
2967 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2968 | 0 | MM_CPL_PATH_BUF_SIZE); |
2969 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'a') ? "A.rel" : "A.REL", |
2970 | 0 | MM_CPL_PATH_BUF_SIZE); |
2971 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
2972 | 0 | CPLFormFilenameSafe( |
2973 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2974 | 0 | szAuxFile, nullptr) |
2975 | 0 | .c_str())); |
2976 | | |
2977 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + A.dbf |
2978 | 0 | CPLStrlcpy(szAuxFile, |
2979 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2980 | 0 | MM_CPL_PATH_BUF_SIZE); |
2981 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'a') ? "A.dbf" : "A.DBF", |
2982 | 0 | MM_CPL_PATH_BUF_SIZE); |
2983 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
2984 | 0 | CPLFormFilenameSafe( |
2985 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2986 | 0 | szAuxFile, nullptr) |
2987 | 0 | .c_str())); |
2988 | | |
2989 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + .nod |
2990 | 0 | CPLStrlcpy(szAuxFile, |
2991 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2992 | 0 | MM_CPL_PATH_BUF_SIZE); |
2993 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'a') ? ".nod" : ".NOD", |
2994 | 0 | MM_CPL_PATH_BUF_SIZE); |
2995 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
2996 | 0 | CPLFormFilenameSafe( |
2997 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
2998 | 0 | szAuxFile, nullptr) |
2999 | 0 | .c_str())); |
3000 | | |
3001 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + N.rel |
3002 | 0 | CPLStrlcpy(szAuxFile, |
3003 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3004 | 0 | MM_CPL_PATH_BUF_SIZE); |
3005 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'a') ? "N.rel" : "N.REL", |
3006 | 0 | MM_CPL_PATH_BUF_SIZE); |
3007 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3008 | 0 | CPLFormFilenameSafe( |
3009 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3010 | 0 | szAuxFile, nullptr) |
3011 | 0 | .c_str())); |
3012 | | |
3013 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + N.dbf |
3014 | 0 | CPLStrlcpy(szAuxFile, |
3015 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3016 | 0 | MM_CPL_PATH_BUF_SIZE); |
3017 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'a') ? "N.dbf" : "N.DBF", |
3018 | 0 | MM_CPL_PATH_BUF_SIZE); |
3019 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3020 | 0 | CPLFormFilenameSafe( |
3021 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3022 | 0 | szAuxFile, nullptr) |
3023 | 0 | .c_str())); |
3024 | 0 | } |
3025 | 0 | else if (phMiraMonLayer->bIsPolygon) |
3026 | 0 | { |
3027 | | // As it's explicit on documentation a point has also eight more files: |
3028 | 0 | char szArcFileName[MM_CPL_PATH_BUF_SIZE]; |
3029 | | |
3030 | | // FILE_NAME_WITHOUT_EXTENSION.pol --> FILE_NAME_WITHOUT_EXTENSION + P.rel |
3031 | 0 | CPLStrlcpy(szAuxFile, |
3032 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3033 | 0 | MM_CPL_PATH_BUF_SIZE); |
3034 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "P.rel" : "P.REL", |
3035 | 0 | MM_CPL_PATH_BUF_SIZE); |
3036 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3037 | 0 | CPLFormFilenameSafe( |
3038 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3039 | 0 | szAuxFile, nullptr) |
3040 | 0 | .c_str())); |
3041 | | |
3042 | | // The name of the arc is in THIS metadata file |
3043 | 0 | char *pszArcLayerName = MMReturnValueFromSectionINIFile( |
3044 | 0 | CPLFormFilenameSafe( |
3045 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3046 | 0 | szAuxFile, nullptr) |
3047 | 0 | .c_str(), |
3048 | 0 | SECTION_OVVW_ASPECTES_TECNICS, KEY_ArcSource); |
3049 | 0 | if (!pszArcLayerName) |
3050 | 0 | { |
3051 | 0 | CPLFree(pszMMExt); |
3052 | 0 | return; //Some files are missing |
3053 | 0 | } |
3054 | 0 | CPLStrlcpy(szArcFileName, pszArcLayerName, MM_CPL_PATH_BUF_SIZE); |
3055 | |
|
3056 | 0 | MM_RemoveInitial_and_FinalQuotationMarks(szArcFileName); |
3057 | | |
3058 | | // If extension is not specified ".arc" will be used |
3059 | 0 | if (MMIsEmptyString(CPLGetExtensionSafe(pszArcLayerName).c_str())) |
3060 | 0 | CPLStrlcat(szArcFileName, (pszMMExt[0] == 'p') ? ".arc" : ".ARC", |
3061 | 0 | MM_CPL_PATH_BUF_SIZE); |
3062 | |
|
3063 | 0 | CPLFree(pszArcLayerName); |
3064 | |
|
3065 | 0 | const std::string osCompleteArcFileName = CPLFormFilenameSafe( |
3066 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3067 | 0 | szArcFileName, nullptr); |
3068 | | |
3069 | | // The arc that has the coordinates of the polygon |
3070 | 0 | oFileList.AddStringDirectly( |
3071 | 0 | VSIGetCanonicalFilename(osCompleteArcFileName.c_str())); |
3072 | | |
3073 | | // FILE_NAME_WITHOUT_EXTENSION.pol --> FILE_NAME_WITHOUT_EXTENSION + P.dbf |
3074 | 0 | CPLStrlcpy(szAuxFile, |
3075 | 0 | CPLGetBasenameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3076 | 0 | MM_CPL_PATH_BUF_SIZE); |
3077 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "P.dbf" : "P.DBF", |
3078 | 0 | MM_CPL_PATH_BUF_SIZE); |
3079 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3080 | 0 | CPLFormFilenameSafe( |
3081 | 0 | CPLGetDirnameSafe(phMiraMonLayer->pszSrcLayerName).c_str(), |
3082 | 0 | szAuxFile, nullptr) |
3083 | 0 | .c_str())); |
3084 | | |
3085 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + A.rel |
3086 | 0 | const std::string osBaseArcName = |
3087 | 0 | CPLGetBasenameSafe(osCompleteArcFileName.c_str()); |
3088 | 0 | CPLStrlcpy(szAuxFile, osBaseArcName.c_str(), MM_CPL_PATH_BUF_SIZE); |
3089 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "A.rel" : "A.REL", |
3090 | 0 | MM_CPL_PATH_BUF_SIZE); |
3091 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3092 | 0 | CPLFormFilenameSafe( |
3093 | 0 | CPLGetDirnameSafe(osCompleteArcFileName.c_str()).c_str(), |
3094 | 0 | szAuxFile, nullptr) |
3095 | 0 | .c_str())); |
3096 | | |
3097 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + A.dbf |
3098 | 0 | CPLStrlcpy(szAuxFile, osBaseArcName.c_str(), MM_CPL_PATH_BUF_SIZE); |
3099 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "A.dbf" : "A.DBF", |
3100 | 0 | MM_CPL_PATH_BUF_SIZE); |
3101 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3102 | 0 | CPLFormFilenameSafe( |
3103 | 0 | CPLGetDirnameSafe(osCompleteArcFileName.c_str()).c_str(), |
3104 | 0 | szAuxFile, nullptr) |
3105 | 0 | .c_str())); |
3106 | | |
3107 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + .nod |
3108 | 0 | CPLStrlcpy(szAuxFile, osBaseArcName.c_str(), MM_CPL_PATH_BUF_SIZE); |
3109 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? ".nod" : ".NOD", |
3110 | 0 | MM_CPL_PATH_BUF_SIZE); |
3111 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3112 | 0 | CPLFormFilenameSafe( |
3113 | 0 | CPLGetDirnameSafe(osCompleteArcFileName.c_str()).c_str(), |
3114 | 0 | szAuxFile, nullptr) |
3115 | 0 | .c_str())); |
3116 | | |
3117 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + N.rel |
3118 | 0 | CPLStrlcpy(szAuxFile, osBaseArcName.c_str(), MM_CPL_PATH_BUF_SIZE); |
3119 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "N.rel" : "N.REL", |
3120 | 0 | MM_CPL_PATH_BUF_SIZE); |
3121 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3122 | 0 | CPLFormFilenameSafe( |
3123 | 0 | CPLGetDirnameSafe(osCompleteArcFileName.c_str()).c_str(), |
3124 | 0 | szAuxFile, nullptr) |
3125 | 0 | .c_str())); |
3126 | | |
3127 | | // FILE_NAME_WITHOUT_EXTENSION.arc --> FILE_NAME_WITHOUT_EXTENSION + N.dbf |
3128 | 0 | CPLStrlcpy(szAuxFile, osBaseArcName.c_str(), MM_CPL_PATH_BUF_SIZE); |
3129 | 0 | CPLStrlcat(szAuxFile, (pszMMExt[0] == 'p') ? "N.dbf" : "N.DBF", |
3130 | 0 | MM_CPL_PATH_BUF_SIZE); |
3131 | 0 | oFileList.AddStringDirectly(VSIGetCanonicalFilename( |
3132 | 0 | CPLFormFilenameSafe( |
3133 | 0 | CPLGetDirnameSafe(osCompleteArcFileName.c_str()).c_str(), |
3134 | 0 | szAuxFile, nullptr) |
3135 | 0 | .c_str())); |
3136 | 0 | } |
3137 | 0 | CPLFree(pszMMExt); |
3138 | 0 | } |