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