Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: EDIGEO Translator
4 : * Purpose: Implements OGREDIGEODataSource class
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "ogr_edigeo.h"
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 :
17 : /************************************************************************/
18 : /* OGREDIGEODataSource() */
19 : /************************************************************************/
20 :
21 0 : OGREDIGEODataSource::OGREDIGEODataSource()
22 : : fpTHF(nullptr), papoLayers(nullptr), nLayers(0), poSRS(nullptr),
23 : bExtentValid(FALSE), dfMinX(0), dfMinY(0), dfMaxX(0), dfMaxY(0),
24 : bRecodeToUTF8(
25 0 : CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_RECODE_TO_UTF8", "YES"))),
26 : bHasUTF8ContentOnly(true), iATR(-1), iDI3(-1), iDI4(-1), iHEI(-1),
27 : iFON(-1), iATR_VAL(-1), iANGLE(-1), iSIZE(-1), iOBJ_LNK(-1),
28 : iOBJ_LNK_LAYER(-1),
29 : // coverity[tainted_data]
30 : dfSizeFactor(
31 0 : CPLAtof(CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"))),
32 0 : bIncludeFontFamily(CPLTestBool(
33 0 : CPLGetConfigOption("OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES")))
34 : {
35 0 : if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
36 0 : dfSizeFactor = 2;
37 0 : }
38 :
39 : /************************************************************************/
40 : /* ~OGREDIGEODataSource() */
41 : /************************************************************************/
42 :
43 0 : OGREDIGEODataSource::~OGREDIGEODataSource()
44 :
45 : {
46 0 : for (int i = 0; i < nLayers; i++)
47 0 : delete papoLayers[i];
48 0 : CPLFree(papoLayers);
49 :
50 0 : if (fpTHF)
51 0 : VSIFCloseL(fpTHF);
52 :
53 0 : if (poSRS)
54 0 : poSRS->Release();
55 0 : }
56 :
57 : /************************************************************************/
58 : /* GetLayer() */
59 : /************************************************************************/
60 :
61 0 : const OGRLayer *OGREDIGEODataSource::GetLayer(int iLayer) const
62 :
63 : {
64 0 : ReadEDIGEO();
65 0 : if (iLayer < 0 || iLayer >= nLayers)
66 0 : return nullptr;
67 : else
68 0 : return papoLayers[iLayer];
69 : }
70 :
71 : /************************************************************************/
72 : /* GetLayerCount() */
73 : /************************************************************************/
74 :
75 0 : int OGREDIGEODataSource::GetLayerCount() const
76 : {
77 0 : ReadEDIGEO();
78 0 : return nLayers;
79 : }
80 :
81 : /************************************************************************/
82 : /* ReadTHF() */
83 : /************************************************************************/
84 :
85 0 : int OGREDIGEODataSource::ReadTHF(VSILFILE *fp) const
86 : {
87 0 : const char *pszLine = nullptr;
88 0 : while ((pszLine = CPLReadLine2L(fp, 81, nullptr)) != nullptr)
89 : {
90 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
91 0 : continue;
92 :
93 : /* Cf Z 52000 tableau 56 for field list*/
94 :
95 0 : if (STARTS_WITH(pszLine, "LONSA"))
96 : {
97 0 : if (!osLON.empty())
98 : {
99 0 : CPLDebug("EDIGEO", "We only handle one lot per THF file");
100 0 : break;
101 : }
102 0 : osLON = pszLine + 8;
103 : }
104 0 : else if (STARTS_WITH(pszLine, "GNNSA"))
105 0 : osGNN = pszLine + 8;
106 0 : else if (STARTS_WITH(pszLine, "GONSA"))
107 0 : osGON = pszLine + 8;
108 0 : else if (STARTS_WITH(pszLine, "QANSA"))
109 0 : osQAN = pszLine + 8;
110 0 : else if (STARTS_WITH(pszLine, "DINSA"))
111 0 : osDIN = pszLine + 8;
112 0 : else if (STARTS_WITH(pszLine, "SCNSA"))
113 0 : osSCN = pszLine + 8;
114 0 : else if (STARTS_WITH(pszLine, "GDNSA"))
115 0 : aosGDN.push_back(pszLine + 8);
116 : }
117 0 : if (osLON.empty())
118 : {
119 0 : CPLDebug("EDIGEO", "LON field missing");
120 0 : return 0;
121 : }
122 0 : if (osGON.empty())
123 : {
124 0 : CPLDebug("EDIGEO", "GON field missing");
125 0 : return 0;
126 : }
127 0 : if (osDIN.empty())
128 : {
129 0 : CPLDebug("EDIGEO", "DIN field missing");
130 0 : return 0;
131 : }
132 0 : if (osSCN.empty())
133 : {
134 0 : CPLDebug("EDIGEO", "SCN field missing");
135 0 : return FALSE;
136 : }
137 :
138 0 : CPLDebug("EDIGEO", "LON = %s", osLON.c_str());
139 0 : CPLDebug("EDIGEO", "GNN = %s", osGNN.c_str());
140 0 : CPLDebug("EDIGEO", "GON = %s", osGON.c_str());
141 0 : CPLDebug("EDIGEO", "QAN = %s", osQAN.c_str());
142 0 : CPLDebug("EDIGEO", "DIN = %s", osDIN.c_str());
143 0 : CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str());
144 0 : for (int i = 0; i < (int)aosGDN.size(); i++)
145 0 : CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str());
146 :
147 0 : return TRUE;
148 : }
149 :
150 : /************************************************************************/
151 : /* OpenFile() */
152 : /************************************************************************/
153 :
154 0 : VSILFILE *OGREDIGEODataSource::OpenFile(const char *pszType,
155 : const CPLString &osExt) const
156 : {
157 0 : CPLString osTmp = osLON + pszType;
158 0 : CPLString osFilename = CPLFormCIFilenameSafe(
159 0 : CPLGetPathSafe(GetDescription()).c_str(), osTmp.c_str(), osExt.c_str());
160 0 : VSILFILE *fp = VSIFOpenL(osFilename, "rb");
161 0 : if (fp == nullptr)
162 : {
163 0 : const CPLString osExtLower = CPLString(osExt).tolower();
164 : const CPLString osFilename2 =
165 0 : CPLFormCIFilenameSafe(CPLGetPathSafe(GetDescription()).c_str(),
166 0 : osTmp.c_str(), osExtLower.c_str());
167 0 : fp = VSIFOpenL(osFilename2, "rb");
168 0 : if (fp == nullptr)
169 : {
170 0 : CPLDebug("EDIGEO", "Cannot open %s", osFilename.c_str());
171 : }
172 : }
173 0 : return fp;
174 : }
175 :
176 : /************************************************************************/
177 : /* ReadGEO() */
178 : /************************************************************************/
179 :
180 0 : int OGREDIGEODataSource::ReadGEO() const
181 : {
182 0 : VSILFILE *fp = OpenFile(osGON, "GEO");
183 0 : if (fp == nullptr)
184 0 : return FALSE;
185 :
186 0 : const char *pszLine = nullptr;
187 0 : while ((pszLine = CPLReadLine2L(fp, 81, nullptr)) != nullptr)
188 : {
189 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
190 0 : continue;
191 :
192 0 : if (STARTS_WITH(pszLine, "RELSA"))
193 : {
194 0 : osREL = pszLine + 8;
195 0 : CPLDebug("EDIGEO", "REL = %s", osREL.c_str());
196 0 : break;
197 : }
198 : }
199 :
200 0 : VSIFCloseL(fp);
201 :
202 0 : if (osREL.empty())
203 : {
204 0 : CPLDebug("EDIGEO", "REL field missing");
205 0 : return FALSE;
206 : }
207 :
208 : /* All the SRS names mentioned in B.8.2.3 and B.8.3.1 are in the IGN file */
209 0 : poSRS = new OGRSpatialReference();
210 0 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
211 0 : CPLString osProj4Str = "+init=IGNF:" + osREL;
212 0 : if (poSRS->SetFromUserInput(osProj4Str.c_str()) != OGRERR_NONE)
213 : {
214 : /* Hard code a few common cases */
215 0 : if (osREL == "LAMB1")
216 0 : poSRS->importFromProj4(
217 : "+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.99987734 "
218 : "+x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 "
219 : "+nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
220 0 : else if (osREL == "LAMB2")
221 0 : poSRS->importFromProj4(
222 : "+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 "
223 : "+x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 "
224 : "+nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
225 0 : else if (osREL == "LAMB3")
226 0 : poSRS->importFromProj4(
227 : "+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.9998775 "
228 : "+x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 "
229 : "+nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
230 0 : else if (osREL == "LAMB4")
231 0 : poSRS->importFromProj4(
232 : "+proj=lcc +lat_1=42.165 +lat_0=42.165 +lon_0=0 "
233 : "+k_0=0.99994471 +x_0=234.358 +y_0=185861.369 +a=6378249.2 "
234 : "+b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris "
235 : "+units=m +no_defs");
236 0 : else if (osREL == "LAMB93")
237 0 : poSRS->importFromProj4(
238 : "+proj=lcc +lat_1=44 +lat_2=49 +lat_0=46.5 +lon_0=3 "
239 : "+x_0=700000 +y_0=6600000 +ellps=GRS81 +towgs84=0,0,0,0,0,0,0 "
240 : "+units=m +no_defs");
241 : else
242 : {
243 0 : CPLDebug("EDIGEO",
244 : "Cannot resolve %s SRS. Check that the IGNF file is in "
245 : "the directory of PROJ.4 resource files",
246 : osREL.c_str());
247 0 : delete poSRS;
248 0 : poSRS = nullptr;
249 : }
250 : }
251 :
252 0 : return TRUE;
253 : }
254 :
255 : /************************************************************************/
256 : /* ReadGEN() */
257 : /************************************************************************/
258 :
259 0 : int OGREDIGEODataSource::ReadGEN() const
260 : {
261 0 : VSILFILE *fp = OpenFile(osGNN, "GEN");
262 0 : if (fp == nullptr)
263 0 : return FALSE;
264 :
265 0 : const char *pszLine = nullptr;
266 0 : CPLString osCM1;
267 0 : CPLString osCM2;
268 0 : while ((pszLine = CPLReadLine2L(fp, 81, nullptr)) != nullptr)
269 : {
270 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
271 0 : continue;
272 :
273 0 : if (STARTS_WITH(pszLine, "CM1CC"))
274 : {
275 0 : osCM1 = pszLine + 8;
276 : }
277 0 : else if (STARTS_WITH(pszLine, "CM2CC"))
278 : {
279 0 : osCM2 = pszLine + 8;
280 : }
281 : }
282 :
283 0 : VSIFCloseL(fp);
284 :
285 0 : if (osCM1.empty() || osCM2.empty())
286 0 : return FALSE;
287 :
288 0 : char **papszTokens1 = CSLTokenizeString2(osCM1.c_str(), ";", 0);
289 0 : char **papszTokens2 = CSLTokenizeString2(osCM2.c_str(), ";", 0);
290 0 : if (CSLCount(papszTokens1) == 2 && CSLCount(papszTokens2) == 2)
291 : {
292 0 : bExtentValid = TRUE;
293 0 : dfMinX = CPLAtof(papszTokens1[0]);
294 0 : dfMinY = CPLAtof(papszTokens1[1]);
295 0 : dfMaxX = CPLAtof(papszTokens2[0]);
296 0 : dfMaxY = CPLAtof(papszTokens2[1]);
297 : }
298 0 : CSLDestroy(papszTokens1);
299 0 : CSLDestroy(papszTokens2);
300 :
301 0 : return bExtentValid;
302 : }
303 :
304 : /************************************************************************/
305 : /* ReadDIC() */
306 : /************************************************************************/
307 :
308 0 : int OGREDIGEODataSource::ReadDIC() const
309 : {
310 0 : VSILFILE *fp = OpenFile(osDIN, "DIC");
311 0 : if (fp == nullptr)
312 0 : return FALSE;
313 :
314 0 : const char *pszLine = nullptr;
315 0 : CPLString osRTY;
316 0 : CPLString osRID;
317 0 : CPLString osLAB;
318 0 : CPLString osTYP;
319 : while (true)
320 : {
321 0 : pszLine = CPLReadLine2L(fp, 81, nullptr);
322 0 : if (pszLine != nullptr)
323 : {
324 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
325 0 : continue;
326 : }
327 :
328 0 : if (pszLine == nullptr || STARTS_WITH(pszLine, "RTYSA"))
329 : {
330 0 : if (osRTY == "DID")
331 : {
332 : // CPLDebug("EDIGEO", "Object %s = %s",
333 : // osRID.c_str(), osLAB.c_str());
334 0 : mapObjects[osRID] = osLAB;
335 : }
336 0 : else if (osRTY == "DIA")
337 : {
338 : // CPLDebug("EDIGEO", "Attribute %s = %s, %s",
339 : // osRID.c_str(), osLAB.c_str(), osTYP.c_str());
340 0 : OGREDIGEOAttributeDef sAttributeDef;
341 0 : sAttributeDef.osLAB = osLAB;
342 0 : sAttributeDef.osTYP = osTYP;
343 0 : mapAttributes[osRID] = std::move(sAttributeDef);
344 : }
345 : }
346 :
347 0 : if (pszLine == nullptr)
348 0 : break;
349 :
350 0 : if (STARTS_WITH(pszLine, "RTYSA"))
351 : {
352 0 : osRTY = pszLine + 8;
353 0 : osRID = "";
354 0 : osLAB = "";
355 0 : osTYP = "";
356 : }
357 0 : else if (STARTS_WITH(pszLine, "RIDSA"))
358 0 : osRID = pszLine + 8;
359 0 : else if (STARTS_WITH(pszLine, "LABSA"))
360 0 : osLAB = pszLine + 8;
361 0 : else if (STARTS_WITH(pszLine, "TYPSA"))
362 0 : osTYP = pszLine + 8;
363 0 : }
364 :
365 0 : VSIFCloseL(fp);
366 :
367 0 : return TRUE;
368 : }
369 :
370 : /************************************************************************/
371 : /* ReadSCD() */
372 : /************************************************************************/
373 :
374 0 : int OGREDIGEODataSource::ReadSCD() const
375 : {
376 0 : VSILFILE *fp = OpenFile(osSCN, "SCD");
377 0 : if (fp == nullptr)
378 0 : return FALSE;
379 :
380 0 : const char *pszLine = nullptr;
381 0 : CPLString osRTY, osRID, osNameRID, osKND;
382 0 : strListType aosAttrRID;
383 0 : int nWidth = 0;
384 : while (true)
385 : {
386 0 : pszLine = CPLReadLine2L(fp, 81, nullptr);
387 0 : if (pszLine != nullptr)
388 : {
389 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
390 0 : continue;
391 : }
392 :
393 0 : if (pszLine == nullptr || STARTS_WITH(pszLine, "RTYSA"))
394 : {
395 0 : if (osRTY == "OBJ")
396 : {
397 0 : if (mapObjects.find(osNameRID) == mapObjects.end())
398 : {
399 0 : CPLDebug("EDIGEO", "Cannot find object %s",
400 : osNameRID.c_str());
401 : }
402 : else
403 : {
404 0 : OGREDIGEOObjectDescriptor objDesc;
405 0 : objDesc.osRID = osRID;
406 0 : objDesc.osNameRID = osNameRID;
407 0 : objDesc.osKND = osKND;
408 0 : objDesc.aosAttrRID = aosAttrRID;
409 : /*CPLDebug("EDIGEO", "Object %s = %s, %s, %d attributes",
410 : osRID.c_str(), osNameRID.c_str(), osKND.c_str(),
411 : (int)aosAttrRID.size());*/
412 :
413 0 : aoObjList.push_back(std::move(objDesc));
414 : }
415 : }
416 0 : else if (osRTY == "ATT")
417 : {
418 0 : if (mapAttributes.find(osNameRID) == mapAttributes.end())
419 : {
420 0 : CPLDebug("EDIGEO", "Cannot find attribute %s",
421 : osNameRID.c_str());
422 : }
423 : else
424 : {
425 0 : OGREDIGEOAttributeDescriptor attDesc;
426 0 : attDesc.osRID = osRID;
427 0 : attDesc.osNameRID = osNameRID;
428 0 : attDesc.nWidth = nWidth;
429 : /*CPLDebug("EDIGEO", "Attribute %s = %s, %d",
430 : osRID.c_str(), osNameRID.c_str(), nWidth);*/
431 :
432 0 : mapAttributesSCD[osRID] = std::move(attDesc);
433 : }
434 : }
435 : }
436 :
437 0 : if (pszLine == nullptr)
438 0 : break;
439 0 : if (STARTS_WITH(pszLine, "RTYSA"))
440 : {
441 0 : osRTY = pszLine + 8;
442 0 : osRID = "";
443 0 : osNameRID = "";
444 0 : osKND = "";
445 0 : aosAttrRID.resize(0);
446 0 : nWidth = 0;
447 : }
448 0 : else if (STARTS_WITH(pszLine, "RIDSA"))
449 0 : osRID = pszLine + 8;
450 0 : else if (STARTS_WITH(pszLine, "DIPCP"))
451 : {
452 0 : const char *pszDIP = pszLine + 8;
453 0 : char **papszTokens = CSLTokenizeString2(pszDIP, ";", 0);
454 0 : if (CSLCount(papszTokens) == 4)
455 : {
456 0 : osNameRID = papszTokens[3];
457 : }
458 0 : CSLDestroy(papszTokens);
459 : }
460 0 : else if (STARTS_WITH(pszLine, "KNDSA"))
461 0 : osKND = pszLine + 8;
462 0 : else if (STARTS_WITH(pszLine, "AAPCP"))
463 : {
464 0 : const char *pszAAP = pszLine + 8;
465 0 : char **papszTokens = CSLTokenizeString2(pszAAP, ";", 0);
466 0 : if (CSLCount(papszTokens) == 4)
467 : {
468 0 : const char *pszAttRID = papszTokens[3];
469 0 : aosAttrRID.push_back(pszAttRID);
470 : }
471 0 : CSLDestroy(papszTokens);
472 : }
473 0 : else if (STARTS_WITH(pszLine, "CANSN"))
474 0 : nWidth = atoi(pszLine + 8);
475 0 : }
476 :
477 0 : VSIFCloseL(fp);
478 :
479 0 : return TRUE;
480 : }
481 :
482 : /************************************************************************/
483 : /* ReadQAL() */
484 : /************************************************************************/
485 :
486 0 : int OGREDIGEODataSource::ReadQAL() const
487 : {
488 0 : VSILFILE *fp = OpenFile(osQAN, "QAL");
489 0 : if (fp == nullptr)
490 0 : return FALSE;
491 :
492 0 : const char *pszLine = nullptr;
493 0 : CPLString osRTY;
494 0 : CPLString osRID;
495 0 : int nODA = 0;
496 0 : int nUDA = 0;
497 : while (true)
498 : {
499 0 : pszLine = CPLReadLine2L(fp, 81, nullptr);
500 0 : if (pszLine != nullptr)
501 : {
502 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
503 0 : continue;
504 : }
505 :
506 0 : if (pszLine == nullptr || STARTS_WITH(pszLine, "RTYSA"))
507 : {
508 0 : if (osRTY == "QUP")
509 : {
510 0 : mapQAL[osRID] = intintType(nODA, nUDA);
511 : }
512 0 : if (pszLine == nullptr)
513 0 : break;
514 0 : osRTY = pszLine + 8;
515 0 : osRID = "";
516 0 : nODA = 0;
517 0 : nUDA = 0;
518 : }
519 0 : else if (STARTS_WITH(pszLine, "RIDSA"))
520 0 : osRID = pszLine + 8;
521 0 : else if (STARTS_WITH(pszLine, "ODASD"))
522 0 : nODA = atoi(pszLine + 8);
523 0 : else if (STARTS_WITH(pszLine, "UDASD"))
524 0 : nUDA = atoi(pszLine + 8);
525 : }
526 :
527 0 : VSIFCloseL(fp);
528 :
529 0 : return TRUE;
530 : }
531 :
532 : /************************************************************************/
533 : /* CreateLayerFromObjectDesc() */
534 : /************************************************************************/
535 :
536 0 : int OGREDIGEODataSource::CreateLayerFromObjectDesc(
537 : const OGREDIGEOObjectDescriptor &objDesc) const
538 : {
539 0 : OGRwkbGeometryType eType = wkbUnknown;
540 0 : if (objDesc.osKND == "ARE")
541 0 : eType = wkbPolygon;
542 0 : else if (objDesc.osKND == "LIN")
543 0 : eType = wkbLineString;
544 0 : else if (objDesc.osKND == "PCT")
545 0 : eType = wkbPoint;
546 : else
547 : {
548 0 : CPLDebug("EDIGEO", "Unknown KND : %s", objDesc.osKND.c_str());
549 0 : return FALSE;
550 : }
551 :
552 0 : const char *pszLayerName = objDesc.osRID.c_str();
553 : // mapObjects.find(objDesc.osNameRID)->second.c_str();
554 : OGREDIGEOLayer *poLayer = new OGREDIGEOLayer(
555 0 : const_cast<OGREDIGEODataSource *>(this), pszLayerName, eType, poSRS);
556 :
557 0 : poLayer->AddFieldDefn("OBJECT_RID", OFTString, "");
558 :
559 0 : for (int j = 0; j < (int)objDesc.aosAttrRID.size(); j++)
560 : {
561 : std::map<CPLString, OGREDIGEOAttributeDescriptor>::iterator it =
562 0 : mapAttributesSCD.find(objDesc.aosAttrRID[j]);
563 0 : if (it != mapAttributesSCD.end())
564 : {
565 0 : const OGREDIGEOAttributeDescriptor &attrDesc = it->second;
566 : const OGREDIGEOAttributeDef &attrDef =
567 0 : mapAttributes[attrDesc.osNameRID];
568 0 : OGRFieldType eFieldType = OFTString;
569 0 : if (attrDef.osTYP == "R" || attrDef.osTYP == "E")
570 0 : eFieldType = OFTReal;
571 0 : else if (attrDef.osTYP == "I" || attrDef.osTYP == "N")
572 0 : eFieldType = OFTInteger;
573 :
574 0 : poLayer->AddFieldDefn(attrDef.osLAB, eFieldType,
575 0 : objDesc.aosAttrRID[j]);
576 : }
577 : }
578 :
579 0 : if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") == 0)
580 : {
581 0 : OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
582 :
583 0 : iATR = poFDefn->GetFieldIndex("ATR");
584 0 : iDI3 = poFDefn->GetFieldIndex("DI3");
585 0 : iDI4 = poFDefn->GetFieldIndex("DI4");
586 0 : iHEI = poFDefn->GetFieldIndex("HEI");
587 0 : iFON = poFDefn->GetFieldIndex("FON");
588 :
589 0 : poLayer->AddFieldDefn("OGR_OBJ_LNK", OFTString, "");
590 0 : iOBJ_LNK = poFDefn->GetFieldIndex("OGR_OBJ_LNK");
591 :
592 0 : poLayer->AddFieldDefn("OGR_OBJ_LNK_LAYER", OFTString, "");
593 0 : iOBJ_LNK_LAYER = poFDefn->GetFieldIndex("OGR_OBJ_LNK_LAYER");
594 :
595 0 : poLayer->AddFieldDefn("OGR_ATR_VAL", OFTString, "");
596 0 : iATR_VAL = poFDefn->GetFieldIndex("OGR_ATR_VAL");
597 :
598 0 : poLayer->AddFieldDefn("OGR_ANGLE", OFTReal, "");
599 0 : iANGLE = poFDefn->GetFieldIndex("OGR_ANGLE");
600 :
601 0 : poLayer->AddFieldDefn("OGR_FONT_SIZE", OFTReal, "");
602 0 : iSIZE = poFDefn->GetFieldIndex("OGR_FONT_SIZE");
603 : }
604 0 : else if (!mapQAL.empty())
605 : {
606 0 : poLayer->AddFieldDefn("CREAT_DATE", OFTInteger, "");
607 0 : poLayer->AddFieldDefn("UPDATE_DATE", OFTInteger, "");
608 : }
609 :
610 0 : mapLayer[objDesc.osRID] = poLayer;
611 :
612 0 : papoLayers =
613 0 : (OGRLayer **)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer *));
614 0 : papoLayers[nLayers] = poLayer;
615 0 : nLayers++;
616 :
617 0 : return TRUE;
618 : }
619 :
620 : /************************************************************************/
621 : /* ReadVEC() */
622 : /************************************************************************/
623 :
624 0 : int OGREDIGEODataSource::ReadVEC(const char *pszVECName) const
625 : {
626 0 : VSILFILE *fp = OpenFile(pszVECName, "VEC");
627 0 : if (fp == nullptr)
628 0 : return FALSE;
629 :
630 0 : const char *pszLine = nullptr;
631 0 : CPLString osRTY, osRID;
632 0 : xyPairListType aXY;
633 0 : CPLString osLnkStartType, osLnkStartName, osLnkEndType, osLnkEndName;
634 0 : strListType osLnkEndNameList;
635 0 : CPLString osAttId;
636 0 : std::vector<strstrType> aosAttIdVal;
637 0 : CPLString osSCP;
638 0 : CPLString osQUP_RID;
639 0 : int bIso8859_1 = FALSE;
640 :
641 : while (true)
642 : {
643 0 : pszLine = CPLReadLine2L(fp, 81, nullptr);
644 0 : skip_read_next_line:
645 0 : if (pszLine != nullptr)
646 : {
647 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
648 0 : continue;
649 : }
650 :
651 0 : if (pszLine == nullptr || STARTS_WITH(pszLine, "RTYSA"))
652 : {
653 0 : if (osRTY == "PAR")
654 : {
655 0 : if (aXY.size() < 2)
656 0 : CPLDebug("EDIGEO", "Error: ARC %s has not enough points",
657 : osRID.c_str());
658 : else
659 0 : mapPAR[osRID] = aXY;
660 : }
661 0 : else if (osRTY == "LNK")
662 : {
663 0 : if (osLnkStartType == "PAR" && osLnkEndType == "PFE")
664 : {
665 : /*CPLDebug("EDIGEO", "PFE[%s] -> PAR[%s]",
666 : osLnkEndName.c_str(), osLnkStartName.c_str());*/
667 0 : if (mapPFE_PAR.find(osLnkEndName) == mapPFE_PAR.end())
668 0 : mapPFE_PAR[osLnkEndName].push_back(osLnkStartName);
669 : else
670 : {
671 0 : int bAlreadyExists = FALSE;
672 0 : strListType &osPARList = mapPFE_PAR[osLnkEndName];
673 0 : for (int j = 0; j < (int)osPARList.size(); j++)
674 : {
675 0 : if (osPARList[j] == osLnkStartName)
676 0 : bAlreadyExists = TRUE;
677 : }
678 0 : if (!bAlreadyExists)
679 0 : osPARList.push_back(osLnkStartName);
680 : }
681 : }
682 0 : else if (osLnkStartType == "FEA" && osLnkEndType == "PFE")
683 : {
684 : /*CPLDebug("EDIGEO", "FEA[%s] -> PFE[%s]",
685 : osLnkStartName.c_str(), osLnkEndName.c_str());*/
686 0 : listFEA_PFE.push_back(
687 0 : std::pair(osLnkStartName, osLnkEndNameList));
688 : }
689 0 : else if (osLnkStartType == "FEA" && osLnkEndType == "PAR")
690 : {
691 : /*CPLDebug("EDIGEO", "FEA[%s] -> PAR[%s]",
692 : osLnkStartName.c_str(), osLnkEndName.c_str());*/
693 0 : listFEA_PAR.push_back(
694 0 : std::pair(osLnkStartName, osLnkEndNameList));
695 : }
696 0 : else if (osLnkStartType == "FEA" && osLnkEndType == "PNO")
697 : {
698 : /*CPLDebug("EDIGEO", "FEA[%s] -> PNO[%s]",
699 : osLnkStartName.c_str(), osLnkEndName.c_str());*/
700 0 : listFEA_PNO.push_back(
701 0 : strstrType(osLnkStartName, osLnkEndName));
702 : }
703 0 : else if (osLnkStartType == "FEA" && osLnkEndType == "FEA")
704 : {
705 : /*CPLDebug("EDIGEO", "FEA[%s] -> FEA[%s]",
706 : osLnkStartName.c_str(), osLnkEndName.c_str());*/
707 0 : if (osSCP == "IS_S_REL_IWW")
708 0 : mapFEA_FEA[osLnkStartName] = osLnkEndName;
709 : }
710 0 : else if (osLnkStartType == "PAR" && osLnkEndType == "PNO")
711 : {
712 : }
713 : else
714 : {
715 0 : CPLDebug("EDIGEO", "Unhandled LNK(%s) %s=%s --> %s=%s",
716 : osRID.c_str(), osLnkStartType.c_str(),
717 : osLnkStartName.c_str(), osLnkEndType.c_str(),
718 : osLnkEndName.c_str());
719 : }
720 : }
721 0 : else if (osRTY == "FEA")
722 : {
723 0 : OGREDIGEOFEADesc feaDesc;
724 0 : feaDesc.aosAttIdVal = aosAttIdVal;
725 0 : feaDesc.osSCP = osSCP;
726 0 : feaDesc.osQUP_RID = osQUP_RID;
727 0 : mapFEA[osRID] = std::move(feaDesc);
728 : }
729 0 : else if (osRTY == "PNO")
730 : {
731 0 : if (aXY.size() == 1)
732 : {
733 : /*CPLDebug("EDIGEO", "PNO[%s] = %f, %f",
734 : osRID.c_str(), aXY[0].first, aXY[0].second);*/
735 0 : mapPNO[osRID] = aXY[0];
736 : }
737 : }
738 0 : if (pszLine == nullptr)
739 0 : break;
740 0 : osRTY = pszLine + 8;
741 0 : osRID = "";
742 0 : aXY.resize(0);
743 0 : osLnkStartType = "";
744 0 : osLnkStartName = "";
745 0 : osLnkEndType = "";
746 0 : osLnkEndName = "";
747 0 : osAttId = "";
748 0 : aosAttIdVal.resize(0);
749 0 : osLnkEndNameList.resize(0);
750 0 : osSCP = "";
751 0 : osQUP_RID = "";
752 0 : bIso8859_1 = FALSE;
753 : }
754 0 : else if (STARTS_WITH(pszLine, "RIDSA"))
755 0 : osRID = pszLine + 8;
756 0 : else if (STARTS_WITH(pszLine, "CORCC"))
757 : {
758 0 : const char *pszY = strchr(pszLine + 8, ';');
759 0 : if (pszY)
760 : {
761 0 : double dfX = CPLAtof(pszLine + 8);
762 0 : double dfY = CPLAtof(pszY + 1);
763 0 : aXY.push_back(xyPairType(dfX, dfY));
764 : }
765 : }
766 0 : else if (STARTS_WITH(pszLine, "FTPCP"))
767 : {
768 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
769 0 : if (CSLCount(papszTokens) == 4)
770 : {
771 0 : if (osLnkStartType.empty())
772 : {
773 0 : osLnkStartType = papszTokens[2];
774 0 : osLnkStartName = papszTokens[3];
775 : }
776 : else
777 : {
778 0 : osLnkEndType = papszTokens[2];
779 0 : osLnkEndName = papszTokens[3];
780 0 : osLnkEndNameList.push_back(osLnkEndName);
781 : }
782 : }
783 0 : CSLDestroy(papszTokens);
784 : }
785 0 : else if (STARTS_WITH(pszLine, "SCPCP"))
786 : {
787 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
788 0 : if (CSLCount(papszTokens) == 4)
789 : {
790 0 : if (osRTY == "LNK")
791 : {
792 0 : if (strcmp(papszTokens[2], "ASS") == 0)
793 0 : osSCP = papszTokens[3];
794 : }
795 0 : else if (strcmp(papszTokens[2], "OBJ") == 0)
796 0 : osSCP = papszTokens[3];
797 : }
798 0 : CSLDestroy(papszTokens);
799 : }
800 0 : else if (STARTS_WITH(pszLine, "ATPCP"))
801 : {
802 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
803 0 : if (CSLCount(papszTokens) == 4)
804 : {
805 0 : if (strcmp(papszTokens[2], "ATT") == 0)
806 0 : osAttId = papszTokens[3];
807 : }
808 0 : CSLDestroy(papszTokens);
809 : }
810 0 : else if (strcmp(pszLine, "TEXT 06:8859-1") == 0)
811 : {
812 0 : bIso8859_1 = TRUE;
813 : }
814 0 : else if (STARTS_WITH(pszLine, "ATVS"))
815 : {
816 0 : CPLString osAttVal = pszLine + 8;
817 : while (true)
818 : {
819 0 : pszLine = CPLReadLine2L(fp, 81, nullptr);
820 0 : if (pszLine != nullptr && strlen(pszLine) >= 8 &&
821 0 : pszLine[7] == ':' && STARTS_WITH(pszLine, "NEXT "))
822 : {
823 0 : osAttVal += pszLine + 8;
824 : }
825 : else
826 : {
827 : break;
828 : }
829 : }
830 0 : if (bIso8859_1 && bRecodeToUTF8)
831 : {
832 0 : char *pszNewVal = CPLRecode(osAttVal.c_str(), CPL_ENC_ISO8859_1,
833 : CPL_ENC_UTF8);
834 0 : osAttVal = pszNewVal;
835 0 : CPLFree(pszNewVal);
836 : }
837 0 : else if (bHasUTF8ContentOnly)
838 : {
839 0 : bHasUTF8ContentOnly =
840 0 : CPL_TO_BOOL(CPLIsUTF8(osAttVal.c_str(), -1));
841 : }
842 0 : if (!osAttId.empty())
843 0 : aosAttIdVal.push_back(strstrType(osAttId, osAttVal));
844 0 : osAttId = "";
845 0 : bIso8859_1 = FALSE;
846 0 : goto skip_read_next_line;
847 : }
848 0 : else if (STARTS_WITH(pszLine, "ATVCP"))
849 : {
850 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
851 0 : if (CSLCount(papszTokens) == 4)
852 : {
853 0 : if (strcmp(papszTokens[2], "ATT") == 0)
854 : {
855 0 : CPLString osAttVal = papszTokens[3];
856 0 : if (!osAttId.empty())
857 0 : aosAttIdVal.push_back(strstrType(osAttId, osAttVal));
858 0 : osAttId = "";
859 : }
860 : }
861 0 : CSLDestroy(papszTokens);
862 : }
863 0 : else if (STARTS_WITH(pszLine, "QAPCP"))
864 : {
865 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
866 0 : if (CSLCount(papszTokens) == 4)
867 : {
868 0 : if (strcmp(papszTokens[2], "QUP") == 0)
869 : {
870 0 : osQUP_RID = papszTokens[3];
871 : }
872 : }
873 0 : CSLDestroy(papszTokens);
874 : }
875 0 : }
876 :
877 0 : VSIFCloseL(fp);
878 :
879 0 : return TRUE;
880 : }
881 :
882 : /************************************************************************/
883 : /* CreateFeature() */
884 : /************************************************************************/
885 :
886 0 : OGRFeature *OGREDIGEODataSource::CreateFeature(const CPLString &osFEA) const
887 : {
888 : const std::map<CPLString, OGREDIGEOFEADesc>::iterator itFEA =
889 0 : mapFEA.find(osFEA);
890 0 : if (itFEA == mapFEA.end())
891 : {
892 0 : CPLDebug("EDIGEO", "ERROR: Cannot find FEA %s", osFEA.c_str());
893 0 : return nullptr;
894 : }
895 :
896 0 : const OGREDIGEOFEADesc &fea = itFEA->second;
897 : const std::map<CPLString, OGREDIGEOLayer *>::iterator itLyr =
898 0 : mapLayer.find(fea.osSCP);
899 0 : if (itLyr != mapLayer.end())
900 : {
901 0 : OGREDIGEOLayer *poLayer = itLyr->second;
902 :
903 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
904 0 : poFeature->SetField(0, itFEA->first.c_str());
905 0 : for (int i = 0; i < (int)fea.aosAttIdVal.size(); i++)
906 : {
907 0 : const CPLString &id = fea.aosAttIdVal[i].first;
908 0 : const CPLString &val = fea.aosAttIdVal[i].second;
909 0 : int iIndex = poLayer->GetAttributeIndex(id);
910 0 : if (iIndex != -1)
911 0 : poFeature->SetField(iIndex, val.c_str());
912 : else
913 0 : CPLDebug("EDIGEO", "ERROR: Cannot find attribute %s",
914 : id.c_str());
915 : }
916 :
917 0 : if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 &&
918 0 : !mapQAL.empty() && !fea.osQUP_RID.empty())
919 : {
920 : const std::map<CPLString, intintType>::iterator itQAL =
921 0 : mapQAL.find(fea.osQUP_RID);
922 0 : if (itQAL != mapQAL.end())
923 : {
924 0 : const intintType &creationUpdateDate = itQAL->second;
925 0 : if (creationUpdateDate.first != 0)
926 0 : poFeature->SetField("CREAT_DATE", creationUpdateDate.first);
927 0 : if (creationUpdateDate.second != 0)
928 0 : poFeature->SetField("UPDATE_DATE",
929 0 : creationUpdateDate.second);
930 : }
931 : }
932 :
933 0 : poLayer->AddFeature(poFeature);
934 :
935 0 : return poFeature;
936 : }
937 : else
938 : {
939 0 : CPLDebug("EDIGEO", "ERROR: Cannot find layer %s", fea.osSCP.c_str());
940 0 : return nullptr;
941 : }
942 : }
943 :
944 : /************************************************************************/
945 : /* SetStyle() */
946 : /************************************************************************/
947 :
948 0 : int OGREDIGEODataSource::SetStyle(const CPLString &osFEA,
949 : OGRFeature *poFeature) const
950 : {
951 : /* EDIGEO PCI specific */
952 : /* See EDIGeO_PCI.pdf, chapter 3 "Principes généraux de */
953 : /* positionnement de la toponymie. */
954 0 : const char *pszATR = nullptr;
955 0 : if (strcmp(poFeature->GetDefnRef()->GetName(), "ID_S_OBJ_Z_1_2_2") == 0 &&
956 0 : iATR != -1 && (pszATR = poFeature->GetFieldAsString(iATR)) != nullptr)
957 : {
958 0 : const CPLString osATR(pszATR);
959 : std::map<CPLString, CPLString>::iterator itFEA_FEA =
960 0 : mapFEA_FEA.find(osFEA);
961 0 : if (itFEA_FEA != mapFEA_FEA.end())
962 : {
963 0 : const CPLString &osOBJ_LNK = itFEA_FEA->second;
964 : std::map<CPLString, OGREDIGEOFEADesc>::iterator itFEA_LNK =
965 0 : mapFEA.find(osOBJ_LNK);
966 0 : if (itFEA_LNK != mapFEA.end())
967 : {
968 0 : const OGREDIGEOFEADesc &fea_lnk = itFEA_LNK->second;
969 0 : for (int j = 0; j < (int)fea_lnk.aosAttIdVal.size(); j++)
970 : {
971 0 : if (fea_lnk.aosAttIdVal[j].first == osATR)
972 : {
973 0 : double dfAngle = 0;
974 0 : if (iDI3 != -1 && iDI4 != -1)
975 : {
976 : double dfBaseVectorX =
977 0 : poFeature->GetFieldAsDouble(iDI3);
978 : double dfBaseVectorY =
979 0 : poFeature->GetFieldAsDouble(iDI4);
980 0 : dfAngle = atan2(dfBaseVectorY, dfBaseVectorX) /
981 : M_PI * 180;
982 0 : if (dfAngle < 0)
983 0 : dfAngle += 360;
984 : }
985 0 : double dfSize = 1;
986 0 : if (iHEI != -1)
987 0 : dfSize = poFeature->GetFieldAsDouble(iHEI);
988 0 : if (dfSize <= 0 || dfSize >= 100)
989 0 : dfSize = 1;
990 0 : const char *pszFontFamily = nullptr;
991 0 : if (iFON != -1)
992 0 : pszFontFamily = poFeature->GetFieldAsString(iFON);
993 :
994 0 : CPLString osStyle("LABEL(t:\"");
995 0 : osStyle += fea_lnk.aosAttIdVal[j].second;
996 0 : osStyle += "\"";
997 0 : if (dfAngle != 0)
998 : {
999 0 : osStyle += ",a:";
1000 0 : osStyle += CPLString().Printf("%.1f", dfAngle);
1001 : }
1002 0 : if (pszFontFamily != nullptr && bIncludeFontFamily)
1003 : {
1004 0 : osStyle += ",f:\"";
1005 0 : osStyle += pszFontFamily;
1006 0 : osStyle += "\"";
1007 : }
1008 0 : osStyle += ",s:";
1009 0 : osStyle += CPLString().Printf("%.1f", dfSize);
1010 0 : osStyle += ",c:#000000)";
1011 0 : poFeature->SetStyleString(osStyle);
1012 :
1013 0 : poFeature->SetField(iATR_VAL,
1014 0 : fea_lnk.aosAttIdVal[j].second);
1015 0 : poFeature->SetField(iANGLE, dfAngle);
1016 0 : poFeature->SetField(iSIZE, dfSize * dfSizeFactor);
1017 0 : poFeature->SetField(iOBJ_LNK, osOBJ_LNK);
1018 0 : poFeature->SetField(iOBJ_LNK_LAYER, fea_lnk.osSCP);
1019 :
1020 0 : setLayersWithLabels.insert(fea_lnk.osSCP);
1021 :
1022 0 : break;
1023 : }
1024 : }
1025 : }
1026 : }
1027 : }
1028 :
1029 0 : return TRUE;
1030 : }
1031 :
1032 : /************************************************************************/
1033 : /* BuildPoints() */
1034 : /************************************************************************/
1035 :
1036 0 : int OGREDIGEODataSource::BuildPoints() const
1037 : {
1038 0 : for (int i = 0; i < (int)listFEA_PNO.size(); i++)
1039 : {
1040 0 : const CPLString &osFEA = listFEA_PNO[i].first;
1041 0 : const CPLString &osPNO = listFEA_PNO[i].second;
1042 : const std::map<CPLString, xyPairType>::iterator itPNO =
1043 0 : mapPNO.find(osPNO);
1044 0 : if (itPNO == mapPNO.end())
1045 : {
1046 0 : CPLDebug("EDIGEO", "Cannot find PNO %s", osPNO.c_str());
1047 : }
1048 : else
1049 : {
1050 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1051 0 : if (poFeature)
1052 : {
1053 0 : const xyPairType &pno = itPNO->second;
1054 0 : OGRPoint *poPoint = new OGRPoint(pno.first, pno.second);
1055 0 : if (poSRS)
1056 0 : poPoint->assignSpatialReference(poSRS);
1057 0 : poFeature->SetGeometryDirectly(poPoint);
1058 :
1059 0 : SetStyle(osFEA, poFeature);
1060 : }
1061 : }
1062 : }
1063 :
1064 0 : return TRUE;
1065 : }
1066 :
1067 : /************************************************************************/
1068 : /* BuildLineStrings() */
1069 : /************************************************************************/
1070 :
1071 0 : int OGREDIGEODataSource::BuildLineStrings() const
1072 : {
1073 : int i, iter;
1074 :
1075 0 : for (iter = 0; iter < (int)listFEA_PAR.size(); iter++)
1076 : {
1077 0 : const CPLString &osFEA = listFEA_PAR[iter].first;
1078 0 : const strListType &aosPAR = listFEA_PAR[iter].second;
1079 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1080 0 : if (poFeature)
1081 : {
1082 0 : OGRGeometry *poGeom = nullptr;
1083 0 : OGRMultiLineString *poMulti = nullptr;
1084 0 : for (int k = 0; k < (int)aosPAR.size(); k++)
1085 : {
1086 : const std::map<CPLString, xyPairListType>::iterator itPAR =
1087 0 : mapPAR.find(aosPAR[k]);
1088 0 : if (itPAR != mapPAR.end())
1089 : {
1090 0 : const xyPairListType &arc = itPAR->second;
1091 :
1092 0 : OGRLineString *poLS = new OGRLineString();
1093 0 : poLS->setNumPoints((int)arc.size());
1094 0 : for (i = 0; i < (int)arc.size(); i++)
1095 : {
1096 0 : poLS->setPoint(i, arc[i].first, arc[i].second);
1097 : }
1098 :
1099 0 : if (poGeom != nullptr)
1100 : {
1101 0 : if (poMulti == nullptr)
1102 : {
1103 0 : poMulti = new OGRMultiLineString();
1104 0 : poMulti->addGeometryDirectly(poGeom);
1105 0 : poGeom = poMulti;
1106 : }
1107 0 : poMulti->addGeometryDirectly(poLS);
1108 : }
1109 : else
1110 0 : poGeom = poLS;
1111 : }
1112 : else
1113 0 : CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s",
1114 0 : aosPAR[k].c_str());
1115 : }
1116 0 : if (poGeom != nullptr)
1117 : {
1118 0 : poGeom->assignSpatialReference(poSRS);
1119 0 : poFeature->SetGeometryDirectly(poGeom);
1120 : }
1121 : }
1122 : }
1123 :
1124 0 : return TRUE;
1125 : }
1126 :
1127 : /************************************************************************/
1128 : /* BuildPolygon() */
1129 : /************************************************************************/
1130 :
1131 0 : int OGREDIGEODataSource::BuildPolygon(const CPLString &osFEA,
1132 : const strListType &aosPFE) const
1133 : {
1134 0 : std::vector<xyPairListType> aoXYList;
1135 :
1136 0 : for (int k = 0; k < (int)aosPFE.size(); k++)
1137 : {
1138 : const std::map<CPLString, strListType>::iterator itPFE_PAR =
1139 0 : mapPFE_PAR.find(aosPFE[k]);
1140 0 : if (itPFE_PAR == mapPFE_PAR.end())
1141 : {
1142 0 : CPLDebug("EDIGEO", "ERROR: Cannot find PFE %s", aosPFE[k].c_str());
1143 0 : return FALSE;
1144 : }
1145 :
1146 0 : const strListType &aosPARList = itPFE_PAR->second;
1147 :
1148 : /* --------------------------------------------------------------------
1149 : */
1150 : /* Resolve arc ids to arc coordinate lists. */
1151 : /* --------------------------------------------------------------------
1152 : */
1153 0 : std::vector<const xyPairListType *> aoPARPtrList;
1154 0 : for (int i = 0; i < (int)aosPARList.size(); i++)
1155 : {
1156 : const std::map<CPLString, xyPairListType>::iterator itPAR =
1157 0 : mapPAR.find(aosPARList[i]);
1158 0 : if (itPAR != mapPAR.end())
1159 0 : aoPARPtrList.push_back(&(itPAR->second));
1160 : else
1161 0 : CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s",
1162 0 : aosPARList[i].c_str());
1163 : }
1164 :
1165 0 : if (aoPARPtrList.empty())
1166 0 : return FALSE;
1167 :
1168 : /* --------------------------------------------------------------------
1169 : */
1170 : /* Now try to chain all arcs together. */
1171 : /* --------------------------------------------------------------------
1172 : */
1173 :
1174 0 : for (int j = 0; j < (int)aoPARPtrList.size(); j++)
1175 : {
1176 0 : if (aoPARPtrList[j] == nullptr)
1177 0 : continue;
1178 0 : const xyPairListType &sFirstRing = *(aoPARPtrList[j]);
1179 0 : const xyPairType *psNext = &(sFirstRing.back());
1180 :
1181 0 : xyPairListType aoXY;
1182 0 : for (int i = 0; i < (int)sFirstRing.size(); i++)
1183 0 : aoXY.push_back(sFirstRing[i]);
1184 0 : aoPARPtrList[j] = nullptr;
1185 :
1186 0 : int nIter = 1;
1187 0 : while (aoXY.back() != aoXY[0] && nIter < (int)aoPARPtrList.size())
1188 : {
1189 0 : bool bFound = false;
1190 0 : bool bReverseSecond = false;
1191 0 : int i = 0; // Used after for.
1192 0 : for (; i < (int)aoPARPtrList.size(); i++)
1193 : {
1194 0 : if (aoPARPtrList[i] != nullptr)
1195 : {
1196 0 : const xyPairListType &sSecondRing = *(aoPARPtrList[i]);
1197 0 : if (*psNext == sSecondRing[0])
1198 : {
1199 0 : bFound = true;
1200 0 : bReverseSecond = false;
1201 0 : break;
1202 : }
1203 0 : else if (*psNext == sSecondRing.back())
1204 : {
1205 0 : bFound = true;
1206 0 : bReverseSecond = true;
1207 0 : break;
1208 : }
1209 : }
1210 : }
1211 :
1212 0 : if (!bFound)
1213 : {
1214 0 : CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s",
1215 0 : osFEA.c_str(), aosPFE[k].c_str());
1216 0 : break;
1217 : }
1218 : else
1219 : {
1220 0 : const xyPairListType &secondRing = *(aoPARPtrList[i]);
1221 0 : aoPARPtrList[i] = nullptr;
1222 0 : if (!bReverseSecond)
1223 : {
1224 0 : for (i = 1; i < (int)secondRing.size(); i++)
1225 0 : aoXY.push_back(secondRing[i]);
1226 0 : psNext = &secondRing.back();
1227 : }
1228 : else
1229 : {
1230 0 : for (i = 1; i < (int)secondRing.size(); i++)
1231 0 : aoXY.push_back(
1232 0 : secondRing[secondRing.size() - 1 - i]);
1233 0 : psNext = &secondRing[0];
1234 : }
1235 : }
1236 :
1237 0 : nIter++;
1238 : }
1239 :
1240 0 : aoXYList.push_back(std::move(aoXY));
1241 : }
1242 : }
1243 :
1244 : /* -------------------------------------------------------------------- */
1245 : /* Create feature. */
1246 : /* -------------------------------------------------------------------- */
1247 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1248 0 : if (poFeature)
1249 : {
1250 0 : std::vector<std::unique_ptr<OGRGeometry>> apoPolygons;
1251 0 : apoPolygons.reserve(aoXYList.size());
1252 0 : for (const xyPairListType &aoXY : aoXYList)
1253 : {
1254 0 : auto poLS = std::make_unique<OGRLinearRing>();
1255 0 : poLS->setNumPoints((int)aoXY.size());
1256 0 : for (int i = 0; i < (int)aoXY.size(); i++)
1257 0 : poLS->setPoint(i, aoXY[i].first, aoXY[i].second);
1258 0 : poLS->closeRings();
1259 0 : auto poPolygon = std::make_unique<OGRPolygon>();
1260 0 : poPolygon->addRing(std::move(poLS));
1261 0 : apoPolygons.push_back(std::move(poPolygon));
1262 : }
1263 :
1264 0 : auto poGeom = OGRGeometryFactory::organizePolygons(apoPolygons);
1265 0 : if (poGeom)
1266 : {
1267 0 : if (poSRS)
1268 0 : poGeom->assignSpatialReference(poSRS);
1269 0 : poFeature->SetGeometry(std::move(poGeom));
1270 : }
1271 : }
1272 0 : return TRUE;
1273 : }
1274 :
1275 : /************************************************************************/
1276 : /* BuildPolygons() */
1277 : /************************************************************************/
1278 :
1279 0 : int OGREDIGEODataSource::BuildPolygons() const
1280 : {
1281 0 : for (int iter = 0; iter < (int)listFEA_PFE.size(); iter++)
1282 : {
1283 0 : const CPLString &osFEA = listFEA_PFE[iter].first;
1284 0 : const strListType &aosPFE = listFEA_PFE[iter].second;
1285 0 : BuildPolygon(osFEA, aosPFE);
1286 : }
1287 :
1288 0 : return TRUE;
1289 : }
1290 :
1291 : /************************************************************************/
1292 : /* OGREDIGEOSortForQGIS() */
1293 : /************************************************************************/
1294 :
1295 0 : static int OGREDIGEOSortForQGIS(const void *a, const void *b)
1296 : {
1297 0 : OGREDIGEOLayer *poLayerA = *((OGREDIGEOLayer **)a);
1298 0 : OGREDIGEOLayer *poLayerB = *((OGREDIGEOLayer **)b);
1299 : int nTypeA, nTypeB;
1300 0 : switch (poLayerA->GetLayerDefn()->GetGeomType())
1301 : {
1302 0 : case wkbPoint:
1303 0 : nTypeA = 1;
1304 0 : break;
1305 0 : case wkbLineString:
1306 0 : nTypeA = 2;
1307 0 : break;
1308 0 : case wkbPolygon:
1309 0 : nTypeA = 3;
1310 0 : break;
1311 0 : default:
1312 0 : nTypeA = 4;
1313 0 : break;
1314 : }
1315 0 : switch (poLayerB->GetLayerDefn()->GetGeomType())
1316 : {
1317 0 : case wkbPoint:
1318 0 : nTypeB = 1;
1319 0 : break;
1320 0 : case wkbLineString:
1321 0 : nTypeB = 2;
1322 0 : break;
1323 0 : case wkbPolygon:
1324 0 : nTypeB = 3;
1325 0 : break;
1326 0 : default:
1327 0 : nTypeB = 4;
1328 0 : break;
1329 : }
1330 0 : if (nTypeA == nTypeB)
1331 : {
1332 0 : int nCmp = strcmp(poLayerA->GetName(), poLayerB->GetName());
1333 0 : if (nCmp == 0)
1334 0 : return 0;
1335 :
1336 : static const char *const apszPolyOrder[] = {
1337 : "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id",
1338 : "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id"};
1339 0 : for (int i = 0; i < (int)(sizeof(apszPolyOrder) / sizeof(char *)); i++)
1340 : {
1341 0 : if (strcmp(poLayerA->GetName(), apszPolyOrder[i]) == 0)
1342 0 : return -1;
1343 0 : if (strcmp(poLayerB->GetName(), apszPolyOrder[i]) == 0)
1344 0 : return 1;
1345 : }
1346 0 : return nCmp;
1347 : }
1348 : else
1349 0 : return nTypeB - nTypeA;
1350 : }
1351 :
1352 : /************************************************************************/
1353 : /* Open() */
1354 : /************************************************************************/
1355 :
1356 0 : int OGREDIGEODataSource::Open(const char *pszFilename)
1357 :
1358 : {
1359 0 : fpTHF = VSIFOpenL(pszFilename, "rb");
1360 0 : if (fpTHF == nullptr)
1361 0 : return FALSE;
1362 :
1363 0 : const char *pszLine = nullptr;
1364 0 : int i = 0;
1365 0 : bool bIsEDIGEO = false;
1366 0 : while (i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, nullptr)) != nullptr)
1367 : {
1368 0 : if (strcmp(pszLine, "RTYSA03:GTS") == 0)
1369 : {
1370 0 : bIsEDIGEO = true;
1371 0 : break;
1372 : }
1373 0 : i++;
1374 : }
1375 :
1376 0 : if (!bIsEDIGEO)
1377 : {
1378 0 : VSIFCloseL(fpTHF);
1379 0 : fpTHF = nullptr;
1380 0 : return FALSE;
1381 : }
1382 :
1383 0 : return TRUE;
1384 : }
1385 :
1386 : /************************************************************************/
1387 : /* ReadEDIGEO() */
1388 : /************************************************************************/
1389 :
1390 0 : void OGREDIGEODataSource::ReadEDIGEO() const
1391 : {
1392 0 : std::lock_guard oLock(m_oMutex);
1393 0 : if (bHasReadEDIGEO)
1394 0 : return;
1395 :
1396 0 : bHasReadEDIGEO = TRUE;
1397 :
1398 : /* -------------------------------------------------------------------- */
1399 : /* Read .THF file */
1400 : /* -------------------------------------------------------------------- */
1401 0 : VSIFSeekL(fpTHF, 0, SEEK_SET);
1402 0 : if (!ReadTHF(fpTHF))
1403 : {
1404 0 : VSIFCloseL(fpTHF);
1405 0 : fpTHF = nullptr;
1406 0 : return;
1407 : }
1408 0 : VSIFCloseL(fpTHF);
1409 0 : fpTHF = nullptr;
1410 :
1411 : /* -------------------------------------------------------------------- */
1412 : /* Read .GEO file */
1413 : /* -------------------------------------------------------------------- */
1414 0 : if (!ReadGEO())
1415 0 : return;
1416 :
1417 : /* -------------------------------------------------------------------- */
1418 : /* Read .GEN file */
1419 : /* -------------------------------------------------------------------- */
1420 0 : if (!osGNN.empty())
1421 0 : ReadGEN();
1422 :
1423 : /* -------------------------------------------------------------------- */
1424 : /* Read .DIC file */
1425 : /* -------------------------------------------------------------------- */
1426 0 : if (!ReadDIC())
1427 0 : return;
1428 :
1429 : /* -------------------------------------------------------------------- */
1430 : /* Read .SCD file */
1431 : /* -------------------------------------------------------------------- */
1432 0 : if (!ReadSCD())
1433 0 : return;
1434 :
1435 : /* -------------------------------------------------------------------- */
1436 : /* Read .QAL file */
1437 : /* -------------------------------------------------------------------- */
1438 0 : if (!osQAN.empty())
1439 0 : ReadQAL();
1440 :
1441 : /* -------------------------------------------------------------------- */
1442 : /* Create layers from SCD definitions */
1443 : /* -------------------------------------------------------------------- */
1444 0 : for (int i = 0; i < (int)aoObjList.size(); i++)
1445 : {
1446 0 : CreateLayerFromObjectDesc(aoObjList[i]);
1447 : }
1448 :
1449 : /* -------------------------------------------------------------------- */
1450 : /* Read .VEC files and create features */
1451 : /* -------------------------------------------------------------------- */
1452 0 : for (int i = 0; i < (int)aosGDN.size(); i++)
1453 : {
1454 0 : ReadVEC(aosGDN[i]);
1455 :
1456 0 : BuildPoints();
1457 0 : BuildLineStrings();
1458 0 : BuildPolygons();
1459 :
1460 0 : mapPNO.clear();
1461 0 : mapPAR.clear();
1462 0 : mapFEA.clear();
1463 0 : mapPFE_PAR.clear();
1464 0 : listFEA_PFE.clear();
1465 0 : listFEA_PAR.clear();
1466 0 : listFEA_PNO.clear();
1467 0 : mapFEA_FEA.clear();
1468 : }
1469 :
1470 0 : mapObjects.clear();
1471 0 : mapAttributes.clear();
1472 0 : mapAttributesSCD.clear();
1473 0 : mapQAL.clear();
1474 :
1475 : /* -------------------------------------------------------------------- */
1476 : /* Delete empty layers */
1477 : /* -------------------------------------------------------------------- */
1478 0 : for (int i = 0; i < nLayers; /*nothing*/)
1479 : {
1480 0 : if (papoLayers[i]->GetFeatureCount(TRUE) == 0)
1481 : {
1482 0 : delete papoLayers[i];
1483 0 : if (i < nLayers - 1)
1484 0 : memmove(papoLayers + i, papoLayers + i + 1,
1485 0 : (nLayers - i - 1) * sizeof(OGREDIGEOLayer *));
1486 0 : nLayers--;
1487 : }
1488 : else
1489 0 : i++;
1490 : }
1491 :
1492 : /* -------------------------------------------------------------------- */
1493 : /* When added from QGIS, the layers must be ordered from */
1494 : /* bottom (Polygon) to top (Point) to get nice visual effect */
1495 : /* -------------------------------------------------------------------- */
1496 0 : if (CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES")))
1497 0 : qsort(papoLayers, nLayers, sizeof(OGREDIGEOLayer *),
1498 : OGREDIGEOSortForQGIS);
1499 :
1500 : /* -------------------------------------------------------------------- */
1501 : /* Create a label layer for each feature layer */
1502 : /* -------------------------------------------------------------------- */
1503 0 : if (CPLTestBool(
1504 : CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES")))
1505 0 : CreateLabelLayers();
1506 :
1507 0 : return;
1508 : }
1509 :
1510 : /************************************************************************/
1511 : /* CreateLabelLayers() */
1512 : /************************************************************************/
1513 :
1514 0 : void OGREDIGEODataSource::CreateLabelLayers() const
1515 : {
1516 0 : OGRLayer *poLayer = const_cast<OGREDIGEODataSource *>(this)->GetLayerByName(
1517 0 : "ID_S_OBJ_Z_1_2_2");
1518 0 : if (poLayer == nullptr)
1519 0 : return;
1520 :
1521 0 : std::map<CPLString, OGREDIGEOLayer *> mapLayerNameToLayer;
1522 :
1523 0 : OGRFeature *poFeature = nullptr;
1524 0 : OGRFeatureDefn *poFeatureDefn = poLayer->GetLayerDefn();
1525 0 : while ((poFeature = poLayer->GetNextFeature()) != nullptr)
1526 : {
1527 : const char *pszBelongingLayerName =
1528 0 : poFeature->GetFieldAsString(iOBJ_LNK_LAYER);
1529 0 : if (pszBelongingLayerName)
1530 : {
1531 0 : CPLString osBelongingLayerName = pszBelongingLayerName;
1532 : std::map<CPLString, OGREDIGEOLayer *>::iterator it =
1533 0 : mapLayerNameToLayer.find(osBelongingLayerName);
1534 0 : OGREDIGEOLayer *poLabelLayer = nullptr;
1535 :
1536 0 : if (it == mapLayerNameToLayer.end())
1537 : {
1538 : /* Create label layer if it does not already exist */
1539 0 : CPLString osLayerLabelName = osBelongingLayerName + "_LABEL";
1540 0 : poLabelLayer = new OGREDIGEOLayer(
1541 : const_cast<OGREDIGEODataSource *>(this),
1542 0 : osLayerLabelName.c_str(), wkbPoint, poSRS);
1543 : OGRFeatureDefn *poLabelFeatureDefn =
1544 0 : poLabelLayer->GetLayerDefn();
1545 0 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
1546 0 : poLabelFeatureDefn->AddFieldDefn(
1547 0 : poFeatureDefn->GetFieldDefn(i));
1548 0 : mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer;
1549 :
1550 0 : papoLayers = (OGRLayer **)CPLRealloc(
1551 0 : papoLayers, (nLayers + 1) * sizeof(OGRLayer *));
1552 0 : papoLayers[nLayers] = poLabelLayer;
1553 0 : nLayers++;
1554 : }
1555 : else
1556 : {
1557 0 : poLabelLayer = mapLayerNameToLayer[osBelongingLayerName];
1558 : }
1559 :
1560 : OGRFeature *poNewFeature =
1561 0 : new OGRFeature(poLabelLayer->GetLayerDefn());
1562 0 : poNewFeature->SetFrom(poFeature);
1563 0 : poLabelLayer->AddFeature(poNewFeature);
1564 : }
1565 0 : delete poFeature;
1566 : }
1567 :
1568 0 : poLayer->ResetReading();
1569 : }
|