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