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