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