1 : /******************************************************************************
2 : * $Id: ili1reader.cpp 20142 2010-07-27 18:43:49Z rouault $
3 : *
4 : * Project: Interlis 1 Reader
5 : * Purpose: Implementation of ILI1Reader class.
6 : * Author: Pirmin Kalberer, Sourcepole AG
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
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_ili1.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "ogr_api.h"
34 : #include "ogr_geos.h"
35 :
36 : #include "ilihelper.h"
37 : #include "iomhelper.h"
38 : #include "ili1reader.h"
39 : #include "ili1readerp.h"
40 :
41 : #include <vector>
42 :
43 : #ifdef HAVE_GEOS
44 : # define POLYGONIZE_AREAS
45 : #endif
46 :
47 : #ifndef POLYGONIZE_AREAS
48 : # if defined(__GNUC_PREREQ)
49 : # warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 2.1.0
50 : # endif
51 : #endif
52 :
53 : CPL_CVSID("$Id: ili1reader.cpp 20142 2010-07-27 18:43:49Z rouault $");
54 :
55 :
56 : //
57 : // ILI1Reader
58 : //
59 0 : IILI1Reader::~IILI1Reader() {
60 0 : }
61 :
62 0 : ILI1Reader::ILI1Reader() {
63 0 : fpItf = NULL;
64 0 : nLayers = 0;
65 0 : papoLayers = NULL;
66 0 : curLayer = NULL;
67 0 : metaLayer = NULL;
68 0 : SetArcDegrees(1);
69 0 : }
70 :
71 0 : ILI1Reader::~ILI1Reader() {
72 : int i;
73 0 : if (fpItf) VSIFClose( fpItf );
74 :
75 0 : for(i=0;i<nLayers;i++)
76 0 : delete papoLayers[i];
77 0 : CPLFree(papoLayers);
78 0 : }
79 :
80 0 : void ILI1Reader::SetArcDegrees(double arcDegrees) {
81 0 : arcIncr = arcDegrees*PI/180;
82 0 : }
83 :
84 : /* -------------------------------------------------------------------- */
85 : /* Open the source file. */
86 : /* -------------------------------------------------------------------- */
87 0 : int ILI1Reader::OpenFile( const char *pszFilename ) {
88 0 : fpItf = VSIFOpen( pszFilename, "r" );
89 0 : if( fpItf == NULL )
90 : {
91 : CPLError( CE_Failure, CPLE_OpenFailed,
92 : "Failed to open ILI file `%s'.",
93 0 : pszFilename );
94 :
95 0 : return FALSE;
96 : }
97 0 : return TRUE;
98 : }
99 :
100 0 : int ILI1Reader::HasMultiplePointGeom(const char* layername) {
101 0 : if (metaLayer != NULL) {
102 0 : OGRFeature *metaFeature = NULL;
103 0 : metaLayer->ResetReading();
104 0 : int i = -1;
105 0 : while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
106 0 : if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
107 0 : i++;
108 : }
109 : }
110 0 : return i;
111 : } else {
112 0 : return -1;
113 : }
114 : }
115 :
116 0 : char* ILI1Reader::GetPointLayerName(const char* layername, char* newlayername) {
117 : static char geomlayername[512];
118 0 : geomlayername[0] = '\0';
119 0 : strcat(geomlayername, layername);
120 0 : strcat(geomlayername, "__");
121 0 : strcat(geomlayername, newlayername);
122 0 : return geomlayername;
123 : }
124 :
125 0 : const char* ILI1Reader::GetLayerNameString(const char* topicname, const char* tablename) {
126 : static char layername[512];
127 0 : layername[0] = '\0';
128 0 : strcat(layername, topicname);
129 0 : strcat(layername, "__");
130 0 : strcat(layername, tablename);
131 0 : return layername;
132 : }
133 :
134 0 : const char* ILI1Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
135 : static char layername[512];
136 0 : IOM_OBJECT topic = GetAttrObj(model, table, "container");
137 0 : layername[0] = '\0';
138 0 : strcat(layername, iom_getattrvalue(topic, "name"));
139 0 : strcat(layername, "__");
140 0 : strcat(layername, iom_getattrvalue(table, "name"));
141 0 : return layername;
142 : }
143 :
144 0 : void ILI1Reader::AddCoord(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT modelele, IOM_OBJECT typeobj) {
145 0 : unsigned int dim = ::GetCoordDim(model, typeobj);
146 0 : for (unsigned int i=0; i<dim; i++) {
147 0 : OGRFieldDefn fieldDef(CPLSPrintf("%s_%d", iom_getattrvalue(modelele, "name"), i), OFTReal);
148 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
149 : //CPLDebug( "AddCoord OGR_ILI", "Field %s: OFTReal", fieldDef.GetNameRef());
150 : }
151 0 : }
152 :
153 0 : OGRILI1Layer* ILI1Reader::AddGeomTable(const char* datalayername, const char* geomname, OGRwkbGeometryType eType) {
154 : static char layername[512];
155 0 : layername[0] = '\0';
156 0 : strcat(layername, datalayername);
157 0 : strcat(layername, "_");
158 0 : strcat(layername, geomname);
159 :
160 0 : OGRILI1Layer* geomlayer = new OGRILI1Layer(layername, NULL, 0, eType, NULL);
161 0 : AddLayer(geomlayer);
162 0 : OGRFieldDefn fieldDef("_TID", OFTString);
163 0 : geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef);
164 0 : if (eType == wkbPolygon)
165 : {
166 0 : OGRFieldDefn fieldDefRef("_RefTID", OFTString);
167 0 : geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDefRef);
168 : }
169 0 : OGRFieldDefn fieldDef2("ILI_Geometry", OFTString); //in write mode only?
170 0 : geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
171 0 : return geomlayer;
172 : }
173 :
174 0 : void ILI1Reader::AddField(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT obj) {
175 0 : const char* typenam = "Reference";
176 0 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
177 : //CPLDebug( "OGR_ILI", "Field %s: %s", iom_getattrvalue(obj, "name"), typenam);
178 0 : if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
179 0 : OGRILI1Layer* polyLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbPolygon);
180 0 : layer->SetSurfacePolyLayer(polyLayer);
181 : //TODO: add line attributes to geometry
182 0 : } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
183 0 : IOM_OBJECT controlPointDomain = GetAttrObj(model, GetTypeObj(model, obj), "controlPointDomain");
184 0 : if (controlPointDomain) {
185 0 : AddCoord(layer, model, obj, GetTypeObj(model, controlPointDomain));
186 0 : layer->GetLayerDefn()->SetGeomType(wkbPoint);
187 : }
188 0 : OGRILI1Layer* areaLineLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbMultiLineString);
189 : #ifdef POLYGONIZE_AREAS
190 0 : OGRILI1Layer* areaLayer = new OGRILI1Layer(CPLSPrintf("%s__Areas",layer->GetLayerDefn()->GetName()), NULL, 0, wkbPolygon, NULL);
191 0 : AddLayer(areaLayer);
192 0 : areaLayer->SetAreaLayers(layer, areaLineLayer);
193 : #endif
194 0 : } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
195 0 : layer->GetLayerDefn()->SetGeomType(wkbMultiLineString);
196 0 : } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
197 0 : AddCoord(layer, model, obj, GetTypeObj(model, obj));
198 0 : if (layer->GetLayerDefn()->GetGeomType() == wkbUnknown) layer->GetLayerDefn()->SetGeomType(wkbPoint);
199 0 : } else if (EQUAL(typenam, "iom04.metamodel.NumericType") ) {
200 0 : OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTReal);
201 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
202 0 : } else if (EQUAL(typenam, "iom04.metamodel.EnumerationType") ) {
203 0 : OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTInteger);
204 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
205 : } else {
206 0 : OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
207 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
208 : }
209 0 : }
210 :
211 0 : int ILI1Reader::ReadModel(const char *pszModelFilename) {
212 :
213 : IOM_BASKET model;
214 : IOM_ITERATOR modelelei;
215 : IOM_OBJECT modelele;
216 :
217 0 : iom_init();
218 :
219 : // set error listener to a iom provided one, that just
220 : // dumps all errors to stderr
221 0 : iom_seterrlistener(iom_stderrlistener);
222 :
223 : // compile ili model
224 0 : char *iomarr[1] = {(char *)pszModelFilename};
225 0 : model=iom_compileIli(1, iomarr);
226 0 : if(!model){
227 0 : CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
228 0 : iom_end();
229 0 : return FALSE;
230 : }
231 :
232 : // create new layer with meta information (ILI table name and geometry column index)
233 : // while reading the features from the ITF we have to know which column is the geometry column
234 0 : metaLayer = new OGRILI1Layer("Metatable", NULL, 0, wkbUnknown, NULL);
235 0 : OGRFieldDefn fieldDef1("layername", OFTString);
236 0 : metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef1);
237 0 : OGRFieldDefn fieldDef2("geomIdx", OFTInteger);
238 0 : metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
239 0 : OGRFieldDefn fieldDef3("geomlayername", OFTString);
240 0 : metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef3);
241 :
242 :
243 : // read tables
244 0 : int j = 0;
245 0 : modelelei=iom_iteratorobject(model);
246 0 : modelele=iom_nextobject(modelelei);
247 0 : while(modelele){
248 0 : const char *tag=iom_getobjecttag(modelele);
249 :
250 0 : if (tag && EQUAL(tag,"iom04.metamodel.Table")) {
251 :
252 0 : const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
253 :
254 0 : if (!EQUAL(topic, "INTERLIS")) {
255 :
256 0 : const char* layername = GetLayerName(model, modelele);
257 0 : OGRSpatialReference *poSRSIn = NULL;
258 0 : int bWriterIn = 0;
259 0 : OGRwkbGeometryType eReqType = wkbUnknown;
260 0 : OGRILI1DataSource *poDSIn = NULL;
261 :
262 0 : CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
263 :
264 : // read fields
265 : IOM_OBJECT fields[255];
266 : IOM_OBJECT roledefs[255];
267 0 : memset(fields, 0, 255);
268 0 : memset(roledefs, 0, 255);
269 0 : int maxIdx = -1;
270 0 : IOM_ITERATOR fieldit=iom_iteratorobject(model);
271 0 : std::vector<IOM_OBJECT> attributes;
272 :
273 0 : for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
274 0 : const char *etag=iom_getobjecttag(fieldele);
275 :
276 0 : if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
277 0 : IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
278 :
279 0 : if (table == modelele) {
280 :
281 0 : IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
282 0 : int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
283 :
284 0 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
285 0 : int ili1AttrIdxOppend = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
286 :
287 0 : if (ili1AttrIdxOppend>=0) {
288 0 : roledefs[ili1AttrIdxOppend] = obj;
289 0 : if (ili1AttrIdxOppend > maxIdx) maxIdx = ili1AttrIdxOppend;
290 : }
291 : } else {
292 0 : fields[ili1AttrIdx] = obj;
293 0 : if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
294 : }
295 : }
296 : }
297 0 : iom_releaseobject(fieldele);
298 : }
299 0 : iom_releaseiterator(fieldit);
300 :
301 : // if multiple gets positive we have more than one geometry column (only points)
302 0 : int multiple = -1;
303 :
304 0 : for (int i=0; i<=maxIdx; i++) {
305 0 : IOM_OBJECT obj = fields[i];
306 0 : if (obj) {
307 0 : attributes.push_back(obj);
308 0 : if (EQUAL(GetTypeName(model, obj), "iom04.metamodel.CoordType")) multiple++;
309 : }
310 : }
311 :
312 0 : std::vector<IOM_OBJECT>::iterator it = attributes.begin();
313 0 : for (int i=0; i<=maxIdx; i++) {
314 0 : IOM_OBJECT obj = roledefs[i];
315 0 : if (obj) attributes.insert(attributes.begin() + i, obj);
316 : }
317 :
318 0 : OGRFeature *feature = NULL;
319 0 : char* geomlayername = '\0';
320 0 : OGRILI1Layer* layer = NULL;
321 :
322 0 : for(size_t i=0; i<attributes.size(); i++) {
323 0 : IOM_OBJECT obj = attributes.at(i);
324 0 : const char* typenam = GetTypeName(model, obj);
325 0 : if (EQUAL(typenam, "iom04.metamodel.CoordType") || EQUAL(typenam, "iom04.metamodel.AreaType")) {
326 0 : feature = OGRFeature::CreateFeature(metaLayer->GetLayerDefn());
327 0 : feature->SetFID(j+1);
328 0 : feature->SetField("layername", layername);
329 0 : feature->SetField("geomIdx", (int)i);
330 :
331 0 : if(multiple > 0) {
332 0 : geomlayername = GetPointLayerName(layername, iom_getattrvalue(obj, "name"));
333 0 : feature->SetField("geomlayername", geomlayername);
334 0 : layer = new OGRILI1Layer(geomlayername, poSRSIn, bWriterIn, eReqType, poDSIn);
335 0 : AddLayer(layer);
336 :
337 : } else {
338 0 : feature->SetField("geomlayername", layername);
339 0 : layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
340 0 : AddLayer(layer);
341 : }
342 0 : metaLayer->AddFeature(feature);
343 : }
344 : }
345 :
346 0 : if(layer == NULL) {
347 0 : layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
348 0 : AddLayer(layer);
349 : }
350 :
351 0 : OGRFieldDefn fieldDef("_TID", OFTString);
352 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
353 :
354 0 : for(size_t i=0; i<attributes.size(); i++) {
355 0 : IOM_OBJECT obj = attributes.at(i);
356 0 : AddField(layer, model, obj);
357 : }
358 :
359 : // additional point layer added
360 0 : if(multiple > 0) {
361 0 : for(int i = 1; i <= multiple; i++) {
362 0 : OGRILI1Layer* pointLayer = papoLayers[nLayers-(i+1)];
363 0 : for (int j=0; j < layer->GetLayerDefn()->GetFieldCount(); j++) {
364 0 : pointLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(j));
365 : }
366 0 : if (pointLayer->GetLayerDefn()->GetGeomType() == wkbUnknown) pointLayer->GetLayerDefn()->SetGeomType(wkbPoint);
367 : }
368 : }
369 :
370 0 : if (papoLayers[nLayers-1]->GetLayerDefn()->GetFieldCount() == 0) {
371 : //Area layer added
372 0 : OGRILI1Layer* areaLayer = papoLayers[nLayers-1];
373 0 : for (int i=0; i < layer->GetLayerDefn()->GetFieldCount(); i++) {
374 0 : areaLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(i));
375 : }
376 0 : }
377 : }
378 : }
379 0 : iom_releaseobject(modelele);
380 :
381 0 : modelele=iom_nextobject(modelelei);
382 0 : j++;
383 : }
384 :
385 0 : iom_releaseiterator(modelelei);
386 :
387 0 : iom_releasebasket(model);
388 :
389 0 : iom_end();
390 :
391 0 : return 0;
392 : }
393 :
394 0 : int ILI1Reader::ReadFeatures() {
395 0 : char **tokens = NULL;
396 0 : const char *firsttok = NULL;
397 : const char *pszLine;
398 0 : char *topic = NULL;
399 0 : int ret = TRUE;
400 :
401 0 : while (ret && (tokens = ReadParseLine()))
402 : {
403 0 : firsttok = tokens[0];
404 0 : if (EQUAL(firsttok, "SCNT"))
405 : {
406 : //read description
407 0 : do
408 : {
409 0 : pszLine = CPLReadLine( fpItf );
410 : }
411 : while (pszLine && !EQUALN(pszLine, "////", 4));
412 0 : ret = (pszLine != NULL);
413 : }
414 0 : else if (EQUAL(firsttok, "MOTR"))
415 : {
416 : //read model
417 0 : do
418 : {
419 0 : pszLine = CPLReadLine( fpItf );
420 : }
421 : while (pszLine && !EQUALN(pszLine, "////", 4));
422 0 : ret = (pszLine != NULL);
423 : }
424 0 : else if (EQUAL(firsttok, "MTID"))
425 : {
426 : }
427 0 : else if (EQUAL(firsttok, "MODL"))
428 : {
429 : }
430 0 : else if (EQUAL(firsttok, "TOPI"))
431 : {
432 0 : CPLFree(topic);
433 0 : topic = CPLStrdup(CSLGetField(tokens, 1));
434 : }
435 0 : else if (EQUAL(firsttok, "TABL"))
436 : {
437 0 : CPLDebug( "OGR_ILI", "Reading table '%s'", GetLayerNameString(topic, CSLGetField(tokens, 1)) );
438 0 : const char *layername = GetLayerNameString(topic, CSLGetField(tokens, 1));
439 0 : curLayer = GetLayerByName(layername);
440 :
441 0 : int multiple = HasMultiplePointGeom(layername);
442 :
443 : // create only a new layer if there is no curLayer AND
444 : // if there are more than one point geometry columns
445 0 : if (curLayer == NULL && multiple < 1) { //create one
446 0 : CPLDebug( "OGR_ILI", "No model found, using default field names." );
447 0 : OGRSpatialReference *poSRSIn = NULL;
448 0 : int bWriterIn = 0;
449 0 : OGRwkbGeometryType eReqType = wkbUnknown;
450 0 : OGRILI1DataSource *poDSIn = NULL;
451 0 : curLayer = new OGRILI1Layer(GetLayerNameString(topic, CSLGetField(tokens, 1)), poSRSIn, bWriterIn, eReqType, poDSIn);
452 0 : AddLayer(curLayer);
453 : }
454 0 : if(curLayer != NULL) {
455 0 : for (int i=0; i < curLayer->GetLayerDefn()->GetFieldCount(); i++) {
456 0 : CPLDebug( "OGR_ILI", "Field %d: %s", i, curLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
457 : }
458 : }
459 0 : ret = ReadTable(layername);
460 : }
461 0 : else if (EQUAL(firsttok, "ETOP"))
462 : {
463 : }
464 0 : else if (EQUAL(firsttok, "EMOD"))
465 : {
466 : }
467 0 : else if (EQUAL(firsttok, "ENDE"))
468 : {
469 0 : CSLDestroy(tokens);
470 0 : CPLFree(topic);
471 0 : return TRUE;
472 : }
473 : else
474 : {
475 0 : CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
476 : }
477 :
478 0 : CSLDestroy(tokens);
479 0 : tokens = NULL;
480 : }
481 :
482 0 : CSLDestroy(tokens);
483 0 : CPLFree(topic);
484 :
485 0 : return ret;
486 : }
487 :
488 0 : int ILI1Reader::AddIliGeom(OGRFeature *feature, int iField, long fpos)
489 : {
490 : #if defined(_WIN32) || defined(__WIN32__)
491 : //Other positions on Windows !?
492 : #else
493 0 : long nBlockLen = VSIFTell( fpItf )-fpos;
494 0 : VSIFSeek( fpItf, fpos, SEEK_SET );
495 :
496 0 : char *pszRawData = (char *) CPLMalloc(nBlockLen+1);
497 0 : if( (int) VSIFRead( pszRawData, 1, nBlockLen, fpItf ) != nBlockLen )
498 : {
499 0 : CPLFree( pszRawData );
500 :
501 0 : CPLError( CE_Failure, CPLE_FileIO, "Read of transfer file failed." );
502 0 : return FALSE;
503 : }
504 0 : pszRawData[nBlockLen]= '\0';
505 0 : feature->SetField(iField, pszRawData);
506 0 : CPLFree( pszRawData );
507 : #endif
508 0 : return TRUE;
509 : }
510 :
511 :
512 0 : int ILI1Reader::ReadTable(const char *layername) {
513 0 : char **tokens = NULL;
514 0 : const char *firsttok = NULL;
515 0 : int ret = TRUE;
516 0 : int warned = FALSE;
517 : int fIndex;
518 0 : int geomIdx = 0;
519 :
520 : // curLayer is NULL if we have more than one
521 : // point geometry column
522 0 : if(curLayer == NULL) {
523 0 : OGRFeature *metaFeature = NULL;
524 0 : metaLayer->ResetReading();
525 0 : while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
526 0 : if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
527 0 : const char *geomlayername = metaFeature->GetFieldAsString(2);
528 0 : curLayer = GetLayerByName(geomlayername);
529 0 : break;
530 : }
531 : }
532 : }
533 :
534 0 : OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
535 0 : OGRFeature *feature = NULL;
536 :
537 : // get the geometry index of the current layer
538 : // only if the model is read
539 0 : if(featureDef->GetFieldCount() != 0) {
540 0 : OGRFeature *metaFeature = NULL;
541 0 : metaLayer->ResetReading();
542 0 : while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
543 0 : if(EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
544 0 : geomIdx = metaFeature->GetFieldAsInteger(1);
545 : }
546 : }
547 : }
548 :
549 0 : long fpos = VSIFTell(fpItf);
550 0 : while (ret && (tokens = ReadParseLine()))
551 : {
552 0 : firsttok = CSLGetField(tokens, 0);
553 0 : if (EQUAL(firsttok, "OBJE"))
554 : {
555 : //Check for features spread over multiple objects
556 0 : if (featureDef->GetGeomType() == wkbPolygon)
557 : {
558 : //Multiple polygon rings
559 0 : feature = curLayer->GetFeatureRef(atol(CSLGetField(tokens, 2)));
560 : }
561 0 : else if (featureDef->GetGeomType() == wkbGeometryCollection)
562 : {
563 : //AREA lines spread over mutltiple objects
564 : }
565 : else
566 : {
567 0 : feature = NULL;
568 : }
569 :
570 0 : if (feature == NULL)
571 : {
572 0 : if (featureDef->GetFieldCount() == 0)
573 : {
574 0 : CPLDebug( "OGR_ILI", "No field definition found for table: %s", featureDef->GetName() );
575 : //Model not read - use heuristics
576 0 : for (fIndex=1; fIndex<CSLCount(tokens); fIndex++)
577 : {
578 : char szFieldName[32];
579 0 : sprintf(szFieldName, "Field%02d", fIndex);
580 0 : OGRFieldDefn oFieldDefn(szFieldName, OFTString);
581 0 : featureDef->AddFieldDefn(&oFieldDefn);
582 : }
583 : }
584 : //start new feature
585 0 : feature = new OGRFeature(featureDef);
586 :
587 0 : int fieldno = 0;
588 0 : for (fIndex=1; fIndex<CSLCount(tokens) && fieldno < featureDef->GetFieldCount(); fIndex++, fieldno++)
589 : {
590 0 : if (!EQUAL(tokens[fIndex], "@")) {
591 : //CPLDebug( "READ TABLE OGR_ILI", "Adding Field %d: %s", fieldno, tokens[fIndex]);
592 0 : feature->SetField(fieldno, tokens[fIndex]);
593 0 : if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTReal
594 : && fieldno > 0
595 : && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal
596 : && featureDef->GetGeomType() == wkbPoint
597 :
598 : /*
599 : // if there is no ili model read,
600 : // we have no chance to detect the
601 : // geometry column!!
602 : */
603 :
604 : && (fieldno-2) == geomIdx) {
605 : //add Point geometry
606 0 : OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-1]), atof(tokens[fIndex]));
607 0 : feature->SetGeometryDirectly(ogrPoint);
608 : }
609 : }
610 : }
611 0 : if (!warned && featureDef->GetFieldCount() != CSLCount(tokens)-1 && !(featureDef->GetFieldCount() == CSLCount(tokens) && EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))) {
612 0 : CPLDebug( "OGR_ILI", "Field count doesn't match. %d declared, %d found", featureDef->GetFieldCount(), CSLCount(tokens)-1);
613 0 : warned = TRUE;
614 : }
615 0 : if (featureDef->GetGeomType() == wkbPolygon)
616 0 : feature->SetFID(atol(feature->GetFieldAsString(1)));
617 0 : else if (feature->GetFieldCount() > 0)
618 0 : feature->SetFID(atol(feature->GetFieldAsString(0)));
619 0 : curLayer->AddFeature(feature);
620 : }
621 : }
622 0 : else if (EQUAL(firsttok, "STPT"))
623 : {
624 0 : ReadGeom(tokens, featureDef->GetGeomType(), feature);
625 0 : if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
626 : {
627 0 : AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos); //TODO: append multi-OBJECT geometries
628 : }
629 : }
630 0 : else if (EQUAL(firsttok, "ELIN"))
631 : {
632 : //empty geom
633 : }
634 0 : else if (EQUAL(firsttok, "EDGE"))
635 : {
636 0 : tokens = ReadParseLine(); //STPT
637 0 : ReadGeom(tokens, wkbMultiLineString, feature);
638 0 : if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
639 : {
640 0 : AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos);
641 : }
642 : }
643 0 : else if (EQUAL(firsttok, "PERI"))
644 : {
645 : }
646 0 : else if (EQUAL(firsttok, "ETAB"))
647 : {
648 0 : if(HasMultiplePointGeom(layername) > 0) {
649 0 : OGRFeature *metaFeature = NULL;
650 0 : metaLayer->ResetReading();
651 0 : while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
652 0 : int pntCln = 1;
653 0 : if(EQUAL(layername, metaFeature->GetFieldAsString(0)) && !EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
654 0 : pntCln++;
655 0 : OGRILI1Layer *curLayerTmp = GetLayerByName(metaFeature->GetFieldAsString(2));
656 0 : OGRFeature *tmpFeature = NULL;
657 0 : int geomIdxTmp = metaFeature->GetFieldAsInteger(1);
658 0 : curLayer->ResetReading();
659 0 : while((tmpFeature = curLayer->GetNextFeature()) != NULL ) {
660 0 : OGRPoint *ogrPoint = new OGRPoint(atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln)), atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln + 1)));
661 0 : tmpFeature->SetGeometryDirectly(ogrPoint);
662 0 : curLayerTmp->AddFeature(tmpFeature);
663 : }
664 : }
665 : }
666 : }
667 0 : CSLDestroy(tokens);
668 0 : return TRUE;
669 : }
670 : else
671 : {
672 0 : CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
673 : }
674 :
675 0 : CSLDestroy(tokens);
676 0 : fpos = VSIFTell(fpItf);
677 : }
678 :
679 0 : return ret;
680 : }
681 :
682 0 : void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature) {
683 :
684 0 : char **tokens = NULL;
685 0 : const char *firsttok = NULL;
686 0 : int end = FALSE;
687 0 : int isArc = FALSE;
688 0 : OGRLineString *ogrLine = NULL; //current line
689 0 : OGRLinearRing *ogrRing = NULL; //current ring
690 0 : OGRPolygon *ogrPoly = NULL; //current polygon
691 0 : OGRPoint ogrPoint, arcPoint, endPoint; //points for arc interpolation
692 0 : OGRMultiLineString *ogrMultiLine = NULL; //current multi line
693 :
694 : //tokens = ["STPT", "1111", "22222"]
695 0 : ogrPoint.setX(atof(stgeom[1])); ogrPoint.setY(atof(stgeom[2]));
696 0 : ogrLine = (eType == wkbPolygon) ? new OGRLinearRing() : new OGRLineString();
697 0 : ogrLine->addPoint(&ogrPoint);
698 :
699 : //Set feature geometry
700 0 : if (eType == wkbMultiLineString)
701 : {
702 0 : ogrMultiLine = new OGRMultiLineString();
703 0 : feature->SetGeometryDirectly(ogrMultiLine);
704 : }
705 0 : else if (eType == wkbGeometryCollection) //AREA
706 : {
707 0 : if (feature->GetGeometryRef())
708 0 : ogrMultiLine = (OGRMultiLineString *)feature->GetGeometryRef();
709 : else
710 : {
711 0 : ogrMultiLine = new OGRMultiLineString();
712 0 : feature->SetGeometryDirectly(ogrMultiLine);
713 : }
714 : }
715 0 : else if (eType == wkbPolygon)
716 : {
717 0 : if (feature->GetGeometryRef())
718 : {
719 0 : ogrPoly = (OGRPolygon *)feature->GetGeometryRef();
720 0 : if (ogrPoly->getNumInteriorRings() > 0)
721 0 : ogrRing = ogrPoly->getInteriorRing(ogrPoly->getNumInteriorRings()-1);
722 : else
723 0 : ogrRing = ogrPoly->getExteriorRing();
724 0 : if (ogrRing && !ogrRing->get_IsClosed()) ogrLine = ogrRing; //SURFACE polygon spread over multiple OBJECTs
725 : }
726 : else
727 : {
728 0 : ogrPoly = new OGRPolygon();
729 0 : feature->SetGeometryDirectly(ogrPoly);
730 : }
731 : }
732 : else
733 : {
734 0 : feature->SetGeometryDirectly(ogrLine);
735 : }
736 :
737 : //Parse geometry
738 0 : while (!end && (tokens = ReadParseLine()))
739 : {
740 0 : firsttok = CSLGetField(tokens, 0);
741 0 : if (EQUAL(firsttok, "LIPT"))
742 : {
743 0 : if (isArc) {
744 0 : endPoint.setX(atof(tokens[1])); endPoint.setY(atof(tokens[2]));
745 0 : interpolateArc(ogrLine, &ogrPoint, &arcPoint, &endPoint, arcIncr);
746 : }
747 0 : ogrPoint.setX(atof(tokens[1])); ogrPoint.setY(atof(tokens[2])); isArc = FALSE;
748 0 : ogrLine->addPoint(&ogrPoint);
749 : }
750 0 : else if (EQUAL(firsttok, "ARCP"))
751 : {
752 0 : isArc = TRUE;
753 0 : arcPoint.setX(atof(tokens[1])); arcPoint.setY(atof(tokens[2]));
754 : }
755 0 : else if (EQUAL(firsttok, "ELIN"))
756 : {
757 0 : if (ogrMultiLine)
758 : {
759 0 : ogrMultiLine->addGeometryDirectly(ogrLine);
760 : }
761 0 : if (ogrPoly && ogrLine != ogrRing)
762 : {
763 0 : ogrPoly->addRingDirectly((OGRLinearRing *)ogrLine);
764 : }
765 0 : end = TRUE;
766 : }
767 0 : else if (EQUAL(firsttok, "EEDG"))
768 : {
769 0 : end = TRUE;
770 : }
771 0 : else if (EQUAL(firsttok, "LATT"))
772 : {
773 : //Line Attributes (ignored)
774 : }
775 0 : else if (EQUAL(firsttok, "EFLA"))
776 : {
777 0 : end = TRUE;
778 : }
779 0 : else if (EQUAL(firsttok, "ETAB"))
780 : {
781 0 : end = TRUE;
782 : }
783 : else
784 : {
785 0 : CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
786 : }
787 :
788 0 : CSLDestroy(tokens);
789 0 : }
790 0 : }
791 :
792 : /************************************************************************/
793 : /* AddLayer() */
794 : /************************************************************************/
795 :
796 0 : void ILI1Reader::AddLayer( OGRILI1Layer * poNewLayer )
797 :
798 : {
799 0 : nLayers++;
800 :
801 : papoLayers = (OGRILI1Layer **)
802 0 : CPLRealloc( papoLayers, sizeof(void*) * nLayers );
803 :
804 0 : papoLayers[nLayers-1] = poNewLayer;
805 0 : }
806 :
807 : /************************************************************************/
808 : /* AddAreaLayer() */
809 : /************************************************************************/
810 :
811 : /************************************************************************/
812 : /* GetLayer() */
813 : /************************************************************************/
814 :
815 0 : OGRILI1Layer *ILI1Reader::GetLayer( int iLayer )
816 :
817 : {
818 0 : if( iLayer < 0 || iLayer >= nLayers )
819 0 : return NULL;
820 : else
821 0 : return papoLayers[iLayer];
822 : }
823 :
824 0 : OGRILI1Layer *ILI1Reader::GetLayerByName( const char* pszLayerName )
825 :
826 : {
827 0 : for(int iLayer = 0; iLayer < nLayers; iLayer++ )
828 : {
829 0 : if( EQUAL(pszLayerName,
830 : papoLayers[iLayer]->GetLayerDefn()->GetName()) )
831 0 : return papoLayers[iLayer];
832 : }
833 0 : return NULL;
834 : }
835 :
836 : /************************************************************************/
837 : /* GetLayerCount() */
838 : /************************************************************************/
839 :
840 0 : int ILI1Reader::GetLayerCount()
841 :
842 : {
843 0 : return nLayers;
844 : }
845 :
846 : /************************************************************************/
847 : /* Read one logical line, and return split into fields. The return */
848 : /* result is a stringlist, in the sense of the CSL functions. */
849 : /************************************************************************/
850 :
851 0 : char ** ILI1Reader::ReadParseLine()
852 : {
853 : const char *pszLine;
854 : char **tokens;
855 : char **conttok;
856 : char *token;
857 :
858 0 : CPLAssert( fpItf != NULL );
859 0 : if( fpItf == NULL )
860 0 : return( NULL );
861 :
862 0 : pszLine = CPLReadLine( fpItf );
863 0 : if( pszLine == NULL )
864 0 : return( NULL );
865 :
866 0 : if (strlen(pszLine) == 0) return NULL;
867 :
868 0 : tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
869 0 : token = tokens[CSLCount(tokens)-1];
870 :
871 : //Append CONT lines
872 0 : while (strlen(pszLine) && EQUALN(token, "\\", 2))
873 : {
874 : //remove last token
875 0 : CPLFree(tokens[CSLCount(tokens)-1]);
876 0 : tokens[CSLCount(tokens)-1] = NULL;
877 :
878 0 : pszLine = CPLReadLine( fpItf );
879 0 : conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
880 0 : if (!conttok || !EQUAL(conttok[0], "CONT"))
881 : {
882 0 : CSLDestroy(conttok);
883 0 : break;
884 : }
885 :
886 : //append
887 0 : tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
888 0 : token = tokens[CSLCount(tokens)-1];
889 :
890 0 : CSLDestroy(conttok);
891 : }
892 0 : return tokens;
893 : }
894 :
895 :
896 :
897 0 : IILI1Reader *CreateILI1Reader() {
898 0 : return new ILI1Reader();
899 : }
900 :
901 174 : void DestroyILI1Reader(IILI1Reader* reader)
902 : {
903 174 : if (reader)
904 0 : delete reader;
905 174 : }
|