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