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 : CPLGetConfigOption("OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"))),
34 0 : bHasReadEDIGEO(FALSE)
35 : {
36 0 : if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
37 0 : dfSizeFactor = 2;
38 0 : }
39 :
40 : /************************************************************************/
41 : /* ~OGREDIGEODataSource() */
42 : /************************************************************************/
43 :
44 0 : OGREDIGEODataSource::~OGREDIGEODataSource()
45 :
46 : {
47 0 : for (int i = 0; i < nLayers; i++)
48 0 : delete papoLayers[i];
49 0 : CPLFree(papoLayers);
50 :
51 0 : if (fpTHF)
52 0 : VSIFCloseL(fpTHF);
53 :
54 0 : if (poSRS)
55 0 : poSRS->Release();
56 0 : }
57 :
58 : /************************************************************************/
59 : /* GetLayer() */
60 : /************************************************************************/
61 :
62 0 : OGRLayer *OGREDIGEODataSource::GetLayer(int iLayer)
63 :
64 : {
65 0 : ReadEDIGEO();
66 0 : if (iLayer < 0 || iLayer >= nLayers)
67 0 : return nullptr;
68 : else
69 0 : return papoLayers[iLayer];
70 : }
71 :
72 : /************************************************************************/
73 : /* GetLayerCount() */
74 : /************************************************************************/
75 :
76 0 : int OGREDIGEODataSource::GetLayerCount()
77 : {
78 0 : ReadEDIGEO();
79 0 : return nLayers;
80 : }
81 :
82 : /************************************************************************/
83 : /* ReadTHF() */
84 : /************************************************************************/
85 :
86 0 : int OGREDIGEODataSource::ReadTHF(VSILFILE *fp)
87 : {
88 0 : const char *pszLine = nullptr;
89 0 : while ((pszLine = CPLReadLine2L(fp, 81, nullptr)) != nullptr)
90 : {
91 0 : if (strlen(pszLine) < 8 || pszLine[7] != ':')
92 0 : continue;
93 :
94 : /* Cf Z 52000 tableau 56 for field list*/
95 :
96 0 : if (STARTS_WITH(pszLine, "LONSA"))
97 : {
98 0 : if (!osLON.empty())
99 : {
100 0 : CPLDebug("EDIGEO", "We only handle one lot per THF file");
101 0 : break;
102 : }
103 0 : osLON = pszLine + 8;
104 : }
105 0 : else if (STARTS_WITH(pszLine, "GNNSA"))
106 0 : osGNN = pszLine + 8;
107 0 : else if (STARTS_WITH(pszLine, "GONSA"))
108 0 : osGON = pszLine + 8;
109 0 : else if (STARTS_WITH(pszLine, "QANSA"))
110 0 : osQAN = pszLine + 8;
111 0 : else if (STARTS_WITH(pszLine, "DINSA"))
112 0 : osDIN = pszLine + 8;
113 0 : else if (STARTS_WITH(pszLine, "SCNSA"))
114 0 : osSCN = pszLine + 8;
115 0 : else if (STARTS_WITH(pszLine, "GDNSA"))
116 0 : aosGDN.push_back(pszLine + 8);
117 : }
118 0 : if (osLON.empty())
119 : {
120 0 : CPLDebug("EDIGEO", "LON field missing");
121 0 : return 0;
122 : }
123 0 : if (osGON.empty())
124 : {
125 0 : CPLDebug("EDIGEO", "GON field missing");
126 0 : return 0;
127 : }
128 0 : if (osDIN.empty())
129 : {
130 0 : CPLDebug("EDIGEO", "DIN field missing");
131 0 : return 0;
132 : }
133 0 : if (osSCN.empty())
134 : {
135 0 : CPLDebug("EDIGEO", "SCN field missing");
136 0 : return FALSE;
137 : }
138 :
139 0 : CPLDebug("EDIGEO", "LON = %s", osLON.c_str());
140 0 : CPLDebug("EDIGEO", "GNN = %s", osGNN.c_str());
141 0 : CPLDebug("EDIGEO", "GON = %s", osGON.c_str());
142 0 : CPLDebug("EDIGEO", "QAN = %s", osQAN.c_str());
143 0 : CPLDebug("EDIGEO", "DIN = %s", osDIN.c_str());
144 0 : CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str());
145 0 : for (int i = 0; i < (int)aosGDN.size(); i++)
146 0 : CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str());
147 :
148 0 : return TRUE;
149 : }
150 :
151 : /************************************************************************/
152 : /* OpenFile() */
153 : /************************************************************************/
154 :
155 0 : VSILFILE *OGREDIGEODataSource::OpenFile(const char *pszType,
156 : const CPLString &osExt)
157 : {
158 0 : CPLString osTmp = osLON + pszType;
159 0 : CPLString osFilename = CPLFormCIFilename(CPLGetPath(GetDescription()),
160 0 : osTmp.c_str(), osExt.c_str());
161 0 : VSILFILE *fp = VSIFOpenL(osFilename, "rb");
162 0 : if (fp == nullptr)
163 : {
164 0 : const CPLString osExtLower = CPLString(osExt).tolower();
165 : const CPLString osFilename2 = CPLFormCIFilename(
166 0 : CPLGetPath(GetDescription()), 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()
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()
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()
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()
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(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()
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)
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 =
555 0 : new OGREDIGEOLayer(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)
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 = CPLIsUTF8(osAttVal.c_str(), -1);
840 : }
841 0 : if (!osAttId.empty())
842 0 : aosAttIdVal.push_back(strstrType(osAttId, osAttVal));
843 0 : osAttId = "";
844 0 : bIso8859_1 = FALSE;
845 0 : goto skip_read_next_line;
846 : }
847 0 : else if (STARTS_WITH(pszLine, "ATVCP"))
848 : {
849 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
850 0 : if (CSLCount(papszTokens) == 4)
851 : {
852 0 : if (strcmp(papszTokens[2], "ATT") == 0)
853 : {
854 0 : CPLString osAttVal = papszTokens[3];
855 0 : if (!osAttId.empty())
856 0 : aosAttIdVal.push_back(strstrType(osAttId, osAttVal));
857 0 : osAttId = "";
858 : }
859 : }
860 0 : CSLDestroy(papszTokens);
861 : }
862 0 : else if (STARTS_WITH(pszLine, "QAPCP"))
863 : {
864 0 : char **papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
865 0 : if (CSLCount(papszTokens) == 4)
866 : {
867 0 : if (strcmp(papszTokens[2], "QUP") == 0)
868 : {
869 0 : osQUP_RID = papszTokens[3];
870 : }
871 : }
872 0 : CSLDestroy(papszTokens);
873 : }
874 0 : }
875 :
876 0 : VSIFCloseL(fp);
877 :
878 0 : return TRUE;
879 : }
880 :
881 : /************************************************************************/
882 : /* CreateFeature() */
883 : /************************************************************************/
884 :
885 0 : OGRFeature *OGREDIGEODataSource::CreateFeature(const CPLString &osFEA)
886 : {
887 : const std::map<CPLString, OGREDIGEOFEADesc>::iterator itFEA =
888 0 : mapFEA.find(osFEA);
889 0 : if (itFEA == mapFEA.end())
890 : {
891 0 : CPLDebug("EDIGEO", "ERROR: Cannot find FEA %s", osFEA.c_str());
892 0 : return nullptr;
893 : }
894 :
895 0 : const OGREDIGEOFEADesc &fea = itFEA->second;
896 : const std::map<CPLString, OGREDIGEOLayer *>::iterator itLyr =
897 0 : mapLayer.find(fea.osSCP);
898 0 : if (itLyr != mapLayer.end())
899 : {
900 0 : OGREDIGEOLayer *poLayer = itLyr->second;
901 :
902 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
903 0 : poFeature->SetField(0, itFEA->first.c_str());
904 0 : for (int i = 0; i < (int)fea.aosAttIdVal.size(); i++)
905 : {
906 0 : const CPLString &id = fea.aosAttIdVal[i].first;
907 0 : const CPLString &val = fea.aosAttIdVal[i].second;
908 0 : int iIndex = poLayer->GetAttributeIndex(id);
909 0 : if (iIndex != -1)
910 0 : poFeature->SetField(iIndex, val.c_str());
911 : else
912 0 : CPLDebug("EDIGEO", "ERROR: Cannot find attribute %s",
913 : id.c_str());
914 : }
915 :
916 0 : if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 &&
917 0 : !mapQAL.empty() && !fea.osQUP_RID.empty())
918 : {
919 : const std::map<CPLString, intintType>::iterator itQAL =
920 0 : mapQAL.find(fea.osQUP_RID);
921 0 : if (itQAL != mapQAL.end())
922 : {
923 0 : const intintType &creationUpdateDate = itQAL->second;
924 0 : if (creationUpdateDate.first != 0)
925 0 : poFeature->SetField("CREAT_DATE", creationUpdateDate.first);
926 0 : if (creationUpdateDate.second != 0)
927 0 : poFeature->SetField("UPDATE_DATE",
928 0 : creationUpdateDate.second);
929 : }
930 : }
931 :
932 0 : poLayer->AddFeature(poFeature);
933 :
934 0 : return poFeature;
935 : }
936 : else
937 : {
938 0 : CPLDebug("EDIGEO", "ERROR: Cannot find layer %s", fea.osSCP.c_str());
939 0 : return nullptr;
940 : }
941 : }
942 :
943 : /************************************************************************/
944 : /* SetStyle() */
945 : /************************************************************************/
946 :
947 0 : int OGREDIGEODataSource::SetStyle(const CPLString &osFEA, OGRFeature *poFeature)
948 : {
949 : /* EDIGEO PCI specific */
950 : /* See EDIGeO_PCI.pdf, chapter 3 "Principes généraux de */
951 : /* positionnement de la toponymie. */
952 0 : const char *pszATR = nullptr;
953 0 : if (strcmp(poFeature->GetDefnRef()->GetName(), "ID_S_OBJ_Z_1_2_2") == 0 &&
954 0 : iATR != -1 && (pszATR = poFeature->GetFieldAsString(iATR)) != nullptr)
955 : {
956 0 : const CPLString osATR = pszATR;
957 : std::map<CPLString, CPLString>::iterator itFEA_FEA =
958 0 : mapFEA_FEA.find(osFEA);
959 0 : if (itFEA_FEA != mapFEA_FEA.end())
960 : {
961 0 : const CPLString &osOBJ_LNK = itFEA_FEA->second;
962 : std::map<CPLString, OGREDIGEOFEADesc>::iterator itFEA_LNK =
963 0 : mapFEA.find(osOBJ_LNK);
964 0 : if (itFEA_LNK != mapFEA.end())
965 : {
966 0 : const OGREDIGEOFEADesc &fea_lnk = itFEA_LNK->second;
967 0 : for (int j = 0; j < (int)fea_lnk.aosAttIdVal.size(); j++)
968 : {
969 0 : if (fea_lnk.aosAttIdVal[j].first == osATR)
970 : {
971 0 : double dfAngle = 0;
972 0 : if (iDI3 != -1 && iDI4 != -1)
973 : {
974 : double dfBaseVectorX =
975 0 : poFeature->GetFieldAsDouble(iDI3);
976 : double dfBaseVectorY =
977 0 : poFeature->GetFieldAsDouble(iDI4);
978 0 : dfAngle = atan2(dfBaseVectorY, dfBaseVectorX) /
979 : M_PI * 180;
980 0 : if (dfAngle < 0)
981 0 : dfAngle += 360;
982 : }
983 0 : double dfSize = 1;
984 0 : if (iHEI != -1)
985 0 : dfSize = poFeature->GetFieldAsDouble(iHEI);
986 0 : if (dfSize <= 0 || dfSize >= 100)
987 0 : dfSize = 1;
988 0 : const char *pszFontFamily = nullptr;
989 0 : if (iFON != -1)
990 0 : pszFontFamily = poFeature->GetFieldAsString(iFON);
991 :
992 0 : CPLString osStyle("LABEL(t:\"");
993 0 : osStyle += fea_lnk.aosAttIdVal[j].second;
994 0 : osStyle += "\"";
995 0 : if (dfAngle != 0)
996 : {
997 0 : osStyle += ",a:";
998 0 : osStyle += CPLString().Printf("%.1f", dfAngle);
999 : }
1000 0 : if (pszFontFamily != nullptr && bIncludeFontFamily)
1001 : {
1002 0 : osStyle += ",f:\"";
1003 0 : osStyle += pszFontFamily;
1004 0 : osStyle += "\"";
1005 : }
1006 0 : osStyle += ",s:";
1007 0 : osStyle += CPLString().Printf("%.1f", dfSize);
1008 0 : osStyle += ",c:#000000)";
1009 0 : poFeature->SetStyleString(osStyle);
1010 :
1011 0 : poFeature->SetField(iATR_VAL,
1012 0 : fea_lnk.aosAttIdVal[j].second);
1013 0 : poFeature->SetField(iANGLE, dfAngle);
1014 0 : poFeature->SetField(iSIZE, dfSize * dfSizeFactor);
1015 0 : poFeature->SetField(iOBJ_LNK, osOBJ_LNK);
1016 0 : poFeature->SetField(iOBJ_LNK_LAYER, fea_lnk.osSCP);
1017 :
1018 0 : setLayersWithLabels.insert(fea_lnk.osSCP);
1019 :
1020 0 : break;
1021 : }
1022 : }
1023 : }
1024 : }
1025 : }
1026 :
1027 0 : return TRUE;
1028 : }
1029 :
1030 : /************************************************************************/
1031 : /* BuildPoints() */
1032 : /************************************************************************/
1033 :
1034 0 : int OGREDIGEODataSource::BuildPoints()
1035 : {
1036 0 : for (int i = 0; i < (int)listFEA_PNO.size(); i++)
1037 : {
1038 0 : const CPLString &osFEA = listFEA_PNO[i].first;
1039 0 : const CPLString &osPNO = listFEA_PNO[i].second;
1040 : const std::map<CPLString, xyPairType>::iterator itPNO =
1041 0 : mapPNO.find(osPNO);
1042 0 : if (itPNO == mapPNO.end())
1043 : {
1044 0 : CPLDebug("EDIGEO", "Cannot find PNO %s", osPNO.c_str());
1045 : }
1046 : else
1047 : {
1048 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1049 0 : if (poFeature)
1050 : {
1051 0 : const xyPairType &pno = itPNO->second;
1052 0 : OGRPoint *poPoint = new OGRPoint(pno.first, pno.second);
1053 0 : if (poSRS)
1054 0 : poPoint->assignSpatialReference(poSRS);
1055 0 : poFeature->SetGeometryDirectly(poPoint);
1056 :
1057 0 : SetStyle(osFEA, poFeature);
1058 : }
1059 : }
1060 : }
1061 :
1062 0 : return TRUE;
1063 : }
1064 :
1065 : /************************************************************************/
1066 : /* BuildLineStrings() */
1067 : /************************************************************************/
1068 :
1069 0 : int OGREDIGEODataSource::BuildLineStrings()
1070 : {
1071 : int i, iter;
1072 :
1073 0 : for (iter = 0; iter < (int)listFEA_PAR.size(); iter++)
1074 : {
1075 0 : const CPLString &osFEA = listFEA_PAR[iter].first;
1076 0 : const strListType &aosPAR = listFEA_PAR[iter].second;
1077 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1078 0 : if (poFeature)
1079 : {
1080 0 : OGRGeometry *poGeom = nullptr;
1081 0 : OGRMultiLineString *poMulti = nullptr;
1082 0 : for (int k = 0; k < (int)aosPAR.size(); k++)
1083 : {
1084 : const std::map<CPLString, xyPairListType>::iterator itPAR =
1085 0 : mapPAR.find(aosPAR[k]);
1086 0 : if (itPAR != mapPAR.end())
1087 : {
1088 0 : const xyPairListType &arc = itPAR->second;
1089 :
1090 0 : OGRLineString *poLS = new OGRLineString();
1091 0 : poLS->setNumPoints((int)arc.size());
1092 0 : for (i = 0; i < (int)arc.size(); i++)
1093 : {
1094 0 : poLS->setPoint(i, arc[i].first, arc[i].second);
1095 : }
1096 :
1097 0 : if (poGeom != nullptr)
1098 : {
1099 0 : if (poMulti == nullptr)
1100 : {
1101 0 : poMulti = new OGRMultiLineString();
1102 0 : poMulti->addGeometryDirectly(poGeom);
1103 0 : poGeom = poMulti;
1104 : }
1105 0 : poMulti->addGeometryDirectly(poLS);
1106 : }
1107 : else
1108 0 : poGeom = poLS;
1109 : }
1110 : else
1111 0 : CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s",
1112 0 : aosPAR[k].c_str());
1113 : }
1114 0 : if (poGeom != nullptr)
1115 : {
1116 0 : poGeom->assignSpatialReference(poSRS);
1117 0 : poFeature->SetGeometryDirectly(poGeom);
1118 : }
1119 : }
1120 : }
1121 :
1122 0 : return TRUE;
1123 : }
1124 :
1125 : /************************************************************************/
1126 : /* BuildPolygon() */
1127 : /************************************************************************/
1128 :
1129 0 : int OGREDIGEODataSource::BuildPolygon(const CPLString &osFEA,
1130 : const strListType &aosPFE)
1131 : {
1132 0 : std::vector<xyPairListType> aoXYList;
1133 :
1134 0 : for (int k = 0; k < (int)aosPFE.size(); k++)
1135 : {
1136 : const std::map<CPLString, strListType>::iterator itPFE_PAR =
1137 0 : mapPFE_PAR.find(aosPFE[k]);
1138 0 : if (itPFE_PAR == mapPFE_PAR.end())
1139 : {
1140 0 : CPLDebug("EDIGEO", "ERROR: Cannot find PFE %s", aosPFE[k].c_str());
1141 0 : return FALSE;
1142 : }
1143 :
1144 0 : const strListType &aosPARList = itPFE_PAR->second;
1145 :
1146 : /* --------------------------------------------------------------------
1147 : */
1148 : /* Resolve arc ids to arc coordinate lists. */
1149 : /* --------------------------------------------------------------------
1150 : */
1151 0 : std::vector<const xyPairListType *> aoPARPtrList;
1152 0 : for (int i = 0; i < (int)aosPARList.size(); i++)
1153 : {
1154 : const std::map<CPLString, xyPairListType>::iterator itPAR =
1155 0 : mapPAR.find(aosPARList[i]);
1156 0 : if (itPAR != mapPAR.end())
1157 0 : aoPARPtrList.push_back(&(itPAR->second));
1158 : else
1159 0 : CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s",
1160 0 : aosPARList[i].c_str());
1161 : }
1162 :
1163 0 : if (aoPARPtrList.empty())
1164 0 : return FALSE;
1165 :
1166 : /* --------------------------------------------------------------------
1167 : */
1168 : /* Now try to chain all arcs together. */
1169 : /* --------------------------------------------------------------------
1170 : */
1171 :
1172 0 : for (int j = 0; j < (int)aoPARPtrList.size(); j++)
1173 : {
1174 0 : if (aoPARPtrList[j] == nullptr)
1175 0 : continue;
1176 0 : const xyPairListType &sFirstRing = *(aoPARPtrList[j]);
1177 0 : const xyPairType *psNext = &(sFirstRing.back());
1178 :
1179 0 : xyPairListType aoXY;
1180 0 : for (int i = 0; i < (int)sFirstRing.size(); i++)
1181 0 : aoXY.push_back(sFirstRing[i]);
1182 0 : aoPARPtrList[j] = nullptr;
1183 :
1184 0 : int nIter = 1;
1185 0 : while (aoXY.back() != aoXY[0] && nIter < (int)aoPARPtrList.size())
1186 : {
1187 0 : bool bFound = false;
1188 0 : bool bReverseSecond = false;
1189 0 : int i = 0; // Used after for.
1190 0 : for (; i < (int)aoPARPtrList.size(); i++)
1191 : {
1192 0 : if (aoPARPtrList[i] != nullptr)
1193 : {
1194 0 : const xyPairListType &sSecondRing = *(aoPARPtrList[i]);
1195 0 : if (*psNext == sSecondRing[0])
1196 : {
1197 0 : bFound = true;
1198 0 : bReverseSecond = false;
1199 0 : break;
1200 : }
1201 0 : else if (*psNext == sSecondRing.back())
1202 : {
1203 0 : bFound = true;
1204 0 : bReverseSecond = true;
1205 0 : break;
1206 : }
1207 : }
1208 : }
1209 :
1210 0 : if (!bFound)
1211 : {
1212 0 : CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s",
1213 0 : osFEA.c_str(), aosPFE[k].c_str());
1214 0 : break;
1215 : }
1216 : else
1217 : {
1218 0 : const xyPairListType &secondRing = *(aoPARPtrList[i]);
1219 0 : aoPARPtrList[i] = nullptr;
1220 0 : if (!bReverseSecond)
1221 : {
1222 0 : for (i = 1; i < (int)secondRing.size(); i++)
1223 0 : aoXY.push_back(secondRing[i]);
1224 0 : psNext = &secondRing.back();
1225 : }
1226 : else
1227 : {
1228 0 : for (i = 1; i < (int)secondRing.size(); i++)
1229 0 : aoXY.push_back(
1230 0 : secondRing[secondRing.size() - 1 - i]);
1231 0 : psNext = &secondRing[0];
1232 : }
1233 : }
1234 :
1235 0 : nIter++;
1236 : }
1237 :
1238 0 : aoXYList.push_back(aoXY);
1239 : }
1240 : }
1241 :
1242 : /* -------------------------------------------------------------------- */
1243 : /* Create feature. */
1244 : /* -------------------------------------------------------------------- */
1245 0 : OGRFeature *poFeature = CreateFeature(osFEA);
1246 0 : if (poFeature)
1247 : {
1248 0 : std::vector<OGRGeometry *> aosPolygons;
1249 0 : for (int j = 0; j < (int)aoXYList.size(); j++)
1250 : {
1251 0 : const xyPairListType &aoXY = aoXYList[j];
1252 0 : OGRLinearRing *poLS = new OGRLinearRing();
1253 0 : poLS->setNumPoints((int)aoXY.size());
1254 0 : for (int i = 0; i < (int)aoXY.size(); i++)
1255 0 : poLS->setPoint(i, aoXY[i].first, aoXY[i].second);
1256 0 : poLS->closeRings();
1257 0 : OGRPolygon *poPolygon = new OGRPolygon();
1258 0 : poPolygon->addRingDirectly(poLS);
1259 0 : aosPolygons.push_back(poPolygon);
1260 : }
1261 :
1262 0 : int bIsValidGeometry = FALSE;
1263 0 : OGRGeometry *poGeom = OGRGeometryFactory::organizePolygons(
1264 0 : &aosPolygons[0], (int)aosPolygons.size(), &bIsValidGeometry,
1265 : nullptr);
1266 0 : if (poGeom)
1267 : {
1268 0 : if (poSRS)
1269 0 : poGeom->assignSpatialReference(poSRS);
1270 0 : poFeature->SetGeometryDirectly(poGeom);
1271 : }
1272 : }
1273 0 : return TRUE;
1274 : }
1275 :
1276 : /************************************************************************/
1277 : /* BuildPolygons() */
1278 : /************************************************************************/
1279 :
1280 0 : int OGREDIGEODataSource::BuildPolygons()
1281 : {
1282 0 : for (int iter = 0; iter < (int)listFEA_PFE.size(); iter++)
1283 : {
1284 0 : const CPLString &osFEA = listFEA_PFE[iter].first;
1285 0 : const strListType &aosPFE = listFEA_PFE[iter].second;
1286 0 : BuildPolygon(osFEA, aosPFE);
1287 : }
1288 :
1289 0 : return TRUE;
1290 : }
1291 :
1292 : /************************************************************************/
1293 : /* OGREDIGEOSortForQGIS() */
1294 : /************************************************************************/
1295 :
1296 0 : static int OGREDIGEOSortForQGIS(const void *a, const void *b)
1297 : {
1298 0 : OGREDIGEOLayer *poLayerA = *((OGREDIGEOLayer **)a);
1299 0 : OGREDIGEOLayer *poLayerB = *((OGREDIGEOLayer **)b);
1300 : int nTypeA, nTypeB;
1301 0 : switch (poLayerA->GetLayerDefn()->GetGeomType())
1302 : {
1303 0 : case wkbPoint:
1304 0 : nTypeA = 1;
1305 0 : break;
1306 0 : case wkbLineString:
1307 0 : nTypeA = 2;
1308 0 : break;
1309 0 : case wkbPolygon:
1310 0 : nTypeA = 3;
1311 0 : break;
1312 0 : default:
1313 0 : nTypeA = 4;
1314 0 : break;
1315 : }
1316 0 : switch (poLayerB->GetLayerDefn()->GetGeomType())
1317 : {
1318 0 : case wkbPoint:
1319 0 : nTypeB = 1;
1320 0 : break;
1321 0 : case wkbLineString:
1322 0 : nTypeB = 2;
1323 0 : break;
1324 0 : case wkbPolygon:
1325 0 : nTypeB = 3;
1326 0 : break;
1327 0 : default:
1328 0 : nTypeB = 4;
1329 0 : break;
1330 : }
1331 0 : if (nTypeA == nTypeB)
1332 : {
1333 0 : int nCmp = strcmp(poLayerA->GetName(), poLayerB->GetName());
1334 0 : if (nCmp == 0)
1335 0 : return 0;
1336 :
1337 : static const char *const apszPolyOrder[] = {
1338 : "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id",
1339 : "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id"};
1340 0 : for (int i = 0; i < (int)(sizeof(apszPolyOrder) / sizeof(char *)); i++)
1341 : {
1342 0 : if (strcmp(poLayerA->GetName(), apszPolyOrder[i]) == 0)
1343 0 : return -1;
1344 0 : if (strcmp(poLayerB->GetName(), apszPolyOrder[i]) == 0)
1345 0 : return 1;
1346 : }
1347 0 : return nCmp;
1348 : }
1349 : else
1350 0 : return nTypeB - nTypeA;
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* Open() */
1355 : /************************************************************************/
1356 :
1357 0 : int OGREDIGEODataSource::Open(const char *pszFilename)
1358 :
1359 : {
1360 0 : fpTHF = VSIFOpenL(pszFilename, "rb");
1361 0 : if (fpTHF == nullptr)
1362 0 : return FALSE;
1363 :
1364 0 : const char *pszLine = nullptr;
1365 0 : int i = 0;
1366 0 : bool bIsEDIGEO = false;
1367 0 : while (i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, nullptr)) != nullptr)
1368 : {
1369 0 : if (strcmp(pszLine, "RTYSA03:GTS") == 0)
1370 : {
1371 0 : bIsEDIGEO = true;
1372 0 : break;
1373 : }
1374 0 : i++;
1375 : }
1376 :
1377 0 : if (!bIsEDIGEO)
1378 : {
1379 0 : VSIFCloseL(fpTHF);
1380 0 : fpTHF = nullptr;
1381 0 : return FALSE;
1382 : }
1383 :
1384 0 : return TRUE;
1385 : }
1386 :
1387 : /************************************************************************/
1388 : /* ReadEDIGEO() */
1389 : /************************************************************************/
1390 :
1391 0 : void OGREDIGEODataSource::ReadEDIGEO()
1392 : {
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()
1515 : {
1516 0 : OGRLayer *poLayer = GetLayerByName("ID_S_OBJ_Z_1_2_2");
1517 0 : if (poLayer == nullptr)
1518 0 : return;
1519 :
1520 0 : std::map<CPLString, OGREDIGEOLayer *> mapLayerNameToLayer;
1521 :
1522 0 : OGRFeature *poFeature = nullptr;
1523 0 : OGRFeatureDefn *poFeatureDefn = poLayer->GetLayerDefn();
1524 0 : while ((poFeature = poLayer->GetNextFeature()) != nullptr)
1525 : {
1526 : const char *pszBelongingLayerName =
1527 0 : poFeature->GetFieldAsString(iOBJ_LNK_LAYER);
1528 0 : if (pszBelongingLayerName)
1529 : {
1530 0 : CPLString osBelongingLayerName = pszBelongingLayerName;
1531 : std::map<CPLString, OGREDIGEOLayer *>::iterator it =
1532 0 : mapLayerNameToLayer.find(osBelongingLayerName);
1533 0 : OGREDIGEOLayer *poLabelLayer = nullptr;
1534 :
1535 0 : if (it == mapLayerNameToLayer.end())
1536 : {
1537 : /* Create label layer if it does not already exist */
1538 0 : CPLString osLayerLabelName = osBelongingLayerName + "_LABEL";
1539 0 : poLabelLayer = new OGREDIGEOLayer(
1540 0 : this, osLayerLabelName.c_str(), wkbPoint, poSRS);
1541 : OGRFeatureDefn *poLabelFeatureDefn =
1542 0 : poLabelLayer->GetLayerDefn();
1543 0 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
1544 0 : poLabelFeatureDefn->AddFieldDefn(
1545 0 : poFeatureDefn->GetFieldDefn(i));
1546 0 : mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer;
1547 :
1548 0 : papoLayers = (OGRLayer **)CPLRealloc(
1549 0 : papoLayers, (nLayers + 1) * sizeof(OGRLayer *));
1550 0 : papoLayers[nLayers] = poLabelLayer;
1551 0 : nLayers++;
1552 : }
1553 : else
1554 : {
1555 0 : poLabelLayer = mapLayerNameToLayer[osBelongingLayerName];
1556 : }
1557 :
1558 : OGRFeature *poNewFeature =
1559 0 : new OGRFeature(poLabelLayer->GetLayerDefn());
1560 0 : poNewFeature->SetFrom(poFeature);
1561 0 : poLabelLayer->AddFeature(poNewFeature);
1562 : }
1563 0 : delete poFeature;
1564 : }
1565 :
1566 0 : poLayer->ResetReading();
1567 : }
|